diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f9cbfa0..301c593 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,7 @@ jobs: uses: actions/setup-go@v2 with: stable: 'false' - go-version: '1.18.0-beta1' + go-version: '1.18.0-beta2' # go-version: ${{ env.GO_VERSION}} - name: Set up Cache diff --git a/Dockerfile b/Dockerfile index 5cca6ac..8f73394 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Build Stage -FROM golang:1.18beta1-alpine AS build-env +FROM golang:1.18beta2-alpine AS build-env ADD . /src diff --git a/dns/client.go b/dns/client.go index 32cbda4..880d0c2 100644 --- a/dns/client.go +++ b/dns/client.go @@ -15,7 +15,7 @@ import ( ) // AnswerHandler function handles the dns TypeA or TypeAAAA answer. -type AnswerHandler func(domain, ip string) error +type AnswerHandler func(domain string, ip netip.Addr) error // Config for dns. type Config struct { @@ -138,12 +138,11 @@ func (c *Client) extractAnswer(resp *Message) ([]string, int) { ttl := c.config.MinTTL for _, answer := range resp.Answers { if answer.TYPE == QTypeA || answer.TYPE == QTypeAAAA { - if answer.IP.IsValid() { - ip := answer.IP.String() + if answer.IP.IsValid() && !answer.IP.IsUnspecified() { for _, h := range c.handlers { - h(resp.Question.QNAME, ip) + h(resp.Question.QNAME, answer.IP) } - ips = append(ips, ip) + ips = append(ips, answer.IP.String()) } if answer.TTL != 0 { ttl = int(answer.TTL) diff --git a/go.mod b/go.mod index 90c17c6..e437290 100644 --- a/go.mod +++ b/go.mod @@ -9,15 +9,15 @@ require ( github.com/dgryski/go-rc2 v0.0.0-20150621095337-8a9021637152 github.com/insomniacslk/dhcp v0.0.0-20220119180841-3c283ff8b7dd github.com/nadoo/conflag v0.2.3 - github.com/nadoo/ipset v0.4.0 + github.com/nadoo/ipset v0.4.1-0.20220202154244-ddbfbad6db35 github.com/xtaci/kcp-go/v5 v5.6.1 - golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed + golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838 golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27 ) require ( github.com/ebfe/rc2 v0.0.0-20131011165748-24b9757f5521 // indirect - github.com/klauspost/cpuid/v2 v2.0.9 // indirect + github.com/klauspost/cpuid/v2 v2.0.10 // indirect github.com/klauspost/reedsolomon v1.9.15 // indirect github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7 // indirect github.com/mdlayher/raw v0.0.0-20211126142749-4eae47f3d54b // indirect diff --git a/go.sum b/go.sum index 854d5aa..817ca62 100644 --- a/go.sum +++ b/go.sum @@ -49,8 +49,8 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV github.com/klauspost/cpuid v1.2.4/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4= github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.0.10 h1:fv5GKR+e2UgD+gcxQECVT5rBwAmlFLl2mkKm7WK3ODY= +github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/klauspost/reedsolomon v1.9.9/go.mod h1:O7yFFHiQwDR6b2t63KPUpccPtNdp5ADgh1gg4fd12wo= github.com/klauspost/reedsolomon v1.9.15 h1:g2erWKD2M6rgnPf89fCji6jNlhMKMdXcuNHMW1SYCIo= github.com/klauspost/reedsolomon v1.9.15/go.mod h1:eqPAcE7xar5CIzcdfwydOEdcmchAKAP/qs14y4GCBOk= @@ -67,8 +67,8 @@ github.com/mdlayher/raw v0.0.0-20211126142749-4eae47f3d54b/go.mod h1:7EpbotpCmVZ github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104/go.mod h1:wqKykBG2QzQDJEzvRkcS8x6MiSJkF52hXZsXcjaB3ls= github.com/nadoo/conflag v0.2.3 h1:/+rTaN0bHTIiQbPl1WZK78JRoqjlNqJ9Zf05ep0o5jI= github.com/nadoo/conflag v0.2.3/go.mod h1:dzFfDUpXdr2uS2oV+udpy5N2vfNOu/bFzjhX1WI52co= -github.com/nadoo/ipset v0.4.0 h1:FBC4F6I0QP9+E2cYDelJfvPX4J7pGuml3ZKcAaplNQ4= -github.com/nadoo/ipset v0.4.0/go.mod h1:x/lqgubO+J0T1KnuzSrV35RzlcERchuzPFYhDg/kMaI= +github.com/nadoo/ipset v0.4.1-0.20220202154244-ddbfbad6db35 h1:ROGpIZqxtrO0mJhSS9bte1VNwVUmmavcjjtw3720t94= +github.com/nadoo/ipset v0.4.1-0.20220202154244-ddbfbad6db35/go.mod h1:rYF5DQLRGGoQ8ZSWeK+6eX5amAuPqwFkWjhQlEITGJQ= 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= @@ -104,8 +104,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.0.0-20220128200615-198e4374d7ed h1:YoWVYYAfvQ4ddHv3OKmIvX7NCAhFGTj62VP2l2kfBbA= -golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838 h1:71vQrMauZZhcTVK6KdYM+rklehEEwb3E+ZhaE5jrPrE= +golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 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= diff --git a/ipset/ipset_linux.go b/ipset/ipset_linux.go index 894fed2..07fa156 100644 --- a/ipset/ipset_linux.go +++ b/ipset/ipset_linux.go @@ -1,7 +1,7 @@ package ipset import ( - "errors" + "net/netip" "strings" "sync" @@ -22,6 +22,13 @@ func addToSet(s, item string) error { return ipset.Add(s, item) } +func addAddrToSet(s string, ip netip.Addr) error { + if ip.Is4() { + return ipset.AddAddr(s, ip) + } + return ipset.AddAddr(s+"6", ip) +} + // NewManager returns a Manager func NewManager(rules []*rule.Config) (*Manager, error) { if err := ipset.Init(); err != nil { @@ -59,16 +66,12 @@ func NewManager(rules []*rule.Config) (*Manager, error) { } // AddDomainIP implements the dns AnswerHandler function, used to update ipset according to domainSet rule. -func (m *Manager) AddDomainIP(domain, ip string) error { - if domain == "" || ip == "" { - return errors.New("please specify the domain and ip address") - } - +func (m *Manager) AddDomainIP(domain string, ip netip.Addr) error { domain = strings.ToLower(domain) for i := len(domain); i != -1; { i = strings.LastIndexByte(domain[:i], '.') if setName, ok := m.domainSet.Load(domain[i+1:]); ok { - addToSet(setName.(string), ip) + addAddrToSet(setName.(string), ip) } } return nil diff --git a/ipset/ipset_other.go b/ipset/ipset_other.go index 43290c3..22cfb22 100644 --- a/ipset/ipset_other.go +++ b/ipset/ipset_other.go @@ -5,6 +5,7 @@ package ipset import ( "errors" + "net/netip" "github.com/nadoo/glider/rule" ) @@ -18,6 +19,6 @@ func NewManager(rules []*rule.Config) (*Manager, error) { } // AddDomainIP implements the DNSAnswerHandler function -func (m *Manager) AddDomainIP(domain, ip string) error { +func (m *Manager) AddDomainIP(domain string, ip netip.Addr) error { return errors.New("ipset not supported on this os") } diff --git a/rule/proxy.go b/rule/proxy.go index 437dc92..b9a8bf6 100644 --- a/rule/proxy.go +++ b/rule/proxy.go @@ -31,7 +31,12 @@ func NewProxy(mainForwarders []string, mainStrategy *Strategy, rules []*Config) rd.domainMap.Store(strings.ToLower(domain), group) } - for _, ip := range r.IP { + for _, s := range r.IP { + ip, err := netip.ParseAddr(s) + if err != nil { + log.F("[rule] parse ip error: %s", err) + continue + } rd.ipMap.Store(ip, group) } @@ -79,23 +84,13 @@ func (p *Proxy) findDialer(dstAddr string) *FwdrGroup { return p.main } - // check ip - // TODO: ipv4 should equal to ipv4-mapped ipv6? but it'll need to parse the ip address - if proxy, ok := p.ipMap.Load(host); ok { - return proxy.(*FwdrGroup) - } - - // check host - host = strings.ToLower(host) - for i := len(host); i != -1; { - i = strings.LastIndexByte(host[:i], '.') - if proxy, ok := p.domainMap.Load(host[i+1:]); ok { + if ip, err := netip.ParseAddr(host); err == nil { + // check ip + if proxy, ok := p.ipMap.Load(ip); ok { return proxy.(*FwdrGroup) } - } - // check cidr - if ip, err := netip.ParseAddr(host); err == nil { + // check cidr var ret *FwdrGroup p.cidrMap.Range(func(key, value any) bool { if key.(netip.Prefix).Contains(ip) { @@ -110,6 +105,15 @@ func (p *Proxy) findDialer(dstAddr string) *FwdrGroup { } } + // check host + host = strings.ToLower(host) + for i := len(host); i != -1; { + i = strings.LastIndexByte(host[:i], '.') + if proxy, ok := p.domainMap.Load(host[i+1:]); ok { + return proxy.(*FwdrGroup) + } + } + return p.main } @@ -130,15 +134,13 @@ func (p *Proxy) Record(dialer proxy.Dialer, success bool) { } // AddDomainIP used to update ipMap rules according to domainMap rule. -func (p *Proxy) AddDomainIP(domain, ip string) error { - if ip != "" { - domain = strings.ToLower(domain) - for i := len(domain); i != -1; { - i = strings.LastIndexByte(domain[:i], '.') - if dialer, ok := p.domainMap.Load(domain[i+1:]); ok { - p.ipMap.Store(ip, dialer) - // log.F("[rule] update map: %s/%s based on rule: domain=%s\n", domain, ip, domain[i+1:]) - } +func (p *Proxy) AddDomainIP(domain string, ip netip.Addr) error { + domain = strings.ToLower(domain) + for i := len(domain); i != -1; { + i = strings.LastIndexByte(domain[:i], '.') + if dialer, ok := p.domainMap.Load(domain[i+1:]); ok { + p.ipMap.Store(ip, dialer) + // log.F("[rule] update map: %s/%s based on rule: domain=%s\n", domain, ip, domain[i+1:]) } } return nil