| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374 |
- // Copyright (c) Tailscale Inc & AUTHORS
- // SPDX-License-Identifier: BSD-3-Clause
- //go:build !ts_omit_netstack
- package ipnlocal
- import (
- "net"
- "net/netip"
- "time"
- "gvisor.dev/gvisor/pkg/tcpip"
- "tailscale.com/types/ptr"
- )
- // TCPHandlerForDst returns a TCP handler for connections to dst, or nil if
- // no handler is needed. It also returns a list of TCP socket options to
- // apply to the socket before calling the handler.
- // TCPHandlerForDst is called both for connections to our node's local IP
- // as well as to the service IP (quad 100).
- func (b *LocalBackend) TCPHandlerForDst(src, dst netip.AddrPort) (handler func(c net.Conn) error, opts []tcpip.SettableSocketOption) {
- // First handle internal connections to the service IP
- hittingServiceIP := dst.Addr() == magicDNSIP || dst.Addr() == magicDNSIPv6
- if hittingServiceIP {
- switch dst.Port() {
- case 80:
- // TODO(mpminardi): do we want to show an error message if the web client
- // has been disabled instead of the more "basic" web UI?
- if b.ShouldRunWebClient() {
- return b.handleWebClientConn, opts
- }
- return b.HandleQuad100Port80Conn, opts
- case DriveLocalPort:
- return b.handleDriveConn, opts
- }
- }
- if f, ok := hookServeTCPHandlerForVIPService.GetOk(); ok {
- if handler := f(b, dst, src); handler != nil {
- return handler, opts
- }
- }
- // Then handle external connections to the local IP.
- if !b.isLocalIP(dst.Addr()) {
- return nil, nil
- }
- if dst.Port() == 22 && b.ShouldRunSSH() {
- // Use a higher keepalive idle time for SSH connections, as they are
- // typically long lived and idle connections are more likely to be
- // intentional. Ideally we would turn this off entirely, but we can't
- // tell the difference between a long lived connection that is idle
- // vs a connection that is dead because the peer has gone away.
- // We pick 72h as that is typically sufficient for a long weekend.
- opts = append(opts, ptr.To(tcpip.KeepaliveIdleOption(72*time.Hour)))
- return b.handleSSHConn, opts
- }
- // TODO(will,sonia): allow customizing web client port ?
- if dst.Port() == webClientPort && b.ShouldExposeRemoteWebClient() {
- return b.handleWebClientConn, opts
- }
- if port, ok := b.GetPeerAPIPort(dst.Addr()); ok && dst.Port() == port {
- return func(c net.Conn) error {
- b.handlePeerAPIConn(src, dst, c)
- return nil
- }, opts
- }
- if f, ok := hookTCPHandlerForServe.GetOk(); ok {
- if handler := f(b, dst.Port(), src, nil); handler != nil {
- return handler, opts
- }
- }
- return nil, nil
- }
|