mirror of
https://github.com/nadoo/glider.git
synced 2025-02-23 01:15:41 +08:00
dhcpd: added dhcpd-failover
service, only keep linux support
This commit is contained in:
parent
1f196c9cf5
commit
c261e5989c
19
README.md
19
README.md
@ -38,7 +38,7 @@ we can set up local listeners as proxy servers, and forward requests to internet
|
|||||||
- Periodical availability checking for forwarders
|
- Periodical availability checking for forwarders
|
||||||
- Send requests from specific local ip/interface
|
- Send requests from specific local ip/interface
|
||||||
- Services:
|
- Services:
|
||||||
- dhcpd: a simple dhcp server that can detect existing dhcp server and avoid conflicts
|
- dhcpd: a simple dhcp server that can run in failover mode
|
||||||
|
|
||||||
## Protocols
|
## Protocols
|
||||||
|
|
||||||
@ -84,6 +84,8 @@ we can set up local listeners as proxy servers, and forward requests to internet
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
#### Run
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
glider -config CONFIG_PATH
|
glider -config CONFIG_PATH
|
||||||
```
|
```
|
||||||
@ -94,7 +96,7 @@ glider -verbose -listen :8443 -forward SCHEME://HOST:PORT
|
|||||||
#### Help
|
#### Help
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>`glider -help` (click to see details)</summary>
|
<summary>`glider -help` (click)</summary>
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
Usage: glider [-listen URL]... [-forward URL]... [OPTION]...
|
Usage: glider [-listen URL]... [-forward URL]... [OPTION]...
|
||||||
@ -207,6 +209,7 @@ Forwarder Options: FORWARD_URL#OPTIONS
|
|||||||
|
|
||||||
Services:
|
Services:
|
||||||
dhcpd: service=dhcpd,INTERFACE,START_IP,END_IP,LEASE_MINUTES[,MAC=IP,MAC=IP...]
|
dhcpd: service=dhcpd,INTERFACE,START_IP,END_IP,LEASE_MINUTES[,MAC=IP,MAC=IP...]
|
||||||
|
service=dhcpd-failover,INTERFACE,START_IP,END_IP,LEASE_MINUTES[,MAC=IP,MAC=IP...]
|
||||||
e.g. service=dhcpd,eth1,192.168.1.100,192.168.1.199,720
|
e.g. service=dhcpd,eth1,192.168.1.100,192.168.1.199,720
|
||||||
|
|
||||||
--
|
--
|
||||||
@ -225,7 +228,7 @@ glider 0.16.0, https://github.com/nadoo/glider
|
|||||||
#### Schemes
|
#### Schemes
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>`glider -scheme all` (click to see details)</summary>
|
<summary>`glider -scheme all` (click)</summary>
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
KCP scheme:
|
KCP scheme:
|
||||||
@ -340,7 +343,7 @@ TLS and Websocket with a specified proxy protocol:
|
|||||||
#### Examples
|
#### Examples
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>`glider -example` (click to see details)</summary>
|
<summary>`glider -example` (click)</summary>
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
Examples:
|
Examples:
|
||||||
@ -391,9 +394,11 @@ Examples:
|
|||||||
|
|
||||||
- dhcpd:
|
- dhcpd:
|
||||||
- service=dhcpd,INTERFACE,START_IP,END_IP,LEASE_MINUTES[,MAC=IP,MAC=IP...]
|
- service=dhcpd,INTERFACE,START_IP,END_IP,LEASE_MINUTES[,MAC=IP,MAC=IP...]
|
||||||
- e.g.:
|
- service=dhcpd,eth1,192.168.1.100,192.168.1.199,720
|
||||||
- service=dhcpd,eth1,192.168.1.100,192.168.1.199,720
|
- service=dhcpd,eth2,192.168.2.100,192.168.2.199,720,fc:23:34:9e:25:01=192.168.2.101
|
||||||
- service=dhcpd,eth2,192.168.2.100,192.168.2.199,720,fc:23:34:9e:25:01=192.168.2.101
|
|
||||||
|
- dhcpd-failover: only serves requests when there's no other dhcp server exists
|
||||||
|
- service=dhcpd-failover,INTERFACE,START_IP,END_IP,LEASE_MINUTES[,MAC=IP,MAC=IP...]
|
||||||
|
|
||||||
## Linux Service
|
## Linux Service
|
||||||
|
|
||||||
|
@ -204,6 +204,7 @@ Forwarder Options: FORWARD_URL#OPTIONS
|
|||||||
|
|
||||||
Services:
|
Services:
|
||||||
dhcpd: service=dhcpd,INTERFACE,START_IP,END_IP,LEASE_MINUTES[,MAC=IP,MAC=IP...]
|
dhcpd: service=dhcpd,INTERFACE,START_IP,END_IP,LEASE_MINUTES[,MAC=IP,MAC=IP...]
|
||||||
|
service=dhcpd-failover,INTERFACE,START_IP,END_IP,LEASE_MINUTES[,MAC=IP,MAC=IP...]
|
||||||
e.g. service=dhcpd,eth1,192.168.1.100,192.168.1.199,720
|
e.g. service=dhcpd,eth1,192.168.1.100,192.168.1.199,720
|
||||||
|
|
||||||
--
|
--
|
||||||
|
@ -3,7 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
// comment out the services you don't need to make the compiled binary smaller.
|
// comment out the services you don't need to make the compiled binary smaller.
|
||||||
// _ "github.com/nadoo/glider/service/xxx"
|
// _ "github.com/nadoo/glider/service/xxx"
|
||||||
_ "github.com/nadoo/glider/service/dhcpd"
|
|
||||||
|
|
||||||
// comment out the protocols you don't need to make the compiled binary smaller.
|
// comment out the protocols you don't need to make the compiled binary smaller.
|
||||||
_ "github.com/nadoo/glider/proxy/http"
|
_ "github.com/nadoo/glider/proxy/http"
|
||||||
|
@ -3,6 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
// comment out the services you don't need to make the compiled binary smaller.
|
// comment out the services you don't need to make the compiled binary smaller.
|
||||||
// _ "github.com/nadoo/glider/service/xxx"
|
// _ "github.com/nadoo/glider/service/xxx"
|
||||||
|
_ "github.com/nadoo/glider/service/dhcpd"
|
||||||
|
|
||||||
// comment out the protocols you don't need to make the compiled binary smaller.
|
// comment out the protocols you don't need to make the compiled binary smaller.
|
||||||
_ "github.com/nadoo/glider/proxy/redir"
|
_ "github.com/nadoo/glider/proxy/redir"
|
||||||
|
@ -3,40 +3,30 @@ package dhcpd
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
"runtime"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/insomniacslk/dhcp/dhcpv4"
|
"github.com/insomniacslk/dhcp/dhcpv4"
|
||||||
|
|
||||||
"github.com/nadoo/glider/pkg/log"
|
|
||||||
"github.com/nadoo/glider/pkg/sockopt"
|
"github.com/nadoo/glider/pkg/sockopt"
|
||||||
)
|
)
|
||||||
|
|
||||||
func existsServer(intf *net.Interface) (exists bool) {
|
func discovery(intf *net.Interface) (found bool) {
|
||||||
lc := &net.ListenConfig{}
|
lc := &net.ListenConfig{}
|
||||||
lc.Control = sockopt.BindControl(intf)
|
lc.Control = sockopt.BindControl(intf)
|
||||||
|
|
||||||
addr := "0.0.0.0:68"
|
pc, err := lc.ListenPacket(context.Background(), "udp4", "255.255.255.255:68")
|
||||||
if runtime.GOOS == "linux" || runtime.GOOS == "android" {
|
|
||||||
addr = "255.255.255.255:68"
|
|
||||||
}
|
|
||||||
|
|
||||||
pc, err := lc.ListenPacket(context.Background(), "udp4", addr)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[dhcpd] failed in dhcp client ListenPacket: %s", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer pc.Close()
|
defer pc.Close()
|
||||||
|
|
||||||
discovery, err := dhcpv4.NewDiscovery(intf.HardwareAddr, dhcpv4.WithBroadcast(true))
|
discovery, err := dhcpv4.NewDiscovery(intf.HardwareAddr, dhcpv4.WithBroadcast(true))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[dhcpd] failed in dhcp client NewDiscovery: %s", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = pc.WriteTo(discovery.ToBytes(), &net.UDPAddr{IP: net.IPv4bcast, Port: 67})
|
_, err = pc.WriteTo(discovery.ToBytes(), &net.UDPAddr{IP: net.IPv4bcast, Port: 67})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[dhcpd] failed in dhcp client WriteTo: %s", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
package dhcpd
|
package dhcpd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/insomniacslk/dhcp/dhcpv4"
|
"github.com/insomniacslk/dhcp/dhcpv4"
|
||||||
@ -18,13 +20,19 @@ import (
|
|||||||
var leaseTime = time.Hour * 12
|
var leaseTime = time.Hour * 12
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
service.Register("dhcpd", &dpcpd{})
|
service.Register("dhcpd", &dhcpd{})
|
||||||
|
service.Register("dhcpd-failover", &dhcpd{detect: true})
|
||||||
}
|
}
|
||||||
|
|
||||||
type dpcpd struct{}
|
type dhcpd struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
detect bool
|
||||||
|
failover bool
|
||||||
|
intface *net.Interface
|
||||||
|
}
|
||||||
|
|
||||||
// Run runs the service.
|
// Run runs the service.
|
||||||
func (*dpcpd) Run(args ...string) {
|
func (d *dhcpd) Run(args ...string) {
|
||||||
if len(args) < 4 {
|
if len(args) < 4 {
|
||||||
log.F("[dhcpd] not enough parameters, exiting")
|
log.F("[dhcpd] not enough parameters, exiting")
|
||||||
return
|
return
|
||||||
@ -40,10 +48,11 @@ func (*dpcpd) Run(args ...string) {
|
|||||||
log.F("[dhcpd] get ip of interface '%s' error: %s", iface, err)
|
log.F("[dhcpd] get ip of interface '%s' error: %s", iface, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
d.intface = intf
|
||||||
|
|
||||||
if existsServer(intf) {
|
if d.detect {
|
||||||
log.F("[dhcpd] found existing dhcp server on interface %s, service exiting", iface)
|
d.setFailoverMode(discovery(intf))
|
||||||
return
|
go d.detectServer(time.Second * 60)
|
||||||
}
|
}
|
||||||
|
|
||||||
startIP, err := netip.ParseAddr(start)
|
startIP, err := netip.ParseAddr(start)
|
||||||
@ -76,23 +85,23 @@ func (*dpcpd) Run(args ...string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
laddr := net.UDPAddr{IP: net.IPv4(0, 0, 0, 0), Port: 67}
|
laddr := net.UDPAddr{IP: net.IPv4(0, 0, 0, 0), Port: 67}
|
||||||
server, err := server4.NewServer(iface, &laddr, handleDHCP(ip, mask, pool))
|
server, err := server4.NewServer(iface, &laddr, d.handleDHCP(ip, mask, pool))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[dhcpd] error in server creation: %s", err)
|
log.F("[dhcpd] error in server creation: %s", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.F("[dhcpd] Listening on interface %s(%s/%d.%d.%d.%d)",
|
log.F("[dhcpd] Listening on interface %s(%s/%d.%d.%d.%d), server detection: %t",
|
||||||
iface, ip, mask[0], mask[1], mask[2], mask[3])
|
iface, ip, mask[0], mask[1], mask[2], mask[3], d.detect)
|
||||||
|
|
||||||
server.Serve()
|
server.Serve()
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleDHCP(serverIP net.IP, mask net.IPMask, pool *Pool) server4.Handler {
|
func (d *dhcpd) handleDHCP(serverIP net.IP, mask net.IPMask, pool *Pool) server4.Handler {
|
||||||
return func(conn net.PacketConn, peer net.Addr, m *dhcpv4.DHCPv4) {
|
return func(conn net.PacketConn, peer net.Addr, m *dhcpv4.DHCPv4) {
|
||||||
|
|
||||||
var replyType dhcpv4.MessageType
|
var reqType, replyType dhcpv4.MessageType
|
||||||
switch mt := m.MessageType(); mt {
|
switch reqType = m.MessageType(); reqType {
|
||||||
case dhcpv4.MessageTypeDiscover:
|
case dhcpv4.MessageTypeDiscover:
|
||||||
replyType = dhcpv4.MessageTypeOffer
|
replyType = dhcpv4.MessageTypeOffer
|
||||||
case dhcpv4.MessageTypeRequest, dhcpv4.MessageTypeInform:
|
case dhcpv4.MessageTypeRequest, dhcpv4.MessageTypeInform:
|
||||||
@ -106,7 +115,11 @@ func handleDHCP(serverIP net.IP, mask net.IPMask, pool *Pool) server4.Handler {
|
|||||||
log.F("[dpcpd] received decline message from %v", m.ClientHWAddr)
|
log.F("[dpcpd] received decline message from %v", m.ClientHWAddr)
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
log.F("[dpcpd] can't handle type %v", mt)
|
log.F("[dpcpd] can't handle type %v", reqType)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.inFailoverMode() || bytes.Equal(d.intface.HardwareAddr, m.ClientHWAddr) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,6 +159,33 @@ func handleDHCP(serverIP net.IP, mask net.IPMask, pool *Pool) server4.Handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *dhcpd) inFailoverMode() bool {
|
||||||
|
d.mu.Lock()
|
||||||
|
defer d.mu.Unlock()
|
||||||
|
return d.failover
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *dhcpd) setFailoverMode(v bool) {
|
||||||
|
d.mu.Lock()
|
||||||
|
defer d.mu.Unlock()
|
||||||
|
|
||||||
|
if d.failover != v {
|
||||||
|
if v {
|
||||||
|
log.F("[dpcpd] existing dhcp server detected, enter failover mode")
|
||||||
|
} else {
|
||||||
|
log.F("[dpcpd] no dhcp server detected, exit failover mode")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d.failover = v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *dhcpd) detectServer(interval time.Duration) {
|
||||||
|
for {
|
||||||
|
d.setFailoverMode(discovery(d.intface))
|
||||||
|
time.Sleep(interval)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func ifaceAddr(iface string) (*net.Interface, net.IP, net.IPMask, error) {
|
func ifaceAddr(iface string) (*net.Interface, net.IP, net.IPMask, error) {
|
||||||
intf, err := net.InterfaceByName(iface)
|
intf, err := net.InterfaceByName(iface)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user