diff --git a/go.mod b/go.mod index 7f018249dc..2fadefbf64 100644 --- a/go.mod +++ b/go.mod @@ -49,7 +49,7 @@ replace github.com/tcnksm/go-httpstat => github.com/kylecarbs/go-httpstat v0.0.0 // There are a few minor changes we make to Tailscale that we're slowly upstreaming. Compare here: // https://github.com/tailscale/tailscale/compare/main...coder:tailscale:main -replace tailscale.com => github.com/coder/tailscale v1.1.1-0.20220907193453-fb5ba5ab658d +replace tailscale.com => github.com/coder/tailscale v1.1.1-0.20220912172152-aa5fb7fc6cac // Switch to our fork that imports fixes from http://github.com/tailscale/ssh. // See: https://github.com/coder/coder/issues/3371 diff --git a/go.sum b/go.sum index 65502e2e2e..abf64c0ae7 100644 --- a/go.sum +++ b/go.sum @@ -355,8 +355,8 @@ github.com/coder/retry v1.3.0 h1:5lAAwt/2Cm6lVmnfBY7sOMXcBOwcwJhmV5QGSELIVWY= github.com/coder/retry v1.3.0/go.mod h1:tXuRgZgWjUnU5LZPT4lJh4ew2elUhexhlnXzrJWdyFY= github.com/coder/ssh v0.0.0-20220811105153-fcea99919338 h1:tN5GKFT68YLVzJoA8AHuiMNJ0qlhoD3pGN3JY9gxSko= github.com/coder/ssh v0.0.0-20220811105153-fcea99919338/go.mod h1:ZSS+CUoKHDrqVakTfTWUlKSr9MtMFkC4UvtQKD7O914= -github.com/coder/tailscale v1.1.1-0.20220907193453-fb5ba5ab658d h1:IQ8wJn8MfDS+sesYPpn3EDAyvoGMxFvyyE9uWtcfU6w= -github.com/coder/tailscale v1.1.1-0.20220907193453-fb5ba5ab658d/go.mod h1:MO+tWkQp2YIF3KBnnej/mQvgYccRS5Xk/IrEpZ4Z3BU= +github.com/coder/tailscale v1.1.1-0.20220912172152-aa5fb7fc6cac h1:8v0giAuGwJKFXO3J3ZULhjUku7dSLnBSvTQwkBjhSYs= +github.com/coder/tailscale v1.1.1-0.20220912172152-aa5fb7fc6cac/go.mod h1:MO+tWkQp2YIF3KBnnej/mQvgYccRS5Xk/IrEpZ4Z3BU= github.com/coder/wireguard-go/tun/netstack v0.0.0-20220823170024-a78136eb0cab h1:9yEvRWXXfyKzXu8AqywCi+tFZAoqCy4wVcsXwuvZNMc= github.com/coder/wireguard-go/tun/netstack v0.0.0-20220823170024-a78136eb0cab/go.mod h1:TCJ66NtXh3urJotTdoYQOHHkyE899vOQl5TuF+WLSes= github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= diff --git a/tailnet/conn.go b/tailnet/conn.go index 10654b02ac..8dcd835fe5 100644 --- a/tailnet/conn.go +++ b/tailnet/conn.go @@ -387,16 +387,17 @@ func (c *Conn) Closed() <-chan struct{} { // Close shuts down the Wireguard connection. func (c *Conn) Close() error { c.mutex.Lock() - defer c.mutex.Unlock() select { case <-c.closed: + c.mutex.Unlock() return nil default: } + close(c.closed) for _, l := range c.listeners { _ = l.closeNoLock() } - close(c.closed) + c.mutex.Unlock() _ = c.dialer.Close() _ = c.magicConn.Close() _ = c.netStack.Close() @@ -406,6 +407,15 @@ func (c *Conn) Close() error { return nil } +func (c *Conn) isClosed() bool { + select { + case <-c.closed: + return true + default: + return false + } +} + // This and below is taken _mostly_ verbatim from Tailscale: // https://github.com/tailscale/tailscale/blob/c88bd53b1b7b2fcf7ba302f2e53dd1ce8c32dad4/tsnet/tsnet.go#L459-L494 @@ -422,9 +432,14 @@ func (c *Conn) Listen(network, addr string) (net.Listener, error) { key: lk, addr: addr, - conn: make(chan net.Conn), + closed: make(chan struct{}), + conn: make(chan net.Conn), } c.mutex.Lock() + if c.isClosed() { + c.mutex.Unlock() + return nil, xerrors.New("closed") + } if c.listeners == nil { c.listeners = map[listenKey]*listener{} } @@ -460,9 +475,12 @@ func (c *Conn) forwardTCP(conn net.Conn, port uint16) { defer t.Stop() select { case ln.conn <- conn: + return + case <-ln.closed: + case <-c.closed: case <-t.C: - _ = conn.Close() } + _ = conn.Close() } func (c *Conn) forwardTCPToLocal(conn net.Conn, port uint16) { @@ -506,15 +524,18 @@ type listenKey struct { } type listener struct { - s *Conn - key listenKey - addr string - conn chan net.Conn + s *Conn + key listenKey + addr string + conn chan net.Conn + closed chan struct{} } func (ln *listener) Accept() (net.Conn, error) { - c, ok := <-ln.conn - if !ok { + var c net.Conn + select { + case c = <-ln.conn: + case <-ln.closed: return nil, xerrors.Errorf("wgnet: %w", net.ErrClosed) } return c, nil @@ -530,7 +551,7 @@ func (ln *listener) Close() error { func (ln *listener) closeNoLock() error { if v, ok := ln.s.listeners[ln.key]; ok && v == ln { delete(ln.s.listeners, ln.key) - close(ln.conn) + close(ln.closed) } return nil }