netstack.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  1. // Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // Package netstack wires up gVisor's netstack into Tailscale.
  5. package netstack
  6. import (
  7. "context"
  8. "errors"
  9. "fmt"
  10. "io"
  11. "log"
  12. "net"
  13. "strconv"
  14. "strings"
  15. "sync"
  16. "sync/atomic"
  17. "time"
  18. "inet.af/netaddr"
  19. "inet.af/netstack/tcpip"
  20. "inet.af/netstack/tcpip/adapters/gonet"
  21. "inet.af/netstack/tcpip/buffer"
  22. "inet.af/netstack/tcpip/header"
  23. "inet.af/netstack/tcpip/link/channel"
  24. "inet.af/netstack/tcpip/network/ipv4"
  25. "inet.af/netstack/tcpip/network/ipv6"
  26. "inet.af/netstack/tcpip/stack"
  27. "inet.af/netstack/tcpip/transport/icmp"
  28. "inet.af/netstack/tcpip/transport/tcp"
  29. "inet.af/netstack/tcpip/transport/udp"
  30. "inet.af/netstack/waiter"
  31. "tailscale.com/net/packet"
  32. "tailscale.com/net/tsaddr"
  33. "tailscale.com/net/tstun"
  34. "tailscale.com/types/logger"
  35. "tailscale.com/types/netmap"
  36. "tailscale.com/util/dnsname"
  37. "tailscale.com/wgengine"
  38. "tailscale.com/wgengine/filter"
  39. "tailscale.com/wgengine/magicsock"
  40. )
  41. const debugNetstack = false
  42. // Impl contains the state for the netstack implementation,
  43. // and implements wgengine.FakeImpl to act as a userspace network
  44. // stack when Tailscale is running in fake mode.
  45. type Impl struct {
  46. // ForwardTCPIn, if non-nil, handles forwarding an inbound TCP
  47. // connection.
  48. // TODO(bradfitz): provide mechanism for tsnet to reject a
  49. // port other than accepting it and closing it.
  50. ForwardTCPIn func(c net.Conn, port uint16)
  51. ipstack *stack.Stack
  52. linkEP *channel.Endpoint
  53. tundev *tstun.Wrapper
  54. e wgengine.Engine
  55. mc *magicsock.Conn
  56. logf logger.Logf
  57. onlySubnets bool // whether we only want to handle subnet relaying
  58. // atomicIsLocalIPFunc holds a func that reports whether an IP
  59. // is a local (non-subnet) Tailscale IP address of this
  60. // machine. It's always a non-nil func. It's changed on netmap
  61. // updates.
  62. atomicIsLocalIPFunc atomic.Value // of func(netaddr.IP) bool
  63. mu sync.Mutex
  64. dns DNSMap
  65. // connsOpenBySubnetIP keeps track of number of connections open
  66. // for each subnet IP temporarily registered on netstack for active
  67. // TCP connections, so they can be unregistered when connections are
  68. // closed.
  69. connsOpenBySubnetIP map[netaddr.IP]int
  70. }
  71. const nicID = 1
  72. const mtu = 1500
  73. // Create creates and populates a new Impl.
  74. func Create(logf logger.Logf, tundev *tstun.Wrapper, e wgengine.Engine, mc *magicsock.Conn, onlySubnets bool) (*Impl, error) {
  75. if mc == nil {
  76. return nil, errors.New("nil magicsock.Conn")
  77. }
  78. if tundev == nil {
  79. return nil, errors.New("nil tundev")
  80. }
  81. if logf == nil {
  82. return nil, errors.New("nil logger")
  83. }
  84. if e == nil {
  85. return nil, errors.New("nil Engine")
  86. }
  87. ipstack := stack.New(stack.Options{
  88. NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocol},
  89. TransportProtocols: []stack.TransportProtocolFactory{tcp.NewProtocol, udp.NewProtocol, icmp.NewProtocol4, icmp.NewProtocol6},
  90. })
  91. linkEP := channel.New(512, mtu, "")
  92. if tcpipProblem := ipstack.CreateNIC(nicID, linkEP); tcpipProblem != nil {
  93. return nil, fmt.Errorf("could not create netstack NIC: %v", tcpipProblem)
  94. }
  95. // By default the netstack NIC will only accept packets for the IPs
  96. // registered to it. Since in some cases we dynamically register IPs
  97. // based on the packets that arrive, the NIC needs to accept all
  98. // incoming packets. The NIC won't receive anything it isn't meant to
  99. // since Wireguard will only send us packets that are meant for us.
  100. ipstack.SetPromiscuousMode(nicID, true)
  101. // Add IPv4 and IPv6 default routes, so all incoming packets from the Tailscale side
  102. // are handled by the one fake NIC we use.
  103. ipv4Subnet, _ := tcpip.NewSubnet(tcpip.Address(strings.Repeat("\x00", 4)), tcpip.AddressMask(strings.Repeat("\x00", 4)))
  104. ipv6Subnet, _ := tcpip.NewSubnet(tcpip.Address(strings.Repeat("\x00", 16)), tcpip.AddressMask(strings.Repeat("\x00", 16)))
  105. ipstack.SetRouteTable([]tcpip.Route{
  106. {
  107. Destination: ipv4Subnet,
  108. NIC: nicID,
  109. },
  110. {
  111. Destination: ipv6Subnet,
  112. NIC: nicID,
  113. },
  114. })
  115. ns := &Impl{
  116. logf: logf,
  117. ipstack: ipstack,
  118. linkEP: linkEP,
  119. tundev: tundev,
  120. e: e,
  121. mc: mc,
  122. connsOpenBySubnetIP: make(map[netaddr.IP]int),
  123. onlySubnets: onlySubnets,
  124. }
  125. ns.atomicIsLocalIPFunc.Store(tsaddr.NewContainsIPFunc(nil))
  126. return ns, nil
  127. }
  128. // Start sets up all the handlers so netstack can start working. Implements
  129. // wgengine.FakeImpl.
  130. func (ns *Impl) Start() error {
  131. ns.e.AddNetworkMapCallback(ns.updateIPs)
  132. // size = 0 means use default buffer size
  133. const tcpReceiveBufferSize = 0
  134. const maxInFlightConnectionAttempts = 16
  135. tcpFwd := tcp.NewForwarder(ns.ipstack, tcpReceiveBufferSize, maxInFlightConnectionAttempts, ns.acceptTCP)
  136. udpFwd := udp.NewForwarder(ns.ipstack, ns.acceptUDP)
  137. ns.ipstack.SetTransportProtocolHandler(tcp.ProtocolNumber, func(tei stack.TransportEndpointID, pb *stack.PacketBuffer) bool {
  138. addr := tei.LocalAddress
  139. var pn tcpip.NetworkProtocolNumber
  140. if addr.To4() != "" {
  141. pn = ipv4.ProtocolNumber
  142. } else {
  143. pn = ipv6.ProtocolNumber
  144. }
  145. ip, ok := netaddr.FromStdIP(net.IP(addr))
  146. if !ok {
  147. ns.logf("netstack: could not parse local address %s for incoming TCP connection", ip)
  148. return false
  149. }
  150. if !ns.isLocalIP(ip) {
  151. ns.addSubnetAddress(pn, ip)
  152. }
  153. return tcpFwd.HandlePacket(tei, pb)
  154. })
  155. ns.ipstack.SetTransportProtocolHandler(udp.ProtocolNumber, udpFwd.HandlePacket)
  156. go ns.injectOutbound()
  157. ns.tundev.PostFilterIn = ns.injectInbound
  158. return nil
  159. }
  160. // DNSMap maps MagicDNS names (both base + FQDN) to their first IP.
  161. // It should not be mutated once created.
  162. type DNSMap map[string]netaddr.IP
  163. func DNSMapFromNetworkMap(nm *netmap.NetworkMap) DNSMap {
  164. ret := make(DNSMap)
  165. suffix := nm.MagicDNSSuffix()
  166. if nm.Name != "" && len(nm.Addresses) > 0 {
  167. ip := nm.Addresses[0].IP()
  168. ret[strings.TrimRight(nm.Name, ".")] = ip
  169. if dnsname.HasSuffix(nm.Name, suffix) {
  170. ret[dnsname.TrimSuffix(nm.Name, suffix)] = ip
  171. }
  172. }
  173. for _, p := range nm.Peers {
  174. if p.Name != "" && len(p.Addresses) > 0 {
  175. ip := p.Addresses[0].IP()
  176. ret[strings.TrimRight(p.Name, ".")] = ip
  177. if dnsname.HasSuffix(p.Name, suffix) {
  178. ret[dnsname.TrimSuffix(p.Name, suffix)] = ip
  179. }
  180. }
  181. }
  182. return ret
  183. }
  184. func (ns *Impl) updateDNS(nm *netmap.NetworkMap) {
  185. ns.mu.Lock()
  186. defer ns.mu.Unlock()
  187. ns.dns = DNSMapFromNetworkMap(nm)
  188. }
  189. func (ns *Impl) addSubnetAddress(pn tcpip.NetworkProtocolNumber, ip netaddr.IP) {
  190. ns.mu.Lock()
  191. ns.connsOpenBySubnetIP[ip]++
  192. needAdd := ns.connsOpenBySubnetIP[ip] == 1
  193. ns.mu.Unlock()
  194. // Only register address into netstack for first concurrent connection.
  195. if needAdd {
  196. ns.ipstack.AddAddress(nicID, pn, tcpip.Address(ip.IPAddr().IP))
  197. }
  198. }
  199. func (ns *Impl) removeSubnetAddress(ip netaddr.IP) {
  200. ns.mu.Lock()
  201. defer ns.mu.Unlock()
  202. ns.connsOpenBySubnetIP[ip]--
  203. // Only unregister address from netstack after last concurrent connection.
  204. if ns.connsOpenBySubnetIP[ip] == 0 {
  205. ns.ipstack.RemoveAddress(nicID, tcpip.Address(ip.IPAddr().IP))
  206. delete(ns.connsOpenBySubnetIP, ip)
  207. }
  208. }
  209. func ipPrefixToAddressWithPrefix(ipp netaddr.IPPrefix) tcpip.AddressWithPrefix {
  210. return tcpip.AddressWithPrefix{
  211. Address: tcpip.Address(ipp.IP().IPAddr().IP),
  212. PrefixLen: int(ipp.Bits()),
  213. }
  214. }
  215. func (ns *Impl) updateIPs(nm *netmap.NetworkMap) {
  216. ns.atomicIsLocalIPFunc.Store(tsaddr.NewContainsIPFunc(nm.Addresses))
  217. ns.updateDNS(nm)
  218. oldIPs := make(map[tcpip.AddressWithPrefix]bool)
  219. for _, protocolAddr := range ns.ipstack.AllAddresses()[nicID] {
  220. oldIPs[protocolAddr.AddressWithPrefix] = true
  221. }
  222. newIPs := make(map[tcpip.AddressWithPrefix]bool)
  223. isAddr := map[netaddr.IPPrefix]bool{}
  224. for _, ipp := range nm.SelfNode.Addresses {
  225. isAddr[ipp] = true
  226. }
  227. for _, ipp := range nm.SelfNode.AllowedIPs {
  228. if ns.onlySubnets && isAddr[ipp] {
  229. continue
  230. }
  231. newIPs[ipPrefixToAddressWithPrefix(ipp)] = true
  232. }
  233. ipsToBeAdded := make(map[tcpip.AddressWithPrefix]bool)
  234. for ipp := range newIPs {
  235. if !oldIPs[ipp] {
  236. ipsToBeAdded[ipp] = true
  237. }
  238. }
  239. ipsToBeRemoved := make(map[tcpip.AddressWithPrefix]bool)
  240. for ip := range oldIPs {
  241. if !newIPs[ip] {
  242. ipsToBeRemoved[ip] = true
  243. }
  244. }
  245. ns.mu.Lock()
  246. for ip := range ns.connsOpenBySubnetIP {
  247. ipp := tcpip.Address(ip.IPAddr().IP).WithPrefix()
  248. delete(ipsToBeRemoved, ipp)
  249. }
  250. ns.mu.Unlock()
  251. for ipp := range ipsToBeRemoved {
  252. err := ns.ipstack.RemoveAddress(nicID, ipp.Address)
  253. if err != nil {
  254. ns.logf("netstack: could not deregister IP %s: %v", ipp, err)
  255. } else {
  256. ns.logf("[v2] netstack: deregistered IP %s", ipp)
  257. }
  258. }
  259. for ipp := range ipsToBeAdded {
  260. var err tcpip.Error
  261. if ipp.Address.To4() == "" {
  262. err = ns.ipstack.AddAddressWithPrefix(nicID, ipv6.ProtocolNumber, ipp)
  263. } else {
  264. err = ns.ipstack.AddAddressWithPrefix(nicID, ipv4.ProtocolNumber, ipp)
  265. }
  266. if err != nil {
  267. ns.logf("netstack: could not register IP %s: %v", ipp, err)
  268. } else {
  269. ns.logf("[v2] netstack: registered IP %s", ipp)
  270. }
  271. }
  272. }
  273. // Resolve resolves addr into an IP:port using first the MagicDNS contents
  274. // of m, else using the system resolver.
  275. func (m DNSMap) Resolve(ctx context.Context, addr string) (netaddr.IPPort, error) {
  276. ipp, pippErr := netaddr.ParseIPPort(addr)
  277. if pippErr == nil {
  278. return ipp, nil
  279. }
  280. host, port, err := net.SplitHostPort(addr)
  281. if err != nil {
  282. // addr is malformed.
  283. return netaddr.IPPort{}, err
  284. }
  285. if net.ParseIP(host) != nil {
  286. // The host part of addr was an IP, so the netaddr.ParseIPPort above should've
  287. // passed. Must've been a bad port number. Return the original error.
  288. return netaddr.IPPort{}, pippErr
  289. }
  290. port16, err := strconv.ParseUint(port, 10, 16)
  291. if err != nil {
  292. return netaddr.IPPort{}, fmt.Errorf("invalid port in address %q", addr)
  293. }
  294. // Host is not an IP, so assume it's a DNS name.
  295. // Try MagicDNS first, else otherwise a real DNS lookup.
  296. ip := m[host]
  297. if !ip.IsZero() {
  298. return netaddr.IPPortFrom(ip, uint16(port16)), nil
  299. }
  300. // No MagicDNS name so try real DNS.
  301. var r net.Resolver
  302. ips, err := r.LookupIP(ctx, "ip", host)
  303. if err != nil {
  304. return netaddr.IPPort{}, err
  305. }
  306. if len(ips) == 0 {
  307. return netaddr.IPPort{}, fmt.Errorf("DNS lookup returned no results for %q", host)
  308. }
  309. ip, _ = netaddr.FromStdIP(ips[0])
  310. return netaddr.IPPortFrom(ip, uint16(port16)), nil
  311. }
  312. func (ns *Impl) DialContextTCP(ctx context.Context, addr string) (*gonet.TCPConn, error) {
  313. ns.mu.Lock()
  314. dnsMap := ns.dns
  315. ns.mu.Unlock()
  316. remoteIPPort, err := dnsMap.Resolve(ctx, addr)
  317. if err != nil {
  318. return nil, err
  319. }
  320. remoteAddress := tcpip.FullAddress{
  321. NIC: nicID,
  322. Addr: tcpip.Address(remoteIPPort.IP().IPAddr().IP),
  323. Port: remoteIPPort.Port(),
  324. }
  325. var ipType tcpip.NetworkProtocolNumber
  326. if remoteIPPort.IP().Is4() {
  327. ipType = ipv4.ProtocolNumber
  328. } else {
  329. ipType = ipv6.ProtocolNumber
  330. }
  331. return gonet.DialContextTCP(ctx, ns.ipstack, remoteAddress, ipType)
  332. }
  333. func (ns *Impl) injectOutbound() {
  334. for {
  335. packetInfo, ok := ns.linkEP.ReadContext(context.Background())
  336. if !ok {
  337. ns.logf("[v2] ReadContext-for-write = ok=false")
  338. continue
  339. }
  340. pkt := packetInfo.Pkt
  341. hdrNetwork := pkt.NetworkHeader()
  342. hdrTransport := pkt.TransportHeader()
  343. full := make([]byte, 0, pkt.Size())
  344. full = append(full, hdrNetwork.View()...)
  345. full = append(full, hdrTransport.View()...)
  346. full = append(full, pkt.Data().AsRange().AsView()...)
  347. if debugNetstack {
  348. ns.logf("[v2] packet Write out: % x", full)
  349. }
  350. if err := ns.tundev.InjectOutbound(full); err != nil {
  351. log.Printf("netstack inject outbound: %v", err)
  352. return
  353. }
  354. }
  355. }
  356. // isLocalIP reports whether ip is a Tailscale IP assigned to this
  357. // node directly (but not a subnet-routed IP).
  358. func (ns *Impl) isLocalIP(ip netaddr.IP) bool {
  359. return ns.atomicIsLocalIPFunc.Load().(func(netaddr.IP) bool)(ip)
  360. }
  361. func (ns *Impl) injectInbound(p *packet.Parsed, t *tstun.Wrapper) filter.Response {
  362. if ns.onlySubnets && ns.isLocalIP(p.Dst.IP()) {
  363. // In hybrid ("only subnets") mode, bail out early if
  364. // the traffic is destined for an actual Tailscale
  365. // address. The real host OS interface will handle it.
  366. return filter.Accept
  367. }
  368. var pn tcpip.NetworkProtocolNumber
  369. switch p.IPVersion {
  370. case 4:
  371. pn = header.IPv4ProtocolNumber
  372. case 6:
  373. pn = header.IPv6ProtocolNumber
  374. }
  375. if debugNetstack {
  376. ns.logf("[v2] packet in (from %v): % x", p.Src, p.Buffer())
  377. }
  378. vv := buffer.View(append([]byte(nil), p.Buffer()...)).ToVectorisedView()
  379. packetBuf := stack.NewPacketBuffer(stack.PacketBufferOptions{
  380. Data: vv,
  381. })
  382. ns.linkEP.InjectInbound(pn, packetBuf)
  383. // We've now delivered this to netstack, so we're done.
  384. // Instead of returning a filter.Accept here (which would also
  385. // potentially deliver it to the host OS), and instead of
  386. // filter.Drop (which would log about rejected traffic),
  387. // instead return filter.DropSilently which just quietly stops
  388. // processing it in the tstun TUN wrapper.
  389. return filter.DropSilently
  390. }
  391. func (ns *Impl) acceptTCP(r *tcp.ForwarderRequest) {
  392. reqDetails := r.ID()
  393. if debugNetstack {
  394. ns.logf("[v2] TCP ForwarderRequest: %s", stringifyTEI(reqDetails))
  395. }
  396. dialAddr := reqDetails.LocalAddress
  397. dialNetAddr, _ := netaddr.FromStdIP(net.IP(dialAddr))
  398. isTailscaleIP := tsaddr.IsTailscaleIP(dialNetAddr)
  399. defer func() {
  400. if !isTailscaleIP {
  401. // if this is a subnet IP, we added this in before the TCP handshake
  402. // so netstack is happy TCP-handshaking as a subnet IP
  403. ns.removeSubnetAddress(dialNetAddr)
  404. }
  405. }()
  406. var wq waiter.Queue
  407. ep, err := r.CreateEndpoint(&wq)
  408. if err != nil {
  409. r.Complete(true)
  410. return
  411. }
  412. r.Complete(false)
  413. c := gonet.NewTCPConn(&wq, ep)
  414. if ns.ForwardTCPIn != nil {
  415. ns.ForwardTCPIn(c, reqDetails.LocalPort)
  416. return
  417. }
  418. if isTailscaleIP {
  419. dialAddr = tcpip.Address(net.ParseIP("127.0.0.1")).To4()
  420. }
  421. ns.forwardTCP(c, &wq, dialAddr, reqDetails.LocalPort)
  422. }
  423. func (ns *Impl) forwardTCP(client *gonet.TCPConn, wq *waiter.Queue, dialAddr tcpip.Address, dialPort uint16) {
  424. defer client.Close()
  425. dialAddrStr := net.JoinHostPort(dialAddr.String(), strconv.Itoa(int(dialPort)))
  426. ns.logf("[v2] netstack: forwarding incoming connection to %s", dialAddrStr)
  427. ctx, cancel := context.WithCancel(context.Background())
  428. defer cancel()
  429. waitEntry, notifyCh := waiter.NewChannelEntry(nil)
  430. wq.EventRegister(&waitEntry, waiter.EventHUp)
  431. defer wq.EventUnregister(&waitEntry)
  432. done := make(chan bool)
  433. // netstack doesn't close the notification channel automatically if there was no
  434. // hup signal, so we close done after we're done to not leak the goroutine below.
  435. defer close(done)
  436. go func() {
  437. select {
  438. case <-notifyCh:
  439. case <-done:
  440. }
  441. cancel()
  442. }()
  443. var stdDialer net.Dialer
  444. server, err := stdDialer.DialContext(ctx, "tcp", dialAddrStr)
  445. if err != nil {
  446. ns.logf("netstack: could not connect to local server at %s: %v", dialAddrStr, err)
  447. return
  448. }
  449. defer server.Close()
  450. backendLocalAddr := server.LocalAddr().(*net.TCPAddr)
  451. backendLocalIPPort, _ := netaddr.FromStdAddr(backendLocalAddr.IP, backendLocalAddr.Port, backendLocalAddr.Zone)
  452. clientRemoteIP, _ := netaddr.FromStdIP(client.RemoteAddr().(*net.TCPAddr).IP)
  453. ns.e.RegisterIPPortIdentity(backendLocalIPPort, clientRemoteIP)
  454. defer ns.e.UnregisterIPPortIdentity(backendLocalIPPort)
  455. connClosed := make(chan error, 2)
  456. go func() {
  457. _, err := io.Copy(server, client)
  458. connClosed <- err
  459. }()
  460. go func() {
  461. _, err := io.Copy(client, server)
  462. connClosed <- err
  463. }()
  464. err = <-connClosed
  465. if err != nil {
  466. ns.logf("proxy connection closed with error: %v", err)
  467. }
  468. ns.logf("[v2] netstack: forwarder connection to %s closed", dialAddrStr)
  469. }
  470. func (ns *Impl) acceptUDP(r *udp.ForwarderRequest) {
  471. reqDetails := r.ID()
  472. if debugNetstack {
  473. ns.logf("[v2] UDP ForwarderRequest: %v", stringifyTEI(reqDetails))
  474. }
  475. var wq waiter.Queue
  476. ep, err := r.CreateEndpoint(&wq)
  477. if err != nil {
  478. ns.logf("acceptUDP: could not create endpoint: %v", err)
  479. return
  480. }
  481. localAddr, err := ep.GetLocalAddress()
  482. if err != nil {
  483. return
  484. }
  485. remoteAddr, err := ep.GetRemoteAddress()
  486. if err != nil {
  487. return
  488. }
  489. c := gonet.NewUDPConn(ns.ipstack, &wq, ep)
  490. go ns.forwardUDP(c, &wq, localAddr, remoteAddr)
  491. }
  492. func (ns *Impl) forwardUDP(client *gonet.UDPConn, wq *waiter.Queue, clientLocalAddr, clientRemoteAddr tcpip.FullAddress) {
  493. port := clientLocalAddr.Port
  494. ns.logf("[v2] netstack: forwarding incoming UDP connection on port %v", port)
  495. backendListenAddr := &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: int(clientRemoteAddr.Port)}
  496. backendRemoteAddr := &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: int(port)}
  497. backendConn, err := net.ListenUDP("udp4", backendListenAddr)
  498. if err != nil {
  499. ns.logf("netstack: could not bind local port %v: %v, trying again with random port", clientRemoteAddr.Port, err)
  500. backendListenAddr.Port = 0
  501. backendConn, err = net.ListenUDP("udp4", backendListenAddr)
  502. if err != nil {
  503. ns.logf("netstack: could not connect to local UDP server on port %v: %v", port, err)
  504. return
  505. }
  506. }
  507. backendLocalAddr := backendConn.LocalAddr().(*net.UDPAddr)
  508. backendLocalIPPort, ok := netaddr.FromStdAddr(backendListenAddr.IP, backendLocalAddr.Port, backendLocalAddr.Zone)
  509. if !ok {
  510. ns.logf("could not get backend local IP:port from %v:%v", backendLocalAddr.IP, backendLocalAddr.Port)
  511. }
  512. clientRemoteIP, _ := netaddr.FromStdIP(net.ParseIP(clientRemoteAddr.Addr.String()))
  513. ns.e.RegisterIPPortIdentity(backendLocalIPPort, clientRemoteIP)
  514. ctx, cancel := context.WithCancel(context.Background())
  515. timer := time.AfterFunc(2*time.Minute, func() {
  516. ns.e.UnregisterIPPortIdentity(backendLocalIPPort)
  517. ns.logf("netstack: UDP session between %s and %s timed out", clientRemoteAddr, backendRemoteAddr)
  518. cancel()
  519. client.Close()
  520. backendConn.Close()
  521. })
  522. extend := func() {
  523. timer.Reset(2 * time.Minute)
  524. }
  525. startPacketCopy(ctx, cancel, client, &net.UDPAddr{
  526. IP: net.ParseIP(clientRemoteAddr.Addr.String()),
  527. Port: int(clientRemoteAddr.Port),
  528. }, backendConn, ns.logf, extend)
  529. startPacketCopy(ctx, cancel, backendConn, backendRemoteAddr, client, ns.logf, extend)
  530. }
  531. func startPacketCopy(ctx context.Context, cancel context.CancelFunc, dst net.PacketConn, dstAddr net.Addr, src net.PacketConn, logf logger.Logf, extend func()) {
  532. go func() {
  533. defer cancel() // tear down the other direction's copy
  534. pkt := make([]byte, mtu)
  535. for {
  536. select {
  537. case <-ctx.Done():
  538. return
  539. default:
  540. n, srcAddr, err := src.ReadFrom(pkt)
  541. if err != nil {
  542. if ctx.Err() == nil {
  543. logf("read packet from %s failed: %v", srcAddr, err)
  544. }
  545. return
  546. }
  547. _, err = dst.WriteTo(pkt[:n], dstAddr)
  548. if err != nil {
  549. if ctx.Err() == nil {
  550. logf("write packet to %s failed: %v", dstAddr, err)
  551. }
  552. return
  553. }
  554. if debugNetstack {
  555. logf("[v2] wrote UDP packet %s -> %s", srcAddr, dstAddr)
  556. }
  557. extend()
  558. }
  559. }
  560. }()
  561. }
  562. func stringifyTEI(tei stack.TransportEndpointID) string {
  563. localHostPort := net.JoinHostPort(tei.LocalAddress.String(), strconv.Itoa(int(tei.LocalPort)))
  564. remoteHostPort := net.JoinHostPort(tei.RemoteAddress.String(), strconv.Itoa(int(tei.RemotePort)))
  565. return fmt.Sprintf("%s -> %s", remoteHostPort, localHostPort)
  566. }