diff --git a/README.md b/README.md
index e0c0b3d..09444a3 100644
--- a/README.md
+++ b/README.md
@@ -101,12 +101,16 @@ glider -h
click to see details
```bash
-glider 0.16.0 usage:
+Usage: glider [-listen URL]... [-forward URL]... [OPTION]...
+ e.g. glider -config /etc/glider/glider.conf
+ glider -listen :8443 -forward socks5://serverA:1080 -forward socks5://serverB:1080 -verbose
+
+OPTION:
-check string
check=tcp[://HOST:PORT]: tcp port connect check
check=http://HOST[:PORT][/URI][#expect=REGEX_MATCH_IN_RESP_LINE]
check=https://HOST[:PORT][/URI][#expect=REGEX_MATCH_IN_RESP_LINE]
- check=file://SCRIPT_PATH: run a check script, healthy when exitcode=0, environment variables: FORWARDER_ADDR,FORWARDER_URL
+ check=file://SCRIPT_PATH: run a check script, healthy when exitcode=0, env vars: FORWARDER_ADDR,FORWARDER_URL
check=disable: disable health check (default "http://www.msftconnecttest.com/connecttest.txt#expect=200")
-checkdisabledonly
check disabled fowarders only
@@ -127,7 +131,7 @@ glider 0.16.0 usage:
-dnscachelog
show query log of dns cache
-dnscachesize int
- size of CACHE (default 4096)
+ max number of dns response in CACHE (default 4096)
-dnsmaxttl int
maximum TTL value for entries in the CACHE(seconds) (default 1800)
-dnsminttl int
@@ -141,15 +145,15 @@ glider 0.16.0 usage:
-dnstimeout int
timeout value used in multiple dnsservers switch(seconds) (default 3)
-forward value
- forward url, format: SCHEME://[USER|METHOD:PASSWORD@][HOST]:PORT?PARAMS[,SCHEME://[USER|METHOD:PASSWORD@][HOST]:PORT?PARAMS]
+ forward url, see the URL section below
-include value
include file
-interface string
source ip or source interface
-listen value
- listen url, format: SCHEME://[USER|METHOD:PASSWORD@][HOST]:PORT?PARAMS
+ listen url, see the URL section below
-logflags int
- log flags, do not change it if you do not know what it is, ref: https://pkg.go.dev/log#pkg-constants (default 19)
+ do not change it if you do not know what it is, ref: https://pkg.go.dev/log#pkg-constants (default 19)
-maxfailures int
max failures to change forwarder status to disabled (default 3)
-relaytimeout int
@@ -158,23 +162,62 @@ glider 0.16.0 usage:
rule file path
-rules-dir string
rule file folder
+ -scheme string
+ show help message of proxy scheme, use 'all' to see all
-service value
run specified services, format: SERVICE_NAME[,SERVICE_CONFIG]
-strategy string
- forward strategy, default: rr (default "rr")
+ rr: Round Robin mode
+ ha: High Availability mode
+ lha: Latency based High Availability mode
+ dh: Destination Hashing mode (default "rr")
-tcpbufsize int
tcp buffer size in Bytes (default 32768)
-udpbufsize int
udp buffer size in Bytes (default 2048)
-verbose
verbose mode
+
+URL:
+ proxy: SCHEME://[USER:PASS@][HOST]:PORT
+ chain: proxy,proxy,[proxy]...
+
+ e.g. -listen socks5://:1080
+ -listen tls://:443?cert=crtFilePath&key=keyFilePath,http:// (protocol chain)
+
+ e.g. -forward socks5://server:1080
+ -forward tls://server.com:443,http:// (protocol chain)
+ -forward socks5://serverA:1080,socks5://serverB:1080 (proxy chain)
+
+SCHEME:
+ listen : sni,mixed,tcp,tls,vless,http,ss,trojan,trojanc,wss,ws,kcp,socks5,pxyproto,smux,udp
+ forward: vmess,wss,simple-obfs,udp,ws,kcp,socks5,ssh,ssr,tls,trojanc,reject,socks4a,smux,socks4,ss,tcp,trojan,vless,direct,http
+
+ Note: use `glider -scheme all` or `glider -scheme SCHEME` to see help info for the scheme.
+
+--
+Forwarder Options: FORWARD_URL#OPTIONS
+ priority : the priority of that forwarder, the larger the higher, default: 0
+ interface: the local interface or ip address used to connect remote server.
+
+ e.g. -forward socks5://server:1080#priority=100
+ -forward socks5://server:1080#interface=eth0
+ -forward socks5://server:1080#priority=100&interface=192.168.1.99
+
+Services:
+ dhcpd: service=dhcpd,INTERFACE,START_IP,END_IP,LEASE_MINUTES[,MAC=IP,MAC=IP...]
+ e.g. service=dhcpd,eth1,192.168.1.100,192.168.1.199,720
+
+see README.md and glider.conf.example for more details.
+--
+glider v0.16.0, https://github.com/nadoo/glider
```
run:
```bash
-glider -config CONFIGPATH
+glider -config CONFIG_PATH
```
```bash
glider -verbose -listen :8443 -forward SCHEME://HOST:PORT
@@ -182,144 +225,118 @@ glider -verbose -listen :8443 -forward SCHEME://HOST:PORT
#### Schemes
+```bash
+glider -scheme all
+```
click to see details
```bash
-Available schemes:
- listen: mixed ss socks5 http vless trojan trojanc redir redir6 tproxy tcp udp tls ws wss unix smux kcp pxyproto
- forward: direct reject ss socks4 socks5 http ssr ssh vless vmess trojan trojanc tcp udp tls ws wss unix smux kcp simple-obfs
+KCP scheme:
+ kcp://CRYPT:KEY@host:port[?dataShards=NUM&parityShards=NUM&mode=MODE]
+
+Available crypt types for KCP:
+ none, sm4, tea, xor, aes, aes-128, aes-192, blowfish, twofish, cast5, 3des, xtea, salsa20
+
+Available modes for KCP:
+ fast, fast2, fast3, normal, default: fast
+--
Socks5 scheme:
socks://[user:pass@]host:port
+--
+Simple-Obfs scheme:
+ simple-obfs://host:port[?type=TYPE&host=HOST&uri=URI&ua=UA]
+
+Available types for simple-obfs:
+ http, tls
+
+--
+Smux scheme:
+ smux://host:port
+
+--
SS scheme:
ss://method:pass@host:port
+
+ Available methods for ss:
+ AEAD Ciphers:
+ AEAD_AES_128_GCM AEAD_AES_192_GCM AEAD_AES_256_GCM AEAD_CHACHA20_POLY1305 AEAD_XCHACHA20_POLY1305
+ Stream Ciphers:
+ AES-128-CFB AES-128-CTR AES-192-CFB AES-192-CTR AES-256-CFB AES-256-CTR CHACHA20-IETF XCHACHA20 CHACHA20 RC4-MD5
+ Alias:
+ chacha20-ietf-poly1305 = AEAD_CHACHA20_POLY1305, xchacha20-ietf-poly1305 = AEAD_XCHACHA20_POLY1305
+ Plain: NONE
-Available methods for ss:
- AEAD Ciphers:
- AEAD_AES_128_GCM AEAD_AES_192_GCM AEAD_AES_256_GCM AEAD_CHACHA20_POLY1305 AEAD_XCHACHA20_POLY1305
- Stream Ciphers:
- AES-128-CFB AES-128-CTR AES-192-CFB AES-192-CTR AES-256-CFB AES-256-CTR CHACHA20-IETF XCHACHA20 CHACHA20 RC4-MD5
- Alias:
- chacha20-ietf-poly1305 = AEAD_CHACHA20_POLY1305, xchacha20-ietf-poly1305 = AEAD_XCHACHA20_POLY1305
- Plain: NONE
-
-SSR scheme:
- ssr://method:pass@host:port?protocol=xxx&protocol_param=yyy&obfs=zzz&obfs_param=xyz
-
+--
SSH scheme:
ssh://user[:pass]@host:port[?key=keypath&timeout=SECONDS]
timeout: timeout of ssh handshake and channel operation, default: 5
-VMess scheme:
- vmess://[security:]uuid@host:port[?alterID=num]
- if alterID=0 or not set, VMessAEAD will be enabled
-
-Available security for vmess:
- zero, none, aes-128-gcm, chacha20-poly1305
-
-VLESS scheme:
- vless://uuid@host:port[?fallback=127.0.0.1:80]
-
-Trojan client scheme:
- trojan://pass@host:port[?serverName=SERVERNAME][&skipVerify=true][&cert=PATH]
- trojanc://pass@host:port (cleartext, without TLS)
-
-Trojan server scheme:
- trojan://pass@host:port?cert=PATH&key=PATH[&fallback=127.0.0.1]
- trojanc://pass@host:port[?fallback=127.0.0.1] (cleartext, without TLS)
+--
+SSR scheme:
+ ssr://method:pass@host:port?protocol=xxx&protocol_param=yyy&obfs=zzz&obfs_param=xyz
+--
TLS client scheme:
tls://host:port[?serverName=SERVERNAME][&skipVerify=true][&cert=PATH][&alpn=proto1][&alpn=proto2]
-
+
Proxy over tls client:
tls://host:port[?skipVerify=true][&serverName=SERVERNAME],scheme://
tls://host:port[?skipVerify=true],http://[user:pass@]
tls://host:port[?skipVerify=true],socks5://[user:pass@]
tls://host:port[?skipVerify=true],vmess://[security:]uuid@?alterID=num
-
+
TLS server scheme:
tls://host:port?cert=PATH&key=PATH[&alpn=proto1][&alpn=proto2]
-
+
Proxy over tls server:
tls://host:port?cert=PATH&key=PATH,scheme://
tls://host:port?cert=PATH&key=PATH,http://
tls://host:port?cert=PATH&key=PATH,socks5://
tls://host:port?cert=PATH&key=PATH,ss://method:pass@
+--
+Trojan client scheme:
+ trojan://pass@host:port[?serverName=SERVERNAME][&skipVerify=true][&cert=PATH]
+ trojanc://pass@host:port (cleartext, without TLS)
+
+Trojan server scheme:
+ trojan://pass@host:port?cert=PATH&key=PATH[&fallback=127.0.0.1]
+ trojanc://pass@host:port[?fallback=127.0.0.1] (cleartext, without TLS)
+
+--
+VLESS scheme:
+ vless://uuid@host:port[?fallback=127.0.0.1:80]
+
+--
+VMess scheme:
+ vmess://[security:]uuid@host:port[?alterID=num]
+ if alterID=0 or not set, VMessAEAD will be enabled
+
+ Available security for vmess:
+ zero, none, aes-128-gcm, chacha20-poly1305
+
+--
Websocket client scheme:
ws://host:port[/path][?host=HOST][&origin=ORIGIN]
wss://host:port[/path][?serverName=SERVERNAME][&skipVerify=true][&cert=PATH][&host=HOST][&origin=ORIGIN]
-
+
Websocket server scheme:
ws://:port[/path][?host=HOST]
wss://:port[/path]?cert=PATH&key=PATH[?host=HOST]
-
+
Websocket with a specified proxy protocol:
ws://host:port[/path][?host=HOST],scheme://
ws://host:port[/path][?host=HOST],http://[user:pass@]
ws://host:port[/path][?host=HOST],socks5://[user:pass@]
-
+
TLS and Websocket with a specified proxy protocol:
tls://host:port[?skipVerify=true][&serverName=SERVERNAME],ws://[@/path[?host=HOST]],scheme://
tls://host:port[?skipVerify=true],ws://[@/path[?host=HOST]],http://[user:pass@]
tls://host:port[?skipVerify=true],ws://[@/path[?host=HOST]],socks5://[user:pass@]
tls://host:port[?skipVerify=true],ws://[@/path[?host=HOST]],vmess://[security:]uuid@?alterID=num
-
-Unix domain socket scheme:
- unix://path
-
-Smux scheme:
- smux://host:port
-
-KCP scheme:
- kcp://CRYPT:KEY@host:port[?dataShards=NUM&parityShards=NUM&mode=MODE]
-
-Available crypt types for KCP:
- none, sm4, tea, xor, aes, aes-128, aes-192, blowfish, twofish, cast5, 3des, xtea, salsa20
-
-Available modes for KCP:
- fast, fast2, fast3, normal, default: fast
-
-Simple-Obfs scheme:
- simple-obfs://host:port[?type=TYPE&host=HOST&uri=URI&ua=UA]
-
-Available types for simple-obfs:
- http, tls
-
-DNS forwarding server:
- dns=:53
- dnsserver=8.8.8.8:53
- dnsserver=1.1.1.1:53
- dnsrecord=www.example.com/1.2.3.4
- dnsrecord=www.example.com/2606:2800:220:1:248:1893:25c8:1946
-
-Available forward strategies:
- rr: Round Robin mode
- ha: High Availability mode
- lha: Latency based High Availability mode
- dh: Destination Hashing mode
-
-Forwarder option scheme: FORWARD_URL#OPTIONS
- priority: set the priority of that forwarder, default:0
- interface: set local interface or ip address used to connect remote server
- -
- Examples:
- socks5://1.1.1.1:1080#priority=100
- vmess://[security:]uuid@host:port?alterID=num#priority=200
- vmess://[security:]uuid@host:port?alterID=num#priority=200&interface=192.168.1.99
- vmess://[security:]uuid@host:port?alterID=num#priority=200&interface=eth0
-
-Services:
- dhcpd: service=dhcpd,INTERFACE,START_IP,END_IP,LEASE_MINUTES[,MAC=IP,MAC=IP...]
- e.g.,service=dhcpd,eth1,192.168.1.100,192.168.1.199,720
-
-Config file format(see `./glider.conf.example` as an example):
- # COMMENT LINE
- KEY=VALUE
- KEY=VALUE
- # KEY equals to command line flag name: listen forward strategy...
```
diff --git a/config.go b/config.go
index c34ca34..1e7dbee 100644
--- a/config.go
+++ b/config.go
@@ -43,15 +43,25 @@ func parseConfig() *Config {
flag.SetOutput(os.Stdout)
+ scheme := flag.String("scheme", "", "show help message of proxy scheme, use 'all' to see all ")
+
flag.BoolVar(&conf.Verbose, "verbose", false, "verbose mode")
- flag.IntVar(&conf.LogFlags, "logflags", 19, "log flags, do not change it if you do not know what it is, ref: https://pkg.go.dev/log#pkg-constants")
+ flag.IntVar(&conf.LogFlags, "logflags", 19, "do not change it if you do not know what it is, ref: https://pkg.go.dev/log#pkg-constants")
flag.IntVar(&conf.TCPBufSize, "tcpbufsize", 32768, "tcp buffer size in Bytes")
flag.IntVar(&conf.UDPBufSize, "udpbufsize", 2048, "udp buffer size in Bytes")
- flag.StringSliceUniqVar(&conf.Listens, "listen", nil, "listen url, format: SCHEME://[USER|METHOD:PASSWORD@][HOST]:PORT?PARAMS")
+ flag.StringSliceUniqVar(&conf.Listens, "listen", nil, "listen url, see the URL section below")
- flag.StringSliceVar(&conf.Forwards, "forward", nil, "forward url, format: SCHEME://[USER|METHOD:PASSWORD@][HOST]:PORT?PARAMS[,SCHEME://[USER|METHOD:PASSWORD@][HOST]:PORT?PARAMS]")
- flag.StringVar(&conf.Strategy.Strategy, "strategy", "rr", "forward strategy, default: rr")
- flag.StringVar(&conf.Strategy.Check, "check", "http://www.msftconnecttest.com/connecttest.txt#expect=200", "check=tcp[://HOST:PORT]: tcp port connect check\ncheck=http://HOST[:PORT][/URI][#expect=REGEX_MATCH_IN_RESP_LINE]\ncheck=https://HOST[:PORT][/URI][#expect=REGEX_MATCH_IN_RESP_LINE]\ncheck=file://SCRIPT_PATH: run a check script, healthy when exitcode=0, environment variables: FORWARDER_ADDR,FORWARDER_URL\ncheck=disable: disable health check")
+ flag.StringSliceVar(&conf.Forwards, "forward", nil, "forward url, see the URL section below")
+ flag.StringVar(&conf.Strategy.Strategy, "strategy", "rr", `rr: Round Robin mode
+ha: High Availability mode
+lha: Latency based High Availability mode
+dh: Destination Hashing mode`)
+ flag.StringVar(&conf.Strategy.Check, "check", "http://www.msftconnecttest.com/connecttest.txt#expect=200",
+ `check=tcp[://HOST:PORT]: tcp port connect check
+check=http://HOST[:PORT][/URI][#expect=REGEX_MATCH_IN_RESP_LINE]
+check=https://HOST[:PORT][/URI][#expect=REGEX_MATCH_IN_RESP_LINE]
+check=file://SCRIPT_PATH: run a check script, healthy when exitcode=0, env vars: FORWARDER_ADDR,FORWARDER_URL
+check=disable: disable health check`)
flag.IntVar(&conf.Strategy.CheckInterval, "checkinterval", 30, "fowarder check interval(seconds)")
flag.IntVar(&conf.Strategy.CheckTimeout, "checktimeout", 10, "fowarder check timeout(seconds)")
flag.IntVar(&conf.Strategy.CheckTolerance, "checktolerance", 0, "fowarder check tolerance(ms), switch only when new_latency < old_latency - tolerance, only used in lha mode")
@@ -71,7 +81,7 @@ func parseConfig() *Config {
flag.IntVar(&conf.DNSConfig.Timeout, "dnstimeout", 3, "timeout value used in multiple dnsservers switch(seconds)")
flag.IntVar(&conf.DNSConfig.MaxTTL, "dnsmaxttl", 1800, "maximum TTL value for entries in the CACHE(seconds)")
flag.IntVar(&conf.DNSConfig.MinTTL, "dnsminttl", 0, "minimum TTL value for entries in the CACHE(seconds)")
- flag.IntVar(&conf.DNSConfig.CacheSize, "dnscachesize", 4096, "size of CACHE")
+ flag.IntVar(&conf.DNSConfig.CacheSize, "dnscachesize", 4096, "max number of dns response in CACHE")
flag.BoolVar(&conf.DNSConfig.CacheLog, "dnscachelog", false, "show query log of dns cache")
flag.BoolVar(&conf.DNSConfig.NoAAAA, "dnsnoaaaa", false, "disable AAAA query")
flag.StringSliceUniqVar(&conf.DNSConfig.Records, "dnsrecord", nil, "custom dns record, format: domain/ip")
@@ -87,6 +97,11 @@ func parseConfig() *Config {
os.Exit(-1)
}
+ if *scheme != "" {
+ fmt.Fprintf(os.Stdout, proxy.Usage(*scheme))
+ os.Exit(0)
+ }
+
// setup logger
log.Set(conf.Verbose, conf.LogFlags)
@@ -139,212 +154,53 @@ func parseConfig() *Config {
}
func usage() {
- app := os.Args[0]
w := flag.Output()
- fmt.Fprintf(w, "\n")
- fmt.Fprintf(w, "%s %s usage:\n", app, version)
+ fmt.Fprint(w, `
+Usage: glider [-listen URL]... [-forward URL]... [OPTION]...
+ e.g. glider -config /etc/glider/glider.conf
+ glider -listen :8443 -forward socks5://serverA:1080 -forward socks5://serverB:1080 -verbose
+
+`)
+
+ fmt.Fprintf(w, "OPTION:\n")
flag.PrintDefaults()
- fmt.Fprintf(w, "\n")
- fmt.Fprintf(w, "Available schemes:\n")
- fmt.Fprintf(w, " listen: mixed ss socks5 http vless trojan trojanc redir redir6 tproxy tcp udp tls ws wss unix smux kcp pxyproto\n")
- fmt.Fprintf(w, " forward: direct reject ss socks4 socks5 http ssr ssh vless vmess trojan trojanc tcp udp tls ws wss unix smux kcp simple-obfs\n")
- fmt.Fprintf(w, "\n")
+ fmt.Fprint(w, `
+URL:
+ proxy: SCHEME://[USER:PASS@][HOST]:PORT
+ chain: proxy,proxy,[proxy]...
- fmt.Fprintf(w, "Socks5 scheme:\n")
- fmt.Fprintf(w, " socks://[user:pass@]host:port\n")
- fmt.Fprintf(w, "\n")
+ e.g. -listen socks5://:1080
+ -listen tls://:443?cert=crtFilePath&key=keyFilePath,http:// (protocol chain)
- fmt.Fprintf(w, "SS scheme:\n")
- fmt.Fprintf(w, " ss://method:pass@host:port\n")
- fmt.Fprintf(w, "\n")
+ e.g. -forward socks5://server:1080
+ -forward tls://server.com:443,http:// (protocol chain)
+ -forward socks5://serverA:1080,socks5://serverB:1080 (proxy chain)
- fmt.Fprintf(w, "Available methods for ss:\n")
- fmt.Fprintf(w, " AEAD Ciphers:\n")
- fmt.Fprintf(w, " AEAD_AES_128_GCM AEAD_AES_192_GCM AEAD_AES_256_GCM AEAD_CHACHA20_POLY1305 AEAD_XCHACHA20_POLY1305\n")
- fmt.Fprintf(w, " Stream Ciphers:\n")
- fmt.Fprintf(w, " AES-128-CFB AES-128-CTR AES-192-CFB AES-192-CTR AES-256-CFB AES-256-CTR CHACHA20-IETF XCHACHA20 CHACHA20 RC4-MD5\n")
- fmt.Fprintf(w, " Alias:\n")
- fmt.Fprintf(w, " chacha20-ietf-poly1305 = AEAD_CHACHA20_POLY1305, xchacha20-ietf-poly1305 = AEAD_XCHACHA20_POLY1305\n")
- fmt.Fprintf(w, " Plain: NONE\n")
- fmt.Fprintf(w, "\n")
+`)
- fmt.Fprintf(w, "SSR scheme:\n")
- fmt.Fprintf(w, " ssr://method:pass@host:port?protocol=xxx&protocol_param=yyy&obfs=zzz&obfs_param=xyz\n")
- fmt.Fprintf(w, "\n")
+ fmt.Fprintf(w, "SCHEME:\n")
+ fmt.Fprintf(w, " listen : %s\n", proxy.ServerSchemes())
+ fmt.Fprintf(w, " forward: %s\n", proxy.DialerSchemes())
+ fmt.Fprintf(w, "\n Note: use `glider -scheme all` or `glider -scheme SCHEME` to see help info for the scheme.\n")
- fmt.Fprintf(w, "SSH scheme:\n")
- fmt.Fprintf(w, " ssh://user[:pass]@host:port[?key=keypath&timeout=SECONDS]\n")
- fmt.Fprintf(w, " timeout: timeout of ssh handshake and channel operation, default: 5\n")
- fmt.Fprintf(w, "\n")
+ fmt.Fprint(w, `
+--
+Forwarder Options: FORWARD_URL#OPTIONS
+ priority : the priority of that forwarder, the larger the higher, default: 0
+ interface: the local interface or ip address used to connect remote server.
- fmt.Fprintf(w, "VMess scheme:\n")
- fmt.Fprintf(w, " vmess://[security:]uuid@host:port[?alterID=num]\n")
- fmt.Fprintf(w, " if alterID=0 or not set, VMessAEAD will be enabled\n")
- fmt.Fprintf(w, "\n")
+ e.g. -forward socks5://server:1080#priority=100
+ -forward socks5://server:1080#interface=eth0
+ -forward socks5://server:1080#priority=100&interface=192.168.1.99
- fmt.Fprintf(w, "Available security for vmess:\n")
- fmt.Fprintf(w, " zero, none, aes-128-gcm, chacha20-poly1305\n")
- fmt.Fprintf(w, "\n")
+Services:
+ dhcpd: service=dhcpd,INTERFACE,START_IP,END_IP,LEASE_MINUTES[,MAC=IP,MAC=IP...]
+ e.g. service=dhcpd,eth1,192.168.1.100,192.168.1.199,720
- fmt.Fprintf(w, "VLESS scheme:\n")
- fmt.Fprintf(w, " vless://uuid@host:port[?fallback=127.0.0.1:80]\n")
- fmt.Fprintf(w, "\n")
+see README.md and glider.conf.example for more details.
+`)
- fmt.Fprintf(w, "Trojan client scheme:\n")
- fmt.Fprintf(w, " trojan://pass@host:port[?serverName=SERVERNAME][&skipVerify=true][&cert=PATH]\n")
- fmt.Fprintf(w, " trojanc://pass@host:port (cleartext, without TLS)\n")
- fmt.Fprintf(w, "\n")
-
- fmt.Fprintf(w, "Trojan server scheme:\n")
- fmt.Fprintf(w, " trojan://pass@host:port?cert=PATH&key=PATH[&fallback=127.0.0.1]\n")
- fmt.Fprintf(w, " trojanc://pass@host:port[?fallback=127.0.0.1] (cleartext, without TLS)\n")
- fmt.Fprintf(w, "\n")
-
- fmt.Fprintf(w, "TLS client scheme:\n")
- fmt.Fprintf(w, " tls://host:port[?serverName=SERVERNAME][&skipVerify=true][&cert=PATH][&alpn=proto1][&alpn=proto2]\n")
- fmt.Fprintf(w, "\n")
-
- fmt.Fprintf(w, "Proxy over tls client:\n")
- fmt.Fprintf(w, " tls://host:port[?skipVerify=true][&serverName=SERVERNAME],scheme://\n")
- fmt.Fprintf(w, " tls://host:port[?skipVerify=true],http://[user:pass@]\n")
- fmt.Fprintf(w, " tls://host:port[?skipVerify=true],socks5://[user:pass@]\n")
- fmt.Fprintf(w, " tls://host:port[?skipVerify=true],vmess://[security:]uuid@?alterID=num\n")
- fmt.Fprintf(w, "\n")
-
- fmt.Fprintf(w, "TLS server scheme:\n")
- fmt.Fprintf(w, " tls://host:port?cert=PATH&key=PATH[&alpn=proto1][&alpn=proto2]\n")
- fmt.Fprintf(w, "\n")
-
- fmt.Fprintf(w, "Proxy over tls server:\n")
- fmt.Fprintf(w, " tls://host:port?cert=PATH&key=PATH,scheme://\n")
- fmt.Fprintf(w, " tls://host:port?cert=PATH&key=PATH,http://\n")
- fmt.Fprintf(w, " tls://host:port?cert=PATH&key=PATH,socks5://\n")
- fmt.Fprintf(w, " tls://host:port?cert=PATH&key=PATH,ss://method:pass@\n")
- fmt.Fprintf(w, "\n")
-
- fmt.Fprintf(w, "Websocket client scheme:\n")
- fmt.Fprintf(w, " ws://host:port[/path][?host=HOST][&origin=ORIGIN]\n")
- fmt.Fprintf(w, " wss://host:port[/path][?serverName=SERVERNAME][&skipVerify=true][&cert=PATH][&host=HOST][&origin=ORIGIN]\n")
- fmt.Fprintf(w, "\n")
-
- fmt.Fprintf(w, "Websocket server scheme:\n")
- fmt.Fprintf(w, " ws://:port[/path][?host=HOST]\n")
- fmt.Fprintf(w, " wss://:port[/path]?cert=PATH&key=PATH[?host=HOST]\n")
- fmt.Fprintf(w, "\n")
-
- fmt.Fprintf(w, "Websocket with a specified proxy protocol:\n")
- fmt.Fprintf(w, " ws://host:port[/path][?host=HOST],scheme://\n")
- fmt.Fprintf(w, " ws://host:port[/path][?host=HOST],http://[user:pass@]\n")
- fmt.Fprintf(w, " ws://host:port[/path][?host=HOST],socks5://[user:pass@]\n")
- fmt.Fprintf(w, "\n")
-
- fmt.Fprintf(w, "TLS and Websocket with a specified proxy protocol:\n")
- fmt.Fprintf(w, " tls://host:port[?skipVerify=true][&serverName=SERVERNAME],ws://[@/path[?host=HOST]],scheme://\n")
- fmt.Fprintf(w, " tls://host:port[?skipVerify=true],ws://[@/path[?host=HOST]],http://[user:pass@]\n")
- fmt.Fprintf(w, " tls://host:port[?skipVerify=true],ws://[@/path[?host=HOST]],socks5://[user:pass@]\n")
- fmt.Fprintf(w, " tls://host:port[?skipVerify=true],ws://[@/path[?host=HOST]],vmess://[security:]uuid@?alterID=num\n")
- fmt.Fprintf(w, "\n")
-
- fmt.Fprintf(w, "Unix domain socket scheme:\n")
- fmt.Fprintf(w, " unix://path\n")
- fmt.Fprintf(w, "\n")
-
- fmt.Fprintf(w, "Smux scheme:\n")
- fmt.Fprintf(w, " smux://host:port\n")
- fmt.Fprintf(w, "\n")
-
- fmt.Fprintf(w, "KCP scheme:\n")
- fmt.Fprintf(w, " kcp://CRYPT:KEY@host:port[?dataShards=NUM&parityShards=NUM&mode=MODE]\n")
- fmt.Fprintf(w, "\n")
-
- fmt.Fprintf(w, "Available crypt types for KCP:\n")
- fmt.Fprintf(w, " none, sm4, tea, xor, aes, aes-128, aes-192, blowfish, twofish, cast5, 3des, xtea, salsa20\n")
- fmt.Fprintf(w, "\n")
-
- fmt.Fprintf(w, "Available modes for KCP:\n")
- fmt.Fprintf(w, " fast, fast2, fast3, normal, default: fast\n")
- fmt.Fprintf(w, "\n")
-
- fmt.Fprintf(w, "Simple-Obfs scheme:\n")
- fmt.Fprintf(w, " simple-obfs://host:port[?type=TYPE&host=HOST&uri=URI&ua=UA]\n")
- fmt.Fprintf(w, "\n")
-
- fmt.Fprintf(w, "Available types for simple-obfs:\n")
- fmt.Fprintf(w, " http, tls\n")
- fmt.Fprintf(w, "\n")
-
- fmt.Fprintf(w, "DNS forwarding server:\n")
- fmt.Fprintf(w, " dns=:53\n")
- fmt.Fprintf(w, " dnsserver=8.8.8.8:53\n")
- fmt.Fprintf(w, " dnsserver=1.1.1.1:53\n")
- fmt.Fprintf(w, " dnsrecord=www.example.com/1.2.3.4\n")
- fmt.Fprintf(w, " dnsrecord=www.example.com/2606:2800:220:1:248:1893:25c8:1946\n")
- fmt.Fprintf(w, "\n")
-
- fmt.Fprintf(w, "Available forward strategies:\n")
- fmt.Fprintf(w, " rr: Round Robin mode\n")
- fmt.Fprintf(w, " ha: High Availability mode\n")
- fmt.Fprintf(w, " lha: Latency based High Availability mode\n")
- fmt.Fprintf(w, " dh: Destination Hashing mode\n")
- fmt.Fprintf(w, "\n")
-
- fmt.Fprintf(w, "Forwarder option scheme: FORWARD_URL#OPTIONS\n")
- fmt.Fprintf(w, " priority: set the priority of that forwarder, default:0\n")
- fmt.Fprintf(w, " interface: set local interface or ip address used to connect remote server\n")
- fmt.Fprintf(w, " -\n")
- fmt.Fprintf(w, " Examples:\n")
- fmt.Fprintf(w, " socks5://1.1.1.1:1080#priority=100\n")
- fmt.Fprintf(w, " vmess://[security:]uuid@host:port?alterID=num#priority=200\n")
- fmt.Fprintf(w, " vmess://[security:]uuid@host:port?alterID=num#priority=200&interface=192.168.1.99\n")
- fmt.Fprintf(w, " vmess://[security:]uuid@host:port?alterID=num#priority=200&interface=eth0\n")
- fmt.Fprintf(w, "\n")
-
- fmt.Fprintf(w, "Services:\n")
- fmt.Fprintf(w, " dhcpd: service=dhcpd,INTERFACE,START_IP,END_IP,LEASE_MINUTES[,MAC=IP,MAC=IP...]\n")
- fmt.Fprintf(w, " e.g.,service=dhcpd,eth1,192.168.1.100,192.168.1.199,720\n")
- fmt.Fprintf(w, "\n")
-
- fmt.Fprintf(w, "Config file format(see `"+app+".conf.example` as an example):\n")
- fmt.Fprintf(w, " # COMMENT LINE\n")
- fmt.Fprintf(w, " KEY=VALUE\n")
- fmt.Fprintf(w, " KEY=VALUE\n")
- fmt.Fprintf(w, " # KEY equals to command line flag name: listen forward strategy...\n")
- fmt.Fprintf(w, "\n")
-
- fmt.Fprintf(w, "Examples:\n")
- fmt.Fprintf(w, " "+app+" -config glider.conf\n")
- fmt.Fprintf(w, " -run glider with specified config file.\n")
- fmt.Fprintf(w, "\n")
- fmt.Fprintf(w, " "+app+" -listen :8443 -verbose\n")
- fmt.Fprintf(w, " -listen on :8443, serve as http/socks5 proxy on the same port, in verbose mode.\n")
- fmt.Fprintf(w, "\n")
- fmt.Fprintf(w, " "+app+" -listen ss://AEAD_AES_128_GCM:pass@:8443 -verbose\n")
- fmt.Fprintf(w, " -listen on 0.0.0.0:8443 as a ss server.\n")
- fmt.Fprintf(w, "\n")
- fmt.Fprintf(w, " "+app+" -listen tls://:443?cert=crtFilePath&key=keyFilePath,http:// -verbose\n")
- fmt.Fprintf(w, " -listen on :443 as a https(http over tls) proxy server.\n")
- fmt.Fprintf(w, "\n")
- fmt.Fprintf(w, " "+app+" -listen http://:8080 -forward socks5://127.0.0.1:1080\n")
- fmt.Fprintf(w, " -listen on :8080 as a http proxy server, forward all requests via socks5 server.\n")
- fmt.Fprintf(w, "\n")
- fmt.Fprintf(w, " "+app+" -listen socks5://:1080 -forward \"tls://abc.com:443,vmess://security:uuid@?alterID=10\"\n")
- fmt.Fprintf(w, " -listen on :1080 as a socks5 server, forward all requests via remote tls+vmess server.\n")
- fmt.Fprintf(w, "\n")
- fmt.Fprintf(w, " "+app+" -listen socks5://:1080 -forward ss://method:pass@server1:port1 -forward ss://method:pass@server2:port2 -strategy rr\n")
- fmt.Fprintf(w, " -listen on :1080 as socks5 server, forward requests via server1 and server2 in round robin mode.\n")
- fmt.Fprintf(w, "\n")
- fmt.Fprintf(w, " "+app+" -listen tcp://:80 -forward tcp://2.2.2.2:80\n")
- fmt.Fprintf(w, " -tcp tunnel: listen on :80 and forward all requests to 2.2.2.2:80.\n")
- fmt.Fprintf(w, "\n")
- fmt.Fprintf(w, " "+app+" -listen udp://:53 -forward ss://method:pass@1.1.1.1:8443,udp://8.8.8.8:53\n")
- fmt.Fprintf(w, " -listen on :53 and forward all udp requests to 8.8.8.8:53 via remote ss server.\n")
- fmt.Fprintf(w, "\n")
- fmt.Fprintf(w, " "+app+" -listen socks5://:1080 -listen http://:8080 -forward ss://method:pass@1.1.1.1:8443\n")
- fmt.Fprintf(w, " -listen on :1080 as socks5 server, :8080 as http proxy server, forward all requests via remote ss server.\n")
- fmt.Fprintf(w, "\n")
- fmt.Fprintf(w, " "+app+" -verbose -listen -dns=:53 -dnsserver=8.8.8.8:53 -forward ss://method:pass@server:port -dnsrecord=www.example.com/1.2.3.4\n")
- fmt.Fprintf(w, " -listen on :53 as dns server, forward to 8.8.8.8:53 via ss server.\n")
- fmt.Fprintf(w, "\n")
+ fmt.Fprintf(w, "--\nglider v%s, https://github.com/nadoo/glider\n\n", version)
}
diff --git a/go.mod b/go.mod
index 155ef64..a2e49b6 100644
--- a/go.mod
+++ b/go.mod
@@ -9,9 +9,9 @@ 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.3.1
- github.com/nadoo/ipset v0.4.1-0.20220202154244-ddbfbad6db35
+ github.com/nadoo/ipset v0.4.1-0.20220214103201-761217ee1ee0
github.com/xtaci/kcp-go/v5 v5.6.1
- golang.org/x/crypto v0.0.0-20220213190939-1e6e3497d506
+ golang.org/x/crypto v0.0.0-20220214200702-86341886e292
golang.org/x/sys v0.0.0-20220209214540-3681064d5158
)
diff --git a/go.sum b/go.sum
index dc34c82..acc7747 100644
--- a/go.sum
+++ b/go.sum
@@ -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.3.1 h1:4pHkLIz8PUsfg6ajNYRRSY3bt6m2LPsu6KOzn5uIXQw=
github.com/nadoo/conflag v0.3.1/go.mod h1:dzFfDUpXdr2uS2oV+udpy5N2vfNOu/bFzjhX1WI52co=
-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/nadoo/ipset v0.4.1-0.20220214103201-761217ee1ee0 h1:i81BROp7xvMIkR1KpLwERTrRVgwwFAN0prz1kQmz9RE=
+github.com/nadoo/ipset v0.4.1-0.20220214103201-761217ee1ee0/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-20220213190939-1e6e3497d506 h1:EuGTJDfeg/PGZJp3gq1K+14eSLFTsrj1eg8KQuiUyKg=
-golang.org/x/crypto v0.0.0-20220213190939-1e6e3497d506/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE=
+golang.org/x/crypto v0.0.0-20220214200702-86341886e292/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/proxy/dialer.go b/proxy/dialer.go
index 5df7174..4112468 100644
--- a/proxy/dialer.go
+++ b/proxy/dialer.go
@@ -66,3 +66,12 @@ func DialerFromURL(s string, dialer Dialer) (Dialer, error) {
return nil, errors.New("unknown scheme '" + scheme + "'")
}
+
+// DialerSchemes returns the registered dialer schemes.
+func DialerSchemes() string {
+ s := make([]string, 0, len(dialerCreators))
+ for name := range dialerCreators {
+ s = append(s, name)
+ }
+ return strings.Join(s, ",")
+}
diff --git a/proxy/kcp/kcp.go b/proxy/kcp/kcp.go
index a0b46e9..3a41e8f 100644
--- a/proxy/kcp/kcp.go
+++ b/proxy/kcp/kcp.go
@@ -266,3 +266,16 @@ func (s *KCP) setParams(c *kcp.UDPSession) {
c.SetMtu(1350)
c.SetACKNoDelay(true)
}
+
+func init() {
+ proxy.AddUsage("kcp", `
+KCP scheme:
+ kcp://CRYPT:KEY@host:port[?dataShards=NUM&parityShards=NUM&mode=MODE]
+
+Available crypt types for KCP:
+ none, sm4, tea, xor, aes, aes-128, aes-192, blowfish, twofish, cast5, 3des, xtea, salsa20
+
+Available modes for KCP:
+ fast, fast2, fast3, normal, default: fast
+`)
+}
diff --git a/proxy/obfs/obfs.go b/proxy/obfs/obfs.go
index 21d1d38..75ffe0b 100644
--- a/proxy/obfs/obfs.go
+++ b/proxy/obfs/obfs.go
@@ -109,3 +109,13 @@ func (s *Obfs) Dial(network, addr string) (net.Conn, error) {
func (s *Obfs) DialUDP(network, addr string) (net.PacketConn, net.Addr, error) {
return nil, nil, proxy.ErrNotSupported
}
+
+func init() {
+ proxy.AddUsage("simple-obfs", `
+Simple-Obfs scheme:
+ simple-obfs://host:port[?type=TYPE&host=HOST&uri=URI&ua=UA]
+
+Available types for simple-obfs:
+ http, tls
+`)
+}
diff --git a/proxy/server.go b/proxy/server.go
index 3271feb..c674420 100644
--- a/proxy/server.go
+++ b/proxy/server.go
@@ -51,3 +51,12 @@ func ServerFromURL(s string, proxy Proxy) (Server, error) {
return nil, errors.New("unknown scheme '" + scheme + "'")
}
+
+// ServerSchemes returns the registered server schemes.
+func ServerSchemes() string {
+ s := make([]string, 0, len(serverCreators))
+ for name := range serverCreators {
+ s = append(s, name)
+ }
+ return strings.Join(s, ",")
+}
diff --git a/proxy/smux/smux.go b/proxy/smux/smux.go
new file mode 100644
index 0000000..fae7406
--- /dev/null
+++ b/proxy/smux/smux.go
@@ -0,0 +1,10 @@
+package smux
+
+import "github.com/nadoo/glider/proxy"
+
+func init() {
+ proxy.AddUsage("smux", `
+Smux scheme:
+ smux://host:port
+`)
+}
diff --git a/proxy/socks5/client.go b/proxy/socks5/client.go
index c470c3c..d0ba28f 100644
--- a/proxy/socks5/client.go
+++ b/proxy/socks5/client.go
@@ -13,6 +13,10 @@ import (
"github.com/nadoo/glider/proxy"
)
+func init() {
+ proxy.RegisterDialer("socks5", NewSocks5Dialer)
+}
+
// NewSocks5Dialer returns a socks5 proxy dialer.
func NewSocks5Dialer(s string, d proxy.Dialer) (proxy.Dialer, error) {
return NewSocks5(s, d, nil)
diff --git a/proxy/socks5/server.go b/proxy/socks5/server.go
index a753193..471255f 100644
--- a/proxy/socks5/server.go
+++ b/proxy/socks5/server.go
@@ -16,6 +16,10 @@ import (
var nm sync.Map
+func init() {
+ proxy.RegisterServer("socks5", NewSocks5Server)
+}
+
// NewSocks5Server returns a socks5 proxy server.
func NewSocks5Server(s string, p proxy.Proxy) (proxy.Server, error) {
return NewSocks5(s, nil, p)
diff --git a/proxy/socks5/socks5.go b/proxy/socks5/socks5.go
index f190e58..dffb204 100644
--- a/proxy/socks5/socks5.go
+++ b/proxy/socks5/socks5.go
@@ -28,11 +28,6 @@ type Socks5 struct {
password string
}
-func init() {
- proxy.RegisterDialer("socks5", NewSocks5Dialer)
- proxy.RegisterServer("socks5", NewSocks5Server)
-}
-
// NewSocks5 returns a Proxy that makes SOCKS v5 connections to the given address.
// with an optional username and password. (RFC 1928)
func NewSocks5(s string, d proxy.Dialer, p proxy.Proxy) (*Socks5, error) {
@@ -56,3 +51,10 @@ func NewSocks5(s string, d proxy.Dialer, p proxy.Proxy) (*Socks5, error) {
return h, nil
}
+
+func init() {
+ proxy.AddUsage("socks5", `
+Socks5 scheme:
+ socks://[user:pass@]host:port
+`)
+}
diff --git a/proxy/ss/ss.go b/proxy/ss/ss.go
index 71351cf..ba6be4a 100644
--- a/proxy/ss/ss.go
+++ b/proxy/ss/ss.go
@@ -48,3 +48,19 @@ func NewSS(s string, d proxy.Dialer, p proxy.Proxy) (*SS, error) {
return ss, nil
}
+
+func init() {
+ proxy.AddUsage("ss", `
+SS scheme:
+ ss://method:pass@host:port
+
+ Available methods for ss:
+ AEAD Ciphers:
+ AEAD_AES_128_GCM AEAD_AES_192_GCM AEAD_AES_256_GCM AEAD_CHACHA20_POLY1305 AEAD_XCHACHA20_POLY1305
+ Stream Ciphers:
+ AES-128-CFB AES-128-CTR AES-192-CFB AES-192-CTR AES-256-CFB AES-256-CTR CHACHA20-IETF XCHACHA20 CHACHA20 RC4-MD5
+ Alias:
+ chacha20-ietf-poly1305 = AEAD_CHACHA20_POLY1305, xchacha20-ietf-poly1305 = AEAD_XCHACHA20_POLY1305
+ Plain: NONE
+`)
+}
diff --git a/proxy/ssh/ssh.go b/proxy/ssh/ssh.go
index 697806d..dc51f0f 100644
--- a/proxy/ssh/ssh.go
+++ b/proxy/ssh/ssh.go
@@ -166,3 +166,11 @@ func privateKeyAuth(file string) (ssh.AuthMethod, error) {
return ssh.PublicKeys(key), nil
}
+
+func init() {
+ proxy.AddUsage("ssh", `
+SSH scheme:
+ ssh://user[:pass]@host:port[?key=keypath&timeout=SECONDS]
+ timeout: timeout of ssh handshake and channel operation, default: 5
+`)
+}
diff --git a/proxy/ssr/ssr.go b/proxy/ssr/ssr.go
index df4b398..257e243 100644
--- a/proxy/ssr/ssr.go
+++ b/proxy/ssr/ssr.go
@@ -155,3 +155,10 @@ func (s *SSR) Dial(network, addr string) (net.Conn, error) {
func (s *SSR) DialUDP(network, addr string) (net.PacketConn, net.Addr, error) {
return nil, nil, proxy.ErrNotSupported
}
+
+func init() {
+ proxy.AddUsage("ssr", `
+SSR scheme:
+ ssr://method:pass@host:port?protocol=xxx&protocol_param=yyy&obfs=zzz&obfs_param=xyz
+`)
+}
diff --git a/proxy/tls/tls.go b/proxy/tls/tls.go
index 9a053de..1cc493b 100644
--- a/proxy/tls/tls.go
+++ b/proxy/tls/tls.go
@@ -210,3 +210,25 @@ func (s *TLS) Dial(network, addr string) (net.Conn, error) {
func (s *TLS) DialUDP(network, addr string) (net.PacketConn, net.Addr, error) {
return nil, nil, proxy.ErrNotSupported
}
+
+func init() {
+ proxy.AddUsage("tls", `
+TLS client scheme:
+ tls://host:port[?serverName=SERVERNAME][&skipVerify=true][&cert=PATH][&alpn=proto1][&alpn=proto2]
+
+Proxy over tls client:
+ tls://host:port[?skipVerify=true][&serverName=SERVERNAME],scheme://
+ tls://host:port[?skipVerify=true],http://[user:pass@]
+ tls://host:port[?skipVerify=true],socks5://[user:pass@]
+ tls://host:port[?skipVerify=true],vmess://[security:]uuid@?alterID=num
+
+TLS server scheme:
+ tls://host:port?cert=PATH&key=PATH[&alpn=proto1][&alpn=proto2]
+
+Proxy over tls server:
+ tls://host:port?cert=PATH&key=PATH,scheme://
+ tls://host:port?cert=PATH&key=PATH,http://
+ tls://host:port?cert=PATH&key=PATH,socks5://
+ tls://host:port?cert=PATH&key=PATH,ss://method:pass@
+`)
+}
diff --git a/proxy/trojan/trojan.go b/proxy/trojan/trojan.go
index 6e065c6..6ee811c 100644
--- a/proxy/trojan/trojan.go
+++ b/proxy/trojan/trojan.go
@@ -71,3 +71,15 @@ func NewTrojan(s string, d proxy.Dialer, p proxy.Proxy) (*Trojan, error) {
return t, nil
}
+
+func init() {
+ proxy.AddUsage("trojan", `
+Trojan client scheme:
+ trojan://pass@host:port[?serverName=SERVERNAME][&skipVerify=true][&cert=PATH]
+ trojanc://pass@host:port (cleartext, without TLS)
+
+Trojan server scheme:
+ trojan://pass@host:port?cert=PATH&key=PATH[&fallback=127.0.0.1]
+ trojanc://pass@host:port[?fallback=127.0.0.1] (cleartext, without TLS)
+`)
+}
diff --git a/proxy/unix/unix.go b/proxy/unix/unix.go
index aee57bd..e8c3e74 100644
--- a/proxy/unix/unix.go
+++ b/proxy/unix/unix.go
@@ -48,3 +48,10 @@ func NewUnix(s string, d proxy.Dialer, p proxy.Proxy) (*Unix, error) {
return unix, nil
}
+
+func init() {
+ proxy.AddUsage("unix", `
+Unix domain socket scheme:
+ unix://path
+`)
+}
diff --git a/proxy/usage.go b/proxy/usage.go
new file mode 100644
index 0000000..f707fd6
--- /dev/null
+++ b/proxy/usage.go
@@ -0,0 +1,24 @@
+package proxy
+
+import "strings"
+
+var msg strings.Builder
+var usages = make(map[string]string)
+
+// AddUsage adds help message for the named proxy.
+func AddUsage(name, usage string) {
+ usages[name] = usage
+ msg.WriteString(usage)
+ msg.WriteString("\n--")
+}
+
+// Usage returns help message of the named proxy.
+func Usage(name string) string {
+ if name == "all" {
+ return msg.String()
+ }
+ if usage, ok := usages[name]; ok {
+ return usage
+ }
+ return "can not find usage for: " + name
+}
diff --git a/proxy/vless/vless.go b/proxy/vless/vless.go
index ce88a78..06efa1e 100644
--- a/proxy/vless/vless.go
+++ b/proxy/vless/vless.go
@@ -81,3 +81,10 @@ func StrToUUID(s string) (uuid [16]byte, err error) {
_, err = hex.Decode(uuid[:], b)
return
}
+
+func init() {
+ proxy.AddUsage("vless", `
+VLESS scheme:
+ vless://uuid@host:port[?fallback=127.0.0.1:80]
+`)
+}
diff --git a/proxy/vmess/vmess.go b/proxy/vmess/vmess.go
index a41a305..6f07f3b 100644
--- a/proxy/vmess/vmess.go
+++ b/proxy/vmess/vmess.go
@@ -109,3 +109,14 @@ func (s *VMess) DialUDP(network, addr string) (net.PacketConn, net.Addr, error)
}
return NewPktConn(rc), nil, err
}
+
+func init() {
+ proxy.AddUsage("vmess", `
+VMess scheme:
+ vmess://[security:]uuid@host:port[?alterID=num]
+ if alterID=0 or not set, VMessAEAD will be enabled
+
+ Available security for vmess:
+ zero, none, aes-128-gcm, chacha20-poly1305
+`)
+}
diff --git a/proxy/ws/ws.go b/proxy/ws/ws.go
index 7de14d0..9a4e978 100644
--- a/proxy/ws/ws.go
+++ b/proxy/ws/ws.go
@@ -115,3 +115,26 @@ func computeServerKey(clientKey string) string {
h.Write(keyGUID)
return base64.StdEncoding.EncodeToString(h.Sum(nil))
}
+
+func init() {
+ proxy.AddUsage("ws", `
+Websocket client scheme:
+ ws://host:port[/path][?host=HOST][&origin=ORIGIN]
+ wss://host:port[/path][?serverName=SERVERNAME][&skipVerify=true][&cert=PATH][&host=HOST][&origin=ORIGIN]
+
+Websocket server scheme:
+ ws://:port[/path][?host=HOST]
+ wss://:port[/path]?cert=PATH&key=PATH[?host=HOST]
+
+Websocket with a specified proxy protocol:
+ ws://host:port[/path][?host=HOST],scheme://
+ ws://host:port[/path][?host=HOST],http://[user:pass@]
+ ws://host:port[/path][?host=HOST],socks5://[user:pass@]
+
+TLS and Websocket with a specified proxy protocol:
+ tls://host:port[?skipVerify=true][&serverName=SERVERNAME],ws://[@/path[?host=HOST]],scheme://
+ tls://host:port[?skipVerify=true],ws://[@/path[?host=HOST]],http://[user:pass@]
+ tls://host:port[?skipVerify=true],ws://[@/path[?host=HOST]],socks5://[user:pass@]
+ tls://host:port[?skipVerify=true],ws://[@/path[?host=HOST]],vmess://[security:]uuid@?alterID=num
+`)
+}