diff --git a/README.md b/README.md index c08b71f..e6f545b 100644 --- a/README.md +++ b/README.md @@ -203,7 +203,7 @@ gost -L=udp://:5353/192.168.1.1:53?ttl=60 [-F=...] #### 远程端口转发(TCP) ```bash -gost -L=rtcp://:2222/192.168.1.1:22 [-F=...] +gost -L=rtcp://:2222/192.168.1.1:22 [-F=... -F=socks5://172.24.10.1:1080] ``` 将172.24.10.1:2222上的数据(通过代理链)转发到192.168.1.1:22上。当代理链末端(最后一个-F参数)为SSH转发通道类型时,gost会直接使用SSH的远程端口转发功能: @@ -214,7 +214,7 @@ gost -L=rtcp://:2222/192.168.1.1:22 -F forward+ssh://:2222 #### 远程端口转发(UDP) ```bash -gost -L=rudp://:5353/192.168.1.1:53 [-F=...] +gost -L=rudp://:5353/192.168.1.1:53?ttl=60 [-F=... -F=socks5://172.24.10.1:1080] ``` 将172.24.10.1:5353上的数据(通过代理链)转发到192.168.1.1:53上。 每条转发通道都有超时时间,当超过此时间,且在此时间段内无任何数据交互,则此通道将关闭。可以通过`ttl`参数来设置超时时间,默认值为60秒。 @@ -398,6 +398,11 @@ gost内置了TLS证书,如果需要使用其他TLS证书,有两种方法: gost -L="http2://:443?cert=/path/to/my/cert/file&key=/path/to/my/key/file" ``` +对于客户端可以通过`secure`参数开启服务器证书和域名校验: +```bash +gost -L=:8080 -F="http2://server_domain_name:443?secure=true" +``` + 对于客户端可以指定CA证书进行[证书锁定](https://en.wikipedia.org/wiki/Transport_Layer_Security#Certificate_pinning)(Certificate Pinning): ```bash gost -L=:8080 -F="http2://:443?ca=ca.pem" diff --git a/README_en.md b/README_en.md index 00263e4..f108c9f 100644 --- a/README_en.md +++ b/README_en.md @@ -199,7 +199,7 @@ Each forwarding channel has a timeout period. When this time is exceeded and the #### Remote TCP port forwarding ```bash -gost -L=rtcp://:2222/192.168.1.1:22 [-F=...] +gost -L=rtcp://:2222/192.168.1.1:22 [-F=... -F=socks5://172.24.10.1:1080] ``` The data on 172.24.10.1:2222 is forwarded to 192.168.1.1:22 (through the proxy chain). If the last node of the chain (the last -F parameter) is a SSH tunnel, then gost will use the remote port forwarding function of SSH directly: @@ -210,7 +210,7 @@ gost -L=rtcp://:2222/192.168.1.1:22 -F forward+ssh://:2222 #### Remote UDP port forwarding ```bash -gost -L=rudp://:5353/192.168.1.1:53?ttl=60 [-F=...] +gost -L=rudp://:5353/192.168.1.1:53?ttl=60 [-F=... -F=socks5://172.24.10.1:1080] ``` The data on 172.24.10.1:5353 is forwarded to 192.168.1.1:53 (through the proxy chain). Each forwarding channel has a timeout period. When this time is exceeded and there is no data interaction during this time period, the channel will be closed. The timeout value can be set by the `ttl` parameter. The default value is 60 seconds. @@ -393,8 +393,12 @@ There is built-in TLS certificate in gost, if you need to use other TLS certific gost -L="http2://:443?cert=/path/to/my/cert/file&key=/path/to/my/key/file" ``` +Client can specify `secure` parameter to perform server's certificate chain and host name verification: +```bash +gost -L=:8080 -F="http2://server_domain_name:443?secure=true" +``` -For client, you can specify a CA certificate to allow for [Certificate Pinning](https://en.wikipedia.org/wiki/Transport_Layer_Security#Certificate_pinning): +Client can specify a CA certificate to allow for [Certificate Pinning](https://en.wikipedia.org/wiki/Transport_Layer_Security#Certificate_pinning): ```bash gost -L=:8080 -F="http2://:443?ca=ca.pem" ``` diff --git a/client.go b/client.go index d26ffa6..d34ddb7 100644 --- a/client.go +++ b/client.go @@ -116,6 +116,7 @@ type HandshakeOptions struct { User *url.Userinfo Timeout time.Duration Interval time.Duration + Retry int TLSConfig *tls.Config WSOptions *WSOptions KCPConfig *KCPConfig @@ -149,6 +150,12 @@ func IntervalHandshakeOption(interval time.Duration) HandshakeOption { } } +func RetryHandshakeOption(retry int) HandshakeOption { + return func(opts *HandshakeOptions) { + opts.Retry = retry + } +} + func TLSConfigHandshakeOption(config *tls.Config) HandshakeOption { return func(opts *HandshakeOptions) { opts.TLSConfig = config diff --git a/ssh.go b/ssh.go index a2e1fe9..19070a1 100644 --- a/ssh.go +++ b/ssh.go @@ -285,7 +285,7 @@ func (tr *sshTunnelTransporter) Handshake(conn net.Conn, options ...HandshakeOpt deaded: make(chan struct{}), } tr.sessions[opts.Addr] = session - go session.Ping(opts.Interval, opts.Timeout, 1) + go session.Ping(opts.Interval, 30*time.Second, 1) go session.waitServer() go session.waitClose() } @@ -322,7 +322,7 @@ func (s *sshSession) Ping(interval, timeout time.Duration, retries int) { return } if timeout <= 0 { - timeout = 30 * time.Second + timeout = 0 } defer close(s.deaded) @@ -331,13 +331,14 @@ func (s *sshSession) Ping(interval, timeout time.Duration, retries int) { t := time.NewTicker(interval) defer t.Stop() + count := retries + 1 for { select { case <-t.C: start := time.Now() - //if Debug { - log.Log("[ssh] sending ping") - //} + if Debug { + log.Log("[ssh] sending ping") + } ctx, cancel := context.WithTimeout(baseCtx, timeout) var err error select { @@ -348,12 +349,16 @@ func (s *sshSession) Ping(interval, timeout time.Duration, retries int) { cancel() if err != nil { log.Log("[ssh] ping:", err) - return + count-- + if count == 0 { + return + } + continue } - //if Debug { - log.Log("[ssh] ping OK, RTT:", time.Since(start)) - //} - + if Debug { + log.Log("[ssh] ping OK, RTT:", time.Since(start)) + } + count = retries + 1 case <-s.closed: return }