| 772 | } |
| 773 | |
| 774 | func (c *Conn) forwardTCP(src, dst netip.AddrPort) (handler func(net.Conn), opts []tcpip.SettableSocketOption, intercept bool) { |
| 775 | logger := c.logger.Named("tcp").With(slog.F("src", src.String()), slog.F("dst", dst.String())) |
| 776 | c.mutex.Lock() |
| 777 | ln, ok := c.listeners[listenKey{"tcp", "", fmt.Sprint(dst.Port())}] |
| 778 | c.mutex.Unlock() |
| 779 | if !ok { |
| 780 | return nil, nil, false |
| 781 | } |
| 782 | // See: https://github.com/tailscale/tailscale/blob/c7cea825aea39a00aca71ea02bab7266afc03e7c/wgengine/netstack/netstack.go#L888 |
| 783 | if dst.Port() == WorkspaceAgentSSHPort || dst.Port() == WorkspaceAgentStandardSSHPort { |
| 784 | opt := tcpip.KeepaliveIdleOption(72 * time.Hour) |
| 785 | opts = append(opts, &opt) |
| 786 | } |
| 787 | |
| 788 | return func(conn net.Conn) { |
| 789 | t := time.NewTimer(time.Second) |
| 790 | defer t.Stop() |
| 791 | select { |
| 792 | case ln.conn <- conn: |
| 793 | logger.Info(context.Background(), "accepted connection") |
| 794 | return |
| 795 | case <-ln.closed: |
| 796 | logger.Info(context.Background(), "listener closed; closing connection") |
| 797 | case <-c.closed: |
| 798 | logger.Info(context.Background(), "tailnet closed; closing connection") |
| 799 | case <-t.C: |
| 800 | logger.Info(context.Background(), "listener timed out accepting; closing connection") |
| 801 | } |
| 802 | _ = conn.Close() |
| 803 | }, opts, true |
| 804 | } |
| 805 | |
| 806 | // SetConnStatsCallback sets a callback to be called after maxPeriod or |
| 807 | // maxConns, whichever comes first. Multiple calls overwrites the callback. |