check: add checktolerance config for lha mode

This commit is contained in:
nadoo 2020-10-12 19:07:54 +08:00
parent a1ff92201c
commit 78e03d7fbf
10 changed files with 50 additions and 36 deletions

View File

@ -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 |Protocol | Listen/TCP | Listen/UDP | Forward/TCP | Forward/UDP | Description
|:-: |:-:|:-:|:-:|:-:|:- |:-: |:-:|:-:|:-:|:-:|:-
|http |√| |√| |client & server
|socks4 | | |√| |client only
|socks5 |√|√|√|√|client & server
|mixed |√|√| | |http+socks5 server |mixed |√|√| | |http+socks5 server
|http |√| |√| |client & server
|socks5 |√|√|√|√|client & server
|ss |√|√|√|√|client & server |ss |√|√|√|√|client & server
|ssr | | |√| |client only
|ssh | | |√| |client only
|trojan |√|√|√|√|client & server |trojan |√|√|√|√|client & server
|trojanc |√|√|√|√|trojan cleartext(without tls) |trojanc |√|√|√|√|trojan cleartext(without tls)
|vless |√|√|√|√|client & server |vless |√|√|√|√|client & server
|vmess | | |√| |client only |vmess | | |√| |client only
|redir |√| | | |linux only |ssr | | |√| |client only
|redir6 |√| | | |linux only(ipv6) |ssh | | |√| |client only
|socks4 | | |√| |client only
|tls |√| |√| |transport client & server |tls |√| |√| |transport client & server
|kcp | |√|√| |transport client & server |kcp | |√|√| |transport client & server
|unix |√| |√| |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 |tcptun |√| | | |transport server only
|udptun | |√| | |transport server only |udptun | |√| | |transport server only
|uottun | |√| | |transport server only |uottun | |√| | |transport server only
|redir |√| | | |linux only
|redir6 |√| | | |linux only(ipv6)
|reject | | |√|√|reject all requests |reject | | |√|√|reject all requests
</details> </details>
@ -89,15 +89,17 @@ glider -h
<summary>click to see details</summary> <summary>click to see details</summary>
```bash ```bash
./glider 0.12.0 usage: glider 0.12.0 usage:
-checkdisabledonly -checkdisabledonly
check disabled fowarders only check disabled fowarders only
-checkinterval int -checkinterval int
proxy check interval(seconds) (default 30) fowarder check interval(seconds) (default 30)
-checktimeout int -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 -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 string
config file path config file path
-dialtimeout int -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" ./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. -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. -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" ./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) - Chain protocols: https proxy (http over tls)
```bash ```bash
forward=tls://1.1.1.1:443,http:// forward=tls://server.com:443,http://
``` ```
- Chain protocols: vmess over ws over tls - Chain protocols: vmess over ws over tls
```bash ```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: - Chain protocols and servers:
``` bash ``` 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 - Chain protocols in listener: https proxy server

View File

