netstack.go 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. //go:build !ts_omit_netstack
  4. package ipnlocal
  5. import (
  6. "net"
  7. "net/netip"
  8. "time"
  9. "gvisor.dev/gvisor/pkg/tcpip"
  10. "tailscale.com/types/ptr"
  11. )
  12. // TCPHandlerForDst returns a TCP handler for connections to dst, or nil if
  13. // no handler is needed. It also returns a list of TCP socket options to
  14. // apply to the socket before calling the handler.
  15. // TCPHandlerForDst is called both for connections to our node's local IP
  16. // as well as to the service IP (quad 100).
  17. func (b *LocalBackend) TCPHandlerForDst(src, dst netip.AddrPort) (handler func(c net.Conn) error, opts []tcpip.SettableSocketOption) {
  18. // First handle internal connections to the service IP
  19. hittingServiceIP := dst.Addr() == magicDNSIP || dst.Addr() == magicDNSIPv6
  20. if hittingServiceIP {
  21. switch dst.Port() {
  22. case 80:
  23. // TODO(mpminardi): do we want to show an error message if the web client
  24. // has been disabled instead of the more "basic" web UI?
  25. if b.ShouldRunWebClient() {
  26. return b.handleWebClientConn, opts
  27. }
  28. return b.HandleQuad100Port80Conn, opts
  29. case DriveLocalPort:
  30. return b.handleDriveConn, opts
  31. }
  32. }
  33. if f, ok := hookServeTCPHandlerForVIPService.GetOk(); ok {
  34. if handler := f(b, dst, src); handler != nil {
  35. return handler, opts
  36. }
  37. }
  38. // Then handle external connections to the local IP.
  39. if !b.isLocalIP(dst.Addr()) {
  40. return nil, nil
  41. }
  42. if dst.Port() == 22 && b.ShouldRunSSH() {
  43. // Use a higher keepalive idle time for SSH connections, as they are
  44. // typically long lived and idle connections are more likely to be
  45. // intentional. Ideally we would turn this off entirely, but we can't
  46. // tell the difference between a long lived connection that is idle
  47. // vs a connection that is dead because the peer has gone away.
  48. // We pick 72h as that is typically sufficient for a long weekend.
  49. opts = append(opts, ptr.To(tcpip.KeepaliveIdleOption(72*time.Hour)))
  50. return b.handleSSHConn, opts
  51. }
  52. // TODO(will,sonia): allow customizing web client port ?
  53. if dst.Port() == webClientPort && b.ShouldExposeRemoteWebClient() {
  54. return b.handleWebClientConn, opts
  55. }
  56. if port, ok := b.GetPeerAPIPort(dst.Addr()); ok && dst.Port() == port {
  57. return func(c net.Conn) error {
  58. b.handlePeerAPIConn(src, dst, c)
  59. return nil
  60. }, opts
  61. }
  62. if f, ok := hookTCPHandlerForServe.GetOk(); ok {
  63. if handler := f(b, dst.Port(), src, nil); handler != nil {
  64. return handler, opts
  65. }
  66. }
  67. return nil, nil
  68. }