From 02220387e9aa738a5e4e1d90771ddc07d4e23b23 Mon Sep 17 00:00:00 2001 From: nadoo <287492+nadoo@users.noreply.github.com> Date: Thu, 1 Oct 2020 19:29:53 +0800 Subject: [PATCH] dpcpd: handle errors --- README.md | 17 ++++++++++++++--- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- service/dhcpd/dhcpd.go | 43 +++++++++++++++++++++--------------------- service/dhcpd/pool.go | 8 ++++++++ 5 files changed, 59 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index e34e3df..8ac9181 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,8 @@ we can set up local listeners as proxy servers, and forward requests to internet - Serve http and socks5 on the same port - Periodical availability checking for forwarders - Send requests from specific local ip/interface +- Services: + - dhcpd: a simple dhcp server ## Protocols
@@ -91,7 +93,7 @@ glider -h click to see details ```bash -glider 0.10.2 usage: +./glider 0.11.0 usage: -checkdisabledonly check disabled fowarders only -checkinterval int @@ -134,6 +136,8 @@ glider 0.10.2 usage: rule file path -rules-dir string rule file folder + -service value + enable services -strategy string forward strategy, default: rr (default "rr") -verbose @@ -357,7 +361,14 @@ glider -config CONFIGPATH -listen :8080 -verbose
-## Service +## Builtin Service + +scheme: service=SERVICE_NAME[,SERVICE_CONFIG] +- dhcpd(from v0.11.0): + - service=dhcpd,INTERFACE,START_IP,END_IP + - e.g., service=dhcpd,en0,192.168.254.100,192.168.254.199 + +## Linux Service - systemd: [https://github.com/nadoo/glider/blob/master/systemd/](https://github.com/nadoo/glider/blob/master/systemd/) @@ -366,4 +377,4 @@ glider -config CONFIGPATH -listen :8080 -verbose - [ipset](https://github.com/nadoo/ipset): netlink ipset package for Go. - [conflag](https://github.com/nadoo/conflag): a drop-in replacement for Go's standard flag package with config file support. - [ArchLinux](https://www.archlinux.org/packages/community/x86_64/glider): a great linux distribution with glider pre-built package. -- [urlencode](https://www.w3schools.com/tags/ref_urlencode.asp): you should encode special characters in scheme url. e.g: `@`->`%40` +- [urlencode](https://www.w3schools.com/tags/ref_urlencode.asp): you should encode special characters in scheme url. e.g., `@`->`%40` diff --git a/go.mod b/go.mod index af396d5..3856c88 100644 --- a/go.mod +++ b/go.mod @@ -9,11 +9,11 @@ require ( github.com/nadoo/go-shadowsocks2 v0.1.2 github.com/nadoo/ipset v0.3.0 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect - github.com/xtaci/kcp-go/v5 v5.5.15 - 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-20200928112810-42b62fc93869 // indirect + github.com/xtaci/kcp-go/v5 v5.5.17 + golang.org/x/crypto v0.0.0-20200930160638-afb6bcd081ae + golang.org/x/net v0.0.0-20200930145003-4acb6c075d10 // indirect + golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f // indirect + golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c // indirect gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect ) diff --git a/go.sum b/go.sum index d6a94af..b010fc2 100644 --- a/go.sum +++ b/go.sum @@ -97,8 +97,8 @@ github.com/xtaci/kcp-go v5.4.11+incompatible h1:tJbtarpmOoOD74cZ41uvvF5Hyt1nvctH github.com/xtaci/kcp-go v5.4.11+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE= github.com/xtaci/kcp-go/v5 v5.5.12 h1:iALGyvti/oBbl1TbVoUpHEUHCorDEb3tEKl1CPY3KXM= github.com/xtaci/kcp-go/v5 v5.5.12/go.mod h1:H0T/EJ+lPNytnFYsKLH0JHUtiwZjG3KXlTM6c+Q4YUo= -github.com/xtaci/kcp-go/v5 v5.5.15 h1:I/T1Mf1xWYJd7jjHlCcP+FsBxuPJJ3VPP/vfTgUX8lk= -github.com/xtaci/kcp-go/v5 v5.5.15/go.mod h1:pVx3jb4LT5edTmPayc77tIU9nRsjGck8wep5ZV/RBO0= +github.com/xtaci/kcp-go/v5 v5.5.17 h1:bkdaqtER0PMlP05BBHfu6W+71kt/NwbAk93KH7F78Ck= +github.com/xtaci/kcp-go/v5 v5.5.17/go.mod h1:pVx3jb4LT5edTmPayc77tIU9nRsjGck8wep5ZV/RBO0= github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae h1:J0GxkO96kL4WF+AIT3M4mfUVinOCPgf2uUWYFUzN0sM= github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -118,8 +118,8 @@ golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de h1:ikNHVSjEfnvz6sxdSPCaPt572qowuyMDMJLLm3Db3ig= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM= -golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200930160638-afb6bcd081ae h1:duLSQW+DZ5MsXKX7kc4rXlq6/mmxz4G6ewJuBPlhRe0= +golang.org/x/crypto v0.0.0-20200930160638-afb6bcd081ae/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= @@ -141,8 +141,8 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgN golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200927032502-5d4f70055728 h1:5wtQIAulKU5AbLQOkjxl32UufnIOqgBX72pS0AV14H0= -golang.org/x/net v0.0.0-20200927032502-5d4f70055728/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200930145003-4acb6c075d10 h1:YfxMZzv3PjGonQYNUaeU2+DhAdqOxerQ30JFB6WgAXo= +golang.org/x/net v0.0.0-20200930145003-4acb6c075d10/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -165,16 +165,16 @@ golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9 h1:yi1hN8dcqI9l8klZfy4B8mJvFmmAxJEePIQQFNSd7Cs= golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200926100807-9d91bd62050c h1:38q6VNPWR010vN82/SB121GujZNIfAUb4YttE2rhGuc= -golang.org/x/sys v0.0.0-20200926100807-9d91bd62050c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 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-20200928112810-42b62fc93869 h1:6Zj8sAhgEtZaHYz4O/Grp2Gyh0FLb8a7sLJTanOG5QQ= -golang.org/x/tools v0.0.0-20200928112810-42b62fc93869/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= +golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c h1:9BSeO6440XJVa2mxIcRAndAol4g4g2KflCVGcHx9Yu8= +golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c/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/service/dhcpd/dhcpd.go b/service/dhcpd/dhcpd.go index 028c131..9429091 100644 --- a/service/dhcpd/dhcpd.go +++ b/service/dhcpd/dhcpd.go @@ -2,6 +2,7 @@ package dhcpd import ( "context" + "errors" "net" "time" @@ -28,25 +29,24 @@ func (*dpcpd) Run(args ...string) { return } - iface, ipStart, ipEnd := args[0], args[1], args[2] + iface := args[0] + ip, mask, err := intfaceIP4(iface) + if err != nil { + log.F("[dhcpd] get ip of interface '%s' error: %s", iface, err) + return + } - if detectServer(iface) { + if findExistServer(iface) { log.F("[dhcpd] found existing dhcp server on interface %s, service exiting", iface) return } - pool, err := NewPool(leaseTime, net.ParseIP(ipStart), net.ParseIP(ipEnd)) + pool, err := NewPool(leaseTime, net.ParseIP(args[1]), net.ParseIP(args[2])) if err != nil { log.F("[dhcpd] error in pool init: %s", err) return } - ip, mask := ifaceIPMask4(iface) - if ip == nil || mask == nil { - log.F("[dhcpd] can not get ip and mask of interface: %s", iface) - return - } - 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 { @@ -54,7 +54,7 @@ func (*dpcpd) Run(args ...string) { 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)", iface, ip, mask[0], mask[1], mask[2], mask[3]) server.Serve() @@ -62,7 +62,6 @@ 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) var replyType dhcpv4.MessageType switch mt := m.MessageType(); mt { @@ -84,15 +83,14 @@ func handleDHCP(serverIP net.IP, mask net.IPMask, pool *Pool) server4.Handler { reply, err := dhcpv4.NewReplyFromRequest(m, dhcpv4.WithMessageType(replyType), dhcpv4.WithServerIP(serverIP), - dhcpv4.WithRouter(serverIP), dhcpv4.WithNetmask(mask), dhcpv4.WithYourIP(replyIp), + dhcpv4.WithRouter(serverIP), + dhcpv4.WithDNS(serverIP), // RFC 2131, Section 4.3.1. Server Identifier: MUST dhcpv4.WithOption(dhcpv4.OptServerIdentifier(serverIP)), // RFC 2131, Section 4.3.1. IP lease time: MUST dhcpv4.WithOption(dhcpv4.OptIPAddressLeaseTime(leaseTime)), - dhcpv4.WithRouter(serverIP), - dhcpv4.WithDNS(serverIP), ) if val := m.Options.Get(dhcpv4.OptionClientIdentifier); len(val) > 0 { @@ -108,7 +106,7 @@ func handleDHCP(serverIP net.IP, mask net.IPMask, pool *Pool) server4.Handler { } } -func detectServer(iface string) (exists bool) { +func findExistServer(iface string) (exists bool) { client, err := nclient4.New(iface) if err != nil { log.F("[dhcpd] failed in dhcp client creation: %s", err) @@ -125,24 +123,27 @@ func detectServer(iface string) (exists bool) { return true } -func ifaceIPMask4(iface string) (net.IP, net.IPMask) { +func intfaceIP4(iface string) (net.IP, net.IPMask, error) { intf, err := net.InterfaceByName(iface) if err != nil { - return nil, nil + return nil, nil, err } addrs, err := intf.Addrs() if err != nil { - return nil, nil + return nil, nil, err } for _, addr := range addrs { - if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { + if ipnet, ok := addr.(*net.IPNet); ok { + if ipnet.IP.IsLoopback() { + return nil, nil, errors.New("can't use loopback interface") + } if ip4 := ipnet.IP.To4(); ip4 != nil { - return ip4, ipnet.Mask + return ip4, ipnet.Mask, nil } } } - return nil, nil + return nil, nil, errors.New("no ip/mask defined on this interface") } diff --git a/service/dhcpd/pool.go b/service/dhcpd/pool.go index 4b9165d..75c0e0e 100644 --- a/service/dhcpd/pool.go +++ b/service/dhcpd/pool.go @@ -14,7 +14,15 @@ type Pool struct { // NewPool returns a new dhcp ip pool. func NewPool(lease time.Duration, start, end net.IP) (*Pool, error) { + if start == nil || end == nil { + return nil, errors.New("start ip or end ip is wrong/nil, please check your config") + } + s, e := ip2num(start.To4()), ip2num(end.To4()) + if e < s { + return nil, errors.New("start ip larger than end ip") + } + items := make([]*item, 0, e-s+1) for n := s; n <= e; n++ { items = append(items, &item{lease: lease, ip: num2ip(n)})