From de8c08c7b2ca2a1dfc5e8f5ff5d002b22826dd3f Mon Sep 17 00:00:00 2001 From: nadoo <287492+nadoo@users.noreply.github.com> Date: Tue, 29 Sep 2020 00:38:35 +0800 Subject: [PATCH] dhcpd: assign random ip --- dns/client.go | 4 +- go.mod | 2 +- go.sum | 4 +- proxy/tcptun/tcptun.go | 2 +- rule/forward.go | 7 +++- rule/group.go | 2 +- service/dhcpd/{dhcpd_linux.go => dhcpd.go} | 28 +++++-------- service/dhcpd/pool.go | 46 ++++++++++++---------- 8 files changed, 46 insertions(+), 49 deletions(-) rename service/dhcpd/{dhcpd_linux.go => dhcpd.go} (85%) diff --git a/dns/client.go b/dns/client.go index c6150dc..fc7c9fb 100644 --- a/dns/client.go +++ b/dns/client.go @@ -155,7 +155,7 @@ func (c *Client) exchange(qname string, reqBytes []byte, preferTCP bool) ( rc, err = dialer.Dial(network, server) if err != nil { newServer := ups.SwitchIf(server) - log.F("[dns] error in resolving %s, failed to connect to server %v via %s: %v, switch to %s", + log.F("[dns] error in resolving %s, failed to connect to server %v via %s: %v, next server: %s", qname, server, dialer.Addr(), err, newServer) server = newServer continue @@ -179,7 +179,7 @@ func (c *Client) exchange(qname string, reqBytes []byte, preferTCP bool) ( } newServer := ups.SwitchIf(server) - log.F("[dns] error in resolving %s, failed to exchange with server %v via %s: %v, switch to %s", + log.F("[dns] error in resolving %s, failed to exchange with server %v via %s: %v, next server: %s", qname, server, dialer.Addr(), err, newServer) server = newServer diff --git a/go.mod b/go.mod index 28c7a59..af396d5 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a golang.org/x/net v0.0.0-20200927032502-5d4f70055728 // indirect golang.org/x/sys v0.0.0-20200926100807-9d91bd62050c // indirect - golang.org/x/tools v0.0.0-20200925191224-5d1fdd8fa346 // indirect + golang.org/x/tools v0.0.0-20200928112810-42b62fc93869 // indirect gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect ) diff --git a/go.sum b/go.sum index f9aabf7..d6a94af 100644 --- a/go.sum +++ b/go.sum @@ -173,8 +173,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200425043458-8463f397d07c h1:iHhCR0b26amDCiiO+kBguKZom9aMF+NrFxh9zeKR/XU= golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200808161706-5bf02b21f123/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200925191224-5d1fdd8fa346 h1:hzJjkvxUIF3bSt+v8N5tBQNx/605vszZJ+3XsIamzZo= -golang.org/x/tools v0.0.0-20200925191224-5d1fdd8fa346/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= +golang.org/x/tools v0.0.0-20200928112810-42b62fc93869 h1:6Zj8sAhgEtZaHYz4O/Grp2Gyh0FLb8a7sLJTanOG5QQ= +golang.org/x/tools v0.0.0-20200928112810-42b62fc93869/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= diff --git a/proxy/tcptun/tcptun.go b/proxy/tcptun/tcptun.go index 7aa2ae6..e76e85b 100644 --- a/proxy/tcptun/tcptun.go +++ b/proxy/tcptun/tcptun.go @@ -55,7 +55,7 @@ func NewTCPTunServer(s string, p proxy.Proxy) (proxy.Server, error) { func (s *TCPTun) ListenAndServe() { l, err := net.Listen("tcp", s.addr) if err != nil { - log.F("failed to listen on %s: %v", s.addr, err) + log.F("[tcptun] failed to listen on %s: %v", s.addr, err) return } diff --git a/rule/forward.go b/rule/forward.go index 32a6e02..a857d5e 100644 --- a/rule/forward.go +++ b/rule/forward.go @@ -115,10 +115,13 @@ func (f *Forwarder) Failures() uint32 { // IncFailures increase the failuer count by 1. func (f *Forwarder) IncFailures() { failures := atomic.AddUint32(&f.failures, 1) + if f.MaxFailures() == 0 { + return + } + log.F("[forwarder] %s recorded %d failures, maxfailures: %d", f.addr, failures, f.MaxFailures()) - if f.MaxFailures() != 0 && failures >= f.MaxFailures() && f.Enabled() { - log.F("[forwarder] %s reaches maxfailures %d", f.addr, f.MaxFailures()) + if failures >= f.MaxFailures() && f.Enabled() { f.Disable() } } diff --git a/rule/group.go b/rule/group.go index ac17a66..8320933 100644 --- a/rule/group.go +++ b/rule/group.go @@ -271,7 +271,7 @@ func checkWebSite(fwdr *Forwarder, website string, timeout time.Duration, buf [] } fwdr.Enable() - log.F("[check] %s(%d) -> %s, SUCCEEDED. connect time: %s", fwdr.Addr(), fwdr.Priority(), + log.F("[check] %s(%d) -> %s, SUCCESS. connect time: %s", fwdr.Addr(), fwdr.Priority(), website, readTime) return true diff --git a/service/dhcpd/dhcpd_linux.go b/service/dhcpd/dhcpd.go similarity index 85% rename from service/dhcpd/dhcpd_linux.go rename to service/dhcpd/dhcpd.go index 2794a3d..167010c 100644 --- a/service/dhcpd/dhcpd_linux.go +++ b/service/dhcpd/dhcpd.go @@ -46,10 +46,10 @@ func (*dpcpd) Run(args ...string) { return } - server, err := server4.NewServer( - iface, &net.UDPAddr{IP: net.IPv4(0, 0, 0, 0), Port: 67}, handleDHCP(ip, mask, pool)) + laddr := net.UDPAddr{IP: net.IPv4(0, 0, 0, 0), Port: 67} + server, err := server4.NewServer(iface, &laddr, handleDHCP(ip, mask, pool)) if err != nil { - log.F("[dhcpd] error in server new: %s", err) + log.F("[dhcpd] error in server creation: %s", err) return } @@ -61,7 +61,7 @@ func (*dpcpd) Run(args ...string) { func handleDHCP(serverIP net.IP, mask net.IPMask, pool *Pool) server4.Handler { return func(conn net.PacketConn, peer net.Addr, m *dhcpv4.DHCPv4) { - log.F("[dpcpd] received request from client %v", m.ClientHWAddr) + // log.F("[dpcpd] received request from client %v", m.ClientHWAddr) var replyType dhcpv4.MessageType switch mt := m.MessageType(); mt { @@ -99,7 +99,7 @@ func handleDHCP(serverIP net.IP, mask net.IPMask, pool *Pool) server4.Handler { } if _, err := conn.WriteTo(reply.ToBytes(), peer); err != nil { - log.F("[dpcpd] could not write %v: %s", reply, err) + log.F("[dpcpd] could not write to client %s(%s): %s", peer, reply.ClientHWAddr, err) return } @@ -136,20 +136,10 @@ func ifaceIPMask4(iface string) (net.IP, net.IPMask) { } for _, addr := range addrs { - var ip net.IP - var mask net.IPMask - - switch v := addr.(type) { - case *net.IPNet: - ip = v.IP - mask = v.Mask - case *net.IPAddr: - ip = v.IP - mask = ip.DefaultMask() - } - - if ip4 := ip.To4(); ip4 != nil { - return ip4, mask + if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { + if ip4 := ipnet.IP.To4(); ip4 != nil { + return ip4, ipnet.Mask + } } } diff --git a/service/dhcpd/pool.go b/service/dhcpd/pool.go index 6ff2fc0..b8ef7ac 100644 --- a/service/dhcpd/pool.go +++ b/service/dhcpd/pool.go @@ -3,38 +3,43 @@ package dhcpd import ( "bytes" "errors" + "math/rand" "net" "time" ) type Pool struct { - lease time.Duration items []*item } func NewPool(lease time.Duration, ipStart, ipEnd net.IP) (*Pool, error) { items := make([]*item, 0) - var currentIp = ipStart.To4() - for bytes.Compare(currentIp, ipEnd.To4()) <= 0 { + curip := ipStart.To4() + for bytes.Compare(curip, ipEnd.To4()) <= 0 { ip := make([]byte, 4) - copy(ip, currentIp) - i := &item{ - lease: lease, - ip: ip, - } - items = append(items, i) - currentIp[3]++ + copy(ip, curip) + items = append(items, &item{lease: lease, ip: ip}) + curip[3]++ } - return &Pool{lease: lease, items: items}, nil + rand.Seed(time.Now().Unix()) + return &Pool{items: items}, nil } func (p *Pool) AssignIP(mac net.HardwareAddr) (net.IP, error) { var ip net.IP for _, item := range p.items { - if mac.String() == item.hardwareAddr.String() { + if bytes.Equal(mac, item.mac) { return item.ip, nil } } + + idx := rand.Intn(len(p.items)) + for _, item := range p.items[idx:] { + if ip = item.take(mac); ip != nil { + return ip, nil + } + } + for _, item := range p.items { if ip = item.take(mac); ip != nil { return ip, nil @@ -44,24 +49,23 @@ func (p *Pool) AssignIP(mac net.HardwareAddr) (net.IP, error) { } type item struct { - ip net.IP - lease time.Duration - taken bool - hardwareAddr net.HardwareAddr + taken bool + ip net.IP + lease time.Duration + mac net.HardwareAddr } func (i *item) take(addr net.HardwareAddr) net.IP { - if i.taken { - return nil - } else { + if !i.taken { i.taken = true go func() { timer := time.NewTimer(i.lease) <-timer.C - i.hardwareAddr = nil + i.mac = nil i.taken = false }() - i.hardwareAddr = addr + i.mac = addr return i.ip } + return nil }