diff --git a/bypass.go b/bypass.go deleted file mode 100644 index 28ca8c8..0000000 --- a/bypass.go +++ /dev/null @@ -1,298 +0,0 @@ -package gost - -import ( - "bufio" - "bytes" - "fmt" - "io" - "net" - "strconv" - "strings" - "sync" - "time" - - glob "github.com/gobwas/glob" -) - -// Matcher is a generic pattern matcher, -// it gives the match result of the given pattern for specific v. -type Matcher interface { - Match(v string) bool - String() string -} - -// NewMatcher creates a Matcher for the given pattern. -// The acutal Matcher depends on the pattern: -// IP Matcher if pattern is a valid IP address. -// CIDR Matcher if pattern is a valid CIDR address. -// Domain Matcher if both of the above are not. -func NewMatcher(pattern string) Matcher { - if pattern == "" { - return nil - } - if ip := net.ParseIP(pattern); ip != nil { - return IPMatcher(ip) - } - if _, inet, err := net.ParseCIDR(pattern); err == nil { - return CIDRMatcher(inet) - } - return DomainMatcher(pattern) -} - -type ipMatcher struct { - ip net.IP -} - -// IPMatcher creates a Matcher for a specific IP address. -func IPMatcher(ip net.IP) Matcher { - return &ipMatcher{ - ip: ip, - } -} - -func (m *ipMatcher) Match(ip string) bool { - if m == nil { - return false - } - return m.ip.Equal(net.ParseIP(ip)) -} - -func (m *ipMatcher) String() string { - return "ip " + m.ip.String() -} - -type cidrMatcher struct { - ipNet *net.IPNet -} - -// CIDRMatcher creates a Matcher for a specific CIDR notation IP address. -func CIDRMatcher(inet *net.IPNet) Matcher { - return &cidrMatcher{ - ipNet: inet, - } -} - -func (m *cidrMatcher) Match(ip string) bool { - if m == nil || m.ipNet == nil { - return false - } - return m.ipNet.Contains(net.ParseIP(ip)) -} - -func (m *cidrMatcher) String() string { - return "cidr " + m.ipNet.String() -} - -type domainMatcher struct { - pattern string - glob glob.Glob -} - -// DomainMatcher creates a Matcher for a specific domain pattern, -// the pattern can be a plain domain such as 'example.com', -// a wildcard such as '*.exmaple.com' or a special wildcard '.example.com'. -func DomainMatcher(pattern string) Matcher { - p := pattern - if strings.HasPrefix(pattern, ".") { - p = pattern[1:] // trim the prefix '.' - pattern = "*" + p - } - return &domainMatcher{ - pattern: p, - glob: glob.MustCompile(pattern), - } -} - -func (m *domainMatcher) Match(domain string) bool { - if m == nil || m.glob == nil { - return false - } - - if domain == m.pattern { - return true - } - return m.glob.Match(domain) -} - -func (m *domainMatcher) String() string { - return "domain " + m.pattern -} - -// Bypass is a filter for address (IP or domain). -// It contains a list of matchers. -type Bypass struct { - matchers []Matcher - period time.Duration // the period for live reloading - reversed bool - stopped chan struct{} - mux sync.RWMutex -} - -// NewBypass creates and initializes a new Bypass using matchers as its match rules. -// The rules will be reversed if the reversed is true. -func NewBypass(reversed bool, matchers ...Matcher) *Bypass { - return &Bypass{ - matchers: matchers, - reversed: reversed, - stopped: make(chan struct{}), - } -} - -// NewBypassPatterns creates and initializes a new Bypass using matcher patterns as its match rules. -// The rules will be reversed if the reverse is true. -func NewBypassPatterns(reversed bool, patterns ...string) *Bypass { - var matchers []Matcher - for _, pattern := range patterns { - if m := NewMatcher(pattern); m != nil { - matchers = append(matchers, m) - } - } - bp := NewBypass(reversed) - bp.AddMatchers(matchers...) - return bp -} - -// Contains reports whether the bypass includes addr. -func (bp *Bypass) Contains(addr string) bool { - if bp == nil || addr == "" { - return false - } - - // try to strip the port - if host, port, _ := net.SplitHostPort(addr); host != "" && port != "" { - if p, _ := strconv.Atoi(port); p > 0 { // port is valid - addr = host - } - } - - bp.mux.RLock() - defer bp.mux.RUnlock() - - if len(bp.matchers) == 0 { - return false - } - - var matched bool - for _, matcher := range bp.matchers { - if matcher == nil { - continue - } - if matcher.Match(addr) { - matched = true - break - } - } - return !bp.reversed && matched || - bp.reversed && !matched -} - -// AddMatchers appends matchers to the bypass matcher list. -func (bp *Bypass) AddMatchers(matchers ...Matcher) { - bp.mux.Lock() - defer bp.mux.Unlock() - - bp.matchers = append(bp.matchers, matchers...) -} - -// Matchers return the bypass matcher list. -func (bp *Bypass) Matchers() []Matcher { - bp.mux.RLock() - defer bp.mux.RUnlock() - - return bp.matchers -} - -// Reversed reports whether the rules of the bypass are reversed. -func (bp *Bypass) Reversed() bool { - bp.mux.RLock() - defer bp.mux.RUnlock() - - return bp.reversed -} - -// Reload parses config from r, then live reloads the bypass. -func (bp *Bypass) Reload(r io.Reader) error { - var matchers []Matcher - var period time.Duration - var reversed bool - - if r == nil || bp.Stopped() { - return nil - } - - scanner := bufio.NewScanner(r) - for scanner.Scan() { - line := scanner.Text() - ss := splitLine(line) - if len(ss) == 0 { - continue - } - switch ss[0] { - case "reload": // reload option - if len(ss) > 1 { - period, _ = time.ParseDuration(ss[1]) - } - case "reverse": // reverse option - if len(ss) > 1 { - reversed, _ = strconv.ParseBool(ss[1]) - } - default: - matchers = append(matchers, NewMatcher(ss[0])) - } - } - - if err := scanner.Err(); err != nil { - return err - } - - bp.mux.Lock() - defer bp.mux.Unlock() - - bp.matchers = matchers - bp.period = period - bp.reversed = reversed - - return nil -} - -// Period returns the reload period. -func (bp *Bypass) Period() time.Duration { - if bp.Stopped() { - return -1 - } - - bp.mux.RLock() - defer bp.mux.RUnlock() - - return bp.period -} - -// Stop stops reloading. -func (bp *Bypass) Stop() { - select { - case <-bp.stopped: - default: - close(bp.stopped) - } -} - -// Stopped checks whether the reloader is stopped. -func (bp *Bypass) Stopped() bool { - select { - case <-bp.stopped: - return true - default: - return false - } -} - -func (bp *Bypass) String() string { - b := &bytes.Buffer{} - fmt.Fprintf(b, "reversed: %v\n", bp.Reversed()) - fmt.Fprintf(b, "reload: %v\n", bp.Period()) - for _, m := range bp.Matchers() { - b.WriteString(m.String()) - b.WriteByte('\n') - } - return b.String() -} diff --git a/bypass_test.go b/bypass_test.go deleted file mode 100644 index d895121..0000000 --- a/bypass_test.go +++ /dev/null @@ -1,303 +0,0 @@ -package gost - -import ( - "bytes" - "fmt" - "io" - "testing" - "time" -) - -var bypassContainTests = []struct { - patterns []string - reversed bool - addr string - bypassed bool -}{ - // empty pattern - {[]string{""}, false, "", false}, - {[]string{""}, false, "192.168.1.1", false}, - {[]string{""}, true, "", false}, - {[]string{""}, true, "192.168.1.1", false}, - - // IP address - {[]string{"192.168.1.1"}, false, "192.168.1.1", true}, - {[]string{"192.168.1.1"}, true, "192.168.1.1", false}, - {[]string{"192.168.1.1"}, false, "192.168.1.2", false}, - {[]string{"192.168.1.1"}, true, "192.168.1.2", true}, - {[]string{"0.0.0.0"}, false, "0.0.0.0", true}, - {[]string{"0.0.0.0"}, true, "0.0.0.0", false}, - - // CIDR address - {[]string{"192.168.1.0/0"}, false, "1.2.3.4", true}, - {[]string{"192.168.1.0/0"}, true, "1.2.3.4", false}, - {[]string{"192.168.1.0/8"}, false, "192.1.0.255", true}, - {[]string{"192.168.1.0/8"}, true, "192.1.0.255", false}, - {[]string{"192.168.1.0/8"}, false, "191.1.0.255", false}, - {[]string{"192.168.1.0/8"}, true, "191.1.0.255", true}, - {[]string{"192.168.1.0/16"}, false, "192.168.0.255", true}, - {[]string{"192.168.1.0/16"}, true, "192.168.0.255", false}, - {[]string{"192.168.1.0/16"}, false, "192.0.1.255", false}, - {[]string{"192.168.1.0/16"}, true, "192.0.0.255", true}, - {[]string{"192.168.1.0/24"}, false, "192.168.1.255", true}, - {[]string{"192.168.1.0/24"}, true, "192.168.1.255", false}, - {[]string{"192.168.1.0/24"}, false, "192.168.0.255", false}, - {[]string{"192.168.1.0/24"}, true, "192.168.0.255", true}, - {[]string{"192.168.1.1/32"}, false, "192.168.1.1", true}, - {[]string{"192.168.1.1/32"}, true, "192.168.1.1", false}, - {[]string{"192.168.1.1/32"}, false, "192.168.1.2", false}, - {[]string{"192.168.1.1/32"}, true, "192.168.1.2", true}, - - // plain domain - {[]string{"www.example.com"}, false, "www.example.com", true}, - {[]string{"www.example.com"}, true, "www.example.com", false}, - {[]string{"http://www.example.com"}, false, "http://www.example.com", true}, - {[]string{"http://www.example.com"}, true, "http://www.example.com", false}, - {[]string{"http://www.example.com"}, false, "http://example.com", false}, - {[]string{"http://www.example.com"}, true, "http://example.com", true}, - {[]string{"www.example.com"}, false, "example.com", false}, - {[]string{"www.example.com"}, true, "example.com", true}, - - // host:port - {[]string{"192.168.1.1"}, false, "192.168.1.1:80", true}, - {[]string{"192.168.1.1"}, true, "192.168.1.1:80", false}, - {[]string{"192.168.1.1:80"}, false, "192.168.1.1", false}, - {[]string{"192.168.1.1:80"}, true, "192.168.1.1", true}, - {[]string{"192.168.1.1:80"}, false, "192.168.1.1:80", false}, - {[]string{"192.168.1.1:80"}, true, "192.168.1.1:80", true}, - {[]string{"192.168.1.1:80"}, false, "192.168.1.1:8080", false}, - {[]string{"192.168.1.1:80"}, true, "192.168.1.1:8080", true}, - - {[]string{"example.com"}, false, "example.com:80", true}, - {[]string{"example.com"}, true, "example.com:80", false}, - {[]string{"example.com:80"}, false, "example.com", false}, - {[]string{"example.com:80"}, true, "example.com", true}, - {[]string{"example.com:80"}, false, "example.com:80", false}, - {[]string{"example.com:80"}, true, "example.com:80", true}, - {[]string{"example.com:80"}, false, "example.com:8080", false}, - {[]string{"example.com:80"}, true, "example.com:8080", true}, - - // domain wildcard - - {[]string{"*"}, false, "", false}, - {[]string{"*"}, false, "192.168.1.1", true}, - {[]string{"*"}, false, "192.168.0.0/16", true}, - {[]string{"*"}, false, "http://example.com", true}, - {[]string{"*"}, false, "example.com:80", true}, - {[]string{"*"}, true, "", false}, - {[]string{"*"}, true, "192.168.1.1", false}, - {[]string{"*"}, true, "192.168.0.0/16", false}, - {[]string{"*"}, true, "http://example.com", false}, - {[]string{"*"}, true, "example.com:80", false}, - - // sub-domain - {[]string{"*.example.com"}, false, "example.com", false}, - {[]string{"*.example.com"}, false, "http://example.com", false}, - {[]string{"*.example.com"}, false, "www.example.com", true}, - {[]string{"*.example.com"}, false, "http://www.example.com", true}, - {[]string{"*.example.com"}, false, "abc.def.example.com", true}, - - {[]string{"*.*.example.com"}, false, "example.com", false}, - {[]string{"*.*.example.com"}, false, "www.example.com", false}, - {[]string{"*.*.example.com"}, false, "abc.def.example.com", true}, - {[]string{"*.*.example.com"}, false, "abc.def.ghi.example.com", true}, - - {[]string{"**.example.com"}, false, "example.com", false}, - {[]string{"**.example.com"}, false, "www.example.com", true}, - {[]string{"**.example.com"}, false, "abc.def.ghi.example.com", true}, - - // prefix wildcard - {[]string{"*example.com"}, false, "example.com", true}, - {[]string{"*example.com"}, false, "www.example.com", true}, - {[]string{"*example.com"}, false, "abc.defexample.com", true}, - {[]string{"*example.com"}, false, "abc.def-example.com", true}, - {[]string{"*example.com"}, false, "abc.def.example.com", true}, - {[]string{"*example.com"}, false, "http://www.example.com", true}, - {[]string{"*example.com"}, false, "e-xample.com", false}, - - {[]string{"http://*.example.com"}, false, "example.com", false}, - {[]string{"http://*.example.com"}, false, "http://example.com", false}, - {[]string{"http://*.example.com"}, false, "http://www.example.com", true}, - {[]string{"http://*.example.com"}, false, "https://www.example.com", false}, - {[]string{"http://*.example.com"}, false, "http://abc.def.example.com", true}, - - {[]string{"www.*.com"}, false, "www.example.com", true}, - {[]string{"www.*.com"}, false, "www.abc.def.com", true}, - - {[]string{"www.*.*.com"}, false, "www.example.com", false}, - {[]string{"www.*.*.com"}, false, "www.abc.def.com", true}, - {[]string{"www.*.*.com"}, false, "www.abc.def.ghi.com", true}, - - {[]string{"www.*example*.com"}, false, "www.example.com", true}, - {[]string{"www.*example*.com"}, false, "www.abc.example.def.com", true}, - {[]string{"www.*example*.com"}, false, "www.e-xample.com", false}, - - {[]string{"www.example.*"}, false, "www.example.com", true}, - {[]string{"www.example.*"}, false, "www.example.io", true}, - {[]string{"www.example.*"}, false, "www.example.com.cn", true}, - - {[]string{".example.com"}, false, "www.example.com", true}, - {[]string{".example.com"}, false, "example.com", true}, - {[]string{".example.com"}, false, "www.example.com.cn", false}, - - {[]string{"example.com*"}, false, "example.com", true}, - {[]string{"example.com:*"}, false, "example.com", false}, - {[]string{"example.com:*"}, false, "example.com:80", false}, - {[]string{"example.com:*"}, false, "example.com:8080", false}, - {[]string{"example.com:*"}, false, "example.com:http", true}, - {[]string{"example.com:*"}, false, "http://example.com:80", false}, - - {[]string{"*example.com*"}, false, "example.com:80", true}, - {[]string{"*example.com:*"}, false, "example.com:80", false}, - - {[]string{".example.com:*"}, false, "www.example.com", false}, - {[]string{".example.com:*"}, false, "http://www.example.com", false}, - {[]string{".example.com:*"}, false, "example.com:80", false}, - {[]string{".example.com:*"}, false, "www.example.com:8080", false}, - {[]string{".example.com:*"}, false, "http://www.example.com:80", true}, -} - -func TestBypassContains(t *testing.T) { - for i, tc := range bypassContainTests { - tc := tc - t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) { - bp := NewBypassPatterns(tc.reversed, tc.patterns...) - if bp.Contains(tc.addr) != tc.bypassed { - t.Errorf("#%d test failed: %v, %s", i, tc.patterns, tc.addr) - } - }) - } -} - -var bypassReloadTests = []struct { - r io.Reader - - reversed bool - period time.Duration - - addr string - bypassed bool - stopped bool -}{ - { - r: nil, - reversed: false, - period: 0, - addr: "192.168.1.1", - bypassed: false, - stopped: false, - }, - { - r: bytes.NewBufferString(""), - reversed: false, - period: 0, - addr: "192.168.1.1", - bypassed: false, - stopped: false, - }, - { - r: bytes.NewBufferString("reverse true\nreload 10s"), - reversed: true, - period: 10 * time.Second, - addr: "192.168.1.1", - bypassed: false, - stopped: false, - }, - { - r: bytes.NewBufferString("reverse false\nreload 10s\n192.168.1.1"), - reversed: false, - period: 10 * time.Second, - addr: "192.168.1.1", - bypassed: true, - stopped: false, - }, - { - r: bytes.NewBufferString("#reverse true\n#reload 10s\n192.168.0.0/16"), - reversed: false, - period: 0, - addr: "192.168.10.2", - bypassed: true, - stopped: true, - }, - { - r: bytes.NewBufferString("#reverse true\n#reload 10s\n192.168.1.0/24 #comment"), - reversed: false, - period: 0, - addr: "192.168.10.2", - bypassed: false, - stopped: true, - }, - { - r: bytes.NewBufferString("reverse false\nreload 10s\n192.168.1.1\n#example.com"), - reversed: false, - period: 10 * time.Second, - addr: "example.com", - bypassed: false, - stopped: false, - }, - { - r: bytes.NewBufferString("#reverse true\n#reload 10s\n192.168.1.1\n#example.com"), - reversed: false, - period: 0, - addr: "192.168.1.1", - bypassed: true, - stopped: true, - }, - { - r: bytes.NewBufferString("#reverse true\n#reload 10s\nexample.com #comment"), - reversed: false, - period: 0, - addr: "example.com", - bypassed: true, - stopped: true, - }, - { - r: bytes.NewBufferString("#reverse true\n#reload 10s\n.example.com"), - reversed: false, - period: 0, - addr: "example.com", - bypassed: true, - stopped: true, - }, - { - r: bytes.NewBufferString("#reverse true\n#reload 10s\n*.example.com"), - reversed: false, - period: 0, - addr: "example.com", - bypassed: false, - stopped: true, - }, -} - -func TestByapssReload(t *testing.T) { - for i, tc := range bypassReloadTests { - bp := NewBypass(false) - if err := bp.Reload(tc.r); err != nil { - t.Error(err) - } - t.Log(bp.String()) - - if bp.Reversed() != tc.reversed { - t.Errorf("#%d test failed: reversed value should be %v, got %v", - i, tc.reversed, bp.reversed) - } - if bp.Period() != tc.period { - t.Errorf("#%d test failed: period value should be %v, got %v", - i, tc.period, bp.Period()) - } - if bp.Contains(tc.addr) != tc.bypassed { - t.Errorf("#%d test failed: %v, %s", i, bp.reversed, tc.addr) - } - if tc.stopped { - bp.Stop() - if bp.Period() >= 0 { - t.Errorf("period of the stopped reloader should be minus value") - } - bp.Stop() - } - if bp.Stopped() != tc.stopped { - t.Errorf("#%d test failed: stopped value should be %v, got %v", - i, tc.stopped, bp.Stopped()) - } - } -} diff --git a/chain.go b/chain.go index 7df6f5c..11656fa 100644 --- a/chain.go +++ b/chain.go @@ -302,7 +302,7 @@ func (c *Chain) selectRouteFor(addr string) (route *Chain, err error) { return } - if node.Bypass.Contains(addr) { + if node.Bypasser.Bypass(addr) { break } diff --git a/cmd/gost/bypass.txt b/cmd/gost/bypass.txt new file mode 100644 index 0000000..e31e258 --- /dev/null +++ b/cmd/gost/bypass.txt @@ -0,0 +1,5 @@ +reload 3s + +reverse true + +.baidu.com diff --git a/cmd/gost/cfg.go b/cmd/gost/cfg.go index 5954d9d..74116b4 100644 --- a/cmd/gost/cfg.go +++ b/cmd/gost/cfg.go @@ -13,6 +13,7 @@ import ( "strings" "github.com/ginuerzh/gost" + "github.com/go-gost/bypass" "github.com/go-gost/reload" ) @@ -175,11 +176,11 @@ func parseIP(s string, port string) (ips []string) { return } -func parseBypass(s string) *gost.Bypass { +func parseBypasser(s string) bypass.Bypasser { if s == "" { return nil } - var matchers []gost.Matcher + var matchers []bypass.Matcher var reversed bool if strings.HasPrefix(s, "~") { reversed = true @@ -193,15 +194,17 @@ func parseBypass(s string) *gost.Bypass { if s == "" { continue } - matchers = append(matchers, gost.NewMatcher(s)) + matchers = append(matchers, bypass.NewMatcher(s)) } - return gost.NewBypass(reversed, matchers...) + return bypass.NewBypasser(reversed, matchers...) } defer f.Close() - bp := gost.NewBypass(reversed) - bp.Reload(f) - go reload.PeriodReload(bp, s) + bp := bypass.NewBypasser(reversed) + if reloader, ok := bp.(reload.Reloader); ok { + reloader.Reload(f) + go reload.PeriodReload(reloader, s) + } return bp } diff --git a/cmd/gost/peer.go b/cmd/gost/peer.go index 9e1d00f..85c986a 100644 --- a/cmd/gost/peer.go +++ b/cmd/gost/peer.go @@ -11,6 +11,7 @@ import ( "time" "github.com/ginuerzh/gost" + "github.com/go-gost/reload" ) type peerConfig struct { @@ -74,8 +75,8 @@ func (cfg *peerConfig) Reload(r io.Reader) error { nodes := group.SetNodes(gNodes...) for _, node := range nodes[len(cfg.baseNodes):] { - if node.Bypass != nil { - node.Bypass.Stop() // clear the old nodes + if s, ok := node.Bypasser.(reload.Stoppable); ok { + s.Stop() // clear the old nodes } } diff --git a/cmd/gost/route.go b/cmd/gost/route.go index 9426f30..ffb85ef 100644 --- a/cmd/gost/route.go +++ b/cmd/gost/route.go @@ -275,7 +275,7 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) { Transporter: tr, } - node.Bypass = parseBypass(node.Get("bypass")) + node.Bypasser = parseBypasser(node.Get("bypass")) ips := parseIP(node.Get("ip"), sport) for _, ip := range ips { @@ -581,7 +581,7 @@ func (r *route) GenRouters() ([]router, error) { } } - node.Bypass = parseBypass(node.Get("bypass")) + node.Bypasser = parseBypasser(node.Get("bypass")) hosts := parseHosts(node.Get("hosts")) ips := parseIP(node.Get("ip"), "") @@ -607,7 +607,7 @@ func (r *route) GenRouters() ([]router, error) { gost.StrategyHandlerOption(gost.NewStrategy(node.Get("strategy"))), gost.MaxFailsHandlerOption(node.GetInt("max_fails")), gost.FailTimeoutHandlerOption(node.GetDuration("fail_timeout")), - gost.BypassHandlerOption(node.Bypass), + gost.BypasserHandlerOption(node.Bypasser), gost.ResolverHandlerOption(resolver), gost.HostsHandlerOption(hosts), gost.RetryHandlerOption(node.GetInt("retry")), // override the global retry option. diff --git a/go.mod b/go.mod index f1a52b5..8036254 100644 --- a/go.mod +++ b/go.mod @@ -16,10 +16,10 @@ require ( github.com/ginuerzh/gosocks5 v0.2.0 github.com/ginuerzh/tls-dissector v0.0.2-0.20200224064855-24ab2b3a3796 github.com/go-gost/bpool v1.0.0 + github.com/go-gost/bypass v1.0.0 github.com/go-gost/log v1.0.0 github.com/go-gost/relay v0.1.0 github.com/go-gost/reload v1.0.0 - github.com/gobwas/glob v0.2.3 github.com/golang/mock v1.2.0 // indirect github.com/google/gopacket v1.1.17 // indirect github.com/gorilla/websocket v1.4.0 // indirect diff --git a/go.sum b/go.sum index 8063cd8..b59e76e 100644 --- a/go.sum +++ b/go.sum @@ -31,6 +31,8 @@ github.com/ginuerzh/tls-dissector v0.0.2-0.20200224064855-24ab2b3a3796 h1:VPXbYR github.com/ginuerzh/tls-dissector v0.0.2-0.20200224064855-24ab2b3a3796/go.mod h1:YyzP8PQrGwDH/XsfHJXwqdHLwWvBYxu77YVKm0+68f0= github.com/go-gost/bpool v1.0.0 h1:Og+6SH6SooHqf8CIwuxcPRHq8k0Si4YEfO2mBEi3/Uk= github.com/go-gost/bpool v1.0.0/go.mod h1:y/Pywm22A4OrJqNF/mL4nW7yb9fCdhlO8cxjyparkFI= +github.com/go-gost/bypass v1.0.0 h1:ZhLzA3WY9JDxmpyuGwVUH0ubaFOmWWzNpejzwExvhMA= +github.com/go-gost/bypass v1.0.0/go.mod h1:r2MYlxn1/fs24NFs+h/m9HiZKfckBrTnONXklxRUwcE= github.com/go-gost/log v1.0.0 h1:maSjjMvQqLSQYb0Ta5nJTdlRI+aiLMt6WIBYVxajJgs= github.com/go-gost/log v1.0.0/go.mod h1:FCOaaJQ7moHTlLxYk7dsFewlS68U9A1GG3OR+yXkF6s= github.com/go-gost/relay v0.1.0 h1:UOf2YwAzzaUjY5mdpMuLfSw0vz62iIFYk7oJQkuhlGw= diff --git a/handler.go b/handler.go index 199a14b..5aa9ac1 100644 --- a/handler.go +++ b/handler.go @@ -9,6 +9,7 @@ import ( "github.com/ginuerzh/gosocks4" "github.com/ginuerzh/gosocks5" + "github.com/go-gost/bypass" "github.com/go-gost/log" ) @@ -30,7 +31,7 @@ type HandlerOptions struct { Strategy Strategy MaxFails int FailTimeout time.Duration - Bypass *Bypass + Bypasser bypass.Bypasser Retries int Timeout time.Duration Resolver Resolver @@ -107,9 +108,9 @@ func BlacklistHandlerOption(blacklist *Permissions) HandlerOption { } // BypassHandlerOption sets the bypass option of HandlerOptions. -func BypassHandlerOption(bypass *Bypass) HandlerOption { +func BypasserHandlerOption(bypasser bypass.Bypasser) HandlerOption { return func(opts *HandlerOptions) { - opts.Bypass = bypass + opts.Bypasser = bypasser } } diff --git a/http.go b/http.go index 893f263..62a03bc 100644 --- a/http.go +++ b/http.go @@ -189,7 +189,7 @@ func (h *httpHandler) handleRequest(conn net.Conn, req *http.Request) { return } - if h.options.Bypass.Contains(host) { + if h.options.Bypasser.Bypass(host) { resp.StatusCode = http.StatusForbidden log.Logf("[http] %s - %s bypass %s", diff --git a/http2.go b/http2.go index fdda4ec..f0f2b06 100644 --- a/http2.go +++ b/http2.go @@ -374,7 +374,7 @@ func (h *http2Handler) roundTrip(w http.ResponseWriter, r *http.Request) { return } - if h.options.Bypass.Contains(host) { + if h.options.Bypasser.Bypass(host) { log.Logf("[http2] %s - %s bypass %s", r.RemoteAddr, laddr, host) w.WriteHeader(http.StatusForbidden) diff --git a/node.go b/node.go index f64afc4..e7f0f2d 100644 --- a/node.go +++ b/node.go @@ -8,6 +8,8 @@ import ( "strings" "sync" "time" + + "github.com/go-gost/bypass" ) var ( @@ -31,7 +33,7 @@ type Node struct { ConnectOptions []ConnectOption Client *Client marker *failMarker - Bypass *Bypass + Bypasser bypass.Bypasser } // ParseNode parses the node info. diff --git a/sni.go b/sni.go index 575e193..64dc9fe 100644 --- a/sni.go +++ b/sni.go @@ -113,7 +113,7 @@ func (h *sniHandler) Handle(conn net.Conn) { conn.RemoteAddr(), conn.LocalAddr(), host) return } - if h.options.Bypass.Contains(host) { + if h.options.Bypasser.Bypass(host) { log.Log("[sni] %s - %s bypass %s", conn.RemoteAddr(), conn.LocalAddr(), host) return diff --git a/socks.go b/socks.go index afb1660..fb35b8d 100644 --- a/socks.go +++ b/socks.go @@ -900,7 +900,7 @@ func (h *socks5Handler) handleConnect(conn net.Conn, req *gosocks5.Request) { } return } - if h.options.Bypass.Contains(host) { + if h.options.Bypasser.Bypass(host) { log.Logf("[socks5] %s - %s : Bypass %s", conn.RemoteAddr(), conn.LocalAddr(), host) rep := gosocks5.NewReply(gosocks5.NotAllowed, nil) @@ -1261,7 +1261,7 @@ func (h *socks5Handler) transportUDP(relay, peer net.PacketConn) (err error) { if err != nil { continue // drop silently } - if h.options.Bypass.Contains(raddr.String()) { + if h.options.Bypasser.Bypass(raddr.String()) { log.Log("[socks5-udp] [bypass] write to", raddr) continue // bypass } @@ -1288,7 +1288,7 @@ func (h *socks5Handler) transportUDP(relay, peer net.PacketConn) (err error) { if clientAddr == nil { continue } - if h.options.Bypass.Contains(raddr.String()) { + if h.options.Bypasser.Bypass(raddr.String()) { log.Log("[socks5-udp] [bypass] read from", raddr) continue // bypass } @@ -1341,7 +1341,7 @@ func (h *socks5Handler) tunnelClientUDP(uc *net.UDPConn, cc net.Conn) (err error clientAddr = addr } raddr := dgram.Header.Addr.String() - if h.options.Bypass.Contains(raddr) { + if h.options.Bypasser.Bypass(raddr) { log.Log("[udp-tun] [bypass] write to", raddr) continue // bypass } @@ -1370,7 +1370,7 @@ func (h *socks5Handler) tunnelClientUDP(uc *net.UDPConn, cc net.Conn) (err error continue } raddr := dgram.Header.Addr.String() - if h.options.Bypass.Contains(raddr) { + if h.options.Bypasser.Bypass(raddr) { log.Log("[udp-tun] [bypass] read from", raddr) continue // bypass } @@ -1469,7 +1469,7 @@ func (h *socks5Handler) tunnelServerUDP(cc net.Conn, pc net.PacketConn) (err err errc <- err return } - if h.options.Bypass.Contains(addr.String()) { + if h.options.Bypasser.Bypass(addr.String()) { log.Log("[socks5] udp-tun bypass read from", addr) continue // bypass } @@ -1502,7 +1502,7 @@ func (h *socks5Handler) tunnelServerUDP(cc net.Conn, pc net.PacketConn) (err err if err != nil { continue // drop silently } - if h.options.Bypass.Contains(addr.String()) { + if h.options.Bypasser.Bypass(addr.String()) { log.Log("[socks5] udp-tun bypass write to", addr) continue // bypass } @@ -1715,7 +1715,7 @@ func (h *socks4Handler) handleConnect(conn net.Conn, req *gosocks4.Request) { } return } - if h.options.Bypass.Contains(addr) { + if h.options.Bypasser.Bypass(addr) { log.Log("[socks4] %s - %s : Bypass %s", conn.RemoteAddr(), conn.LocalAddr(), addr) rep := gosocks4.NewReply(gosocks4.Rejected, nil) diff --git a/ss.go b/ss.go index 7c13998..5eaac7a 100644 --- a/ss.go +++ b/ss.go @@ -149,7 +149,7 @@ func (h *shadowHandler) Handle(conn net.Conn) { return } - if h.options.Bypass.Contains(host) { + if h.options.Bypasser.Bypass(host) { log.Logf("[ss] %s - %s : Bypass %s", conn.RemoteAddr(), conn.LocalAddr(), host) return @@ -435,7 +435,7 @@ func (h *shadowUDPHandler) transportUDP(conn net.Conn, cc net.PacketConn) error if err != nil { return } - if h.options.Bypass.Contains(addr.String()) { + if h.options.Bypasser.Bypass(addr.String()) { log.Log("[ssu] bypass", addr) return // bypass } @@ -463,7 +463,7 @@ func (h *shadowUDPHandler) transportUDP(conn net.Conn, cc net.PacketConn) error if Debug { log.Logf("[ssu] %s <<< %s length: %d", conn.RemoteAddr(), addr, n) } - if h.options.Bypass.Contains(addr.String()) { + if h.options.Bypasser.Bypass(addr.String()) { log.Log("[ssu] bypass", addr) return // bypass } diff --git a/ssh.go b/ssh.go index 2aeff0b..41250ad 100644 --- a/ssh.go +++ b/ssh.go @@ -608,7 +608,7 @@ func (h *sshForwardHandler) directPortForwardChannel(channel ssh.Channel, raddr return } - if h.options.Bypass.Contains(raddr) { + if h.options.Bypasser.Bypass(raddr) { log.Logf("[ssh-tcp] [bypass] %s", raddr) return }