From 68fccfacc03cb0e562e40d67a99d4a99e3ec3229 Mon Sep 17 00:00:00 2001 From: MetaCubeX Date: Tue, 15 Mar 2022 02:20:19 +0800 Subject: [PATCH] [Skip CI] --- component/trie/ipcidr_trie.go | 2 +- component/trie/trie_test.go | 18 ++++++++++++++++++ constant/path.go | 1 - go.mod | 5 +++-- hub/executor/executor.go | 3 +++ listener/tproxy/tproxy_linux_iptables.go | 2 +- listener/tun/ipstack/gvisor/tundns.go | 15 ++++++++++++--- listener/tun/ipstack/gvisor/utils.go | 14 ++++++++++++-- rule/provider/parse.go | 3 +++ rule/provider/provider.go | 6 +++--- 10 files changed, 56 insertions(+), 13 deletions(-) diff --git a/component/trie/ipcidr_trie.go b/component/trie/ipcidr_trie.go index 8b931c2d..a3a63f95 100644 --- a/component/trie/ipcidr_trie.go +++ b/component/trie/ipcidr_trie.go @@ -103,7 +103,7 @@ func subIpCidr(ip net.IP, maskSize int, isIpv4 bool) ([]net.IP, int, error) { lastByteMaskSize := maskSize % 8 lastByteMaskIndex := maskSize / 8 subIpCidrNum := 0xFF >> lastByteMaskSize - for i := 0; i < subIpCidrNum; i++ { + for i := 0; i <= subIpCidrNum; i++ { subIpCidr := make([]byte, len(ip)) copy(subIpCidr, ip) subIpCidr[lastByteMaskIndex] += byte(i) diff --git a/component/trie/trie_test.go b/component/trie/trie_test.go index ec4f1fd2..dca77c05 100644 --- a/component/trie/trie_test.go +++ b/component/trie/trie_test.go @@ -26,12 +26,20 @@ func TestIpv4AddFail(t *testing.T) { func TestIpv4Search(t *testing.T) { trie := NewIpCidrTrie() + // Boundary testing + assert.NoError(t, trie.AddIpCidrForString("149.154.160.0/20")) + assert.Equal(t, true, trie.IsContainForString("149.154.160.0")) + assert.Equal(t, true, trie.IsContainForString("149.154.175.255")) + assert.Equal(t, false, trie.IsContainForString("149.154.176.0")) + assert.Equal(t, false, trie.IsContainForString("149.154.159.255")) + assert.NoError(t, trie.AddIpCidrForString("129.2.36.0/16")) assert.NoError(t, trie.AddIpCidrForString("10.2.36.0/18")) assert.NoError(t, trie.AddIpCidrForString("16.2.23.0/24")) assert.NoError(t, trie.AddIpCidrForString("11.2.13.2/26")) assert.NoError(t, trie.AddIpCidrForString("55.5.6.3/8")) assert.NoError(t, trie.AddIpCidrForString("66.23.25.4/6")) + assert.Equal(t, true, trie.IsContainForString("129.2.3.65")) assert.Equal(t, false, trie.IsContainForString("15.2.3.1")) assert.Equal(t, true, trie.IsContainForString("11.2.13.1")) @@ -41,6 +49,7 @@ func TestIpv4Search(t *testing.T) { assert.Equal(t, false, trie.IsContain(net.ParseIP("22"))) assert.Equal(t, false, trie.IsContain(net.ParseIP(""))) + } func TestIpv6AddSuccess(t *testing.T) { @@ -66,6 +75,14 @@ func TestIpv6AddFail(t *testing.T) { func TestIpv6Search(t *testing.T) { trie := NewIpCidrTrie() + + // Boundary testing + assert.NoError(t, trie.AddIpCidrForString("2a0a:f280::/32")) + assert.Equal(t, true, trie.IsContainForString("2a0a:f280:0000:0000:0000:0000:0000:0000")) + assert.Equal(t, true, trie.IsContainForString("2a0a:f280:ffff:ffff:ffff:ffff:ffff:ffff")) + assert.Equal(t, false, trie.IsContainForString("2a0a:f279:ffff:ffff:ffff:ffff:ffff:ffff")) + assert.Equal(t, false, trie.IsContainForString("2a0a:f281:0000:0000:0000:0000:0000:0000")) + assert.NoError(t, trie.AddIpCidrForString("2001:b28:f23d:f001::e/128")) assert.NoError(t, trie.AddIpCidrForString("2001:67c:4e8:f002::e/12")) assert.NoError(t, trie.AddIpCidrForString("2001:b28:f23d:f003::e/96")) @@ -79,4 +96,5 @@ func TestIpv6Search(t *testing.T) { assert.Equal(t, true, trie.IsContainForString("2001:67c:4e8:9666::1213")) assert.Equal(t, false, trie.IsContain(net.ParseIP("22233:22"))) + } diff --git a/constant/path.go b/constant/path.go index 31b1ef80..b49b2180 100644 --- a/constant/path.go +++ b/constant/path.go @@ -55,7 +55,6 @@ func (p *path) Resolve(path string) string { if !filepath.IsAbs(path) { return filepath.Join(p.HomeDir(), path) } - return path } diff --git a/go.mod b/go.mod index 4b6bbaf9..49f8492a 100644 --- a/go.mod +++ b/go.mod @@ -46,11 +46,12 @@ require ( github.com/oschwald/maxminddb-golang v1.8.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/u-root/uio v0.0.0-20210528114334-82958018845c // indirect - golang.org/x/mod v0.4.2 // indirect + golang.org/x/mod v0.5.1 // indirect golang.org/x/text v0.3.8-0.20211004125949-5bd84dd9b33b // indirect golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect - golang.org/x/tools v0.1.7 // indirect + golang.org/x/tools v0.1.9 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect + ) diff --git a/hub/executor/executor.go b/hub/executor/executor.go index 27eef5e0..7783bd41 100644 --- a/hub/executor/executor.go +++ b/hub/executor/executor.go @@ -242,6 +242,9 @@ func updateGeneral(general *config.General, Tun *config.Tun, force bool) { return } + geodataLoader := general.GeodataLoader + G.SetLoader(geodataLoader) + allowLan := general.AllowLan P.SetAllowLan(allowLan) diff --git a/listener/tproxy/tproxy_linux_iptables.go b/listener/tproxy/tproxy_linux_iptables.go index 96e26387..017238c6 100644 --- a/listener/tproxy/tproxy_linux_iptables.go +++ b/listener/tproxy/tproxy_linux_iptables.go @@ -3,11 +3,11 @@ package tproxy import ( "errors" "fmt" + "github.com/Dreamacro/clash/component/dialer" "os/exec" "runtime" "strings" - "github.com/Dreamacro/clash/component/dialer" "github.com/Dreamacro/clash/log" ) diff --git a/listener/tun/ipstack/gvisor/tundns.go b/listener/tun/ipstack/gvisor/tundns.go index 7fba6bbe..51368675 100644 --- a/listener/tun/ipstack/gvisor/tundns.go +++ b/listener/tun/ipstack/gvisor/tundns.go @@ -85,7 +85,8 @@ func (e *dnsEndpoint) HandlePacket(id stack.TransportEndpointID, pkt *stack.Pack var msg D.Msg msg.Unpack(pkt.Data().AsRange().ToOwnedView()) writer := dnsResponseWriter{s: e.stack, pkt: pkt, id: id} - log.Debugln("[DNS] hijack udp:%s:%d", id.LocalAddress.String(), id.LocalPort) + log.Debugln("[DNS] hijack udp:%s:%d from %s:%d", id.LocalAddress.String(), id.LocalPort, + id.RemoteAddress.String(), id.RemotePort) go e.server.ServeDNS(&writer, &msg) } @@ -139,9 +140,17 @@ func (w *dnsResponseWriter) Write(b []byte) (int, error) { v := buffer.NewView(len(b)) copy(v, b) data := v.ToVectorisedView() + // w.id.LocalAddress is the source ip of DNS response - r, _ := w.s.FindRoute(w.pkt.NICID, w.id.LocalAddress, w.id.RemoteAddress, w.pkt.NetworkProtocolNumber, false /* multicastLoop */) - return writeUDP(r, data, w.id.LocalPort, w.id.RemotePort) + if !w.pkt.NetworkHeader().View().IsEmpty() && + (w.pkt.NetworkProtocolNumber == ipv4.ProtocolNumber || + w.pkt.NetworkProtocolNumber == ipv6.ProtocolNumber) { + r, _ := w.s.FindRoute(w.pkt.NICID, w.id.LocalAddress, w.id.RemoteAddress, w.pkt.NetworkProtocolNumber, false /* multicastLoop */) + return writeUDP(r, data, w.id.LocalPort, w.id.RemotePort) + } else { + log.Debugln("the network protocl[%d] is not available", w.pkt.NetworkProtocolNumber) + return 0, fmt.Errorf("the network protocl[%d] is not available", w.pkt.NetworkProtocolNumber) + } } func (w *dnsResponseWriter) Close() error { diff --git a/listener/tun/ipstack/gvisor/utils.go b/listener/tun/ipstack/gvisor/utils.go index 44063f0b..7b1b2588 100644 --- a/listener/tun/ipstack/gvisor/utils.go +++ b/listener/tun/ipstack/gvisor/utils.go @@ -2,6 +2,9 @@ package gvisor import ( "fmt" + "github.com/Dreamacro/clash/log" + "gvisor.dev/gvisor/pkg/tcpip/network/ipv4" + "gvisor.dev/gvisor/pkg/tcpip/network/ipv6" "net" "github.com/Dreamacro/clash/component/resolver" @@ -40,8 +43,15 @@ func (c *fakeConn) WriteBack(b []byte, addr net.Addr) (n int, err error) { localPort = uint16(udpaddr.Port) } - r, _ := c.s.FindRoute(c.pkt.NICID, localAddress, c.id.RemoteAddress, c.pkt.NetworkProtocolNumber, false /* multicastLoop */) - return writeUDP(r, data, localPort, c.id.RemotePort) + if !c.pkt.NetworkHeader().View().IsEmpty() && + (c.pkt.NetworkProtocolNumber == ipv4.ProtocolNumber || + c.pkt.NetworkProtocolNumber == ipv6.ProtocolNumber) { + r, _ := c.s.FindRoute(c.pkt.NICID, localAddress, c.id.RemoteAddress, c.pkt.NetworkProtocolNumber, false /* multicastLoop */) + return writeUDP(r, data, localPort, c.id.RemotePort) + } else { + log.Debugln("the network protocl[%d] is not available", c.pkt.NetworkProtocolNumber) + return 0, fmt.Errorf("the network protocl[%d] is not available", c.pkt.NetworkProtocolNumber) + } } func (c *fakeConn) LocalAddr() net.Addr { diff --git a/rule/provider/parse.go b/rule/provider/parse.go index f0c094c6..20cdd557 100644 --- a/rule/provider/parse.go +++ b/rule/provider/parse.go @@ -82,6 +82,9 @@ func parseRule(tp, payload, target string, params []string) (C.Rule, error) { parsed, parseErr = RC.NewPort(payload, target, false, ruleExtra) case "PROCESS-NAME": parsed, parseErr = RC.NewProcess(payload, target, ruleExtra) + case "GEOIP": + noResolve := RC.HasNoResolve(params) + parsed, parseErr = RC.NewGEOIP(payload, target, noResolve, ruleExtra) default: parseErr = fmt.Errorf("unsupported rule type %s", tp) } diff --git a/rule/provider/provider.go b/rule/provider/provider.go index f37e6289..2befc694 100644 --- a/rule/provider/provider.go +++ b/rule/provider/provider.go @@ -81,9 +81,9 @@ func (rp *ruleSetProvider) Match(metadata *C.Metadata) bool { switch rp.behavior { case P.Domain: - return rp.DomainRules.Search(metadata.Host) != nil + return rp.DomainRules != nil && rp.DomainRules.Search(metadata.Host) != nil case P.IPCIDR: - return rp.IPCIDRRules.IsContain(metadata.DstIP) + return rp.IPCIDRRules != nil && rp.IPCIDRRules.IsContain(metadata.DstIP) case P.Classical: for _, rule := range rp.ClassicalRules { if rule.Match(metadata) { @@ -124,12 +124,12 @@ func NewRuleSetProvider(name string, behavior P.RuleType, interval time.Duration onUpdate := func(elm interface{}) error { rulesRaw := elm.([]string) - rp.count = len(rulesRaw) rules, err := constructRules(rp.behavior, rulesRaw) if err != nil { return err } + rp.count = len(rulesRaw) rp.setRules(rules) return nil }