diff --git a/go.mod b/go.mod index 006d047..09f1398 100644 --- a/go.mod +++ b/go.mod @@ -7,30 +7,29 @@ require ( github.com/dgryski/go-camellia v0.0.0-20191119043421-69a8a13fb23d github.com/dgryski/go-idea v0.0.0-20170306091226-d2fb45a411fb github.com/dgryski/go-rc2 v0.0.0-20150621095337-8a9021637152 - github.com/insomniacslk/dhcp v0.0.0-20231126010706-b0416c0f187a + github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2 github.com/nadoo/conflag v0.3.1 github.com/nadoo/ipset v0.5.0 - github.com/xtaci/kcp-go/v5 v5.6.1 - golang.org/x/crypto v0.16.0 - golang.org/x/sys v0.15.0 + github.com/xtaci/kcp-go/v5 v5.6.7 + golang.org/x/crypto v0.18.0 + golang.org/x/sys v0.16.0 ) require ( github.com/ebfe/rc2 v0.0.0-20131011165748-24b9757f5521 // indirect github.com/josharian/native v1.1.0 // indirect github.com/klauspost/cpuid/v2 v2.2.6 // indirect - github.com/klauspost/reedsolomon v1.11.8 // indirect - github.com/pierrec/lz4/v4 v4.1.18 // indirect + github.com/klauspost/reedsolomon v1.12.0 // indirect + github.com/pierrec/lz4/v4 v4.1.21 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/templexxx/cpu v0.1.0 // indirect github.com/templexxx/xorsimd v0.4.2 // indirect github.com/tjfoc/gmsm v1.4.1 // indirect - github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 // indirect - golang.org/x/net v0.19.0 // indirect + github.com/u-root/uio v0.0.0-20240118234441-a3c409a6018e // indirect + golang.org/x/net v0.20.0 // indirect ) // Replace dependency modules with local developing copy // use `go list -m all` to confirm the final module used -// replace ( -// github.com/nadoo/conflag => ../conflag -// ) +// replace github.com/nadoo/conflag => ../conflag +replace github.com/xtaci/kcp-go/v5 => github.com/xtaci/kcp-go/v5 v5.6.1 // Go1.20 diff --git a/go.sum b/go.sum index 91ac830..29217b9 100644 --- a/go.sum +++ b/go.sum @@ -33,18 +33,19 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/insomniacslk/dhcp v0.0.0-20231126010706-b0416c0f187a h1:biHpNhTkyeXNEzLqTOM6DkIkMedNh/j+ft+POj0Xcko= -github.com/insomniacslk/dhcp v0.0.0-20231126010706-b0416c0f187a/go.mod h1:3A9PQ1cunSDF/1rbTq99Ts4pVnycWg+vlPkfeD2NLFI= +github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2 h1:9K06NfxkBh25x56yVhWWlKFE8YpicaSfHwoV8SFbueA= +github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2/go.mod h1:3A9PQ1cunSDF/1rbTq99Ts4pVnycWg+vlPkfeD2NLFI= github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA= github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/klauspost/cpuid v1.2.4/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s= github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4= github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/reedsolomon v1.9.9/go.mod h1:O7yFFHiQwDR6b2t63KPUpccPtNdp5ADgh1gg4fd12wo= -github.com/klauspost/reedsolomon v1.11.8 h1:s8RpUW5TK4hjr+djiOpbZJB4ksx+TdYbRH7vHQpwPOY= -github.com/klauspost/reedsolomon v1.11.8/go.mod h1:4bXRN+cVzMdml6ti7qLouuYi32KHJ5MGv0Qd8a47h6A= +github.com/klauspost/reedsolomon v1.12.0 h1:I5FEp3xSwVCcEh3F5A7dofEfhXdF/bWhQWPH+XwBFno= +github.com/klauspost/reedsolomon v1.12.0/go.mod h1:EPLZJeh4l27pUGC3aXOjheaoh1I9yut7xTURiW3LQ9Y= github.com/mdlayher/packet v1.1.2 h1:3Up1NG6LZrsgDVn6X4L9Ge/iyRyxFEFD9o6Pr3Q1nQY= github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104/go.mod h1:wqKykBG2QzQDJEzvRkcS8x6MiSJkF52hXZsXcjaB3ls= @@ -53,8 +54,8 @@ github.com/nadoo/conflag v0.3.1/go.mod h1:dzFfDUpXdr2uS2oV+udpy5N2vfNOu/bFzjhX1W github.com/nadoo/ipset v0.5.0 h1:5GJUAuZ7ITQQQGne5J96AmFjRtI8Avlbk6CabzYWVUc= github.com/nadoo/ipset v0.5.0/go.mod h1:rYF5DQLRGGoQ8ZSWeK+6eX5amAuPqwFkWjhQlEITGJQ= github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ= -github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= +github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -73,8 +74,8 @@ github.com/templexxx/xorsimd v0.4.2/go.mod h1:HgwaPoDREdi6OnULpSfxhzaiiSUY4Fi3JP github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w= github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho= github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE= -github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 h1:YcojQL98T/OO+rybuzn2+5KrD5dBwXIvYBvQ2cD3Avg= -github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264= +github.com/u-root/uio v0.0.0-20240118234441-a3c409a6018e h1:BA9O3BmlTmpjbvajAwzWx4Wo2TRVdpPXZEeemGQcajw= +github.com/u-root/uio v0.0.0-20240118234441-a3c409a6018e/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264= github.com/xtaci/kcp-go/v5 v5.6.1 h1:Pwn0aoeNSPF9dTS7IgiPXn0HEtaIlVb6y5UKWPsx8bI= github.com/xtaci/kcp-go/v5 v5.6.1/go.mod h1:W3kVPyNYwZ06p79dNwFWQOVFrdcBpDBsdyvK8moQrYo= github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae h1:J0GxkO96kL4WF+AIT3M4mfUVinOCPgf2uUWYFUzN0sM= @@ -88,8 +89,8 @@ golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/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/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= -golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -106,8 +107,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -123,9 +124,9 @@ golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/main.go b/main.go index 7403a0a..c4cc65b 100644 --- a/main.go +++ b/main.go @@ -17,7 +17,7 @@ import ( ) var ( - version = "0.16.3" + version = "0.16.4" config = parseConfig() ) diff --git a/proxy/vmess/client.go b/proxy/vmess/client.go index 273fbdb..cde95a8 100644 --- a/proxy/vmess/client.go +++ b/proxy/vmess/client.go @@ -116,9 +116,6 @@ func NewClient(uuidStr, security string, alterID int, aead bool) (*Client, error return nil, errors.New("unknown security type: " + security) } - // NOTE: give rand a new seed to avoid the same sequence of values - rand.Seed(time.Now().UnixNano()) - return c, nil } diff --git a/service/dhcpd/dhcpd.go b/service/dhcpd/dhcpd.go index da08efa..d6dceb7 100644 --- a/service/dhcpd/dhcpd.go +++ b/service/dhcpd/dhcpd.go @@ -126,58 +126,68 @@ func (d *dhcpd) handleDHCP(serverIP net.IP, mask net.IPMask, pool *Pool) server4 return } + var reqIP netip.Addr var reqType, replyType dhcpv4.MessageType - switch reqType = m.MessageType(); reqType { + + reqType = m.MessageType() + log.F("[dpcpd] %s: %s from %v(%v)", d.name, reqType, m.ClientHWAddr, m.ClientIPAddr) + + switch reqType { case dhcpv4.MessageTypeDiscover: replyType = dhcpv4.MessageTypeOffer - case dhcpv4.MessageTypeRequest, dhcpv4.MessageTypeInform: + case dhcpv4.MessageTypeInform: replyType = dhcpv4.MessageTypeAck - case dhcpv4.MessageTypeRelease: + case dhcpv4.MessageTypeRequest: + replyType = dhcpv4.MessageTypeAck + if m.Options.Has(dhcpv4.OptionRequestedIPAddress) { + reqIP, _ = netip.AddrFromSlice(m.Options.Get(dhcpv4.OptionRequestedIPAddress)) + } else { + // client uses Unicast to renew ip address lease, just take client ip + reqIP = netip.AddrFrom4([4]byte(m.ClientIPAddr.To4())) + } + case dhcpv4.MessageTypeRelease, dhcpv4.MessageTypeDecline: pool.ReleaseIP(m.ClientHWAddr) - log.F("[dpcpd] %s: %v requests to release ip %v", d.name, m.ClientHWAddr, m.ClientIPAddr) - return - case dhcpv4.MessageTypeDecline: - pool.ReleaseIP(m.ClientHWAddr) - log.F("[dpcpd] %s: received decline message from %v", d.name, m.ClientHWAddr) return default: - log.F("[dpcpd] %s: can't handle type %v", d.name, reqType) + log.F("[dpcpd] %s: can't handle type %v from %v", d.name, reqType, m.ClientHWAddr) return } - replyIP, err := pool.LeaseIP(m.ClientHWAddr) + replyIP, err := pool.LeaseIP(m.ClientHWAddr, reqIP) if err != nil { - log.F("[dpcpd] %s: can not assign IP for %v, error %s", d.name, m.ClientHWAddr, err) + log.F("[dpcpd] %s: can not assign IP for %v, error: %s", d.name, m.ClientHWAddr, err) return } + if reqType == dhcpv4.MessageTypeRequest && !reqIP.IsUnspecified() && reqIP != replyIP { + replyType = dhcpv4.MessageTypeNak + } + reply, err := dhcpv4.NewReplyFromRequest(m, dhcpv4.WithMessageType(replyType), - dhcpv4.WithServerIP(serverIP), dhcpv4.WithNetmask(mask), dhcpv4.WithYourIP(replyIP.AsSlice()), 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(d.lease)), + // RFC 2131, Section 4.3.1. Server Identifier: MUST + dhcpv4.WithOption(dhcpv4.OptServerIdentifier(serverIP)), ) if err != nil { - log.F("[dpcpd] %s: can not create reply message, error %s", d.name, err) + log.F("[dpcpd] %s: can not create reply message, error: %s", d.name, err) return } - if val := m.Options.Get(dhcpv4.OptionClientIdentifier); len(val) > 0 { - reply.UpdateOption(dhcpv4.OptGeneric(dhcpv4.OptionClientIdentifier, val)) - } - if _, err := conn.WriteTo(reply.ToBytes(), peer); err != nil { - log.F("[dpcpd] %s: could not write to client %s(%s): %s", d.name, peer, reply.ClientHWAddr, err) + log.F("[dpcpd] %s: could not write to %v(%v): %s", + d.name, reply.ClientHWAddr, peer, err) return } - log.F("[dpcpd] %s: lease %v to client %v", d.name, replyIP, reply.ClientHWAddr) + log.F("[dpcpd] %s: %s to %v for %v", + d.name, replyType, reply.ClientHWAddr, replyIP) + } } diff --git a/service/dhcpd/pool.go b/service/dhcpd/pool.go index 84e62c5..4cf94a1 100644 --- a/service/dhcpd/pool.go +++ b/service/dhcpd/pool.go @@ -38,7 +38,6 @@ func NewPool(lease time.Duration, start, end netip.Addr) (*Pool, error) { for n := s; n <= e; n++ { items = append(items, &item{ip: numToIPv4(n)}) } - rand.Seed(time.Now().Unix()) p := &Pool{items: items, lease: lease} go func() { @@ -58,16 +57,30 @@ func NewPool(lease time.Duration, start, end netip.Addr) (*Pool, error) { } // LeaseIP leases an ip to mac from dhcp pool. -func (p *Pool) LeaseIP(mac net.HardwareAddr) (netip.Addr, error) { +func (p *Pool) LeaseIP(mac net.HardwareAddr, ip netip.Addr) (netip.Addr, error) { p.mutex.Lock() defer p.mutex.Unlock() + // static ip and leased ip for _, item := range p.items { if bytes.Equal(mac, item.mac) { + if !item.expire.IsZero() { + item.expire = time.Now().Add(p.lease) + } return item.ip, nil } } + // requested ip + for _, item := range p.items { + if item.ip == ip && item.mac == nil { + item.mac = mac + item.expire = time.Now().Add(p.lease) + return item.ip, nil + } + } + + // lease new ip idx := rand.Intn(len(p.items)) for _, item := range p.items[idx:] { if item.mac == nil {