From 78e03d7fbf638da516889d59cec1923d318dd020 Mon Sep 17 00:00:00 2001 From: nadoo <287492+nadoo@users.noreply.github.com> Date: Mon, 12 Oct 2020 19:07:54 +0800 Subject: [PATCH] check: add `checktolerance` config for lha mode --- README.md | 34 ++++++++++++++++++---------------- config.go | 9 +++++---- config/glider.conf.example | 13 ++++++++----- dns/cache.go | 2 +- go.mod | 2 +- go.sum | 4 ++-- proxy/trojan/server.go | 1 + proxy/vless/server.go | 1 + rule/config.go | 8 +++++--- rule/group.go | 12 ++++++++---- 10 files changed, 50 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index a006b6c..10ee179 100644 --- a/README.md +++ b/README.md @@ -45,19 +45,17 @@ we can set up local listeners as proxy servers, and forward requests to internet |Protocol | Listen/TCP | Listen/UDP | Forward/TCP | Forward/UDP | Description |:-: |:-:|:-:|:-:|:-:|:- -|http |√| |√| |client & server -|socks4 | | |√| |client only -|socks5 |√|√|√|√|client & server |mixed |√|√| | |http+socks5 server +|http |√| |√| |client & server +|socks5 |√|√|√|√|client & server |ss |√|√|√|√|client & server -|ssr | | |√| |client only -|ssh | | |√| |client only |trojan |√|√|√|√|client & server -|trojanc |√|√|√|√|trojan cleartext(without tls) +|trojanc |√|√|√|√|trojan cleartext(without tls) |vless |√|√|√|√|client & server |vmess | | |√| |client only -|redir |√| | | |linux only -|redir6 |√| | | |linux only(ipv6) +|ssr | | |√| |client only +|ssh | | |√| |client only +|socks4 | | |√| |client only |tls |√| |√| |transport client & server |kcp | |√|√| |transport client & server |unix |√| |√| |transport client & server @@ -66,6 +64,8 @@ we can set up local listeners as proxy servers, and forward requests to internet |tcptun |√| | | |transport server only |udptun | |√| | |transport server only |uottun | |√| | |transport server only +|redir |√| | | |linux only +|redir6 |√| | | |linux only(ipv6) |reject | | |√|√|reject all requests @@ -89,15 +89,17 @@ glider -h click to see details ```bash -./glider 0.12.0 usage: +glider 0.12.0 usage: -checkdisabledonly check disabled fowarders only -checkinterval int - proxy check interval(seconds) (default 30) + fowarder check interval(seconds) (default 30) -checktimeout int - proxy check timeout(seconds) (default 10) + fowarder check timeout(seconds) (default 10) + -checktolerance int + fowarder check tolerance(ms), switch only when new_latency < old_latency - tolerance, only used in lha mode -checkwebsite string - proxy check HTTP(NOT HTTPS) website address, format: HOST[:PORT], default port: 80 (default "www.apple.com") + fowarder check HTTP(NOT HTTPS) website address, format: HOST[:PORT], default port: 80 (default "www.apple.com") -config string config file path -dialtimeout int @@ -285,7 +287,7 @@ Examples: ./glider -listen redir://:1081 -forward "ssr://method:pass@1.1.1.1:8444?protocol=a&protocol_param=b&obfs=c&obfs_param=d" -listen on :1081 as a transparent redirect server, forward all requests via remote ssr server. - ./glider -listen redir://:1081 -forward "tls://1.1.1.1:443,vmess://security:uuid@?alterID=10" + ./glider -listen redir://:1081 -forward "tls://abc.com:443,vmess://security:uuid@?alterID=10" -listen on :1081 as a transparent redirect server, forward all requests via remote tls+vmess server. ./glider -listen redir://:1081 -forward "ws://1.1.1.1:80,vmess://security:uuid@?alterID=10" @@ -384,19 +386,19 @@ glider -config CONFIGPATH -listen :8080 -verbose - Chain protocols: https proxy (http over tls) ```bash - forward=tls://1.1.1.1:443,http:// + forward=tls://server.com:443,http:// ``` - Chain protocols: vmess over ws over tls ```bash - forward=tls://1.1.1.1:443,ws://,vmess://5a146038-0b56-4e95-b1dc-5c6f5a32cd98@?alterID=2 + forward=tls://server.com:443,ws://,vmess://5a146038-0b56-4e95-b1dc-5c6f5a32cd98@?alterID=2 ``` - Chain protocols and servers: ``` bash - forward=socks5://1.1.1.1:1080,tls://2.2.2.2:443,vmess://5a146038-0b56-4e95-b1dc-5c6f5a32cd98@?alterID=2 + forward=socks5://1.1.1.1:1080,tls://server.com:443,vmess://5a146038-0b56-4e95-b1dc-5c6f5a32cd98@?alterID=2 ``` - Chain protocols in listener: https proxy server diff --git a/config.go b/config.go index b4c991b..59ada64 100644 --- a/config.go +++ b/config.go @@ -44,9 +44,10 @@ func parseConfig() *Config { flag.StringSliceUniqVar(&conf.Forwards, "forward", nil, "forward url, format: SCHEME://[USER|METHOD:PASSWORD@][HOST]:PORT?PARAMS[,SCHEME://[USER|METHOD:PASSWORD@][HOST]:PORT?PARAMS]") flag.StringVar(&conf.StrategyConfig.Strategy, "strategy", "rr", "forward strategy, default: rr") - flag.StringVar(&conf.StrategyConfig.CheckWebSite, "checkwebsite", "www.apple.com", "proxy check HTTP(NOT HTTPS) website address, format: HOST[:PORT], default port: 80") - flag.IntVar(&conf.StrategyConfig.CheckInterval, "checkinterval", 30, "proxy check interval(seconds)") - flag.IntVar(&conf.StrategyConfig.CheckTimeout, "checktimeout", 10, "proxy check timeout(seconds)") + flag.StringVar(&conf.StrategyConfig.CheckWebSite, "checkwebsite", "www.apple.com", "fowarder check HTTP(NOT HTTPS) website address, format: HOST[:PORT], default port: 80") + flag.IntVar(&conf.StrategyConfig.CheckInterval, "checkinterval", 30, "fowarder check interval(seconds)") + flag.IntVar(&conf.StrategyConfig.CheckTimeout, "checktimeout", 10, "fowarder check timeout(seconds)") + flag.IntVar(&conf.StrategyConfig.CheckTolerance, "checktolerance", 0, "fowarder check tolerance(ms), switch only when new_latency < old_latency - tolerance, only used in lha mode") flag.BoolVar(&conf.StrategyConfig.CheckDisabledOnly, "checkdisabledonly", false, "check disabled fowarders only") flag.IntVar(&conf.StrategyConfig.MaxFailures, "maxfailures", 3, "max failures to change forwarder status to disabled") flag.IntVar(&conf.StrategyConfig.DialTimeout, "dialtimeout", 3, "dial timeout(seconds)") @@ -300,7 +301,7 @@ func usage() { fmt.Fprintf(w, " "+app+" -listen redir://:1081 -forward \"ssr://method:pass@1.1.1.1:8444?protocol=a&protocol_param=b&obfs=c&obfs_param=d\"\n") fmt.Fprintf(w, " -listen on :1081 as a transparent redirect server, forward all requests via remote ssr server.\n") fmt.Fprintf(w, "\n") - fmt.Fprintf(w, " "+app+" -listen redir://:1081 -forward \"tls://1.1.1.1:443,vmess://security:uuid@?alterID=10\"\n") + fmt.Fprintf(w, " "+app+" -listen redir://:1081 -forward \"tls://abc.com:443,vmess://security:uuid@?alterID=10\"\n") fmt.Fprintf(w, " -listen on :1081 as a transparent redirect server, forward all requests via remote tls+vmess server.\n") fmt.Fprintf(w, "\n") fmt.Fprintf(w, " "+app+" -listen redir://:1081 -forward \"ws://1.1.1.1:80,vmess://security:uuid@?alterID=10\"\n") diff --git a/config/glider.conf.example b/config/glider.conf.example index 42cd03d..c1d3a16 100644 --- a/config/glider.conf.example +++ b/config/glider.conf.example @@ -135,17 +135,17 @@ listen=socks5://:1080 # forward=vmess://aes-128-gcm:5a146038-0b56-4e95-b1dc-5c6f5a32cd98@1.1.1.1:443?alterID=2 # vmess over tls -# forward=tls://1.1.1.1:443,vmess://5a146038-0b56-4e95-b1dc-5c6f5a32cd98@?alterID=2 +# forward=tls://server.com:443,vmess://5a146038-0b56-4e95-b1dc-5c6f5a32cd98@?alterID=2 # vmess over websocket -# forward=ws://1.1.1.1:80/path,vmess://chacha20-poly1305:5a146038-0b56-4e95-b1dc-5c6f5a32cd98@?alterID=2 +# forward=ws://server.com:80/path,vmess://chacha20-poly1305:5a146038-0b56-4e95-b1dc-5c6f5a32cd98@?alterID=2 # vmess over ws over tls -# forward=tls://1.1.1.1:443,ws://,vmess://5a146038-0b56-4e95-b1dc-5c6f5a32cd98@?alterID=2 -# forward=tls://1.1.1.1:443,ws://@/path,vmess://5a146038-0b56-4e95-b1dc-5c6f5a32cd98@?alterID=2 +# forward=tls://server.com:443,ws://,vmess://5a146038-0b56-4e95-b1dc-5c6f5a32cd98@?alterID=2 +# forward=tls://server.com:443,ws://@/path,vmess://5a146038-0b56-4e95-b1dc-5c6f5a32cd98@?alterID=2 # ss over tls -# forward=tls://1.1.1.1:443,ss://AEAD_CHACHA20_POLY1305:pass@ +# forward=tls://server.com:443,ss://AEAD_CHACHA20_POLY1305:pass@ # ss over kcp # forward=kcp://aes:key@127.0.0.1:8444?dataShards=10&parityShards=3,ss://AEAD_CHACHA20_POLY1305:pass@ @@ -203,6 +203,9 @@ checkinterval=30 # timeout to set a forwarder to be disabled(seconds) checktimeout=10 +# switch forwarder only when new_latency < old_latency - tolerance, used in lha mode +checktolerance=100 + # check disabled fowarders only checkdisabledonly=false diff --git a/dns/cache.go b/dns/cache.go index 1c7fc2b..374595c 100644 --- a/dns/cache.go +++ b/dns/cache.go @@ -62,7 +62,7 @@ func (c *LruCache) Get(k string) (v []byte, expired bool) { // Set sets an item with key, value, and ttl(seconds). // if the ttl is zero, this item will be set and never be deleted. // if the key exists, update it with value and exp and move it to head. -// if the key does not exist, put an item to the cache's head. +// if the key does not exist, put a new item to the cache's head. // finally, remove the tail if the cache is full. func (c *LruCache) Set(k string, v []byte, ttl int) { c.mu.Lock() diff --git a/go.mod b/go.mod index e5876b2..f7a8796 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 golang.org/x/net v0.0.0-20201010224723-4f7140c49acb // indirect golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634 // indirect - golang.org/x/tools v0.0.0-20201010145503-6e5c6d77ddcc // indirect + golang.org/x/tools v0.0.0-20201011145850-ed2f50202694 // indirect gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect ) diff --git a/go.sum b/go.sum index cf2bc72..118fb82 100644 --- a/go.sum +++ b/go.sum @@ -177,8 +177,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn 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-20201010145503-6e5c6d77ddcc h1:NJuVOHii6+cOLWV2ofkVwU7frODgrUFHcjHCxyQ4DqI= -golang.org/x/tools v0.0.0-20201010145503-6e5c6d77ddcc/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= +golang.org/x/tools v0.0.0-20201011145850-ed2f50202694 h1:BANdcOVw3KTuUiyfDp7wrzCpkCe8UP3lowugJngxBTg= +golang.org/x/tools v0.0.0-20201011145850-ed2f50202694/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/proxy/trojan/server.go b/proxy/trojan/server.go index 724ef14..e5a6802 100644 --- a/proxy/trojan/server.go +++ b/proxy/trojan/server.go @@ -136,6 +136,7 @@ func (s *Trojan) Serve(c net.Conn) { } func (s *Trojan) serveFallback(c net.Conn, tgt string, headBuf *bytes.Buffer) { + // TODO: should we access fallback directly or via proxy? dialer := s.proxy.NextDialer(tgt) rc, err := dialer.Dial("tcp", tgt) if err != nil { diff --git a/proxy/vless/server.go b/proxy/vless/server.go index 4d2e612..19a8afc 100644 --- a/proxy/vless/server.go +++ b/proxy/vless/server.go @@ -92,6 +92,7 @@ func (s *VLess) Serve(c net.Conn) { } func (s *VLess) serveFallback(c net.Conn, tgt string, headBuf *bytes.Buffer) { + // TODO: should we access fallback directly or via proxy? dialer := s.proxy.NextDialer(tgt) rc, err := dialer.Dial("tcp", tgt) if err != nil { diff --git a/rule/config.go b/rule/config.go index a12084c..82296cc 100644 --- a/rule/config.go +++ b/rule/config.go @@ -29,6 +29,7 @@ type StrategyConfig struct { CheckWebSite string CheckInterval int CheckTimeout int + CheckTolerance int CheckDisabledOnly bool MaxFailures int DialTimeout int @@ -43,9 +44,10 @@ func NewConfFromFile(ruleFile string) (*Config, error) { f := conflag.NewFromFile("rule", ruleFile) f.StringSliceUniqVar(&p.Forward, "forward", nil, "forward url, format: SCHEME://[USER|METHOD:PASSWORD@][HOST]:PORT?PARAMS[,SCHEME://[USER|METHOD:PASSWORD@][HOST]:PORT?PARAMS]") f.StringVar(&p.StrategyConfig.Strategy, "strategy", "rr", "forward strategy, default: rr") - f.StringVar(&p.StrategyConfig.CheckWebSite, "checkwebsite", "www.apple.com", "proxy check HTTP(NOT HTTPS) website address, format: HOST[:PORT], default port: 80") - f.IntVar(&p.StrategyConfig.CheckInterval, "checkinterval", 30, "proxy check interval(seconds)") - f.IntVar(&p.StrategyConfig.CheckTimeout, "checktimeout", 10, "proxy check timeout(seconds)") + f.StringVar(&p.StrategyConfig.CheckWebSite, "checkwebsite", "www.apple.com", "fowarder check HTTP(NOT HTTPS) website address, format: HOST[:PORT], default port: 80") + f.IntVar(&p.StrategyConfig.CheckInterval, "checkinterval", 30, "fowarder check interval(seconds)") + f.IntVar(&p.StrategyConfig.CheckTimeout, "checktimeout", 10, "fowarder check timeout(seconds)") + f.IntVar(&p.StrategyConfig.CheckTolerance, "checktolerance", 0, "fowarder check tolerance(ms), switch only when new_latency < old_latency - tolerance, only used in lha mode") f.BoolVar(&p.StrategyConfig.CheckDisabledOnly, "checkdisabledonly", false, "check disabled fowarders only") f.IntVar(&p.StrategyConfig.MaxFailures, "maxfailures", 3, "max failures to change forwarder status to disabled") f.IntVar(&p.StrategyConfig.DialTimeout, "dialtimeout", 3, "dial timeout(seconds)") diff --git a/rule/group.go b/rule/group.go index 3793a75..52808e7 100644 --- a/rule/group.go +++ b/rule/group.go @@ -283,15 +283,19 @@ func (p *FwdrGroup) scheduleHA(dstAddr string) *Forwarder { // Latency based High Availability. func (p *FwdrGroup) scheduleLHA(dstAddr string) *Forwarder { - fwdr := p.avail[0] - lowest := fwdr.Latency() + oldfwdr, newfwdr := p.avail[0], p.avail[0] + lowest := oldfwdr.Latency() for _, f := range p.avail { if f.Latency() < lowest { lowest = f.Latency() - fwdr = f + newfwdr = f } } - return fwdr + tolerance := int64(p.config.CheckTolerance) * int64(time.Millisecond) + if newfwdr.Latency() < (oldfwdr.Latency() - tolerance) { + return newfwdr + } + return oldfwdr } // Destination Hashing.