@ -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.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.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.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, "proxy check interval(seconds)") flag.IntVar(&conf.StrategyConfig.CheckInterval, "checkinterval", 30, "fowarder check interval(seconds)")
flag.IntVar(&conf.StrategyConfig.CheckTimeout, "checktimeout", 10, "proxy check timeout(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.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.MaxFailures, "maxfailures", 3, "max failures to change forwarder status to disabled")
flag.IntVar(&conf.StrategyConfig.DialTimeout, "dialtimeout", 3, "dial timeout(seconds)") 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, " "+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, " -listen on :1081 as a transparent redirect server, forward all requests via remote ssr server.\n")
fmt.Fprintf(w, "\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, " -listen on :1081 as a transparent redirect server, forward all requests via remote tls+vmess server.\n")
fmt.Fprintf(w, "\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") fmt.Fprintf(w, " "+app+" -listen redir://:1081 -forward \"ws://1.1.1.1:80,vmess://security:uuid@?alterID=10\"\n")

View File

@ -135,17 +135,17 @@ listen=socks5://:1080
# forward=vmess://aes-128-gcm:5a146038-0b56-4e95-b1dc-5c6f5a32cd98@1.1.1.1:443?alterID=2 # forward=vmess://aes-128-gcm:5a146038-0b56-4e95-b1dc-5c6f5a32cd98@1.1.1.1:443?alterID=2
# vmess over tls # 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 # 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 # vmess over ws over tls
# 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
# forward=tls://1.1.1.1:443,ws://@/path,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 # 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 # ss over kcp
# forward=kcp://aes:key@127.0.0.1:8444?dataShards=10&parityShards=3,ss://AEAD_CHACHA20_POLY1305:pass@ # 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) # timeout to set a forwarder to be disabled(seconds)
checktimeout=10 checktimeout=10
# switch forwarder only when new_latency < old_latency - tolerance, used in lha mode
checktolerance=100
# check disabled fowarders only # check disabled fowarders only
checkdisabledonly=false checkdisabledonly=false

View File

@ -62,7 +62,7 @@ func (c *LruCache) Get(k string) (v []byte, expired bool) {
// Set sets an item with key, value, and ttl(seconds). // 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 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 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. // finally, remove the tail if the cache is full.
func (c *LruCache) Set(k string, v []byte, ttl int) { func (c *LruCache) Set(k string, v []byte, ttl int) {
c.mu.Lock() c.mu.Lock()

2
go.mod
View File

@ -13,7 +13,7 @@ require (
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb // indirect golang.org/x/net v0.0.0-20201010224723-4f7140c49acb // indirect
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634 // 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 gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect
) )

4
go.sum
View File

@ -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 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-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-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-20201011145850-ed2f50202694 h1:BANdcOVw3KTuUiyfDp7wrzCpkCe8UP3lowugJngxBTg=
golang.org/x/tools v0.0.0-20201010145503-6e5c6d77ddcc/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= 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-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-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=

View File

@ -136,6 +136,7 @@ func (s *Trojan) Serve(c net.Conn) {
} }
func (s *Trojan) serveFallback(c net.Conn, tgt string, headBuf *bytes.Buffer) { 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) dialer := s.proxy.NextDialer(tgt)
rc, err := dialer.Dial("tcp", tgt) rc, err := dialer.Dial("tcp", tgt)
if err != nil { if err != nil {

View File

@ -92,6 +92,7 @@ func (s *VLess) Serve(c net.Conn) {
} }
func (s *VLess) serveFallback(c net.Conn, tgt string, headBuf *bytes.Buffer) { 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) dialer := s.proxy.NextDialer(tgt)
rc, err := dialer.Dial("tcp", tgt) rc, err := dialer.Dial("tcp", tgt)
if err != nil { if err != nil {

View File

@ -29,6 +29,7 @@ type StrategyConfig struct {
CheckWebSite string CheckWebSite string
CheckInterval int CheckInterval int
CheckTimeout int CheckTimeout int
CheckTolerance int
CheckDisabledOnly bool CheckDisabledOnly bool
MaxFailures int MaxFailures int
DialTimeout int DialTimeout int
@ -43,9 +44,10 @@ func NewConfFromFile(ruleFile string) (*Config, error) {
f := conflag.NewFromFile("rule", ruleFile) 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.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.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.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, "proxy check interval(seconds)") f.IntVar(&p.StrategyConfig.CheckInterval, "checkinterval", 30, "fowarder check interval(seconds)")
f.IntVar(&p.StrategyConfig.CheckTimeout, "checktimeout", 10, "proxy check timeout(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.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.MaxFailures, "maxfailures", 3, "max failures to change forwarder status to disabled")
f.IntVar(&p.StrategyConfig.DialTimeout, "dialtimeout", 3, "dial timeout(seconds)") f.IntVar(&p.StrategyConfig.DialTimeout, "dialtimeout", 3, "dial timeout(seconds)")

View File

@ -283,15 +283,19 @@ func (p *FwdrGroup) scheduleHA(dstAddr string) *Forwarder {
// Latency based High Availability. // Latency based High Availability.
func (p *FwdrGroup) scheduleLHA(dstAddr string) *Forwarder { func (p *FwdrGroup) scheduleLHA(dstAddr string) *Forwarder {
fwdr := p.avail[0] oldfwdr, newfwdr := p.avail[0], p.avail[0]
lowest := fwdr.Latency() lowest := oldfwdr.Latency()
for _, f := range p.avail { for _, f := range p.avail {
if f.Latency() < lowest { if f.Latency() < lowest {
lowest = f.Latency() 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. // Destination Hashing.