mirror of
https://github.com/nadoo/glider.git
synced 2025-02-23 01:15:41 +08:00
ssh: added timeout parameter (optimize #289 @299)
This commit is contained in:
parent
ff09c45fb6
commit
5cbfcf815f
@ -100,7 +100,7 @@ glider -h
|
||||
<summary>click to see details</summary>
|
||||
|
||||
```bash
|
||||
glider 0.15.0 usage:
|
||||
glider 0.15.1 usage:
|
||||
-check string
|
||||
check=tcp[://HOST:PORT]: tcp port connect check
|
||||
check=http://HOST[:PORT][/URI][#expect=STRING_IN_RESP_LINE]
|
||||
@ -205,7 +205,8 @@ 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]
|
||||
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]
|
||||
|
@ -177,7 +177,8 @@ func usage() {
|
||||
fmt.Fprintf(w, "\n")
|
||||
|
||||
fmt.Fprintf(w, "SSH scheme:\n")
|
||||
fmt.Fprintf(w, " ssh://user[:pass]@host:port[?key=keypath]\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.Fprintf(w, "VMess scheme:\n")
|
||||
|
@ -109,9 +109,10 @@ listen=socks5://:1080
|
||||
# forward=ssr://method:pass@1.1.1.1:8443?protocol=auth_aes128_md5&protocol_param=xxx&obfs=tls1.2_ticket_auth&obfs_param=yyy
|
||||
|
||||
# ssh forwarder
|
||||
# forward=ssh://user[:pass]@host:port[?key=keypath]
|
||||
# forward=ssh://user[:pass]@host:port[?key=keypath&timeout=SECONDS]
|
||||
# forward=ssh://root:pass@host:port
|
||||
# forward=ssh://root@host:port?key=/path/to/keyfile
|
||||
# forward=ssh://root@host:port?key=/path/to/keyfile&timeout=5
|
||||
|
||||
# http proxy as forwarder
|
||||
# forward=http://1.1.1.1:8080
|
||||
|
2
go.mod
2
go.mod
@ -26,7 +26,7 @@ require (
|
||||
github.com/templexxx/xorsimd v0.4.1 // indirect
|
||||
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||
github.com/u-root/uio v0.0.0-20210528151154-e40b768296a7 // indirect
|
||||
golang.org/x/net v0.0.0-20211205041911-012df41ee64c // indirect
|
||||
golang.org/x/net v0.0.0-20211208012354-db4efeb81f4b // indirect
|
||||
)
|
||||
|
||||
// Replace dependency modules with local developing copy
|
||||
|
4
go.sum
4
go.sum
@ -130,8 +130,8 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R
|
||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211205041911-012df41ee64c h1:7SfqwP5fxEtl/P02w5IhKc86ziJ+A25yFrkVgoy2FT8=
|
||||
golang.org/x/net v0.0.0-20211205041911-012df41ee64c/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211208012354-db4efeb81f4b h1:MWaHNqZy3KTpuTMAGvv+Kw+ylsEpmyJZizz1dqxnu28=
|
||||
golang.org/x/net v0.0.0-20211208012354-db4efeb81f4b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
2
main.go
2
main.go
@ -18,7 +18,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
version = "0.15.0"
|
||||
version = "0.15.1"
|
||||
config = parseConfig()
|
||||
)
|
||||
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@ -19,9 +20,10 @@ type SSH struct {
|
||||
proxy proxy.Proxy
|
||||
addr string
|
||||
|
||||
mu sync.Mutex
|
||||
sshCfg *ssh.ClientConfig
|
||||
sshClient *ssh.Client
|
||||
mu sync.Mutex
|
||||
conn net.Conn
|
||||
client *ssh.Client
|
||||
config *ssh.ClientConfig
|
||||
}
|
||||
|
||||
func init() {
|
||||
@ -42,18 +44,16 @@ func NewSSH(s string, d proxy.Dialer, p proxy.Proxy) (*SSH, error) {
|
||||
}
|
||||
|
||||
config := &ssh.ClientConfig{
|
||||
User: user,
|
||||
Timeout: time.Second * 3,
|
||||
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
|
||||
return nil
|
||||
},
|
||||
User: user,
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
}
|
||||
|
||||
if pass, _ := u.User.Password(); pass != "" {
|
||||
config.Auth = []ssh.AuthMethod{ssh.Password(pass)}
|
||||
}
|
||||
|
||||
if key := u.Query().Get("key"); key != "" {
|
||||
query := u.Query()
|
||||
if key := query.Get("key"); key != "" {
|
||||
keyAuth, err := privateKeyAuth(key)
|
||||
if err != nil {
|
||||
log.F("[ssh] read key file error: %s", err)
|
||||
@ -62,11 +62,23 @@ func NewSSH(s string, d proxy.Dialer, p proxy.Proxy) (*SSH, error) {
|
||||
config.Auth = append(config.Auth, keyAuth)
|
||||
}
|
||||
|
||||
// timeout of ssh handshake and channel operation
|
||||
qtimeout := query.Get("timeout")
|
||||
if qtimeout == "" {
|
||||
qtimeout = "5" // default timeout
|
||||
}
|
||||
timeout, err := strconv.ParseUint(qtimeout, 10, 32)
|
||||
if err != nil {
|
||||
log.F("[ssh] parse timeout err: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
config.Timeout = time.Second * time.Duration(timeout)
|
||||
|
||||
t := &SSH{
|
||||
dialer: d,
|
||||
proxy: p,
|
||||
addr: u.Host,
|
||||
sshCfg: config,
|
||||
config: config,
|
||||
}
|
||||
|
||||
if _, port, _ := net.SplitHostPort(t.addr); port == "" {
|
||||
@ -89,6 +101,32 @@ func (s *SSH) Addr() string {
|
||||
return s.addr
|
||||
}
|
||||
|
||||
// Dial connects to the address addr on the network net via the proxy.
|
||||
func (s *SSH) Dial(network, addr string) (net.Conn, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
if s.client != nil {
|
||||
if c, err := s.dial(network, addr); err == nil {
|
||||
return c, nil
|
||||
}
|
||||
s.conn.Close()
|
||||
}
|
||||
|
||||
if err := s.initConn(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.dial(network, addr)
|
||||
}
|
||||
|
||||
func (s *SSH) dial(network, addr string) (net.Conn, error) {
|
||||
s.conn.SetDeadline(time.Now().Add(s.config.Timeout))
|
||||
c, err := s.client.Dial(network, addr)
|
||||
s.conn.SetDeadline(time.Time{})
|
||||
return c, err
|
||||
}
|
||||
|
||||
func (s *SSH) initConn() error {
|
||||
c, err := s.dialer.Dial("tcp", s.addr)
|
||||
if err != nil {
|
||||
@ -96,32 +134,20 @@ func (s *SSH) initConn() error {
|
||||
return err
|
||||
}
|
||||
|
||||
sshConn, sshChan, sshReq, err := ssh.NewClientConn(c, s.addr, s.sshCfg)
|
||||
c.SetDeadline(time.Now().Add(s.config.Timeout))
|
||||
sshConn, sshChan, sshReq, err := ssh.NewClientConn(c, s.addr, s.config)
|
||||
if err != nil {
|
||||
log.F("[ssh]: initial connection to %s error: %s", s.addr, err)
|
||||
c.Close()
|
||||
return err
|
||||
}
|
||||
s.sshClient = ssh.NewClient(sshConn, sshChan, sshReq)
|
||||
c.SetDeadline(time.Time{})
|
||||
|
||||
s.conn = c
|
||||
s.client = ssh.NewClient(sshConn, sshChan, sshReq)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Dial connects to the address addr on the network net via the proxy.
|
||||
func (s *SSH) Dial(network, addr string) (net.Conn, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
if s.sshClient != nil {
|
||||
if c, err := s.sshClient.Dial(network, addr); err == nil {
|
||||
return c, nil
|
||||
}
|
||||
s.sshClient.Conn.Close()
|
||||
}
|
||||
if err := s.initConn(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.sshClient.Dial(network, addr)
|
||||
}
|
||||
|
||||
// DialUDP connects to the given address via the proxy.
|
||||
func (s *SSH) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
|
||||
return nil, nil, proxy.ErrNotSupported
|
||||
|
Loading…
Reference in New Issue
Block a user