From 1e01d8692d94d332525a59addcbd94c31efa03c4 Mon Sep 17 00:00:00 2001 From: nadoo <287492+nadoo@users.noreply.github.com> Date: Thu, 5 May 2022 17:12:45 +0800 Subject: [PATCH] ssh: fixed an issue for unreachable addrs (fix #324) --- README.md | 4 ++-- go.mod | 4 ++-- go.sum | 8 ++++---- proxy/ssh/ssh.go | 53 ++++++++++++++++++++++++++++++++---------------- 4 files changed, 43 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 76eb809..691f6b9 100644 --- a/README.md +++ b/README.md @@ -449,14 +449,14 @@ glider -config CONFIG_PATH -v /etc/localtime:/etc/localtime:ro \ nadoo/glider -config=/etc/glider/glider.conf ``` - - run watchtower (if you need auto update for glider) + - run watchtower if you need auto update ``` docker run -d --name watchtower --restart=always \ -v /var/run/docker.sock:/var/run/docker.sock \ containrrr/watchtower --interval 21600 --cleanup \ glider ``` - - open udp ports (if you need udp nat fullcone) + - open udp ports if you need udp nat fullcone ``` iptables -I INPUT -p udp -m udp --dport 1024:65535 -j ACCEPT ``` diff --git a/go.mod b/go.mod index 9a92b47..f9661d9 100644 --- a/go.mod +++ b/go.mod @@ -7,12 +7,12 @@ require ( github.com/dgryski/go-camellia v0.0.0-20191119043421-69a8a13fb23d github.com/dgryski/go-idea v0.0.0-20170306091226-d2fb45a411fb github.com/dgryski/go-rc2 v0.0.0-20150621095337-8a9021637152 - github.com/insomniacslk/dhcp v0.0.0-20220405050111-12fbdcb11b41 + github.com/insomniacslk/dhcp v0.0.0-20220504074936-1ca156eafb9f github.com/nadoo/conflag v0.3.1 github.com/nadoo/ipset v0.5.0 github.com/xtaci/kcp-go/v5 v5.6.1 golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f - golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba + golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 ) require ( diff --git a/go.sum b/go.sum index 3101cbc..e2f87ee 100644 --- a/go.sum +++ b/go.sum @@ -39,8 +39,8 @@ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis= -github.com/insomniacslk/dhcp v0.0.0-20220405050111-12fbdcb11b41 h1:Yg3n3AI7GoHnWt7dyjsLPU+TEuZfPAg0OdiA3MJUV6I= -github.com/insomniacslk/dhcp v0.0.0-20220405050111-12fbdcb11b41/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E= +github.com/insomniacslk/dhcp v0.0.0-20220504074936-1ca156eafb9f h1:l1QCwn715k8nYkj4Ql50rzEog3WnMdrd4YYMMwemxEo= +github.com/insomniacslk/dhcp v0.0.0-20220504074936-1ca156eafb9f/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E= github.com/josharian/native v1.0.0 h1:Ts/E8zCSEsG17dUqv7joXJFybuMLjQfWE04tsBODTxk= github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw= @@ -164,8 +164,8 @@ golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba h1:AyHWHCBVlIYI5rgEM3o+1PLd0sLPcIAoaUckGQMaWtw= -golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 h1:nonptSpoQ4vQjyraW20DXPAglgQfVnM9ZC6MmNLMR60= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= diff --git a/proxy/ssh/ssh.go b/proxy/ssh/ssh.go index 044238a..7942c81 100644 --- a/proxy/ssh/ssh.go +++ b/proxy/ssh/ssh.go @@ -1,6 +1,7 @@ package ssh import ( + "errors" "net" "net/url" "os" @@ -20,7 +21,8 @@ type SSH struct { proxy proxy.Proxy addr string - mu sync.Mutex + mu sync.RWMutex + once sync.Once conn net.Conn client *ssh.Client config *ssh.ClientConfig @@ -103,20 +105,14 @@ func (s *SSH) Addr() string { // 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() + s.once.Do(func() { go s.keepConn() }) - if s.client != nil { - if c, err := s.dial(network, addr); err == nil { - return c, nil - } - s.conn.Close() + s.mu.RLock() + defer s.mu.RUnlock() + + if s.client == nil { + return nil, errors.New("ssh client is nil") } - - if err := s.initConn(); err != nil { - return nil, err - } - return s.dial(network, addr) } @@ -127,27 +123,48 @@ func (s *SSH) dial(network, addr string) (net.Conn, error) { return c, err } -func (s *SSH) initConn() error { +func (s *SSH) connect() error { + s.mu.Lock() + defer s.mu.Unlock() + + log.F("[ssh] trying connecting to %s", s.addr) c, err := s.dialer.Dial("tcp", s.addr) if err != nil { - log.F("[ssh]: dial to %s error: %s", s.addr, err) + log.F("[ssh] dial connection to %s error: %s", s.addr, err) return err } c.SetDeadline(time.Now().Add(s.config.Timeout)) - sshConn, sshChan, sshReq, err := ssh.NewClientConn(c, s.addr, s.config) + conn, ch, req, err := ssh.NewClientConn(c, s.addr, s.config) if err != nil { - log.F("[ssh]: initial connection to %s error: %s", s.addr, err) + log.F("[ssh] initial connection to %s error: %s", s.addr, err) c.Close() return err } c.SetDeadline(time.Time{}) s.conn = c - s.client = ssh.NewClient(sshConn, sshChan, sshReq) + s.client = ssh.NewClient(conn, ch, req) return nil } +func (s *SSH) keepConn() { + sleep := time.Second + for { + if err := s.connect(); err != nil { + sleep *= 2 + if sleep > time.Second*60 { + sleep = time.Second * 60 + } + time.Sleep(sleep) + continue + } + sleep = time.Second + s.client.Conn.Wait() + s.conn.Close() + } +} + // DialUDP connects to the given address via the proxy. func (s *SSH) DialUDP(network, addr string) (pc net.PacketConn, err error) { return nil, proxy.ErrNotSupported