2023-01-27 13:37:20 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// Copyright (c) Tailscale Inc & AUTHORS 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// SPDX-License-Identifier: BSD-3-Clause 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// Package magicsock implements a socket that can change its communication path while 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// in use, actively searching for the best way to communicate. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								package  magicsock 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								import  ( 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-31 15:29:04 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"bufio" 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-06 19:20:15 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"bytes" 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									"context" 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-30 13:31:35 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"encoding/binary" 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-18 13:32:04 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"errors" 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-25 17:20:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"expvar" 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									"fmt" 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-29 10:57:54 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"io" 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									"net" 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-15 15:33:06 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"net/netip" 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-23 18:50:55 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"reflect" 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-20 12:14:19 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"runtime" 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-12 19:14:04 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"slices" 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-21 14:01:51 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"strconv" 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									"strings" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									"sync" 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-18 08:57:11 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"sync/atomic" 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									"time" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-12-09 15:12:20 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"github.com/tailscale/wireguard-go/conn" 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-28 11:07:25 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"go4.org/mem" 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 17:58:14 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"golang.org/x/net/ipv6" 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-02 11:09:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 12:03:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/control/controlknobs" 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-30 12:22:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/disco" 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-20 19:29:25 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/envknob" 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-24 21:29:51 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/health" 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-20 10:17:21 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/hostinfo" 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-25 22:57:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/ipn/ipnstate" 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-28 15:59:33 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/net/connstats" 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-25 09:15:50 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/net/netcheck" 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-30 11:11:50 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/net/neterror" 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-18 14:26:58 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/net/netmon" 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-28 15:27:04 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/net/netns" 
							 
						 
					
						
							
								
									
										
										
										
											2023-03-30 12:39:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/net/packet" 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-02 17:49:56 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/net/ping" 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-19 22:15:41 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/net/portmapper" 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-03 12:07:58 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/net/sockstats" 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-25 09:15:50 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/net/stun" 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-07 08:10:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/net/tstun" 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-12 11:16:54 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/syncs" 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-03 22:21:56 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/tailcfg" 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 09:52:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/tstime" 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-21 11:04:36 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/tstime/mono" 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-17 13:52:11 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/types/key" 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-02 17:49:56 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/types/lazy" 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-03 22:21:56 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/types/logger" 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-05 15:44:46 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/types/netmap" 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-10 14:26:04 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/types/nettype" 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 19:17:24 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/types/views" 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-13 18:51:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/util/clientmetric" 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-19 20:28:19 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/util/eventbus" 
							 
						 
					
						
							
								
									
										
										
										
											2022-04-21 20:25:24 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/util/mak" 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-21 15:57:08 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/util/ringbuffer" 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-09 09:55:57 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/util/set" 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 10:13:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/util/testenv" 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-23 18:34:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/util/usermetric" 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-16 08:42:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/wgengine/filter" 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-28 07:33:15 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									"tailscale.com/wgengine/wgint" 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-08-29 10:57:54 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								const  ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// These are disco.Magic in big-endian form, 4 then 2 bytes. The 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// BPF filters need the magic in this format to match on it. Used 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// only in magicsock_linux.go, but defined here so that the test 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// which verifies this is the correct magic doesn't also need a 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// _linux variant. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									discoMagic1  =  0x5453f09f 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									discoMagic2  =  0x92ac 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 15:49:59 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// UDP socket read/write buffer size (7MB). The value of 7MB is chosen as it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// is the max supported by a default configuration of macOS. Some platforms 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// will silently clamp the value. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									socketBufferSize  =  7  <<  20 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-29 10:57:54 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-25 17:20:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// Path is a label indicating the type of path a packet took. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								type  Path  string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								const  ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									PathDirectIPv4  Path  =  "direct_ipv4" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									PathDirectIPv6  Path  =  "direct_ipv6" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									PathDERP        Path  =  "derp" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								type  pathLabel  struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Path indicates the path that the packet took: 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// - direct_ipv4 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// - direct_ipv6 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// - derp 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									Path  Path 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// metrics in wgengine contains the usermetrics counters for magicsock, it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// is however a bit special. All them metrics are labeled, but looking up 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// the metric everytime we need to record it has an overhead, and includes 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// a lock in MultiLabelMap. The metrics are therefore instead created with 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// wgengine and the underlying expvar.Int is stored to be used directly. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								type  metrics  struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// inboundPacketsTotal is the total number of inbound packets received, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// labeled by the path the packet took. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									inboundPacketsIPv4Total  expvar . Int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									inboundPacketsIPv6Total  expvar . Int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									inboundPacketsDERPTotal  expvar . Int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// inboundBytesTotal is the total number of inbound bytes received, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// labeled by the path the packet took. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									inboundBytesIPv4Total  expvar . Int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									inboundBytesIPv6Total  expvar . Int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									inboundBytesDERPTotal  expvar . Int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// outboundPacketsTotal is the total number of outbound packets sent, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// labeled by the path the packet took. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									outboundPacketsIPv4Total  expvar . Int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									outboundPacketsIPv6Total  expvar . Int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									outboundPacketsDERPTotal  expvar . Int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// outboundBytesTotal is the total number of outbound bytes sent, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// labeled by the path the packet took. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									outboundBytesIPv4Total  expvar . Int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									outboundBytesIPv6Total  expvar . Int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									outboundBytesDERPTotal  expvar . Int 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-29 09:19:40 +00:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// outboundPacketsDroppedErrors is the total number of outbound packets 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// dropped due to errors. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									outboundPacketsDroppedErrors  expvar . Int 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-25 17:20:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								// A Conn routes UDP packets and actively manages a list of its endpoints. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								type  Conn  struct  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-14 23:58:35 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// This block mirrors the contents and field order of the Options 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// struct. Initialized once at construction, then constant. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-19 20:28:19 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									eventBus                * eventbus . Bus 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-24 09:47:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									eventClient             * eventbus . Client 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 22:26:25 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									logf                    logger . Logf 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									epFunc                  func ( [ ] tailcfg . Endpoint ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									derpActiveFunc          func ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									idleFunc                func ( )  time . Duration  // nil means unknown 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									testOnlyPacketListener  nettype . PacketListener 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-01 17:53:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									noteRecvActivity        func ( key . NodePublic )  // or nil, see Options.NoteRecvActivity 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-26 18:28:01 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									netMon                  * netmon . Monitor       // must be non-nil 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-26 08:06:06 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									health                  * health . Tracker       // or nil 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 12:03:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									controlKnobs            * controlknobs . Knobs   // or nil 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-18 10:55:25 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-14 23:58:35 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// ================================================================ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// No locking required to access these fields, either because 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// they're static after construction, or are wholly owned by a 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// single goroutine. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									connCtx        context . Context  // closed on Conn.Close 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									connCtxCancel  func ( )           // closes connCtx 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-15 19:13:59 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									donec          <- chan  struct { }  // connCtx.Done()'s to avoid context.cancelCtx.Done()'s mutex per call 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-14 23:58:35 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// pconn4 and pconn6 are the underlying UDP sockets used to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// send/receive packets for wireguard and other magicsock 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// protocols. 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-02 14:24:51 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									pconn4  RebindingUDPConn 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									pconn6  RebindingUDPConn 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-14 23:58:35 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 17:58:14 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									receiveBatchPool  sync . Pool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-08-29 10:57:54 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// closeDisco4 and closeDisco6 are io.Closers to shut down the raw 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// disco packet receivers. If nil, no raw disco receiver is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// running for the given family. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									closeDisco4  io . Closer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									closeDisco6  io . Closer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-14 23:58:35 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// netChecker is the prober that discovers local network 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// conditions, including the closest DERP relay and NAT mappings. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									netChecker  * netcheck . Client 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-02-19 22:15:41 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// portMapper is the NAT-PMP/PCP/UPnP prober/client, for requesting 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// port mappings from NAT devices. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									portMapper  * portmapper . Client 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-12 17:04:57 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// portMapperLogfUnregister is the function to call to unregister 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// the portmapper log limiter. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									portMapperLogfUnregister  func ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-24 09:41:57 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// derpRecvCh is used by receiveDERP to read DERP messages. 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-14 13:43:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// It must have buffer size > 0; see issue 3736. 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									derpRecvCh  chan  derpReadResult 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-24 09:41:57 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// bind is the wireguard-go conn.Bind for Conn. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									bind  * connBind 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-18 08:39:52 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-07-10 16:46:31 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// cloudInfo is used to query cloud metadata services. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									cloudInfo  * cloudInfo 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-26 14:38:53 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// ============================================================ 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-22 13:00:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// Fields that must be accessed via atomic load/stores. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// noV4 and noV6 are whether IPv4 and IPv6 are known to be 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// missing.  They're only used to suppress log spam. The name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// is named negatively because in early start-up, we don't yet 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// necessarily have a netcheck.Report and don't want to skip 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// logging. 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-03 21:51:02 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									noV4 ,  noV6  atomic . Bool 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-22 13:00:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-11-13 10:05:04 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									silentDiscoOn  atomic . Bool  // whether silent disco is enabled 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-01-23 09:37:32 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									probeUDPLifetimeOn  atomic . Bool  // whether probing of UDP lifetime is enabled 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-10-07 09:43:37 +09:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// noV4Send is whether IPv4 UDP is known to be unable to transmit 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// at all. This could happen if the socket is in an invalid state 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// (as can happen on darwin after a network link status change). 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-03 21:51:02 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									noV4Send  atomic . Bool 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-07 09:43:37 +09:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-06-22 13:00:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// networkUp is whether the network is up (some interface is up 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// with IPv4 or IPv6). It's used to suppress log spam and prevent 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// new connection that'll fail. 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-03 21:51:02 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									networkUp  atomic . Bool 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-22 13:00:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-10-03 20:39:45 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// Whether debugging logging is enabled. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									debugLogging  atomic . Bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-06-22 13:00:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// havePrivateKey is whether privateKey is non-zero. 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-03 21:51:02 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									havePrivateKey   atomic . Bool 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-04 10:43:49 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									publicKeyAtomic  syncs . AtomicValue [ key . NodePublic ]  // or NodeKey zero value if !havePrivateKey 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-22 13:00:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-13 13:37:26 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// derpMapAtomic is the same as derpMap, but without requiring 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// sync.Mutex. For use with NewRegionClient's callback, to avoid 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// lock ordering deadlocks. See issue 3726 and mu field docs. 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-03 21:31:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									derpMapAtomic  atomic . Pointer [ tailcfg . DERPMap ] 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-13 13:37:26 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-08-03 21:31:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									lastNetCheckReport  atomic . Pointer [ netcheck . Report ] 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-29 14:52:00 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-06-22 13:00:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// port is the preferred port from opts.Port; 0 means auto. 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-03 21:51:02 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									port  atomic . Uint32 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-22 13:00:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-18 21:21:46 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// peerMTUEnabled is whether path MTU discovery to peers is enabled. 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-21 19:40:03 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									//lint:ignore U1000 used on Linux/Darwin only 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-18 21:21:46 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									peerMTUEnabled  atomic . Bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-10-27 16:26:52 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// stats maintains per-connection counters. 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-28 15:59:33 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									stats  atomic . Pointer [ connstats . Statistics ] 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-27 16:26:52 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-08 15:48:27 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// captureHook, if non-nil, is the pcap logging callback when capturing. 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-23 20:39:28 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									captureHook  syncs . AtomicValue [ packet . CaptureCallback ] 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-08 15:48:27 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-09 16:59:18 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// discoPrivate is the private naclbox key used for active 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// discovery traffic. It is always present, and immutable. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									discoPrivate  key . DiscoPrivate 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// public of discoPrivate. It is always present and immutable. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									discoPublic  key . DiscoPublic 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// ShortString of discoPublic (to save logging work later). It is always 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// present and immutable. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									discoShort  string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-06-22 13:00:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// ============================================================ 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-13 13:37:26 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// mu guards all following fields; see userspaceEngine lock 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// ordering rules against the engine. For derphttp, mu must 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// be held before derphttp.Client.mu. 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-22 13:00:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									mu      sync . Mutex 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-04 09:36:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									muCond  * sync . Cond 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-22 14:18:04 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									onlyTCP443  atomic . Bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-17 18:54:03 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									closed   bool         // Close was called 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									closing  atomic . Bool  // Close is in progress (or done) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-19 15:29:50 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// derpCleanupTimer is the timer that fires to occasionally clean 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// up idle DERP connections. It's only used when there is a non-home 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// DERP connection in use. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									derpCleanupTimer  * time . Timer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// derpCleanupTimerArmed is whether derpCleanupTimer is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// scheduled to fire within derpCleanStaleInterval. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									derpCleanupTimerArmed  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 09:52:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// periodicReSTUNTimer, when non-nil, is an AfterFunc timer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// that will call Conn.doPeriodicSTUN. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									periodicReSTUNTimer  * time . Timer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-14 23:58:35 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// endpointsUpdateActive indicates that updateEndpoints is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// currently running. It's used to deduplicate concurrent endpoint 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// update requests. 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									endpointsUpdateActive  bool 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-14 23:58:35 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// wantEndpointsUpdate, if non-empty, means that a new endpoints 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// update should begin immediately after the currently-running one 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// completes. It can only be non-empty if 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// endpointsUpdateActive==true. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									wantEndpointsUpdate  string  // true if non-empty; string is reason 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// lastEndpoints records the endpoints found during the previous 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// endpoint discovery. It's used to avoid duplicate endpoint 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// change notifications. 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												tailcfg: add Endpoint, EndpointType, MapRequest.EndpointType
Track endpoints internally with a new tailcfg.Endpoint type that
includes a typed netaddr.IPPort (instead of just a string) and
includes a type for how that endpoint was discovered (STUN, local,
etc).
Use []tailcfg.Endpoint instead of []string internally.
At the last second, send it to the control server as the existing
[]string for endpoints, but also include a new parallel
MapRequest.EndpointType []tailcfg.EndpointType, so the control server
can start filtering out less-important endpoint changes from
new-enough clients. Notably, STUN-discovered endpoints can be filtered
out from 1.6+ clients, as they can discover them amongst each other
via CallMeMaybe disco exchanges started over DERP. And STUN endpoints
change a lot, causing a lot of MapResposne updates. But portmapped
endpoints are worth keeping for now, as they they work right away
without requiring the firewall traversal extra RTT dance.
End result will be less control->client bandwidth. (despite negligible
increase in client->control bandwidth)
Updates tailscale/corp#1543
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2021-04-12 13:24:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									lastEndpoints  [ ] tailcfg . Endpoint 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-14 23:58:35 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 09:52:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// lastEndpointsTime is the last time the endpoints were updated, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// even if there was no change. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									lastEndpointsTime  time . Time 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// onEndpointRefreshed are funcs to run (in their own goroutines) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// when endpoints are refreshed. 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 22:20:31 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									onEndpointRefreshed  map [ * endpoint ] func ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 09:52:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-14 16:37:10 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// endpointTracker tracks the set of cached endpoints that we advertise 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// for a period of time before withdrawing them. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									endpointTracker  endpointTracker 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-14 23:58:35 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// peerSet is the set of peers that are currently configured in 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// WireGuard. These are not used to filter inbound or outbound 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// traffic at all, but only to track what state can be cleaned up 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// in other maps below that are keyed by peer public key. 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-09 09:55:57 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									peerSet  set . Set [ key . NodePublic ] 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-14 23:58:35 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 10:13:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// peerMap tracks the networkmap Node entity for each peer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// by node key, node ID, and discovery key. 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 19:39:20 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									peerMap  peerMap 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 20:45:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-05-02 13:08:17 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// relayManager manages allocation and handshaking of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// [tailscale.com/net/udprelay.Server] endpoints. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									relayManager  relayManager 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// discoInfo is the state for an active peer DiscoKey. 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-29 14:27:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									discoInfo  map [ key . DiscoPublic ] * discoInfo 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-14 23:58:35 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// netInfoFunc is a callback that provides a tailcfg.NetInfo when 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// discovered network conditions change. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// TODO(danderson): why can't it be set at construction time? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// There seem to be a few natural places in ipn/local.go to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// swallow untimely invocations. 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-03 22:21:56 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									netInfoFunc  func ( * tailcfg . NetInfo )  // nil until set 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-14 23:58:35 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// netInfoLast is the NetInfo provided in the last call to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// netInfoFunc. It's used to deduplicate calls to netInfoFunc. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// TODO(danderson): should all the deduping happen in 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// ipn/local.go? We seem to be doing dedupe at several layers, and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// magicsock could do with any complexity reduction it can get. 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-03 22:21:56 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									netInfoLast  * tailcfg . NetInfo 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 19:17:24 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									derpMap           * tailcfg . DERPMap               // nil (or zero regions/nodes) means DERP is disabled 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									peers             views . Slice [ tailcfg . NodeView ]  // from last SetNetworkMap update 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									lastFlags         debugFlags                     // at time of last SetNetworkMap 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									firstAddrForTest  netip . Addr                     // from last SetNetworkMap update; for tests only 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									privateKey        key . NodePrivate                // WireGuard private key for this node 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									everHadKey        bool                           // whether we ever had a non-zero private key 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									myDerp            int                            // nearest DERP region ID; 0 means none/unknown 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-15 15:10:45 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									homeless          bool                           // if true, don't try to find & stay conneted to a DERP home (myDerp will stay 0) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 19:17:24 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									derpStarted       chan  struct { }                  // closed on first connection to DERP; for tests & cleaner Close 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									activeDerp        map [ int ] activeDerp             // DERP regionID -> connection to a node in that region 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									prevDerp          map [ int ] * syncs . WaitGroupChan 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-23 14:12:23 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// derpRoute contains optional alternate routes to use as an 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// optimization instead of contacting a peer via their home 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// DERP connection.  If they sent us a message on a different 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// DERP connection (which should really only be on our DERP 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// home connection, or what was once our home), then we 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// remember that route here to optimistically use instead of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// creating a new DERP connection back to their home. 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-29 13:15:27 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									derpRoute  map [ key . NodePublic ] derpRoute 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-23 14:12:23 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// peerLastDerp tracks which DERP node we last used to speak with a 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// peer. It's only used to quiet logging, so we only log on change. 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-29 13:15:27 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									peerLastDerp  map [ key . NodePublic ] int 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-02 17:49:56 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// wgPinger is the WireGuard only pinger used for latency measurements. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									wgPinger  lazy . SyncValue [ * ping . Pinger ] 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-05 18:12:02 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// onPortUpdate is called with the new port when magicsock rebinds to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// a new port. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									onPortUpdate  func ( port  uint16 ,  network  string ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-28 07:33:15 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// getPeerByKey optionally specifies a function to look up a peer's 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// wireguard state by its public key. If nil, it's not used. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									getPeerByKey  func ( key . NodePublic )  ( _  wgint . Peer ,  ok  bool ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-15 13:57:55 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-01-06 13:10:56 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// lastErrRebind tracks the last time a rebind was performed after 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// experiencing a write error, and is used to throttle the rate of rebinds. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									lastErrRebind  syncs . AtomicValue [ time . Time ] 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-23 18:50:55 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// staticEndpoints are user set endpoints that this node should 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// advertise amongst its wireguard endpoints. It is user's 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// responsibility to ensure that traffic from these endpoints is routed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// to the node. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									staticEndpoints  views . Slice [ netip . AddrPort ] 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-25 17:20:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// metrics contains the metrics for the magicsock instance. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metrics  * metrics 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-21 18:24:28 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-10-03 20:39:45 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// SetDebugLoggingEnabled controls whether spammy debug logging is enabled. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// Note that this is currently independent from the log levels, even though 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// they're pretty correlated: debugging logs should be [v1] (or higher), but 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// some non-debug logs may also still have a [vN] annotation. The [vN] level 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// controls which gets shown in stderr. The dlogf method, on the other hand, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// controls which gets even printed or uploaded at any level. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  SetDebugLoggingEnabled ( v  bool )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . debugLogging . Store ( v ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// dlogf logs a debug message if debug logging is enabled via SetDebugLoggingEnabled. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  dlogf ( format  string ,  a  ... any )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  c . debugLogging . Load ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . logf ( format ,  a ... ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								// Options contains options for Listen. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								type  Options  struct  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-19 20:28:19 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// EventBus, if non-nil, is used for event publication and subscription by 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// each Conn created from these Options. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// TODO(creachadair): As of 2025-03-19 this is optional, but is intended to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// become required non-nil. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									EventBus  * eventbus . Bus 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Logf provides a log function to use. It must not be nil. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Use [logger.Discard] to disrcard logs. 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-07 13:11:52 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									Logf  logger . Logf 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									// Port is the port to listen on. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Zero means to pick one automatically. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									Port  uint16 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// EndpointsFunc optionally provides a func to be called when 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// endpoints change. The called func does not own the slice. 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												tailcfg: add Endpoint, EndpointType, MapRequest.EndpointType
Track endpoints internally with a new tailcfg.Endpoint type that
includes a typed netaddr.IPPort (instead of just a string) and
includes a type for how that endpoint was discovered (STUN, local,
etc).
Use []tailcfg.Endpoint instead of []string internally.
At the last second, send it to the control server as the existing
[]string for endpoints, but also include a new parallel
MapRequest.EndpointType []tailcfg.EndpointType, so the control server
can start filtering out less-important endpoint changes from
new-enough clients. Notably, STUN-discovered endpoints can be filtered
out from 1.6+ clients, as they can discover them amongst each other
via CallMeMaybe disco exchanges started over DERP. And STUN endpoints
change a lot, causing a lot of MapResposne updates. But portmapped
endpoints are worth keeping for now, as they they work right away
without requiring the firewall traversal extra RTT dance.
End result will be less control->client bandwidth. (despite negligible
increase in client->control bandwidth)
Updates tailscale/corp#1543
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2021-04-12 13:24:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									EndpointsFunc  func ( [ ] tailcfg . Endpoint ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-25 14:19:12 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-08-25 16:21:29 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// DERPActiveFunc optionally provides a func to be called when 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// a connection is made to a DERP server. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									DERPActiveFunc  func ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-25 14:19:12 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// IdleFunc optionally provides a func to return how long 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// it's been since a TUN packet was sent or received. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									IdleFunc  func ( )  time . Duration 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-10 14:26:04 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 22:26:25 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// TestOnlyPacketListener optionally specifies how to create PacketConns. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Only used by tests. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									TestOnlyPacketListener  nettype . PacketListener 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-23 15:15:28 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-08-31 19:06:04 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// NoteRecvActivity, if provided, is a func for magicsock to call 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// whenever it receives a packet from a a peer if it's been more 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// than ~10 seconds since the last one. (10 seconds is somewhat 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// arbitrary; the sole user just doesn't need or want it called on 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-04 12:10:17 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// every packet, just every minute or two for WireGuard timeouts, 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-31 19:06:04 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// and 10 seconds seems like a good trade-off between often enough 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// and not too often.) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// The provided func is likely to call back into 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Conn.ParseEndpoint, which acquires Conn.mu. As such, you should 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// not hold Conn.mu while calling it. 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-01 17:53:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									NoteRecvActivity  func ( key . NodePublic ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-10-28 08:23:12 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-18 14:26:58 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// NetMon is the network monitor to use. 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-26 18:28:01 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// It must be non-nil. 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-18 14:26:58 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									NetMon  * netmon . Monitor 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 12:03:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-04-26 08:06:06 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// HealthTracker optionally specifies the health tracker to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// report errors and warnings to. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									HealthTracker  * health . Tracker 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-23 18:34:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// Metrics specifies the metrics registry to record metrics to. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									Metrics  * usermetric . Registry 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 12:03:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// ControlKnobs are the set of control knobs to use. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// If nil, they're ignored and not updated. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									ControlKnobs  * controlknobs . Knobs 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-05 18:12:02 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// OnPortUpdate is called with the new port when magicsock rebinds to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// a new port. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									OnPortUpdate  func ( port  uint16 ,  network  string ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-28 07:33:15 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// PeerByKeyFunc optionally specifies a function to look up a peer's 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// WireGuard state by its public key. If nil, it's not used. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// In regular use, this will be wgengine.(*userspaceEngine).PeerByKey. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									PeerByKeyFunc  func ( key . NodePublic )  ( _  wgint . Peer ,  ok  bool ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-17 21:32:18 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// DisablePortMapper, if true, disables the portmapper. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// This is primarily useful in tests. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									DisablePortMapper  bool 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-19 09:39:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( o  * Options )  logf ( )  logger . Logf  { 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Add tstest.PanicOnLog(), and fix various problems detected by this.
If a test calls log.Printf, 'go test' horrifyingly rearranges the
output to no longer be in chronological order, which makes debugging
virtually impossible. Let's stop that from happening by making
log.Printf panic if called from any module, no matter how deep, during
tests.
This required us to change the default error handler in at least one
http.Server, as well as plumbing a bunch of logf functions around,
especially in magicsock and wgengine, but also in logtail and backoff.
To add insult to injury, 'go test' also rearranges the output when a
parent test has multiple sub-tests (all the sub-test's t.Logf is always
printed after all the parent tests t.Logf), so we need to screw around
with a special Logf that can point at the "current" t (current_t.Logf)
in some places. Probably our entire way of using subtests is wrong,
since 'go test' would probably like to run them all in parallel if you
called t.Parallel(), but it definitely can't because the're all
manipulating the shared state created by the parent test. They should
probably all be separate toplevel tests instead, with common
setup/teardown logic. But that's a job for another time.
Signed-off-by: Avery Pennarun <apenwarr@tailscale.com>
											 
										 
										
											2020-05-13 22:59:54 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  o . Logf  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										panic ( "must provide magicsock.Options.logf" ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-19 09:39:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												Add tstest.PanicOnLog(), and fix various problems detected by this.
If a test calls log.Printf, 'go test' horrifyingly rearranges the
output to no longer be in chronological order, which makes debugging
virtually impossible. Let's stop that from happening by making
log.Printf panic if called from any module, no matter how deep, during
tests.
This required us to change the default error handler in at least one
http.Server, as well as plumbing a bunch of logf functions around,
especially in magicsock and wgengine, but also in logtail and backoff.
To add insult to injury, 'go test' also rearranges the output when a
parent test has multiple sub-tests (all the sub-test's t.Logf is always
printed after all the parent tests t.Logf), so we need to screw around
with a special Logf that can point at the "current" t (current_t.Logf)
in some places. Probably our entire way of using subtests is wrong,
since 'go test' would probably like to run them all in parallel if you
called t.Parallel(), but it definitely can't because the're all
manipulating the shared state created by the parent test. They should
probably all be separate toplevel tests instead, with common
setup/teardown logic. But that's a job for another time.
Signed-off-by: Avery Pennarun <apenwarr@tailscale.com>
											 
										 
										
											2020-05-13 22:59:54 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  o . Logf 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-19 09:39:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												tailcfg: add Endpoint, EndpointType, MapRequest.EndpointType
Track endpoints internally with a new tailcfg.Endpoint type that
includes a typed netaddr.IPPort (instead of just a string) and
includes a type for how that endpoint was discovered (STUN, local,
etc).
Use []tailcfg.Endpoint instead of []string internally.
At the last second, send it to the control server as the existing
[]string for endpoints, but also include a new parallel
MapRequest.EndpointType []tailcfg.EndpointType, so the control server
can start filtering out less-important endpoint changes from
new-enough clients. Notably, STUN-discovered endpoints can be filtered
out from 1.6+ clients, as they can discover them amongst each other
via CallMeMaybe disco exchanges started over DERP. And STUN endpoints
change a lot, causing a lot of MapResposne updates. But portmapped
endpoints are worth keeping for now, as they they work right away
without requiring the firewall traversal extra RTT dance.
End result will be less control->client bandwidth. (despite negligible
increase in client->control bandwidth)
Updates tailscale/corp#1543
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2021-04-12 13:24:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( o  * Options )  endpointsFunc ( )  func ( [ ] tailcfg . Endpoint )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									if  o  ==  nil  ||  o . EndpointsFunc  ==  nil  { 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												tailcfg: add Endpoint, EndpointType, MapRequest.EndpointType
Track endpoints internally with a new tailcfg.Endpoint type that
includes a typed netaddr.IPPort (instead of just a string) and
includes a type for how that endpoint was discovered (STUN, local,
etc).
Use []tailcfg.Endpoint instead of []string internally.
At the last second, send it to the control server as the existing
[]string for endpoints, but also include a new parallel
MapRequest.EndpointType []tailcfg.EndpointType, so the control server
can start filtering out less-important endpoint changes from
new-enough clients. Notably, STUN-discovered endpoints can be filtered
out from 1.6+ clients, as they can discover them amongst each other
via CallMeMaybe disco exchanges started over DERP. And STUN endpoints
change a lot, causing a lot of MapResposne updates. But portmapped
endpoints are worth keeping for now, as they they work right away
without requiring the firewall traversal extra RTT dance.
End result will be less control->client bandwidth. (despite negligible
increase in client->control bandwidth)
Updates tailscale/corp#1543
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2021-04-12 13:24:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  func ( [ ] tailcfg . Endpoint )  { } 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  o . EndpointsFunc 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-08-25 16:21:29 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( o  * Options )  derpActiveFunc ( )  func ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  o  ==  nil  ||  o . DERPActiveFunc  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  func ( )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  o . DERPActiveFunc 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-06-16 08:42:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// NodeAddrsHostInfoUpdate represents an update event of the addresses and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// [tailcfg.HostInfoView] for a node set. This event is published over an 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// [eventbus.Bus]. [magicsock.Conn] is the sole subscriber as of 2025-06. If 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// you are adding more subscribers consider moving this type out of magicsock. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								type  NodeAddrsHostInfoUpdate  struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									NodesByID  map [ tailcfg . NodeID ] NodeAddrsHostInfo 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									Complete   bool  // true if NodesByID contains all known nodes, false if it may be a subset 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// NodeAddrsHostInfo represents the addresses and [tailcfg.HostinfoView] for a 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// Tailscale node. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								type  NodeAddrsHostInfo  struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									Addresses  views . Slice [ netip . Prefix ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									Hostinfo   tailcfg . HostinfoView 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// FilterUpdate represents an update event for a [*filter.Filter]. This event is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// signaled over an [eventbus.Bus]. [magicsock.Conn] is the sole subscriber as 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// of 2025-06. If you are adding more subscribers consider moving this type out 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// of magicsock. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								type  FilterUpdate  struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									* filter . Filter 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-05-17 09:51:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// newConn is the error-free, network-listening-side-effect-free based 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// of NewConn. Mostly for tests. 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-10 16:46:31 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  newConn ( logf  logger . Logf )  * Conn  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-09 16:59:18 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									discoPrivate  :=  key . NewDisco ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									c  :=  & Conn { 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-10 16:46:31 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										logf :          logf , 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-14 13:43:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										derpRecvCh :    make ( chan  derpReadResult ,  1 ) ,  // must be buffered, see issue 3736 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 20:45:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										derpStarted :   make ( chan  struct { } ) , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-29 13:15:27 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										peerLastDerp :  make ( map [ key . NodePublic ] int ) , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 20:45:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										peerMap :       newPeerMap ( ) , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-29 14:27:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										discoInfo :     make ( map [ key . DiscoPublic ] * discoInfo ) , 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-09 16:59:18 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										discoPrivate :  discoPrivate , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										discoPublic :   discoPrivate . Public ( ) , 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-10 16:46:31 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										cloudInfo :     newCloudInfo ( logf ) , 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-09 16:59:18 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . discoShort  =  c . discoPublic . ShortString ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-24 09:41:57 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . bind  =  & connBind { Conn :  c ,  closed :  true } 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 17:58:14 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . receiveBatchPool  =  sync . Pool { New :  func ( )  any  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										msgs  :=  make ( [ ] ipv6 . Message ,  c . bind . BatchSize ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										for  i  :=  range  msgs  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											msgs [ i ] . Buffers  =  make ( [ ] [ ] byte ,  1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-04 16:32:16 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											msgs [ i ] . OOB  =  make ( [ ] byte ,  controlMessageSize ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 17:58:14 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										batch  :=  & receiveBatch { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											msgs :  msgs , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  batch 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} } 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-04 09:36:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . muCond  =  sync . NewCond ( & c . mu ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-03 21:51:02 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . networkUp . Store ( true )  // assume up until told otherwise 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-17 09:51:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  c 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-06-16 08:42:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// consumeEventbusTopic consumes events from sub and passes them to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// handlerFn until sub.Done() is closed. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  consumeEventbusTopic [ T  any ] ( sub  * eventbus . Subscriber [ T ] ,  handlerFn  func ( t  T ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  sub . Close ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									for  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										select  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										case  evt  :=  <- sub . Events ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											handlerFn ( evt ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										case  <- sub . Done ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-05-17 09:51:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// NewConn creates a magic Conn listening on opts.Port. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// As the set of possible endpoints for a Conn changes, the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// callback opts.EndpointsFunc is called. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  NewConn ( opts  Options )  ( * Conn ,  error )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-26 18:28:01 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  opts . NetMon  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  nil ,  errors . New ( "magicsock.Options.NetMon must be non-nil" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-07-10 16:46:31 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c  :=  newConn ( opts . logf ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-19 20:28:19 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . eventBus  =  opts . EventBus 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-03 21:51:02 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . port . Store ( uint32 ( opts . Port ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 12:03:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . controlKnobs  =  opts . ControlKnobs 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-17 09:51:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . epFunc  =  opts . endpointsFunc ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-25 16:21:29 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . derpActiveFunc  =  opts . derpActiveFunc ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-25 14:19:12 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . idleFunc  =  opts . IdleFunc 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 22:26:25 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . testOnlyPacketListener  =  opts . TestOnlyPacketListener 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-23 15:15:28 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . noteRecvActivity  =  opts . NoteRecvActivity 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-12 17:04:57 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-24 09:47:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// If an event bus is enabled, subscribe to portmapping changes; otherwise 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// use the callback mechanism of portmapper.Client. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// TODO(creachadair): Remove the switch once the event bus is mandatory. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									onPortMapChanged  :=  c . onPortMapChanged 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  c . eventBus  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . eventClient  =  c . eventBus . Client ( "magicsock.Conn" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										pmSub  :=  eventbus . Subscribe [ portmapper . Mapping ] ( c . eventClient ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-16 08:42:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										go  consumeEventbusTopic ( pmSub ,  func ( _  portmapper . Mapping )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											c . onPortMapChanged ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										filterSub  :=  eventbus . Subscribe [ FilterUpdate ] ( c . eventClient ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										go  consumeEventbusTopic ( filterSub ,  func ( t  FilterUpdate )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// TODO(jwhited): implement 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										nodeSub  :=  eventbus . Subscribe [ NodeAddrsHostInfoUpdate ] ( c . eventClient ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										go  consumeEventbusTopic ( nodeSub ,  func ( t  NodeAddrsHostInfoUpdate )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// TODO(jwhited): implement 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-24 09:47:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// Disable the explicit callback from the portmapper, the subscriber handles it. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										onPortMapChanged  =  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-12 17:04:57 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// Don't log the same log messages possibly every few seconds in our 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// portmapper. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									portmapperLogf  :=  logger . WithPrefix ( c . logf ,  "portmapper: " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									portmapperLogf ,  c . portMapperLogfUnregister  =  netmon . LinkChangeLogLimiter ( portmapperLogf ,  opts . NetMon ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-22 14:18:04 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									portMapOpts  :=  & portmapper . DebugKnobs { 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-17 21:32:18 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										DisableAll :  func ( )  bool  {  return  opts . DisablePortMapper  ||  c . onlyTCP443 . Load ( )  } , 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-22 14:18:04 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-19 15:50:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . portMapper  =  portmapper . NewClient ( portmapper . Config { 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-19 20:28:19 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										EventBus :      c . eventBus , 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-19 15:50:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										Logf :          portmapperLogf , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										NetMon :        opts . NetMon , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										DebugKnobs :    portMapOpts , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										ControlKnobs :  opts . ControlKnobs , 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-24 09:47:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										OnChange :      onPortMapChanged , 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-19 15:50:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-26 18:28:01 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . portMapper . SetGatewayLookupFunc ( opts . NetMon . GatewayAndSelfIP ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-18 14:26:58 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . netMon  =  opts . NetMon 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-26 08:06:06 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . health  =  opts . HealthTracker 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-05 18:12:02 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . onPortUpdate  =  opts . OnPortUpdate 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-28 07:33:15 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . getPeerByKey  =  opts . PeerByKeyFunc 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-19 09:39:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-09-02 14:24:51 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  err  :=  c . rebind ( keepCurrentPort ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-19 09:39:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . connCtx ,  c . connCtxCancel  =  context . WithCancel ( context . Background ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-15 19:13:59 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . donec  =  c . connCtx . Done ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-09 15:20:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . netChecker  =  & netcheck . Client { 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-16 19:00:12 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										Logf :                 logger . WithPrefix ( c . logf ,  "netcheck: " ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										NetMon :               c . netMon , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										SendPacket :           c . sendUDPNetcheck , 
							 
						 
					
						
							
								
									
										
										
										
											2020-10-28 08:23:12 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										SkipExternalNetwork :  inTest ( ) , 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-19 22:15:41 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										PortMapper :           c . portMapper , 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-14 12:13:03 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										UseDNSCache :          true , 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-19 09:39:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-19 22:15:41 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-25 17:20:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . metrics  =  registerMetrics ( opts . Metrics ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-08-29 10:57:54 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  d4 ,  err  :=  c . listenRawDisco ( "ip4" ) ;  err  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . logf ( "[v1] using BPF disco receiver for IPv4" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . closeDisco4  =  d4 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-16 11:27:04 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									}  else  if  ! errors . Is ( err ,  errors . ErrUnsupported )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-29 10:57:54 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . logf ( "[v1] couldn't create raw v4 disco listener, using regular listener instead: %v" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  d6 ,  err  :=  c . listenRawDisco ( "ip6" ) ;  err  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . logf ( "[v1] using BPF disco receiver for IPv6" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . closeDisco6  =  d6 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-16 11:27:04 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									}  else  if  ! errors . Is ( err ,  errors . ErrUnsupported )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-29 10:57:54 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . logf ( "[v1] couldn't create raw v6 disco listener, using regular listener instead: %v" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-09 16:59:18 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . logf ( "magicsock: disco key = %v" ,  c . discoShort ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-17 09:51:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  c ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-25 17:20:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// registerMetrics wires up the metrics for wgengine, instead of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// registering the label metric directly, the underlying expvar is exposed. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// See metrics for more info. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  registerMetrics ( reg  * usermetric . Registry )  * metrics  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									pathDirectV4  :=  pathLabel { Path :  PathDirectIPv4 } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									pathDirectV6  :=  pathLabel { Path :  PathDirectIPv6 } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									pathDERP  :=  pathLabel { Path :  PathDERP } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									inboundPacketsTotal  :=  usermetric . NewMultiLabelMapWithRegistry [ pathLabel ] ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										reg , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										"tailscaled_inbound_packets_total" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										"counter" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										"Counts the number of packets received from other peers" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									inboundBytesTotal  :=  usermetric . NewMultiLabelMapWithRegistry [ pathLabel ] ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										reg , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										"tailscaled_inbound_bytes_total" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										"counter" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										"Counts the number of bytes received from other peers" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									outboundPacketsTotal  :=  usermetric . NewMultiLabelMapWithRegistry [ pathLabel ] ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										reg , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										"tailscaled_outbound_packets_total" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										"counter" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										"Counts the number of packets sent to other peers" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									outboundBytesTotal  :=  usermetric . NewMultiLabelMapWithRegistry [ pathLabel ] ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										reg , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										"tailscaled_outbound_bytes_total" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										"counter" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										"Counts the number of bytes sent to other peers" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									) 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-29 09:19:40 +00:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									outboundPacketsDroppedErrors  :=  reg . DroppedPacketsOutbound ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-25 17:20:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									m  :=  new ( metrics ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Map clientmetrics to the usermetric counters. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricRecvDataPacketsIPv4 . Register ( & m . inboundPacketsIPv4Total ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricRecvDataPacketsIPv6 . Register ( & m . inboundPacketsIPv6Total ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricRecvDataPacketsDERP . Register ( & m . inboundPacketsDERPTotal ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricSendUDP . Register ( & m . outboundPacketsIPv4Total ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricSendUDP . Register ( & m . outboundPacketsIPv6Total ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricSendDERP . Register ( & m . outboundPacketsDERPTotal ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									inboundPacketsTotal . Set ( pathDirectV4 ,  & m . inboundPacketsIPv4Total ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									inboundPacketsTotal . Set ( pathDirectV6 ,  & m . inboundPacketsIPv6Total ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									inboundPacketsTotal . Set ( pathDERP ,  & m . inboundPacketsDERPTotal ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									inboundBytesTotal . Set ( pathDirectV4 ,  & m . inboundBytesIPv4Total ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									inboundBytesTotal . Set ( pathDirectV6 ,  & m . inboundBytesIPv6Total ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									inboundBytesTotal . Set ( pathDERP ,  & m . inboundBytesDERPTotal ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									outboundPacketsTotal . Set ( pathDirectV4 ,  & m . outboundPacketsIPv4Total ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									outboundPacketsTotal . Set ( pathDirectV6 ,  & m . outboundPacketsIPv6Total ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									outboundPacketsTotal . Set ( pathDERP ,  & m . outboundPacketsDERPTotal ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									outboundBytesTotal . Set ( pathDirectV4 ,  & m . outboundBytesIPv4Total ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									outboundBytesTotal . Set ( pathDirectV6 ,  & m . outboundBytesIPv6Total ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									outboundBytesTotal . Set ( pathDERP ,  & m . outboundBytesDERPTotal ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-10-29 09:19:40 +00:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									outboundPacketsDroppedErrors . Set ( usermetric . DropLabels { Reason :  usermetric . ReasonError } ,  & m . outboundPacketsDroppedErrors ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-25 17:20:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  m 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// deregisterMetrics unregisters the underlying usermetrics expvar counters 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// from clientmetrics. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  deregisterMetrics ( m  * metrics )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricRecvDataPacketsIPv4 . UnregisterAll ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricRecvDataPacketsIPv6 . UnregisterAll ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricRecvDataPacketsDERP . UnregisterAll ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricSendUDP . UnregisterAll ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricSendDERP . UnregisterAll ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-08 15:48:27 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// InstallCaptureHook installs a callback which is called to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// log debug information into the pcap stream. This function 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// can be called with a nil argument to uninstall the capture 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// hook. 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-23 20:39:28 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  InstallCaptureHook ( cb  packet . CaptureCallback )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-08 15:48:27 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . captureHook . Store ( cb ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 09:52:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// doPeriodicSTUN is called (in a new goroutine) by 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// periodicReSTUNTimer when periodic STUNs are active. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  doPeriodicSTUN ( )  {  c . ReSTUN ( "periodic" )  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  stopPeriodicReSTUNTimerLocked ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  t  :=  c . periodicReSTUNTimer ;  t  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										t . Stop ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . periodicReSTUNTimer  =  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// c.mu must NOT be held. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  updateEndpoints ( why  string )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-04-22 10:40:49 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									metricUpdateEndpoints . Add ( 1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									defer  func ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										why  :=  c . wantEndpointsUpdate 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . wantEndpointsUpdate  =  "" 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 09:52:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  ! c . closed  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  why  !=  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												go  c . updateEndpoints ( why ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  c . shouldDoPeriodicReSTUNLocked ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												// Pick a random duration between 20 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												// and 26 seconds (just under 30s, a 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												// common UDP NAT timeout on Linux, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												// etc) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												d  :=  tstime . RandomDurationBetween ( 20 * time . Second ,  26 * time . Second ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												if  t  :=  c . periodicReSTUNTimer ;  t  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-14 12:49:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													if  debugReSTUNStopOnIdle ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 09:52:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
														c . logf ( "resetting existing periodicSTUN to run in %v" ,  d ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													t . Reset ( d ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-14 12:49:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													if  debugReSTUNStopOnIdle ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 09:52:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
														c . logf ( "scheduling periodicSTUN to run in %v" ,  d ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													c . periodicReSTUNTimer  =  time . AfterFunc ( d ,  c . doPeriodicSTUN ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-14 12:49:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												if  debugReSTUNStopOnIdle ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 09:52:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													c . logf ( "periodic STUN idle" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												c . stopPeriodicReSTUNTimerLocked ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 09:52:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . endpointsUpdateActive  =  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . muCond . Broadcast ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-03 20:39:45 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . dlogf ( "[v1] magicsock: starting endpoint update (%s)" ,  why ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-01 04:01:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  c . noV4Send . Load ( )  &&  runtime . GOOS  !=  "js"  &&  ! c . onlyTCP443 . Load ( )  &&  ! hostinfo . IsInVM86 ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 13:59:13 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										closed  :=  c . closed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  ! closed  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											c . logf ( "magicsock: last netcheck reported send error. Rebinding." ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											c . Rebind ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-07 09:43:37 +09:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												tailcfg: add Endpoint, EndpointType, MapRequest.EndpointType
Track endpoints internally with a new tailcfg.Endpoint type that
includes a typed netaddr.IPPort (instead of just a string) and
includes a type for how that endpoint was discovered (STUN, local,
etc).
Use []tailcfg.Endpoint instead of []string internally.
At the last second, send it to the control server as the existing
[]string for endpoints, but also include a new parallel
MapRequest.EndpointType []tailcfg.EndpointType, so the control server
can start filtering out less-important endpoint changes from
new-enough clients. Notably, STUN-discovered endpoints can be filtered
out from 1.6+ clients, as they can discover them amongst each other
via CallMeMaybe disco exchanges started over DERP. And STUN endpoints
change a lot, causing a lot of MapResposne updates. But portmapped
endpoints are worth keeping for now, as they they work right away
without requiring the firewall traversal extra RTT dance.
End result will be less control->client bandwidth. (despite negligible
increase in client->control bandwidth)
Updates tailscale/corp#1543
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2021-04-12 13:24:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									endpoints ,  err  :=  c . determineEndpoints ( c . connCtx ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-23 14:12:23 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . logf ( "magicsock: endpoint update (%s) failed: %v" ,  why ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										// TODO(crawshaw): are there any conditions under which 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// we should trigger a retry based on the error here? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-03 22:21:56 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												tailcfg: add Endpoint, EndpointType, MapRequest.EndpointType
Track endpoints internally with a new tailcfg.Endpoint type that
includes a typed netaddr.IPPort (instead of just a string) and
includes a type for how that endpoint was discovered (STUN, local,
etc).
Use []tailcfg.Endpoint instead of []string internally.
At the last second, send it to the control server as the existing
[]string for endpoints, but also include a new parallel
MapRequest.EndpointType []tailcfg.EndpointType, so the control server
can start filtering out less-important endpoint changes from
new-enough clients. Notably, STUN-discovered endpoints can be filtered
out from 1.6+ clients, as they can discover them amongst each other
via CallMeMaybe disco exchanges started over DERP. And STUN endpoints
change a lot, causing a lot of MapResposne updates. But portmapped
endpoints are worth keeping for now, as they they work right away
without requiring the firewall traversal extra RTT dance.
End result will be less control->client bandwidth. (despite negligible
increase in client->control bandwidth)
Updates tailscale/corp#1543
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2021-04-12 13:24:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  c . setEndpoints ( endpoints )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . logEndpointChange ( endpoints ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . epFunc ( endpoints ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-03 22:21:56 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// setEndpoints records the new endpoints, reporting whether they're changed. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// It takes ownership of the slice. 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												tailcfg: add Endpoint, EndpointType, MapRequest.EndpointType
Track endpoints internally with a new tailcfg.Endpoint type that
includes a typed netaddr.IPPort (instead of just a string) and
includes a type for how that endpoint was discovered (STUN, local,
etc).
Use []tailcfg.Endpoint instead of []string internally.
At the last second, send it to the control server as the existing
[]string for endpoints, but also include a new parallel
MapRequest.EndpointType []tailcfg.EndpointType, so the control server
can start filtering out less-important endpoint changes from
new-enough clients. Notably, STUN-discovered endpoints can be filtered
out from 1.6+ clients, as they can discover them amongst each other
via CallMeMaybe disco exchanges started over DERP. And STUN endpoints
change a lot, causing a lot of MapResposne updates. But portmapped
endpoints are worth keeping for now, as they they work right away
without requiring the firewall traversal extra RTT dance.
End result will be less control->client bandwidth. (despite negligible
increase in client->control bandwidth)
Updates tailscale/corp#1543
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2021-04-12 13:24:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  setEndpoints ( endpoints  [ ] tailcfg . Endpoint )  ( changed  bool )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-10-14 10:44:54 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									anySTUN  :=  false 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												tailcfg: add Endpoint, EndpointType, MapRequest.EndpointType
Track endpoints internally with a new tailcfg.Endpoint type that
includes a typed netaddr.IPPort (instead of just a string) and
includes a type for how that endpoint was discovered (STUN, local,
etc).
Use []tailcfg.Endpoint instead of []string internally.
At the last second, send it to the control server as the existing
[]string for endpoints, but also include a new parallel
MapRequest.EndpointType []tailcfg.EndpointType, so the control server
can start filtering out less-important endpoint changes from
new-enough clients. Notably, STUN-discovered endpoints can be filtered
out from 1.6+ clients, as they can discover them amongst each other
via CallMeMaybe disco exchanges started over DERP. And STUN endpoints
change a lot, causing a lot of MapResposne updates. But portmapped
endpoints are worth keeping for now, as they they work right away
without requiring the firewall traversal extra RTT dance.
End result will be less control->client bandwidth. (despite negligible
increase in client->control bandwidth)
Updates tailscale/corp#1543
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2021-04-12 13:24:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									for  _ ,  ep  :=  range  endpoints  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  ep . Type  ==  tailcfg . EndpointSTUN  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-10-14 10:44:54 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											anySTUN  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-10-14 10:44:54 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  ! anySTUN  &&  c . derpMap  ==  nil  &&  ! inTest ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// Don't bother storing or reporting this yet. We 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// don't have a DERP map or any STUN entries, so we're 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// just starting up. A DERP map should arrive shortly 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// and then we'll have more interesting endpoints to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// report. This saves a map update. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// TODO(bradfitz): this optimization is currently 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// skipped during the e2e tests because they depend 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// too much on the exact sequence of updates.  Fix the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// tests. But a protocol rewrite might happen first. 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-03 20:39:45 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . dlogf ( "[v1] magicsock: ignoring pre-DERP map, STUN-less endpoint update: %v" ,  endpoints ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-10-14 10:44:54 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 09:52:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . lastEndpointsTime  =  time . Now ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									for  de ,  fn  :=  range  c . onEndpointRefreshed  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										go  fn ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										delete ( c . onEndpointRefreshed ,  de ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												tailcfg: add Endpoint, EndpointType, MapRequest.EndpointType
Track endpoints internally with a new tailcfg.Endpoint type that
includes a typed netaddr.IPPort (instead of just a string) and
includes a type for how that endpoint was discovered (STUN, local,
etc).
Use []tailcfg.Endpoint instead of []string internally.
At the last second, send it to the control server as the existing
[]string for endpoints, but also include a new parallel
MapRequest.EndpointType []tailcfg.EndpointType, so the control server
can start filtering out less-important endpoint changes from
new-enough clients. Notably, STUN-discovered endpoints can be filtered
out from 1.6+ clients, as they can discover them amongst each other
via CallMeMaybe disco exchanges started over DERP. And STUN endpoints
change a lot, causing a lot of MapResposne updates. But portmapped
endpoints are worth keeping for now, as they they work right away
without requiring the firewall traversal extra RTT dance.
End result will be less control->client bandwidth. (despite negligible
increase in client->control bandwidth)
Updates tailscale/corp#1543
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2021-04-12 13:24:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  endpointSetsEqual ( endpoints ,  c . lastEndpoints )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  false 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . lastEndpoints  =  endpoints 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  true 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-07-23 18:50:55 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// SetStaticEndpoints sets static endpoints to the provided value and triggers 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// an asynchronous update of the endpoints that this node advertises. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// Static endpoints are endpoints explicitly configured by user. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  SetStaticEndpoints ( ep  views . Slice [ netip . AddrPort ] )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  reflect . DeepEqual ( c . staticEndpoints . AsSlice ( ) ,  ep . AsSlice ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . staticEndpoints  =  ep 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Technically this is not a reSTUNning, but ReSTUN does what we need at 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// this point- calls updateEndpoints or queues an update if there is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// already an in-progress update. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . ReSTUN ( "static-endpoint-change" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-09 15:09:10 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// setNetInfoHavePortMap updates NetInfo.HavePortMap to true. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  setNetInfoHavePortMap ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  c . netInfoLast  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// No NetInfo yet. Nothing to update. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  c . netInfoLast . HavePortMap  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// No change. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									ni  :=  c . netInfoLast . Clone ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									ni . HavePortMap  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . callNetInfoCallbackLocked ( ni ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-09 15:20:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  updateNetInfo ( ctx  context . Context )  ( * netcheck . Report ,  error )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-17 09:51:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									dm  :=  c . derpMap 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-10-06 20:24:10 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  dm  ==  nil  ||  c . networkDown ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-10 11:35:43 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  new ( netcheck . Report ) ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-06 07:47:54 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-12-08 15:03:15 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									report ,  err  :=  c . netChecker . GetReport ( ctx ,  dm ,  & netcheck . GetReportOpts { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// Pass information about the last time that we received a 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// frame from a DERP server to our netchecker to help avoid 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// flapping the home region while there's still active 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// communication. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// NOTE(andrew-d): I don't love that we're depending on the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// health package here, but I'd rather do that and not store 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// the exact same state in two different places. 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-26 08:06:06 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										GetLastDERPActivity :  c . health . GetDERPRegionReceivedTime , 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-17 12:24:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										OnlyTCP443 :           c . onlyTCP443 . Load ( ) , 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-08 15:03:15 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-03 22:21:56 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-09 15:20:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-03 22:21:56 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-29 14:52:00 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . lastNetCheckReport . Store ( report ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-03 21:51:02 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . noV4 . Store ( ! report . IPv4 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . noV6 . Store ( ! report . IPv6 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . noV4Send . Store ( ! report . IPv4CanSend ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-29 12:40:51 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-03 22:21:56 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									ni  :=  & tailcfg . NetInfo { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										DERPLatency :            map [ string ] float64 { } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										MappingVariesByDestIP :  report . MappingVariesByDestIP , 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-06 13:51:17 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										UPnP :                   report . UPnP , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										PMP :                    report . PMP , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										PCP :                    report . PCP , 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-09 15:09:10 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										HavePortMap :            c . portMapper . HaveMapping ( ) , 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-03 22:21:56 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-17 09:51:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									for  rid ,  d  :=  range  report . RegionV4Latency  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										ni . DERPLatency [ fmt . Sprintf ( "%d-v4" ,  rid ) ]  =  d . Seconds ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									for  rid ,  d  :=  range  report . RegionV6Latency  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										ni . DERPLatency [ fmt . Sprintf ( "%d-v6" ,  rid ) ]  =  d . Seconds ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-03 22:21:56 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									ni . WorkingIPv6 . Set ( report . IPv6 ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-21 15:13:49 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									ni . OSHasIPv6 . Set ( report . OSHasIPv6 ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-03 22:21:56 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									ni . WorkingUDP . Set ( report . UDP ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-04 17:10:13 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									ni . WorkingICMPv4 . Set ( report . ICMPv4 ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-08 12:32:15 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									ni . PreferredDERP  =  c . maybeSetNearestDERP ( report ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-15 21:52:04 +00:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									ni . FirewallMode  =  hostinfo . FirewallMode ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-03 22:21:56 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . callNetInfoCallback ( ni ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-09 15:20:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  report ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-03 22:21:56 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-12 14:49:48 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// callNetInfoCallback calls the callback (if previously 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-03 22:21:56 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// registered with SetNetInfoCallback) if ni has substantially changed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// since the last state. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// callNetInfoCallback takes ownership of ni. 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// c.mu must NOT be held. 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-03 22:21:56 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  callNetInfoCallback ( ni  * tailcfg . NetInfo )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-03 22:21:56 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  ni . BasicallyEqual ( c . netInfoLast )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-09 15:09:10 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . callNetInfoCallbackLocked ( ni ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  callNetInfoCallbackLocked ( ni  * tailcfg . NetInfo )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-03 22:21:56 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . netInfoLast  =  ni 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  c . netInfoFunc  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-03 20:39:45 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . dlogf ( "[v1] magicsock: netInfo update: %+v" ,  ni ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-03 22:21:56 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										go  c . netInfoFunc ( ni ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-15 12:50:33 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// addValidDiscoPathForTest makes addr a validated disco address for 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// discoKey. It's used in tests to enable receiving of packets from 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// addr without having to spin up the entire active discovery 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// machinery. 
							 
						 
					
						
							
								
									
										
										
											
												all: convert more code to use net/netip directly
    perl -i -npe 's,netaddr.IPPrefixFrom,netip.PrefixFrom,' $(git grep -l -F netaddr.)
    perl -i -npe 's,netaddr.IPPortFrom,netip.AddrPortFrom,' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPPrefix,netip.Prefix,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPPort,netip.AddrPort,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IP\b,netip.Addr,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPv6Raw\b,netip.AddrFrom16,g' $(git grep -l -F netaddr. )
    goimports -w .
Then delete some stuff from the net/netaddr shim package which is no
longer neeed.
Updates #5162
Change-Id: Ia7a86893fe21c7e3ee1ec823e8aba288d4566cd8
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2022-07-25 21:14:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  addValidDiscoPathForTest ( nodeKey  key . NodePublic ,  addr  netip . AddrPort )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-15 12:50:33 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . peerMap . setNodeKeyForEpAddr ( epAddr { ap :  addr } ,  nodeKey ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-15 12:50:33 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-12 14:49:48 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// SetNetInfoCallback sets the func to be called whenever the network conditions 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// change. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// At most one func can be registered; the most recent one replaces any previous 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// registration. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// This is called by LocalBackend. 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-03 22:21:56 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  SetNetInfoCallback ( fn  func ( * tailcfg . NetInfo ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  fn  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										panic ( "nil NetInfoCallback" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-03 22:21:56 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									last  :=  c . netInfoLast 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . netInfoFunc  =  fn 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . mu . Unlock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-03 22:21:56 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  last  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										fn ( last ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 14:40:49 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// LastRecvActivityOfNodeKey describes the time we last got traffic from 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-11 19:07:08 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// this endpoint (updated every ~10 seconds). 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-01 17:53:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  LastRecvActivityOfNodeKey ( nk  key . NodePublic )  string  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-11 19:07:08 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 14:40:49 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									de ,  ok  :=  c . peerMap . endpointForNodeKey ( nk ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-11 19:07:08 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  ! ok  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-21 11:04:36 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  "never" 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-11 19:07:08 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-23 09:37:32 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									saw  :=  de . lastRecvWG . LoadAtomic ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-21 11:04:36 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  saw  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  "never" 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-11 19:07:08 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-21 11:04:36 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  mono . Since ( saw ) . Round ( time . Second ) . String ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-09 14:49:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// Ping handles a "tailscale ping" CLI query. 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-18 07:57:44 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  Ping ( peer  tailcfg . NodeView ,  res  * ipnstate . PingResult ,  size  int ,  cb  func ( * ipnstate . PingResult ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-09 14:49:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  c . privateKey . IsZero ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										res . Err  =  "local tailscaled stopped" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										cb ( res ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-18 07:57:44 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  peer . Addresses ( ) . Len ( )  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										res . NodeIP  =  peer . Addresses ( ) . At ( 0 ) . Addr ( ) . String ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-09 14:49:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-18 07:57:44 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									res . NodeName  =  peer . Name ( )  // prefer DNS name 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-09 14:49:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  res . NodeName  ==  ""  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-18 07:57:44 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										res . NodeName  =  peer . Hostinfo ( ) . Hostname ( )  // else hostname 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-09 14:49:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-19 12:42:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										res . NodeName ,  _ ,  _  =  strings . Cut ( res . NodeName ,  "." ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-09 14:49:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-08-18 07:57:44 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									ep ,  ok  :=  c . peerMap . endpointForNodeKey ( peer . Key ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-09 14:49:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  ! ok  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-31 16:55:22 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										res . Err  =  "unknown peer" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										cb ( res ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-09 14:49:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-14 13:16:04 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									ep . discoPing ( res ,  size ,  cb ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-09 14:49:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// c.mu must be held 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  populateCLIPingResponseLocked ( res  * ipnstate . PingResult ,  latency  time . Duration ,  ep  epAddr )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-09 14:49:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									res . LatencySeconds  =  latency . Seconds ( ) 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  ep . ap . Addr ( )  !=  tailcfg . DerpMagicIPAddr  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// TODO(jwhited): if ep.vni.isSet() we are using a Tailscale client 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										//  as a UDP relay; update PingResult and its interpretation by 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										//  "tailscale ping" to make this clear. 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-09 14:49:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										res . Endpoint  =  ep . String ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									regionID  :=  int ( ep . ap . Port ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-09 14:49:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									res . DERPRegionID  =  regionID 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-23 10:59:07 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									res . DERPRegionCode  =  c . derpRegionCodeLocked ( regionID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-21 15:57:08 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// GetEndpointChanges returns the most recent changes for a particular 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// endpoint. The returned EndpointChange structs are for debug use only and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// there are no guarantees about order, size, or content. 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-18 07:57:44 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  GetEndpointChanges ( peer  tailcfg . NodeView )  ( [ ] EndpointChange ,  error )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-21 15:57:08 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  c . privateKey . IsZero ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  nil ,  fmt . Errorf ( "tailscaled stopped" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-18 07:57:44 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									ep ,  ok  :=  c . peerMap . endpointForNodeKey ( peer . Key ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-21 15:57:08 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  nil ,  fmt . Errorf ( "unknown peer" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  ep . debugUpdates . GetAll ( ) ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-07-06 12:10:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// DiscoPublicKey returns the discovery public key. 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-29 14:27:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  DiscoPublicKey ( )  key . DiscoPublic  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-06 12:10:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  c . discoPublic 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-19 12:06:49 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-07-23 18:50:55 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// determineEndpoints returns the machine's endpoint addresses. It does a STUN 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// lookup (via netcheck) to determine its public address. Additionally any 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// static enpoints provided by user are always added to the returned endpoints 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// without validating if the node can be reached via those endpoints. 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// c.mu must NOT be held. 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												tailcfg: add Endpoint, EndpointType, MapRequest.EndpointType
Track endpoints internally with a new tailcfg.Endpoint type that
includes a typed netaddr.IPPort (instead of just a string) and
includes a type for how that endpoint was discovered (STUN, local,
etc).
Use []tailcfg.Endpoint instead of []string internally.
At the last second, send it to the control server as the existing
[]string for endpoints, but also include a new parallel
MapRequest.EndpointType []tailcfg.EndpointType, so the control server
can start filtering out less-important endpoint changes from
new-enough clients. Notably, STUN-discovered endpoints can be filtered
out from 1.6+ clients, as they can discover them amongst each other
via CallMeMaybe disco exchanges started over DERP. And STUN endpoints
change a lot, causing a lot of MapResposne updates. But portmapped
endpoints are worth keeping for now, as they they work right away
without requiring the firewall traversal extra RTT dance.
End result will be less control->client bandwidth. (despite negligible
increase in client->control bandwidth)
Updates tailscale/corp#1543
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2021-04-12 13:24:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  determineEndpoints ( ctx  context . Context )  ( [ ] tailcfg . Endpoint ,  error )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-22 09:09:37 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									var  havePortmap  bool 
							 
						 
					
						
							
								
									
										
										
											
												all: convert more code to use net/netip directly
    perl -i -npe 's,netaddr.IPPrefixFrom,netip.PrefixFrom,' $(git grep -l -F netaddr.)
    perl -i -npe 's,netaddr.IPPortFrom,netip.AddrPortFrom,' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPPrefix,netip.Prefix,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPPort,netip.AddrPort,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IP\b,netip.Addr,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPv6Raw\b,netip.AddrFrom16,g' $(git grep -l -F netaddr. )
    goimports -w .
Then delete some stuff from the net/netaddr shim package which is no
longer neeed.
Updates #5162
Change-Id: Ia7a86893fe21c7e3ee1ec823e8aba288d4566cd8
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2022-07-25 21:14:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									var  portmapExt  netip . AddrPort 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-22 09:09:37 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  runtime . GOOS  !=  "js"  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										portmapExt ,  havePortmap  =  c . portMapper . GetCachedMappingOrStartCreatingOne ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-20 12:57:10 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-09 10:01:50 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									nr ,  err  :=  c . updateNetInfo ( ctx ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . logf ( "magicsock.Conn.determineEndpoints: updateNetInfo: %v" ,  err ) 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												tailcfg: add Endpoint, EndpointType, MapRequest.EndpointType
Track endpoints internally with a new tailcfg.Endpoint type that
includes a typed netaddr.IPPort (instead of just a string) and
includes a type for how that endpoint was discovered (STUN, local,
etc).
Use []tailcfg.Endpoint instead of []string internally.
At the last second, send it to the control server as the existing
[]string for endpoints, but also include a new parallel
MapRequest.EndpointType []tailcfg.EndpointType, so the control server
can start filtering out less-important endpoint changes from
new-enough clients. Notably, STUN-discovered endpoints can be filtered
out from 1.6+ clients, as they can discover them amongst each other
via CallMeMaybe disco exchanges started over DERP. And STUN endpoints
change a lot, causing a lot of MapResposne updates. But portmapped
endpoints are worth keeping for now, as they they work right away
without requiring the firewall traversal extra RTT dance.
End result will be less control->client bandwidth. (despite negligible
increase in client->control bandwidth)
Updates tailscale/corp#1543
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2021-04-12 13:24:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-10-22 09:09:37 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  runtime . GOOS  ==  "js"  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// TODO(bradfitz): why does control require an 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// endpoint? Otherwise it doesn't stream map responses 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// back. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  [ ] tailcfg . Endpoint { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											{ 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-25 20:55:44 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												Addr :  netip . MustParseAddrPort ( "[fe80:123:456:789::1]:12345" ) , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-22 09:09:37 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												Type :  tailcfg . EndpointLocal , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
											
												all: convert more code to use net/netip directly
    perl -i -npe 's,netaddr.IPPrefixFrom,netip.PrefixFrom,' $(git grep -l -F netaddr.)
    perl -i -npe 's,netaddr.IPPortFrom,netip.AddrPortFrom,' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPPrefix,netip.Prefix,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPPort,netip.AddrPort,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IP\b,netip.Addr,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPv6Raw\b,netip.AddrFrom16,g' $(git grep -l -F netaddr. )
    goimports -w .
Then delete some stuff from the net/netaddr shim package which is no
longer neeed.
Updates #5162
Change-Id: Ia7a86893fe21c7e3ee1ec823e8aba288d4566cd8
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2022-07-25 21:14:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									var  already  map [ netip . AddrPort ] tailcfg . EndpointType  // endpoint -> how it was found 
							 
						 
					
						
							
								
									
										
										
										
											2022-04-22 10:40:49 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									var  eps  [ ] tailcfg . Endpoint                           // unique endpoints 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
											
												all: convert more code to use net/netip directly
    perl -i -npe 's,netaddr.IPPrefixFrom,netip.PrefixFrom,' $(git grep -l -F netaddr.)
    perl -i -npe 's,netaddr.IPPortFrom,netip.AddrPortFrom,' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPPrefix,netip.Prefix,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPPort,netip.AddrPort,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IP\b,netip.Addr,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPv6Raw\b,netip.AddrFrom16,g' $(git grep -l -F netaddr. )
    goimports -w .
Then delete some stuff from the net/netaddr shim package which is no
longer neeed.
Updates #5162
Change-Id: Ia7a86893fe21c7e3ee1ec823e8aba288d4566cd8
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2022-07-25 21:14:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									ipp  :=  func ( s  string )  ( ipp  netip . AddrPort )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-25 20:55:44 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										ipp ,  _  =  netip . ParseAddrPort ( s ) 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												tailcfg: add Endpoint, EndpointType, MapRequest.EndpointType
Track endpoints internally with a new tailcfg.Endpoint type that
includes a typed netaddr.IPPort (instead of just a string) and
includes a type for how that endpoint was discovered (STUN, local,
etc).
Use []tailcfg.Endpoint instead of []string internally.
At the last second, send it to the control server as the existing
[]string for endpoints, but also include a new parallel
MapRequest.EndpointType []tailcfg.EndpointType, so the control server
can start filtering out less-important endpoint changes from
new-enough clients. Notably, STUN-discovered endpoints can be filtered
out from 1.6+ clients, as they can discover them amongst each other
via CallMeMaybe disco exchanges started over DERP. And STUN endpoints
change a lot, causing a lot of MapResposne updates. But portmapped
endpoints are worth keeping for now, as they they work right away
without requiring the firewall traversal extra RTT dance.
End result will be less control->client bandwidth. (despite negligible
increase in client->control bandwidth)
Updates tailscale/corp#1543
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2021-04-12 13:24:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
											
												all: convert more code to use net/netip directly
    perl -i -npe 's,netaddr.IPPrefixFrom,netip.PrefixFrom,' $(git grep -l -F netaddr.)
    perl -i -npe 's,netaddr.IPPortFrom,netip.AddrPortFrom,' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPPrefix,netip.Prefix,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPPort,netip.AddrPort,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IP\b,netip.Addr,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPv6Raw\b,netip.AddrFrom16,g' $(git grep -l -F netaddr. )
    goimports -w .
Then delete some stuff from the net/netaddr shim package which is no
longer neeed.
Updates #5162
Change-Id: Ia7a86893fe21c7e3ee1ec823e8aba288d4566cd8
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2022-07-25 21:14:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									addAddr  :=  func ( ipp  netip . AddrPort ,  et  tailcfg . EndpointType )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-14 12:49:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  ! ipp . IsValid ( )  ||  ( debugOmitLocalAddresses ( )  &&  et  ==  tailcfg . EndpointLocal )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-02 09:53:10 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												tailcfg: add Endpoint, EndpointType, MapRequest.EndpointType
Track endpoints internally with a new tailcfg.Endpoint type that
includes a typed netaddr.IPPort (instead of just a string) and
includes a type for how that endpoint was discovered (STUN, local,
etc).
Use []tailcfg.Endpoint instead of []string internally.
At the last second, send it to the control server as the existing
[]string for endpoints, but also include a new parallel
MapRequest.EndpointType []tailcfg.EndpointType, so the control server
can start filtering out less-important endpoint changes from
new-enough clients. Notably, STUN-discovered endpoints can be filtered
out from 1.6+ clients, as they can discover them amongst each other
via CallMeMaybe disco exchanges started over DERP. And STUN endpoints
change a lot, causing a lot of MapResposne updates. But portmapped
endpoints are worth keeping for now, as they they work right away
without requiring the firewall traversal extra RTT dance.
End result will be less control->client bandwidth. (despite negligible
increase in client->control bandwidth)
Updates tailscale/corp#1543
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2021-04-12 13:24:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  _ ,  ok  :=  already [ ipp ] ;  ! ok  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-04-21 20:25:24 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											mak . Set ( & already ,  ipp ,  et ) 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												tailcfg: add Endpoint, EndpointType, MapRequest.EndpointType
Track endpoints internally with a new tailcfg.Endpoint type that
includes a typed netaddr.IPPort (instead of just a string) and
includes a type for how that endpoint was discovered (STUN, local,
etc).
Use []tailcfg.Endpoint instead of []string internally.
At the last second, send it to the control server as the existing
[]string for endpoints, but also include a new parallel
MapRequest.EndpointType []tailcfg.EndpointType, so the control server
can start filtering out less-important endpoint changes from
new-enough clients. Notably, STUN-discovered endpoints can be filtered
out from 1.6+ clients, as they can discover them amongst each other
via CallMeMaybe disco exchanges started over DERP. And STUN endpoints
change a lot, causing a lot of MapResposne updates. But portmapped
endpoints are worth keeping for now, as they they work right away
without requiring the firewall traversal extra RTT dance.
End result will be less control->client bandwidth. (despite negligible
increase in client->control bandwidth)
Updates tailscale/corp#1543
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2021-04-12 13:24:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											eps  =  append ( eps ,  tailcfg . Endpoint { Addr :  ipp ,  Type :  et } ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-07-09 10:01:50 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// If we didn't have a portmap earlier, maybe it's done by now. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  ! havePortmap  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										portmapExt ,  havePortmap  =  c . portMapper . GetCachedMappingOrStartCreatingOne ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  havePortmap  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										addAddr ( portmapExt ,  tailcfg . EndpointPortmapped ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-09 15:09:10 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . setNetInfoHavePortMap ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-19 22:15:41 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-05-16 15:58:19 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									v4Addrs ,  v6Addrs  :=  nr . GetGlobalAddrs ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									for  _ ,  addr  :=  range  v4Addrs  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										addAddr ( addr ,  tailcfg . EndpointSTUN ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									for  _ ,  addr  :=  range  v6Addrs  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										addAddr ( addr ,  tailcfg . EndpointSTUN ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-04 09:48:34 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-05-16 15:58:19 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  len ( v4Addrs )  >=  1  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-04 09:48:34 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										// If they're behind a hard NAT and are using a fixed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// port locally, assume they might've added a static 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// port mapping on their router to the same explicit 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// port that tailscaled is running with. Worst case 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// it's an invalid candidate mapping. 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-03 21:51:02 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  port  :=  c . port . Load ( ) ;  nr . MappingVariesByDestIP . EqualBool ( true )  &&  port  !=  0  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-16 15:58:19 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											addAddr ( netip . AddrPortFrom ( v4Addrs [ 0 ] . Addr ( ) ,  uint16 ( port ) ) ,  tailcfg . EndpointSTUN4LocalPort ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-04 09:48:34 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-07-08 07:21:21 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// Temporarily (2024-07-08) during investigations, allow setting 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-09 18:47:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// pretend endpoint(s) for testing NAT traversal scenarios. 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-08 07:21:21 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// TODO(bradfitz): probably promote this to the config file. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// https://github.com/tailscale/tailscale/issues/12578 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-09 18:47:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									for  _ ,  ap  :=  range  pretendpoints ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										addAddr ( ap ,  tailcfg . EndpointExplicitConf ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-08 07:21:21 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-07-10 16:46:31 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// If we're on a cloud instance, we might have a public IPv4 or IPv6 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// address that we can be reached at. Find those, if they exist, and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// add them. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  addrs ,  err  :=  c . cloudInfo . GetPublicIPs ( ctx ) ;  err  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										var  port4 ,  port6  uint16 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  addr  :=  c . pconn4 . LocalAddr ( ) ;  addr  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											port4  =  uint16 ( addr . Port ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  addr  :=  c . pconn6 . LocalAddr ( ) ;  addr  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											port6  =  uint16 ( addr . Port ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										for  _ ,  addr  :=  range  addrs  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  addr . Is4 ( )  &&  port4  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												addAddr ( netip . AddrPortFrom ( addr ,  port4 ) ,  tailcfg . EndpointLocal ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											}  else  if  addr . Is6 ( )  &&  port6  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												addAddr ( netip . AddrPortFrom ( addr ,  port6 ) ,  tailcfg . EndpointLocal ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-14 16:37:10 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// Update our set of endpoints by adding any endpoints that we 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// previously found but haven't expired yet. This also updates the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// cache with the set of endpoints discovered in this function. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// NOTE: we do this here and not below so that we don't cache local 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// endpoints; we know that the local endpoints we discover are all 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// possible local endpoints since we determine them by looking at the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// set of addresses on our local interfaces. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// TODO(andrew): If we pull in any cached endpoints, we should probably 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// do something to ensure we're propagating the removal of those cached 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// endpoints if they do actually time out without being rediscovered. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// For now, though, rely on a minor LinkChange event causing this to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// re-run. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									eps  =  c . endpointTracker . update ( time . Now ( ) ,  eps ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-11 13:08:47 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									for  _ ,  ep  :=  range  c . staticEndpoints . All ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										addAddr ( ep ,  tailcfg . EndpointExplicitConf ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-23 18:50:55 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-19 08:49:30 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  localAddr  :=  c . pconn4 . LocalAddr ( ) ;  localAddr . IP . IsUnspecified ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-27 21:18:18 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										ips ,  loopback ,  err  :=  netmon . LocalAddresses ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												tailcfg: add Endpoint, EndpointType, MapRequest.EndpointType
Track endpoints internally with a new tailcfg.Endpoint type that
includes a typed netaddr.IPPort (instead of just a string) and
includes a type for how that endpoint was discovered (STUN, local,
etc).
Use []tailcfg.Endpoint instead of []string internally.
At the last second, send it to the control server as the existing
[]string for endpoints, but also include a new parallel
MapRequest.EndpointType []tailcfg.EndpointType, so the control server
can start filtering out less-important endpoint changes from
new-enough clients. Notably, STUN-discovered endpoints can be filtered
out from 1.6+ clients, as they can discover them amongst each other
via CallMeMaybe disco exchanges started over DERP. And STUN endpoints
change a lot, causing a lot of MapResposne updates. But portmapped
endpoints are worth keeping for now, as they they work right away
without requiring the firewall traversal extra RTT dance.
End result will be less control->client bandwidth. (despite negligible
increase in client->control bandwidth)
Updates tailscale/corp#1543
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2021-04-12 13:24:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											return  nil ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-28 14:16:23 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  len ( ips )  ==  0  &&  len ( eps )  ==  0  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
											// Only include loopback addresses if we have no 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-28 14:16:23 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											// interfaces at all to use as endpoints and don't 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// have a public IPv4 or IPv6 address. This allows 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
											// for localhost testing when you're on a plane and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// offline, for example. 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-02 10:38:44 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											ips  =  loopback 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 22:02:45 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										for  _ ,  ip  :=  range  ips  { 
							 
						 
					
						
							
								
									
										
										
											
												all: convert more code to use net/netip directly
    perl -i -npe 's,netaddr.IPPrefixFrom,netip.PrefixFrom,' $(git grep -l -F netaddr.)
    perl -i -npe 's,netaddr.IPPortFrom,netip.AddrPortFrom,' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPPrefix,netip.Prefix,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPPort,netip.AddrPort,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IP\b,netip.Addr,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPv6Raw\b,netip.AddrFrom16,g' $(git grep -l -F netaddr. )
    goimports -w .
Then delete some stuff from the net/netaddr shim package which is no
longer neeed.
Updates #5162
Change-Id: Ia7a86893fe21c7e3ee1ec823e8aba288d4566cd8
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2022-07-25 21:14:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											addAddr ( netip . AddrPortFrom ( ip ,  uint16 ( localAddr . Port ) ) ,  tailcfg . EndpointLocal ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// Our local endpoint is bound to a particular address. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// Do not offer addresses on other local interfaces. 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												tailcfg: add Endpoint, EndpointType, MapRequest.EndpointType
Track endpoints internally with a new tailcfg.Endpoint type that
includes a typed netaddr.IPPort (instead of just a string) and
includes a type for how that endpoint was discovered (STUN, local,
etc).
Use []tailcfg.Endpoint instead of []string internally.
At the last second, send it to the control server as the existing
[]string for endpoints, but also include a new parallel
MapRequest.EndpointType []tailcfg.EndpointType, so the control server
can start filtering out less-important endpoint changes from
new-enough clients. Notably, STUN-discovered endpoints can be filtered
out from 1.6+ clients, as they can discover them amongst each other
via CallMeMaybe disco exchanges started over DERP. And STUN endpoints
change a lot, causing a lot of MapResposne updates. But portmapped
endpoints are worth keeping for now, as they they work right away
without requiring the firewall traversal extra RTT dance.
End result will be less control->client bandwidth. (despite negligible
increase in client->control bandwidth)
Updates tailscale/corp#1543
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2021-04-12 13:24:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										addAddr ( ipp ( localAddr . String ( ) ) ,  tailcfg . EndpointLocal ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Note: the endpoints are intentionally returned in priority order, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// from "farthest but most reliable" to "closest but least 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// reliable." Addresses returned from STUN should be globally 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// addressable, but might go farther on the network than necessary. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Local interface addresses might have lower latency, but not be 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// globally addressable. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// The STUN address(es) are always first so that legacy wireguard 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// can use eps[0] as its only known endpoint address (although that's 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// obviously non-ideal). 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												tailcfg: add Endpoint, EndpointType, MapRequest.EndpointType
Track endpoints internally with a new tailcfg.Endpoint type that
includes a typed netaddr.IPPort (instead of just a string) and
includes a type for how that endpoint was discovered (STUN, local,
etc).
Use []tailcfg.Endpoint instead of []string internally.
At the last second, send it to the control server as the existing
[]string for endpoints, but also include a new parallel
MapRequest.EndpointType []tailcfg.EndpointType, so the control server
can start filtering out less-important endpoint changes from
new-enough clients. Notably, STUN-discovered endpoints can be filtered
out from 1.6+ clients, as they can discover them amongst each other
via CallMeMaybe disco exchanges started over DERP. And STUN endpoints
change a lot, causing a lot of MapResposne updates. But portmapped
endpoints are worth keeping for now, as they they work right away
without requiring the firewall traversal extra RTT dance.
End result will be less control->client bandwidth. (despite negligible
increase in client->control bandwidth)
Updates tailscale/corp#1543
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2021-04-12 13:24:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Despite this sorting, though, clients since 0.100 haven't relied 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// on the sorting order for any decisions. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  eps ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												tailcfg: add Endpoint, EndpointType, MapRequest.EndpointType
Track endpoints internally with a new tailcfg.Endpoint type that
includes a typed netaddr.IPPort (instead of just a string) and
includes a type for how that endpoint was discovered (STUN, local,
etc).
Use []tailcfg.Endpoint instead of []string internally.
At the last second, send it to the control server as the existing
[]string for endpoints, but also include a new parallel
MapRequest.EndpointType []tailcfg.EndpointType, so the control server
can start filtering out less-important endpoint changes from
new-enough clients. Notably, STUN-discovered endpoints can be filtered
out from 1.6+ clients, as they can discover them amongst each other
via CallMeMaybe disco exchanges started over DERP. And STUN endpoints
change a lot, causing a lot of MapResposne updates. But portmapped
endpoints are worth keeping for now, as they they work right away
without requiring the firewall traversal extra RTT dance.
End result will be less control->client bandwidth. (despite negligible
increase in client->control bandwidth)
Updates tailscale/corp#1543
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2021-04-12 13:24:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// endpointSetsEqual reports whether x and y represent the same set of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// endpoints. The order doesn't matter. 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-22 10:23:26 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// It does not mutate the slices. 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												tailcfg: add Endpoint, EndpointType, MapRequest.EndpointType
Track endpoints internally with a new tailcfg.Endpoint type that
includes a typed netaddr.IPPort (instead of just a string) and
includes a type for how that endpoint was discovered (STUN, local,
etc).
Use []tailcfg.Endpoint instead of []string internally.
At the last second, send it to the control server as the existing
[]string for endpoints, but also include a new parallel
MapRequest.EndpointType []tailcfg.EndpointType, so the control server
can start filtering out less-important endpoint changes from
new-enough clients. Notably, STUN-discovered endpoints can be filtered
out from 1.6+ clients, as they can discover them amongst each other
via CallMeMaybe disco exchanges started over DERP. And STUN endpoints
change a lot, causing a lot of MapResposne updates. But portmapped
endpoints are worth keeping for now, as they they work right away
without requiring the firewall traversal extra RTT dance.
End result will be less control->client bandwidth. (despite negligible
increase in client->control bandwidth)
Updates tailscale/corp#1543
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2021-04-12 13:24:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  endpointSetsEqual ( x ,  y  [ ] tailcfg . Endpoint )  bool  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-22 10:23:26 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  len ( x )  ==  len ( y )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										orderMatches  :=  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										for  i  :=  range  x  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  x [ i ]  !=  y [ i ]  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												orderMatches  =  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  orderMatches  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												tailcfg: add Endpoint, EndpointType, MapRequest.EndpointType
Track endpoints internally with a new tailcfg.Endpoint type that
includes a typed netaddr.IPPort (instead of just a string) and
includes a type for how that endpoint was discovered (STUN, local,
etc).
Use []tailcfg.Endpoint instead of []string internally.
At the last second, send it to the control server as the existing
[]string for endpoints, but also include a new parallel
MapRequest.EndpointType []tailcfg.EndpointType, so the control server
can start filtering out less-important endpoint changes from
new-enough clients. Notably, STUN-discovered endpoints can be filtered
out from 1.6+ clients, as they can discover them amongst each other
via CallMeMaybe disco exchanges started over DERP. And STUN endpoints
change a lot, causing a lot of MapResposne updates. But portmapped
endpoints are worth keeping for now, as they they work right away
without requiring the firewall traversal extra RTT dance.
End result will be less control->client bandwidth. (despite negligible
increase in client->control bandwidth)
Updates tailscale/corp#1543
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2021-04-12 13:24:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									m  :=  map [ tailcfg . Endpoint ] int { } 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-22 10:23:26 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									for  _ ,  v  :=  range  x  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										m [ v ]  |=  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									for  _ ,  v  :=  range  y  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										m [ v ]  |=  2 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-22 10:23:26 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									for  _ ,  n  :=  range  m  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  n  !=  3  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
											return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-02-19 22:15:41 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// LocalPort returns the current IPv4 listener's port number. 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  LocalPort ( )  uint16  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-20 12:57:10 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  runtime . GOOS  ==  "js"  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  12345 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-19 08:49:30 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									laddr  :=  c . pconn4 . LocalAddr ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									return  uint16 ( laddr . Port ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-10-06 15:22:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								var  errNetworkDown  =  errors . New ( "magicsock: network down" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-08-03 21:51:02 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  networkDown ( )  bool  {  return  ! c . networkUp . Load ( )  } 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-18 13:32:04 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-16 08:44:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// Send implements conn.Bind. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-02 13:22:28 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// See https://pkg.go.dev/github.com/tailscale/wireguard-go/conn#Bind.Send 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  Send ( buffs  [ ] [ ] byte ,  ep  conn . Endpoint ,  offset  int )  ( err  error )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 17:58:14 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									n  :=  int64 ( len ( buffs ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-29 09:19:40 +00:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									defer  func ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											c . metrics . outboundPacketsDroppedErrors . Add ( n ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 17:58:14 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									metricSendData . Add ( n ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-10-06 15:22:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  c . networkDown ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 17:58:14 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										metricSendDataNetworkDown . Add ( n ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-10-06 15:22:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  errNetworkDown 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-30 21:07:15 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  ep ,  ok  :=  ep . ( * endpoint ) ;  ok  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-02 13:22:28 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  ep . send ( buffs ,  offset ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-30 21:07:15 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// If it's not of type *endpoint, it's probably *lazyEndpoint, which means 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// we don't actually know who the peer is and we're waiting for wireguard-go 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// to switch the endpoint. See go/corp/20732. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  nil 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-18 13:32:04 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-02-18 13:32:04 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								var  errConnClosed  =  errors . New ( "Conn closed" ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-02-18 13:32:04 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								var  errDropDerpPacket  =  errors . New ( "too many DERP packets queued; dropping" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-10-22 09:09:37 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								var  errNoUDP  =  errors . New ( "no UDP available on platform" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-18 20:23:27 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								var  errUnsupportedConnType  =  errors . New ( "unsupported connection type" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  sendUDPBatch ( addr  epAddr ,  buffs  [ ] [ ] byte ,  offset  int )  ( sent  bool ,  err  error )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 17:58:14 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									isIPv6  :=  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									switch  { 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									case  addr . ap . Addr ( ) . Is4 ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									case  addr . ap . Addr ( ) . Is6 ( ) : 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 17:58:14 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										isIPv6  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										panic ( "bogus sendUDPBatch addr type" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  isIPv6  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-02 13:22:28 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										err  =  c . pconn6 . WriteBatchTo ( buffs ,  addr ,  offset ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 17:58:14 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-02 13:22:28 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										err  =  c . pconn4 . WriteBatchTo ( buffs ,  addr ,  offset ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-04 16:32:16 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										var  errGSO  neterror . ErrUDPGSODisabled 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  errors . As ( err ,  & errGSO )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											c . logf ( "magicsock: %s" ,  errGSO . Error ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											err  =  errGSO . RetryErr 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-15 13:57:55 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-06 13:10:56 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											c . maybeRebindOnError ( err ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-04 16:32:16 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 17:58:14 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  err  ==  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-30 12:22:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// sendUDP sends UDP packet b to ipp. 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-01 14:39:21 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// See sendAddr's docs on the return value meanings. 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-25 16:00:21 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  sendUDP ( ipp  netip . AddrPort ,  b  [ ] byte ,  isDisco  bool )  ( sent  bool ,  err  error )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-22 09:09:37 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  runtime . GOOS  ==  "js"  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  false ,  errNoUDP 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-24 20:08:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									sent ,  err  =  c . sendUDPStd ( ipp ,  b ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-13 18:51:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										metricSendUDPError . Add ( 1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-06 13:10:56 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . maybeRebindOnError ( err ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-13 18:51:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-25 16:00:21 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  sent  &&  ! isDisco  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-25 17:20:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											switch  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											case  ipp . Addr ( ) . Is4 ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												c . metrics . outboundPacketsIPv4Total . Add ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												c . metrics . outboundBytesIPv4Total . Add ( int64 ( len ( b ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											case  ipp . Addr ( ) . Is6 ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												c . metrics . outboundPacketsIPv6Total . Add ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												c . metrics . outboundBytesIPv6Total . Add ( int64 ( len ( b ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-13 18:51:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-17 17:11:27 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-30 12:22:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-01-06 13:10:56 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// maybeRebindOnError performs a rebind and restun if the error is one that is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// known to be healed by a rebind, and the rebind is not throttled. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  maybeRebindOnError ( err  error )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									ok ,  reason  :=  shouldRebind ( err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  c . lastErrRebind . Load ( ) . Before ( time . Now ( ) . Add ( - 5  *  time . Second ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . logf ( "magicsock: performing rebind due to %q" ,  reason ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . Rebind ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										go  c . ReSTUN ( reason ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . logf ( "magicsock: not performing %q rebind due to throttle" ,  reason ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-16 19:00:12 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// sendUDPNetcheck sends b via UDP to addr. It is used exclusively by netcheck. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// It returns the number of bytes sent along with any error encountered. It 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// returns errors.ErrUnsupported if the client is explicitly configured to only 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// send data over TCP port 443 and/or we're running on wasm. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  sendUDPNetcheck ( b  [ ] byte ,  addr  netip . AddrPort )  ( int ,  error )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  c . onlyTCP443 . Load ( )  ||  runtime . GOOS  ==  "js"  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  0 ,  errors . ErrUnsupported 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									switch  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									case  addr . Addr ( ) . Is4 ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  c . pconn4 . WriteToUDPAddrPort ( b ,  addr ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									case  addr . Addr ( ) . Is6 ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  c . pconn6 . WriteToUDPAddrPort ( b ,  addr ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										panic ( "bogus sendUDPNetcheck addr type" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-16 19:28:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// sendUDPStd sends UDP packet b to addr. 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-01 14:39:21 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// See sendAddr's docs on the return value meanings. 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-24 20:08:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  sendUDPStd ( addr  netip . AddrPort ,  b  [ ] byte )  ( sent  bool ,  err  error )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-22 14:18:04 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  c . onlyTCP443 . Load ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  false ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-30 12:22:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									switch  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-24 20:08:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									case  addr . Addr ( ) . Is4 ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										_ ,  err  =  c . pconn4 . WriteToUDPAddrPort ( b ,  addr ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-03 21:51:02 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  err  !=  nil  &&  ( c . noV4 . Load ( )  ||  neterror . TreatAsLostUDP ( err ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-01 14:39:21 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											return  false ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-29 12:40:51 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-24 20:08:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									case  addr . Addr ( ) . Is6 ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										_ ,  err  =  c . pconn6 . WriteToUDPAddrPort ( b ,  addr ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-03 21:51:02 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  err  !=  nil  &&  ( c . noV6 . Load ( )  ||  neterror . TreatAsLostUDP ( err ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-01 14:39:21 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											return  false ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-29 12:40:51 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-30 12:22:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									default : 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-01 14:39:21 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										panic ( "bogus sendUDPStd addr type" ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-20 13:38:21 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-01 14:39:21 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  err  ==  nil ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-20 13:38:21 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-02-18 13:32:04 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// sendAddr sends packet b to addr, which is either a real UDP address 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// or a fake UDP address representing a DERP server (see derpmap.go). 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// The provided public key identifies the recipient. 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-01 14:39:21 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// The returned err is whether there was an error writing when it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// should've worked. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// The returned sent is whether a packet went out at all. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// An example of when they might be different: sending to an 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// IPv6 address when the local machine doesn't have IPv6 support 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// returns (false, nil); it's not an error, but nothing was sent. 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-29 13:46:34 +00:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  sendAddr ( addr  netip . AddrPort ,  pubKey  key . NodePublic ,  b  [ ] byte ,  isDisco  bool )  ( sent  bool ,  err  error )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-26 12:06:03 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  addr . Addr ( )  !=  tailcfg . DerpMagicIPAddr  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-25 16:00:21 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  c . sendUDP ( addr ,  b ,  isDisco ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-04 12:21:40 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-07-06 19:20:15 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									regionID  :=  int ( addr . Port ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									ch  :=  c . derpWriteChanForRegion ( regionID ,  pubKey ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-04 12:21:40 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  ch  ==  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-13 18:51:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										metricSendDERPErrorChan . Add ( 1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-01 14:39:21 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  false ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-04 12:21:40 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-12 12:05:32 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// TODO(bradfitz): this makes garbage for now; we could use a 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// buffer pool later.  Previously we passed ownership of this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// to derpWriteRequest and waited for derphttp.Client.Send to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// complete, but that's too slow while holding wireguard-go 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// internal locks. 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-06 19:20:15 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									pkt  :=  bytes . Clone ( b ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-12 12:05:32 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-04 12:21:40 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									select  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-15 19:13:59 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									case  <- c . donec : 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-13 18:51:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										metricSendDERPErrorClosed . Add ( 1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-01 14:39:21 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  false ,  errConnClosed 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-29 13:46:34 +00:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									case  ch  <-  derpWriteRequest { addr ,  pubKey ,  pkt ,  isDisco } : 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-13 18:51:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										metricSendDERPQueued . Add ( 1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-01 14:39:21 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  true ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-04 12:21:40 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									default : 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-13 18:51:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										metricSendDERPErrorQueue . Add ( 1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-04 12:21:40 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										// Too many writes queued. Drop packet. 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-01 14:39:21 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  false ,  errDropDerpPacket 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-18 13:32:04 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 17:58:14 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								type  receiveBatch  struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									msgs  [ ] ipv6 . Message 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-04 16:32:16 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  getReceiveBatchForBuffs ( buffs  [ ] [ ] byte )  * receiveBatch  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 17:58:14 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									batch  :=  c . receiveBatchPool . Get ( ) . ( * receiveBatch ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-04 16:32:16 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									for  i  :=  range  buffs  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										batch . msgs [ i ] . Buffers [ 0 ]  =  buffs [ i ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										batch . msgs [ i ] . OOB  =  batch . msgs [ i ] . OOB [ : cap ( batch . msgs [ i ] . OOB ) ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 17:58:14 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  batch 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  putReceiveBatch ( batch  * receiveBatch )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									for  i  :=  range  batch . msgs  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-04 16:32:16 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										batch . msgs [ i ]  =  ipv6 . Message { Buffers :  batch . msgs [ i ] . Buffers ,  OOB :  batch . msgs [ i ] . OOB } 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 17:58:14 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . receiveBatchPool . Put ( batch ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-14 08:09:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  receiveIPv4 ( )  conn . ReceiveFunc  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-25 17:20:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  c . mkReceiveFunc ( & c . pconn4 ,  c . health . ReceiveFuncStats ( health . ReceiveIPv4 ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										& c . metrics . inboundPacketsIPv4Total , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										& c . metrics . inboundBytesIPv4Total , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									) 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-14 08:09:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 17:58:14 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-14 08:09:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// receiveIPv6 creates an IPv6 ReceiveFunc reading from c.pconn6. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  receiveIPv6 ( )  conn . ReceiveFunc  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-25 17:20:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  c . mkReceiveFunc ( & c . pconn6 ,  c . health . ReceiveFuncStats ( health . ReceiveIPv6 ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										& c . metrics . inboundPacketsIPv6Total , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										& c . metrics . inboundBytesIPv6Total , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									) 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-14 08:09:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 17:58:14 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-14 08:09:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// mkReceiveFunc creates a ReceiveFunc reading from ruc. 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-25 17:20:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// The provided healthItem and metrics are updated if non-nil. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  mkReceiveFunc ( ruc  * RebindingUDPConn ,  healthItem  * health . ReceiveFuncStats ,  packetMetric ,  bytesMetric  * expvar . Int )  conn . ReceiveFunc  { 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// epCache caches an epAddr->endpoint for hot flows. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									var  epCache  epAddrEndpointCache 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 17:58:14 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-08-14 10:28:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  func ( buffs  [ ] [ ] byte ,  sizes  [ ] int ,  eps  [ ] conn . Endpoint )  ( _  int ,  retErr  error )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-14 08:09:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  healthItem  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											healthItem . Enter ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											defer  healthItem . Exit ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-14 10:28:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											defer  func ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-02 18:10:20 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												if  retErr  !=  nil  &&  ! c . closing . Load ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-14 10:28:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													c . logf ( "Receive func %s exiting with error: %T, %v" ,  healthItem . Name ( ) ,  retErr ,  retErr ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-14 08:09:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  ruc  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											panic ( "nil RebindingUDPConn" ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-30 12:22:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 17:58:14 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-14 08:09:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										batch  :=  c . getReceiveBatchForBuffs ( buffs ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										defer  c . putReceiveBatch ( batch ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										for  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											numMsgs ,  err  :=  ruc . ReadBatch ( batch . msgs [ : len ( buffs ) ] ,  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												if  neterror . PacketWasTruncated ( err )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												return  0 ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 17:58:14 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-14 08:09:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											reportToCaller  :=  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											for  i ,  msg  :=  range  batch . msgs [ : numMsgs ]  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												if  msg . N  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													sizes [ i ]  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												ipp  :=  msg . Addr . ( * net . UDPAddr ) . AddrPort ( ) 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												if  ep ,  size ,  ok  :=  c . receiveIP ( msg . Buffers [ 0 ] [ : msg . N ] ,  ipp ,  & epCache ) ;  ok  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-25 17:20:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													if  packetMetric  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
														packetMetric . Add ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													if  bytesMetric  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
														bytesMetric . Add ( int64 ( msg . N ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-14 08:09:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													eps [ i ]  =  ep 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													sizes [ i ]  =  size 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-14 08:09:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
													reportToCaller  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													sizes [ i ]  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-04 16:32:16 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-14 08:09:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											if  reportToCaller  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												return  numMsgs ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 17:58:14 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-18 13:32:04 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-18 08:39:52 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-06 17:50:36 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-18 08:39:52 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// receiveIP is the shared bits of ReceiveIPv4 and ReceiveIPv6. 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-03 18:15:01 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// size is the length of 'b' to report up to wireguard-go (only relevant if 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 'ok' is true) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-03 18:15:01 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// ok is whether this read should be reported up to wireguard-go (our 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// caller). 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  receiveIP ( b  [ ] byte ,  ipp  netip . AddrPort ,  cache  * epAddrEndpointCache )  ( _  conn . Endpoint ,  size  int ,  ok  bool )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-08 20:31:16 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									var  ep  * endpoint 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									size  =  len ( b ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									var  geneve  packet . GeneveHeader 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									pt ,  isGeneveEncap  :=  packetLooksLike ( b ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									src  :=  epAddr { ap :  ipp } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  isGeneveEncap  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										err  :=  geneve . Decode ( b ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// Decode only returns an error when 'b' is too short, and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// 'isGeneveEncap' indicates it's a sufficient length. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											c . logf ( "[unexpected] geneve header decoding error: %v" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return  nil ,  0 ,  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										src . vni . set ( geneve . VNI ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									switch  pt  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									case  packetLooksLikeDisco : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  isGeneveEncap  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											b  =  b [ packet . GeneveFixedHeaderLength : ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// The Geneve header control bit should only be set for relay handshake 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// messages terminating on or originating from a UDP relay server. We 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// have yet to open the encrypted disco payload to determine the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// [disco.MessageType], but we assert it should be handshake-related. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										shouldByRelayHandshakeMsg  :=  geneve . Control  ==  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . handleDiscoMessage ( b ,  src ,  shouldByRelayHandshakeMsg ,  key . NodePublic { } ,  discoRXPathUDP ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  nil ,  0 ,  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									case  packetLooksLikeSTUNBinding : 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-26 17:01:32 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . netChecker . ReceiveSTUNPacket ( b ,  ipp ) 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  nil ,  0 ,  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// Fall through for all other packet types as they are assumed to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// be potentially WireGuard. 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-18 08:39:52 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-08-03 21:51:02 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  ! c . havePrivateKey . Load ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-03 18:15:01 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										// If we have no private key, we're logged out or 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-24 09:41:57 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										// stopped. Don't try to pass these wireguard packets 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// up to wireguard-go; it'll just complain (issue 1167). 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  nil ,  0 ,  false 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-03 18:15:01 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  src . vni . isSet ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// Strip away the Geneve header before returning the packet to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// wireguard-go. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// TODO(jwhited): update [github.com/tailscale/wireguard-go/conn.ReceiveFunc] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										//  to support returning start offset in order to get rid of this memmove perf 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										//  penalty. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										size  =  copy ( b ,  b [ packet . GeneveFixedHeaderLength : ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  cache . epAddr  ==  src  &&  cache . de  !=  nil  &&  cache . gen  ==  cache . de . numStopAndReset ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-18 15:27:44 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										ep  =  cache . de 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 22:15:48 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . mu . Lock ( ) 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										de ,  ok  :=  c . peerMap . endpointForEpAddr ( src ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 22:15:48 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . mu . Unlock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 19:39:20 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  ! ok  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-08 20:31:16 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											if  c . controlKnobs  !=  nil  &&  c . controlKnobs . DisableCryptorouting . Load ( )  { 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												return  nil ,  0 ,  false 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-08 20:31:16 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											return  & lazyEndpoint { c :  c ,  src :  src } ,  size ,  true 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-18 15:27:44 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										cache . epAddr  =  src 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 19:39:20 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										cache . de  =  de 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										cache . gen  =  de . numStopAndReset ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										ep  =  de 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-18 08:39:52 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-23 09:37:32 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									now  :=  mono . Now ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									ep . lastRecvUDPAny . StoreAtomic ( now ) 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									ep . noteRecvActivity ( src ,  now ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-28 15:59:33 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  stats  :=  c . stats . Load ( ) ;  stats  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-23 17:07:38 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										stats . UpdateRxPhysical ( ep . nodeAddr ,  ipp ,  1 ,  len ( b ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-27 16:26:52 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  ep ,  size ,  true 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-18 08:39:52 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-07-18 13:50:08 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// discoLogLevel controls the verbosity of discovery log messages. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								type  discoLogLevel  int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								const  ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// discoLog means that a message should be logged. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									discoLog  discoLogLevel  =  iota 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// discoVerboseLog means that a message should only be logged 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// in TS_DEBUG_DISCO mode. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									discoVerboseLog 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-12-20 19:29:25 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// TS_DISCO_PONG_IPV4_DELAY, if set, is a time.Duration string that is how much 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// fake latency to add before replying to disco pings. This can be used to bias 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// peers towards using IPv6 when both IPv4 and IPv6 are available at similar 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// speeds. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								var  debugIPv4DiscoPingPenalty  =  envknob . RegisterDuration ( "TS_DISCO_PONG_IPV4_DELAY" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-05-19 19:14:08 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// virtualNetworkID is a Geneve header (RFC8926) 3-byte virtual network 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// identifier. Its field must only ever be accessed via its methods. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								type  virtualNetworkID  struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									_vni  uint32 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								const  ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									vniSetMask  uint32  =  0xFF000000 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									vniGetMask  uint32  =  ^ vniSetMask 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// isSet returns true if set() had been called previously, otherwise false. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( v  * virtualNetworkID )  isSet ( )  bool  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  v . _vni & vniSetMask  !=  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// set sets the provided VNI. If VNI exceeds the 3-byte storage it will be 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// clamped. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( v  * virtualNetworkID )  set ( vni  uint32 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									v . _vni  =  vni  |  vniSetMask 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// get returns the VNI value. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( v  * virtualNetworkID )  get ( )  uint32  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  v . _vni  &  vniGetMask 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 21:44:52 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// sendDiscoMessage sends discovery message m to dstDisco at dst. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// If dst.ap is a DERP IP:port, then dstKey must be non-zero. 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 21:44:52 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// If dst.vni.isSet(), the [disco.Message] will be preceded by a Geneve header 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// with the VNI field set to the value returned by vni.get(). 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-28 15:55:49 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 21:44:52 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// The dstKey should only be non-zero if the dstDisco key 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// unambiguously maps to exactly one peer. 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  sendDiscoMessage ( dst  epAddr ,  dstKey  key . NodePublic ,  dstDisco  key . DiscoPublic ,  m  disco . Message ,  logLevel  discoLogLevel )  ( sent  bool ,  err  error )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									isDERP  :=  dst . ap . Addr ( )  ==  tailcfg . DerpMagicIPAddr 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  _ ,  isPong  :=  m . ( * disco . Pong ) ;  isPong  &&  ! isDERP  &&  dst . ap . Addr ( ) . Is4 ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-20 19:29:25 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										time . Sleep ( debugIPv4DiscoPingPenalty ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-28 15:55:49 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									isRelayHandshakeMsg  :=  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									switch  m . ( type )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									case  * disco . BindUDPRelayEndpoint ,  * disco . BindUDPRelayEndpointAnswer : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										isRelayHandshakeMsg  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-07-01 12:56:17 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-08 16:50:31 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  c . closed  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . mu . Unlock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-30 13:59:23 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  false ,  errConnClosed 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-08 16:50:31 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-30 19:07:31 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									var  di  * discoInfo 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									switch  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									case  isRelayHandshakeMsg : 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-02 13:08:17 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										var  ok  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										di ,  ok  =  c . relayManager . discoInfo ( dstDisco ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return  false ,  errors . New ( "unknown relay server" ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-30 19:07:31 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-02 09:04:18 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									case  c . peerMap . knownPeerDiscoKey ( dstDisco ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										di  =  c . discoInfoForKnownPeerLocked ( dstDisco ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-30 19:07:31 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// This is an attempt to send to an unknown peer that is not a relay 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// server. This can happen when a call to the current function, which is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// often via a new goroutine, races with applying a change in the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// netmap, e.g. the associated peer(s) for dstDisco goes away. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  false ,  errors . New ( "unknown peer" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-07-01 12:56:17 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									pkt  :=  make ( [ ] byte ,  0 ,  512 )  // TODO: size it correctly? pool? if it matters. 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  dst . vni . isSet ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-28 15:55:49 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										gh  :=  packet . GeneveHeader { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											Version :   0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											Protocol :  packet . GeneveProtocolDisco , 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											VNI :       dst . vni . get ( ) , 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-28 15:55:49 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											Control :   isRelayHandshakeMsg , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										pkt  =  append ( pkt ,  make ( [ ] byte ,  packet . GeneveFixedHeaderLength ) ... ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										err  :=  gh . Encode ( pkt ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return  false ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-01 12:56:17 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									pkt  =  append ( pkt ,  disco . Magic ... ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-29 14:27:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									pkt  =  c . discoPublic . AppendTo ( pkt ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-01 12:56:17 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-13 18:51:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  isDERP  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										metricSendDiscoDERP . Add ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										metricSendDiscoUDP . Add ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-10-29 14:27:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									box  :=  di . sharedKey . Seal ( m . AppendMarshal ( nil ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									pkt  =  append ( pkt ,  box ... ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-29 13:46:34 +00:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									const  isDisco  =  true 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									sent ,  err  =  c . sendAddr ( dst . ap ,  dstKey ,  pkt ,  isDisco ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-01 14:39:21 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  sent  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-14 12:49:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  logLevel  ==  discoLog  ||  ( logLevel  ==  discoVerboseLog  &&  debugDisco ( ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 21:44:52 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											node  :=  "?" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  ! dstKey . IsZero ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												node  =  dstKey . ShortString ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-08 13:11:28 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											c . dlogf ( "[v1] magicsock: disco: %v->%v (%v, %v) sent %v len %v\n" ,  c . discoShort ,  dstDisco . ShortString ( ) ,  node ,  derpStr ( dst . String ( ) ) ,  disco . MessageSummary ( m ) ,  len ( pkt ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-18 13:50:08 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-13 18:51:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  isDERP  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											metricSentDiscoDERP . Add ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											metricSentDiscoUDP . Add ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-20 09:29:31 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										switch  m . ( type )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										case  * disco . Ping : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											metricSentDiscoPing . Add ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										case  * disco . Pong : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											metricSentDiscoPong . Add ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										case  * disco . CallMeMaybe : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											metricSentDiscoCallMeMaybe . Add ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-01 14:39:21 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									}  else  if  err  ==  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-02 10:48:13 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										// Can't send. (e.g. no IPv6 locally) 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-01 14:39:21 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-19 20:04:22 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  ! c . networkDown ( )  &&  pmtuShouldLogDiscoTxErr ( m ,  err )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-17 18:52:29 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											c . logf ( "magicsock: disco: failed to send %v to %v: %v" ,  disco . MessageSummary ( m ) ,  dst ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-10-06 15:22:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-01 14:39:21 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  sent ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-01 12:56:17 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-04 16:32:16 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								type  discoRXPath  string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								const  ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									discoRXPathUDP        discoRXPath  =  "UDP socket" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									discoRXPathDERP       discoRXPath  =  "DERP" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									discoRXPathRawSocket  discoRXPath  =  "raw socket" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-30 13:31:35 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								const  discoHeaderLen  =  len ( disco . Magic )  +  key . DiscoPublicRawLen 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								type  packetLooksLikeType  int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								const  ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									packetLooksLikeWireGuard  packetLooksLikeType  =  iota 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									packetLooksLikeSTUNBinding 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									packetLooksLikeDisco 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// packetLooksLike reports a [packetsLooksLikeType] for 'msg', and whether 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 'msg' is encapsulated by a Geneve header (or naked). 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// [packetLooksLikeSTUNBinding] is never Geneve-encapsulated. 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-30 13:31:35 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// Naked STUN binding, Naked Disco, Geneve followed by Disco, naked WireGuard, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// and Geneve followed by WireGuard can be confidently distinguished based on 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// the following: 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-30 13:31:35 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								//  1. STUN binding @ msg[1] (0x01) is sufficiently non-overlapping with the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//     Geneve header where the LSB is always 0 (part of 6 "reserved" bits). 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//  2. STUN binding @ msg[1] (0x01) is sufficiently non-overlapping with naked 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//     WireGuard, which is always a 0 byte value (WireGuard message type 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//     occupies msg[0:4], and msg[1:4] are always 0). 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//  3. STUN binding @ msg[1] (0x01) is sufficiently non-overlapping with the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//     second byte of [disco.Magic] (0x53). 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//  4. [disco.Magic] @ msg[2:4] (0xf09f) is sufficiently non-overlapping with a 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//     Geneve protocol field value of [packet.GeneveProtocolDisco] or 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//     [packet.GeneveProtocolWireGuard] . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//  5. [disco.Magic] @ msg[0] (0x54) is sufficiently non-overlapping with the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//     first byte of a WireGuard packet (0x01-0x04). 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//  6. [packet.GeneveHeader] with a Geneve protocol field value of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//     [packet.GeneveProtocolDisco] or [packet.GeneveProtocolWireGuard] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//     (msg[2:4]) is sufficiently non-overlapping with the second 2 bytes of a 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//     WireGuard packet which are always 0x0000. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  packetLooksLike ( msg  [ ] byte )  ( t  packetLooksLikeType ,  isGeneveEncap  bool )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  stun . Is ( msg )  && 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										msg [ 1 ]  ==  0x01  {  // method binding 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  packetLooksLikeSTUNBinding ,  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// TODO(jwhited): potentially collapse into disco.LooksLikeDiscoWrapper() 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									//  if safe to do so. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									looksLikeDisco  :=  func ( msg  [ ] byte )  bool  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  len ( msg )  >=  discoHeaderLen  &&  string ( msg [ : len ( disco . Magic ) ] )  ==  disco . Magic  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Do we have a Geneve header? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  len ( msg )  >=  packet . GeneveFixedHeaderLength  && 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										msg [ 0 ] & 0xC0  ==  0  &&  // version bits that we always transmit as 0s 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										msg [ 1 ] & 0x3F  ==  0  &&  // reserved bits that we always transmit as 0s 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										msg [ 7 ]  ==  0  {  // reserved byte that we always transmit as 0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										switch  binary . BigEndian . Uint16 ( msg [ 2 : 4 ] )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										case  packet . GeneveProtocolDisco : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  looksLikeDisco ( msg [ packet . GeneveFixedHeaderLength : ] )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												return  packetLooksLikeDisco ,  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												// The Geneve header is well-formed, and it indicated this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												// was disco, but it's not. The evaluated bytes at this point 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												// are always distinct from naked WireGuard (msg[2:4] are always 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												// 0x0000) and naked Disco (msg[2:4] are always 0xf09f), but 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												// maintain pre-Geneve behavior and fall back to assuming it's 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												// naked WireGuard. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												return  packetLooksLikeWireGuard ,  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										case  packet . GeneveProtocolWireGuard : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return  packetLooksLikeWireGuard ,  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// The Geneve header is well-formed, but the protocol field value is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// unknown to us. The evaluated bytes at this point are not 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// necessarily distinct from naked WireGuard or naked Disco, fall 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// through. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  looksLikeDisco ( msg )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  packetLooksLikeDisco ,  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  packetLooksLikeWireGuard ,  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// handleDiscoMessage handles a discovery message. The caller is assumed to have 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// verified 'msg' returns [packetLooksLikeDisco] from packetLooksLike(). 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-26 14:38:53 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// A discovery message has the form: 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-02 09:33:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								//   - magic             [6]byte 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//   - senderDiscoPubKey [32]byte 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//   - nonce             [24]byte 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//   - naclbox of payload (see tailscale.com/disco package for inner payload format) 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-30 12:22:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// For messages received over DERP, the src.ap.Addr() will be derpMagicIP (with 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// src.ap.Port() being the region ID) and the derpNodeSrc will be the node key 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 16:42:24 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// it was received from at the DERP layer. derpNodeSrc is zero when received 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// over UDP. 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// If 'msg' was encapsulated by a Geneve header it is assumed to have already 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// been stripped. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 'shouldBeRelayHandshakeMsg' will be true if 'msg' was encapsulated 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// by a Geneve header with the control bit set. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  handleDiscoMessage ( msg  [ ] byte ,  src  epAddr ,  shouldBeRelayHandshakeMsg  bool ,  derpNodeSrc  key . NodePublic ,  via  discoRXPath )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-30 13:31:35 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									sender  :=  key . DiscoPublicFromRaw32 ( mem . B ( msg [ len ( disco . Magic ) : discoHeaderLen ] ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-26 14:38:53 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-07-08 16:50:31 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  c . closed  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-03 18:15:01 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-08 16:50:31 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-14 12:49:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  debugDisco ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-08 13:11:28 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . logf ( "magicsock: disco: got disco-looking frame from %v via %s len %v" ,  sender . ShortString ( ) ,  via ,  len ( msg ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-01 12:56:17 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-30 13:48:32 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  c . privateKey . IsZero ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// Ignore disco messages when we're stopped. 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-03 18:15:01 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-30 13:48:32 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-26 14:38:53 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-05-02 09:04:18 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									var  di  * discoInfo 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									switch  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									case  shouldBeRelayHandshakeMsg : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										var  ok  bool 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-02 13:08:17 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										di ,  ok  =  c . relayManager . discoInfo ( sender ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-02 09:04:18 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  debugDisco ( )  { 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												c . logf ( "magicsock: disco: ignoring disco-looking relay handshake frame, no active handshakes with key %v over %v" ,  sender . ShortString ( ) ,  src ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-02 09:04:18 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									case  c . peerMap . knownPeerDiscoKey ( sender ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										di  =  c . discoInfoForKnownPeerLocked ( sender ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									default : 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-13 18:51:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										metricRecvDiscoBadPeer . Add ( 1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-14 12:49:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  debugDisco ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-27 16:35:34 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											c . logf ( "magicsock: disco: ignoring disco-looking frame, don't know of key %v" ,  sender . ShortString ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-01 12:56:17 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-03 18:15:01 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-26 14:38:53 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 19:39:20 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									isDERP  :=  src . ap . Addr ( )  ==  tailcfg . DerpMagicIPAddr 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-02 09:04:18 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  ! isDERP  &&  ! shouldBeRelayHandshakeMsg  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-23 09:37:32 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										// Record receive time for UDP transport packets. 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										pi ,  ok  :=  c . peerMap . byEpAddr [ src ] 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-23 09:37:32 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											pi . ep . lastRecvUDPAny . StoreAtomic ( mono . Now ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-05-02 09:04:18 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// We're now reasonably sure we're expecting communication from 'sender', 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// do the heavy crypto lifting to see what they want. 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 20:45:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-30 13:31:35 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									sealedBox  :=  msg [ discoHeaderLen : ] 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-29 14:27:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									payload ,  ok  :=  di . sharedKey . Open ( sealedBox ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-26 14:38:53 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  ! ok  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-02 09:04:18 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										// This might have been intended for a previous 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-30 13:14:41 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										// disco key.  When we restart we get a new disco key 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// and old packets might've still been in flight (or 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// scheduled). This is particularly the case for LANs 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-04 16:32:16 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										// or non-NATed endpoints. UDP offloading on Linux 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// can also cause this when a disco message is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// received via raw socket at the head of a coalesced 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// group of messages. Don't log in normal case. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// Callers may choose to pass on to wireguard, in case 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// it's actually a wireguard packet (super unlikely, but). 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-14 12:49:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  debugDisco ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-04 16:32:16 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											c . logf ( "magicsock: disco: failed to open naclbox from %v (wrong rcpt?) via %s" ,  sender ,  via ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-01 12:56:17 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-13 18:51:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										metricRecvDiscoBadKey . Add ( 1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-03 18:15:01 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-26 14:38:53 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-08 15:48:27 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// Emit information about the disco frame into the pcap stream 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// if a capture hook is installed. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  cb  :=  c . captureHook . Load ( ) ;  cb  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										// TODO(jwhited): include VNI context? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										cb ( packet . PathDisco ,  time . Now ( ) ,  disco . ToPCAPFrame ( src . ap ,  derpNodeSrc ,  payload ) ,  packet . CaptureMeta { } ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-08 15:48:27 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-30 12:22:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									dm ,  err  :=  disco . Parse ( payload ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-14 12:49:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  debugDisco ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-01 12:56:17 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . logf ( "magicsock: disco: disco.Parse = %T, %v" ,  dm ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-30 12:22:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// Couldn't parse it, but it was inside a correctly 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// signed box, so just ignore it, assuming it's from a 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// newer version of Tailscale that we don't 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// understand. Not even worth logging about, lest it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// be too spammy for old clients. 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-13 18:51:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										metricRecvDiscoBadParse . Add ( 1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-03 18:15:01 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-30 12:22:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-13 18:51:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  isDERP  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										metricRecvDiscoDERP . Add ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										metricRecvDiscoUDP . Add ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-05-02 09:04:18 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  shouldBeRelayHandshakeMsg  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-02 13:08:17 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										challenge ,  ok  :=  dm . ( * disco . BindUDPRelayEndpointChallenge ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-02 09:04:18 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// We successfully parsed the disco message, but it wasn't a 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// challenge. We should never receive other message types 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// from a relay server with the Geneve header control bit set. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											c . logf ( "[unexpected] %T packets should not come from a relay server with Geneve control bit set" ,  dm ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . relayManager . handleGeneveEncapDiscoMsgNotBestAddr ( challenge ,  di ,  src ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-02 09:04:18 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-30 12:22:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									switch  dm  :=  dm . ( type )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									case  * disco . Ping : 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-13 18:51:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										metricRecvDiscoPing . Add ( 1 ) 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . handlePingLocked ( dm ,  src ,  di ,  derpNodeSrc ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-30 12:22:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									case  * disco . Pong : 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-13 18:51:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										metricRecvDiscoPong . Add ( 1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 21:55:59 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										// There might be multiple nodes for the sender's DiscoKey. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// Ask each to handle it, stopping once one reports that 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// the Pong's TxID was theirs. 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-28 10:45:59 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										knownTxID  :=  false 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-27 21:04:32 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . peerMap . forEachEndpointWithDiscoKey ( sender ,  func ( ep  * endpoint )  ( keepGoing  bool )  { 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											if  ep . handlePongConnLocked ( dm ,  di ,  src )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-28 10:45:59 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												knownTxID  =  true 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-27 21:04:32 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												return  false 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 21:55:59 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-27 21:04:32 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											return  true 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 21:55:59 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} ) 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  ! knownTxID  &&  src . vni . isSet ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											c . relayManager . handleGeneveEncapDiscoMsgNotBestAddr ( dm ,  di ,  src ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-28 10:45:59 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-02 13:08:17 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									case  * disco . CallMeMaybe ,  * disco . CallMeMaybeVia : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										var  via  * disco . CallMeMaybeVia 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										isVia  :=  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										msgType  :=  "CallMeMaybe" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										cmm ,  ok  :=  dm . ( * disco . CallMeMaybe ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											via  =  dm . ( * disco . CallMeMaybeVia ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											msgType  =  "CallMeMaybeVia" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											isVia  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-13 18:51:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										metricRecvDiscoCallMeMaybe . Add ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  ! isDERP  ||  derpNodeSrc . IsZero ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-02 13:08:17 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											// CallMeMaybe{Via} messages should only come via DERP. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											c . logf ( "[unexpected] %s packets should only come via DERP" ,  msgType ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-03 18:15:01 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											return 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-30 12:22:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-01 17:53:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										nodeKey  :=  derpNodeSrc 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-17 11:31:21 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										ep ,  ok  :=  c . peerMap . endpointForNodeKey ( nodeKey ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 16:42:24 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  ! ok  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-13 18:51:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											metricRecvDiscoCallMeMaybeBadNode . Add ( 1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-02 13:08:17 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											c . logf ( "magicsock: disco: ignoring %s from %v; %v is unknown" ,  msgType ,  sender . ShortString ( ) ,  derpNodeSrc . ShortString ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 16:42:24 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-09 14:50:01 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										ep . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										relayCapable  :=  ep . relayCapable 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										ep . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  isVia  &&  ! relayCapable  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											c . logf ( "magicsock: disco: ignoring %s from %v; %v is not known to be relay capable" ,  msgType ,  sender . ShortString ( ) ,  sender . ShortString ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-08 15:36:47 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										epDisco  :=  ep . disco . Load ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  epDisco  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  epDisco . key  !=  di . discoKey  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-13 18:51:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											metricRecvDiscoCallMeMaybeBadDisco . Add ( 1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-02 13:08:17 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											c . logf ( "[unexpected] %s from peer via DERP whose netmap discokey != disco source" ,  msgType ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-17 11:31:21 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-02 13:08:17 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  isVia  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											c . dlogf ( "[v1] magicsock: disco: %v<-%v via %v (%v, %v)  got call-me-maybe-via, %d endpoints" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												c . discoShort ,  epDisco . short ,  via . ServerDisco . ShortString ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												ep . publicKey . ShortString ( ) ,  derpStr ( src . String ( ) ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												len ( via . AddrPorts ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-16 13:51:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											c . relayManager . handleCallMeMaybeVia ( ep ,  via ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-02 13:08:17 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											c . dlogf ( "[v1] magicsock: disco: %v<-%v (%v, %v)  got call-me-maybe, %d endpoints" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												c . discoShort ,  epDisco . short , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												ep . publicKey . ShortString ( ) ,  derpStr ( src . String ( ) ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												len ( cmm . MyNumber ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											go  ep . handleCallMeMaybe ( cmm ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-30 12:22:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-03 18:15:01 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-26 14:38:53 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-10-17 11:31:21 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// unambiguousNodeKeyOfPingLocked attempts to look up an unambiguous mapping 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// from a DiscoKey dk (which sent ping dm) to a NodeKey. ok is true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// if there's the NodeKey is known unambiguously. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// derpNodeSrc is non-zero if the disco ping arrived via DERP. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// c.mu must be held. 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-01 17:53:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  unambiguousNodeKeyOfPingLocked ( dm  * disco . Ping ,  dk  key . DiscoPublic ,  derpNodeSrc  key . NodePublic )  ( nk  key . NodePublic ,  ok  bool )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-17 11:31:21 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  ! derpNodeSrc . IsZero ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-08 15:36:47 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  ep ,  ok  :=  c . peerMap . endpointForNodeKey ( derpNodeSrc ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											epDisco  :=  ep . disco . Load ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  epDisco  !=  nil  &&  epDisco . key  ==  dk  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												return  derpNodeSrc ,  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-17 11:31:21 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Pings after 1.16.0 contains its node source. See if it maps back. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  ! dm . NodeKey . IsZero ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-08 15:36:47 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  ep ,  ok  :=  c . peerMap . endpointForNodeKey ( dm . NodeKey ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											epDisco  :=  ep . disco . Load ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  epDisco  !=  nil  &&  epDisco . key  ==  dk  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												return  dm . NodeKey ,  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-17 11:31:21 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// If there's exactly 1 node in our netmap with DiscoKey dk, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// then it's not ambiguous which node key dm was from. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  set  :=  c . peerMap . nodesOfDisco [ dk ] ;  len ( set )  ==  1  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										for  nk  =  range  set  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return  nk ,  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  nk ,  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 20:45:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// di is the discoInfo of the source of the ping. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// derpNodeSrc is non-zero if the ping arrived via DERP. 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  handlePingLocked ( dm  * disco . Ping ,  src  epAddr ,  di  * discoInfo ,  derpNodeSrc  key . NodePublic )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 20:45:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									likelyHeartBeat  :=  src  ==  di . lastPingFrom  &&  time . Since ( di . lastPingTime )  <  5 * time . Second 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									di . lastPingFrom  =  src 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									di . lastPingTime  =  time . Now ( ) 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									isDerp  :=  src . ap . Addr ( )  ==  tailcfg . DerpMagicIPAddr 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-18 13:29:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-06-09 13:17:14 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// numNodes tracks how many nodes (node keys) are associated with the disco 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// key tied to this inbound ping. Multiple nodes may share the same disco 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// key in the case of node sharing and users switching accounts. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									var  numNodes  int 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 21:44:52 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// If we got a ping over DERP, then derpNodeSrc is non-zero and we reply 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// over DERP (in which case ipDst is also a DERP address). 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// But if the ping was over UDP (ipDst is not a DERP address), then dstKey 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// will be zero here, but that's fine: sendDiscoMessage only requires 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// a dstKey if the dst ip:port is DERP. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									dstKey  :=  derpNodeSrc 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-02 08:37:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-06-09 13:17:14 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									switch  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									case  src . vni . isSet ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  isDerp  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											c . logf ( "[unexpected] got Geneve-encapsulated disco ping from %v/%v over DERP" ,  src ,  derpNodeSrc ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										var  bestEpAddr  epAddr 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										var  discoKey  key . DiscoPublic 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										ep ,  ok  :=  c . peerMap . endpointForEpAddr ( src ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											ep . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											bestEpAddr  =  ep . bestAddr . epAddr 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											ep . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											disco  :=  ep . disco . Load ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  disco  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												discoKey  =  disco . key 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-27 21:04:32 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-09 13:17:14 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  src  ==  bestEpAddr  &&  discoKey  ==  di . discoKey  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// We have an associated endpoint with src as its bestAddr. Set 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// numNodes so we TX a pong further down. 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 21:44:52 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											numNodes  =  1 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-09 13:17:14 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// We have no [endpoint] in the [peerMap] for this relay [epAddr] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// using it as a bestAddr. [relayManager] might be in the middle of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// probing it or attempting to set it as best via 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// [endpoint.relayEndpointReady()]. Make [relayManager] aware. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											c . relayManager . handleGeneveEncapDiscoMsgNotBestAddr ( dm ,  di ,  src ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 21:44:52 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-09 13:17:14 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									default :  // no VNI 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// If we can figure out with certainty which node key this disco 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// message is for, eagerly update our [epAddr]<>node and disco<>node 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// mappings to make p2p path discovery faster in simple 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// cases. Without this, disco would still work, but would be 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// reliant on DERP call-me-maybe to establish the disco<>node 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// mapping, and on subsequent disco handlePongConnLocked to establish 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// the IP:port<>disco mapping. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  nk ,  ok  :=  c . unambiguousNodeKeyOfPingLocked ( dm ,  di . discoKey ,  derpNodeSrc ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  ! isDerp  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												c . peerMap . setNodeKeyForEpAddr ( src ,  nk ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 21:44:52 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-27 21:04:32 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-09 13:17:14 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// Remember this route if not present. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										var  dup  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  isDerp  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  ep ,  ok  :=  c . peerMap . endpointForNodeKey ( derpNodeSrc ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												if  ep . addCandidateEndpoint ( src . ap ,  dm . TxID )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												numNodes  =  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											c . peerMap . forEachEndpointWithDiscoKey ( di . discoKey ,  func ( ep  * endpoint )  ( keepGoing  bool )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												if  ep . addCandidateEndpoint ( src . ap ,  dm . TxID )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													dup  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												numNodes ++ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												if  numNodes  ==  1  &&  dstKey . IsZero ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													dstKey  =  ep . publicKey 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												return  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  dup  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  numNodes  >  1  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												// Zero it out if it's ambiguous, so sendDiscoMessage logging 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												// isn't confusing. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												dstKey  =  key . NodePublic { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 21:44:52 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  numNodes  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . logf ( "[unexpected] got disco ping from %v/%v for node not in peers" ,  src ,  derpNodeSrc ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-09-14 12:49:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  ! likelyHeartBeat  ||  debugDisco ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 21:44:52 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										pingNodeSrcStr  :=  dstKey . ShortString ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  numNodes  >  1  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											pingNodeSrcStr  =  "[one-of-multi]" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-05 20:05:19 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . dlogf ( "[v1] magicsock: disco: %v<-%v (%v, %v)  got ping tx=%x padding=%v" ,  c . discoShort ,  di . discoShort ,  pingNodeSrcStr ,  src ,  dm . TxID [ : 6 ] ,  dm . Padding ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 21:44:52 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-02 08:37:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-07-23 15:15:28 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									ipDst  :=  src 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 20:45:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									discoDest  :=  di . discoKey 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									go  c . sendDiscoMessage ( ipDst ,  dstKey ,  discoDest ,  & disco . Pong { 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-02 08:37:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										TxID :  dm . TxID , 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										Src :   src . ap , 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-18 13:50:08 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} ,  discoVerboseLog ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-02 08:37:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 12:41:25 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// enqueueCallMeMaybe schedules a send of disco.CallMeMaybe to de via derpAddr 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// once we know that our STUN endpoint is fresh. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// derpAddr is de.derpAddr at the time of send. It's assumed the peer won't be 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// flipping primary DERPs in the 0-30ms it takes to confirm our STUN endpoint. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// If they do, traffic will just go over DERP for a bit longer until the next 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// discovery round. 
							 
						 
					
						
							
								
									
										
										
											
												all: convert more code to use net/netip directly
    perl -i -npe 's,netaddr.IPPrefixFrom,netip.PrefixFrom,' $(git grep -l -F netaddr.)
    perl -i -npe 's,netaddr.IPPortFrom,netip.AddrPortFrom,' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPPrefix,netip.Prefix,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPPort,netip.AddrPort,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IP\b,netip.Addr,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPv6Raw\b,netip.AddrFrom16,g' $(git grep -l -F netaddr. )
    goimports -w .
Then delete some stuff from the net/netaddr shim package which is no
longer neeed.
Updates #5162
Change-Id: Ia7a86893fe21c7e3ee1ec823e8aba288d4566cd8
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2022-07-25 21:14:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  enqueueCallMeMaybe ( derpAddr  netip . AddrPort ,  de  * endpoint )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 12:41:25 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-08 15:36:47 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									epDisco  :=  de . disco . Load ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  epDisco  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 09:52:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  ! c . lastEndpointsTime . After ( time . Now ( ) . Add ( - endpointsFreshEnoughDuration ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-03 20:39:45 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . dlogf ( "[v1] magicsock: want call-me-maybe but endpoints stale; restunning" ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-31 13:47:25 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										mak . Set ( & c . onEndpointRefreshed ,  de ,  func ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-08 15:36:47 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											c . dlogf ( "[v1] magicsock: STUN done; sending call-me-maybe to %v %v" ,  epDisco . short ,  de . publicKey . ShortString ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 09:52:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											c . enqueueCallMeMaybe ( derpAddr ,  de ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-31 13:47:25 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 09:52:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										// TODO(bradfitz): make a new 'reSTUNQuickly' method 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// that passes down a do-a-lite-netcheck flag down to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// netcheck that does 1 (or 2 max) STUN queries 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// (UDP-only, not HTTPs) to find our port mapping to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// our home DERP and maybe one other. For now we do a 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// "full" ReSTUN which may or may not be a full one 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// (depending on age) and may do HTTPS timing queries 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// (if UDP is blocked). Good enough for now. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										go  c . ReSTUN ( "refresh-for-peering" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 12:41:25 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
											
												all: convert more code to use net/netip directly
    perl -i -npe 's,netaddr.IPPrefixFrom,netip.PrefixFrom,' $(git grep -l -F netaddr.)
    perl -i -npe 's,netaddr.IPPortFrom,netip.AddrPortFrom,' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPPrefix,netip.Prefix,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPPort,netip.AddrPort,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IP\b,netip.Addr,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPv6Raw\b,netip.AddrFrom16,g' $(git grep -l -F netaddr. )
    goimports -w .
Then delete some stuff from the net/netaddr shim package which is no
longer neeed.
Updates #5162
Change-Id: Ia7a86893fe21c7e3ee1ec823e8aba288d4566cd8
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2022-07-25 21:14:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									eps  :=  make ( [ ] netip . AddrPort ,  0 ,  len ( c . lastEndpoints ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 12:41:25 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									for  _ ,  ep  :=  range  c . lastEndpoints  { 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												tailcfg: add Endpoint, EndpointType, MapRequest.EndpointType
Track endpoints internally with a new tailcfg.Endpoint type that
includes a typed netaddr.IPPort (instead of just a string) and
includes a type for how that endpoint was discovered (STUN, local,
etc).
Use []tailcfg.Endpoint instead of []string internally.
At the last second, send it to the control server as the existing
[]string for endpoints, but also include a new parallel
MapRequest.EndpointType []tailcfg.EndpointType, so the control server
can start filtering out less-important endpoint changes from
new-enough clients. Notably, STUN-discovered endpoints can be filtered
out from 1.6+ clients, as they can discover them amongst each other
via CallMeMaybe disco exchanges started over DERP. And STUN endpoints
change a lot, causing a lot of MapResposne updates. But portmapped
endpoints are worth keeping for now, as they they work right away
without requiring the firewall traversal extra RTT dance.
End result will be less control->client bandwidth. (despite negligible
increase in client->control bandwidth)
Updates tailscale/corp#1543
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2021-04-12 13:24:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										eps  =  append ( eps ,  ep . Addr ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 12:41:25 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									go  de . c . sendDiscoMessage ( epAddr { ap :  derpAddr } ,  de . publicKey ,  epDisco . key ,  & disco . CallMeMaybe { MyNumber :  eps } ,  discoLog ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-03-24 19:11:48 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  debugSendCallMeUnknownPeer ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// Send a callMeMaybe packet to a non-existent peer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										unknownKey  :=  key . NewNode ( ) . Public ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . logf ( "magicsock: sending CallMeMaybe to unknown peer per TS_DEBUG_SEND_CALLME_UNKNOWN_PEER" ) 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										go  de . c . sendDiscoMessage ( epAddr { ap :  derpAddr } ,  unknownKey ,  epDisco . key ,  & disco . CallMeMaybe { MyNumber :  eps } ,  discoLog ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-03-24 19:11:48 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 12:41:25 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-30 19:07:31 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// discoInfoForKnownPeerLocked returns the previous or new discoInfo for k. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// Callers must only pass key.DiscoPublic's that are present in and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// lifetime-managed via [Conn].peerMap. UDP relay server disco keys are discovered 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// at relay endpoint allocation time or [disco.CallMeMaybeVia] reception time 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// and therefore must never pass through this method. 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 20:45:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// c.mu must be held. 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-30 19:07:31 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  discoInfoForKnownPeerLocked ( k  key . DiscoPublic )  * discoInfo  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 20:45:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									di ,  ok  :=  c . discoInfo [ k ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										di  =  & discoInfo { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											discoKey :    k , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											discoShort :  k . ShortString ( ) , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-29 14:27:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											sharedKey :   c . discoPrivate . Shared ( k ) , 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 20:45:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . discoInfo [ k ]  =  di 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-29 14:26:25 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 20:45:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  di 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-29 14:26:25 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-10-06 15:22:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  SetNetworkUp ( up  bool )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-03 21:51:02 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  c . networkUp . Load ( )  ==  up  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-10-06 15:22:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . logf ( "magicsock: SetNetworkUp(%v)" ,  up ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-03 21:51:02 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . networkUp . Store ( up ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-10-06 15:22:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-02-10 10:04:42 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  up  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . startDerpHomeConnectLocked ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-19 22:15:41 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . portMapper . NoteNetworkDown ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-10-06 15:22:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . closeAllDerpLocked ( "network-down" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-06-22 13:00:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// SetPreferredPort sets the connection's preferred local port. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  SetPreferredPort ( port  uint16 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-03 21:51:02 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  uint16 ( c . port . Load ( ) )  ==  port  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-22 13:00:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-03 21:51:02 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . port . Store ( uint32 ( port ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-22 13:00:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  err  :=  c . rebind ( dropCurrentPort ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-02 11:09:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . logf ( "%v" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-22 13:00:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . resetEndpointStates ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-02 09:31:25 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// SetPrivateKey sets the connection's private key. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// This is only used to be able prove our identity when connecting to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// DERP servers. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// If the private key changes, any DERP connections are torn down & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// recreated when needed. 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-28 11:07:25 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  SetPrivateKey ( privateKey  key . NodePrivate )  error  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-28 11:13:28 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-10-29 13:15:27 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									oldKey ,  newKey  :=  c . privateKey ,  privateKey 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  newKey . Equal ( oldKey )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-28 11:13:28 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . privateKey  =  newKey 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-03 21:51:02 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . havePrivateKey . Store ( ! newKey . IsZero ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-28 11:13:28 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 14:55:26 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  newKey . IsZero ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-01 17:53:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . publicKeyAtomic . Store ( key . NodePublic { } ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 14:55:26 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-01 17:53:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . publicKeyAtomic . Store ( newKey . Public ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-16 14:55:26 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-24 08:09:30 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  oldKey . IsZero ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-27 16:26:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . everHadKey  =  true 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-24 08:09:30 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . logf ( "magicsock: SetPrivateKey called (init)" ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-31 18:09:52 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										go  c . ReSTUN ( "set-private-key" ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-27 10:19:05 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									}  else  if  newKey . IsZero ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . logf ( "magicsock: SetPrivateKey called (zeroed)" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . closeAllDerpLocked ( "zero-private-key" ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 09:52:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . stopPeriodicReSTUNTimerLocked ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . onEndpointRefreshed  =  nil 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-24 08:09:30 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-27 10:19:05 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . logf ( "magicsock: SetPrivateKey called (changed)" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . closeAllDerpLocked ( "new-private-key" ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-24 08:09:30 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Key changed. Close existing DERP connections and reconnect to home. 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-27 10:19:05 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  c . myDerp  !=  0  &&  ! newKey . IsZero ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-09 14:21:36 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . logf ( "magicsock: private key changed, reconnecting to home derp-%d" ,  c . myDerp ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-10 10:04:42 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . startDerpHomeConnectLocked ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-24 08:09:30 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-02 09:31:25 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-07-30 13:48:32 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  newKey . IsZero ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 22:25:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . peerMap . forEachEndpoint ( func ( ep  * endpoint )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 19:39:20 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											ep . stopAndReset ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-30 13:48:32 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-02 09:31:25 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-04-18 08:48:01 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// UpdatePeers is called when the set of WireGuard peers changes. It 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// then removes any state for old peers. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// The caller passes ownership of newPeers map to UpdatePeers. 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-09 09:55:57 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  UpdatePeers ( newPeers  set . Set [ key . NodePublic ] )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-18 08:48:01 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									oldPeers  :=  c . peerSet 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . peerSet  =  newPeers 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-10-29 13:15:27 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// Clean up any key.NodePublic-keyed maps for peers that no longer 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-18 08:48:01 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// exist. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									for  peer  :=  range  oldPeers  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-09 09:55:57 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  ! newPeers . Contains ( peer )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-18 08:48:01 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											delete ( c . derpRoute ,  peer ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											delete ( c . peerLastDerp ,  peer ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-28 13:41:18 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  len ( oldPeers )  ==  0  &&  len ( newPeers )  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										go  c . ReSTUN ( "non-zero-peers" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-18 08:48:01 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 19:17:24 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  nodesEqual ( x ,  y  views . Slice [ tailcfg . NodeView ] )  bool  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  x . Len ( )  !=  y . Len ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-25 19:37:08 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-25 07:57:11 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									for  i  :=  range  x . Len ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 19:17:24 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  ! x . At ( i ) . Equal ( y . At ( i ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-25 19:37:08 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 10:13:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// debugRingBufferSize returns a maximum size for our set of endpoint ring 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// buffers by assuming that a single large update is ~500 bytes, and that we 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// want to not use more than 1MiB of memory on phones / 4MiB on other devices. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// Calculate the per-endpoint ring buffer size by dividing that out, but always 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// storing at least two entries. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  debugRingBufferSize ( numPeers  int )  int  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									const  defaultVal  =  2 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  numPeers  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  defaultVal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									var  maxRingBufferSize  int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  runtime . GOOS  ==  "ios"  ||  runtime . GOOS  ==  "android"  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-20 21:09:23 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										maxRingBufferSize  =  1  <<  20 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// But as of 2024-03-20, we now just disable the ring buffer entirely 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// on mobile as it hadn't proven useful enough to justify even 1 MB. 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 10:13:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-20 21:09:23 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										maxRingBufferSize  =  4  <<  20 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 10:13:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  v  :=  debugRingBufferMaxSizeBytes ( ) ;  v  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										maxRingBufferSize  =  v 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									const  averageRingBufferElemSize  =  512 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  max ( defaultVal ,  maxRingBufferSize / ( averageRingBufferElemSize * numPeers ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 19:17:24 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// debugFlags are the debug flags in use by the magicsock package. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// They might be set by envknob and/or controlknob. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// The value is comparable. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								type  debugFlags  struct  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-23 09:37:32 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									heartbeatDisabled   bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									probeUDPLifetimeOn  bool 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 19:17:24 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  debugFlagsLocked ( )  ( f  debugFlags )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-13 10:05:04 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									f . heartbeatDisabled  =  debugEnableSilentDisco ( )  ||  c . silentDiscoOn . Load ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-23 09:37:32 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									f . probeUDPLifetimeOn  =  c . probeUDPLifetimeOn . Load ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 19:17:24 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-11-13 10:05:04 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// SetSilentDisco toggles silent disco based on v. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  SetSilentDisco ( v  bool )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									old  :=  c . silentDiscoOn . Swap ( v ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  old  ==  v  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . peerMap . forEachEndpoint ( func ( ep  * endpoint )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										ep . setHeartbeatDisabled ( v ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// SilentDisco returns true if silent disco is enabled, otherwise false. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  SilentDisco ( )  bool  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									flags  :=  c . debugFlagsLocked ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  flags . heartbeatDisabled 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-01-23 09:37:32 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// SetProbeUDPLifetime toggles probing of UDP lifetime based on v. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  SetProbeUDPLifetime ( v  bool )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									old  :=  c . probeUDPLifetimeOn . Swap ( v ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  old  ==  v  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . peerMap . forEachEndpoint ( func ( ep  * endpoint )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										ep . setProbeUDPLifetimeOn ( v ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-06-10 17:31:14 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  capVerIsRelayCapable ( version  tailcfg . CapabilityVersion )  bool  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// TODO(jwhited): implement once capVer is bumped 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-25 11:04:52 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// SetNetworkMap is called when the control client gets a new network 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-25 19:37:08 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// map from the control server. It must always be non-nil. 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-25 11:04:52 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// It should not use the DERPMap field of NetworkMap; that's 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// conditionally sent to SetDERPMap instead. 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-05 15:44:46 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  SetNetworkMap ( nm  * netmap . NetworkMap )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-25 11:04:52 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 19:39:20 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  c . closed  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 19:17:24 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									priorPeers  :=  c . peers 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-13 18:51:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									metricNumPeers . Set ( int64 ( len ( nm . Peers ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-24 14:03:57 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// Update c.netMap regardless, before the following early return. 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 19:17:24 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									curPeers  :=  views . SliceOf ( nm . Peers ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . peers  =  curPeers 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-26 14:38:53 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 19:17:24 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									flags  :=  c . debugFlagsLocked ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-17 12:53:23 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  addrs  :=  nm . GetAddresses ( ) ;  addrs . Len ( )  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . firstAddrForTest  =  addrs . At ( 0 ) . Addr ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 19:17:24 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . firstAddrForTest  =  netip . Addr { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  nodesEqual ( priorPeers ,  curPeers )  &&  c . lastFlags  ==  flags  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-24 14:03:57 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										// The rest of this function is all adjusting state for peers that have 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// changed. But if the set of peers is equal and the debug flags (for 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-23 09:37:32 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										// silent disco and probe UDP lifetime) haven't changed, there is no 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// need to do anything else. 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-24 14:03:57 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 19:17:24 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . lastFlags  =  flags 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-24 14:03:57 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . logf ( "[v1] magicsock: got updated network map; %d peers" ,  len ( nm . Peers ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-16 23:48:46 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 10:13:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									entriesPerBuffer  :=  debugRingBufferSize ( len ( nm . Peers ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-21 15:57:08 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-08-31 13:25:58 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// Try a pass of just upserting nodes and creating missing 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// endpoints. If the set of nodes is the same, this is an 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// efficient alloc-free update. If the set of nodes is different, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// we'll fall through to the next pass, which allocates but can 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// handle full set updates. 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 19:39:20 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									for  _ ,  n  :=  range  nm . Peers  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 10:13:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  n . ID ( )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											devPanicf ( "node with zero ID" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  n . Key ( ) . IsZero ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											devPanicf ( "node with zero key" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										ep ,  ok  :=  c . peerMap . endpointForNodeID ( n . ID ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  ok  &&  ep . publicKey  !=  n . Key ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// The node rotated public keys. Delete the old endpoint and create 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// it anew. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											c . peerMap . deleteEndpoint ( ep ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											ok  =  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// At this point we're modifying an existing endpoint (ep) whose 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// public key and nodeID match n. Its other fields (such as disco 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// key or endpoints) might've changed. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-08-18 07:57:44 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											if  n . DiscoKey ( ) . IsZero ( )  &&  ! n . IsWireGuardOnly ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-05 17:28:28 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												// Discokey transitioned from non-zero to zero? This should not 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												// happen in the wild, however it could mean: 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												// 1. A node was downgraded from post 0.100 to pre 0.100. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												// 2. A Tailscale node key was extracted and used on a 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												//    non-Tailscale node (should not enter here due to the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												//    IsWireGuardOnly check) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												// 3. The server is misbehaving. 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-18 12:43:09 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												c . peerMap . deleteEndpoint ( ep ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-08 15:36:47 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											var  oldDiscoKey  key . DiscoPublic 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  epDisco  :=  ep . disco . Load ( ) ;  epDisco  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												oldDiscoKey  =  epDisco . key 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-23 09:37:32 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											ep . updateFromNode ( n ,  flags . heartbeatDisabled ,  flags . probeUDPLifetimeOn ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 14:03:47 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											c . peerMap . upsertEndpoint ( ep ,  oldDiscoKey )  // maybe update discokey mappings in peerMap 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-31 16:55:22 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 10:13:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  ep ,  ok  :=  c . peerMap . endpointForNodeKey ( n . Key ( ) ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// At this point n.Key() should be for a key we've never seen before. If 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// ok was true above, it was an update to an existing matching key and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// we don't get this far. If ok was false above, that means it's a key 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// that differs from the one the NodeID had. But double check. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  ep . nodeID  !=  n . ID ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												// Server error. 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-27 13:32:08 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												devPanicf ( "public key moved between nodeIDs (old=%v new=%v, key=%s)" ,  ep . nodeID ,  n . ID ( ) ,  n . Key ( ) . String ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 10:13:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												// Internal data structures out of sync. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												devPanicf ( "public key found in peerMap but not by nodeID" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-18 07:57:44 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  n . DiscoKey ( ) . IsZero ( )  &&  ! n . IsWireGuardOnly ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 10:13:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											// Ancient pre-0.100 node, which does not have a disco key. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// No longer supported. 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-18 12:43:09 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-31 13:25:58 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 10:13:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										ep  =  & endpoint { 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-16 23:48:46 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											c :                  c , 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 10:13:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											nodeID :             n . ID ( ) , 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-18 07:57:44 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											publicKey :          n . Key ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											publicKeyHex :       n . Key ( ) . UntypedHexString ( ) , 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-16 23:48:46 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											sentPing :           map [ stun . TxID ] sentPing { } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											endpointState :      map [ netip . AddrPort ] * endpointState { } , 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 19:17:24 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											heartbeatDisabled :  flags . heartbeatDisabled , 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-18 07:57:44 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											isWireguardOnly :    n . IsWireGuardOnly ( ) , 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-31 16:55:22 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-20 21:09:23 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										switch  runtime . GOOS  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										case  "ios" ,  "android" : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// Omit, to save memory. Prior to 2024-03-20 we used to limit it to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// ~1MB on mobile but we never used the data so the memory was just 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											// wasted. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											ep . debugUpdates  =  ringbuffer . New [ EndpointChange ] ( entriesPerBuffer ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-18 07:57:44 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  n . Addresses ( ) . Len ( )  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											ep . nodeAddr  =  n . Addresses ( ) . At ( 0 ) . Addr ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-27 16:26:52 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-31 16:55:22 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										ep . initFakeUDPAddr ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-18 07:57:44 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  n . DiscoKey ( ) . IsZero ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-05 17:28:28 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											ep . disco . Store ( nil ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											ep . disco . Store ( & endpointDisco { 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-18 07:57:44 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												key :    n . DiscoKey ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												short :  n . DiscoKey ( ) . ShortString ( ) , 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-05 17:28:28 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											} ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 10:13:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-05 17:28:28 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 10:13:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  debugPeerMap ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											c . logEndpointCreated ( n ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-18 10:51:34 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 10:13:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-01-23 09:37:32 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										ep . updateFromNode ( n ,  flags . heartbeatDisabled ,  flags . probeUDPLifetimeOn ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-10 14:03:47 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . peerMap . upsertEndpoint ( ep ,  key . DiscoPublic { } ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-26 14:38:53 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 19:39:20 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// If the set of nodes changed since the last SetNetworkMap, the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// upsert loop just above made c.peerMap contain the union of the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// old and new peers - which will be larger than the set from the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// current netmap. If that happens, go through the allocful 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// deletion path to clean up moribund nodes. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  c . peerMap . nodeCount ( )  !=  len ( nm . Peers )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 10:13:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										keep  :=  set . Set [ key . NodePublic ] { } 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 19:39:20 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										for  _ ,  n  :=  range  nm . Peers  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 10:13:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											keep . Add ( n . Key ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-28 11:53:37 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 22:25:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . peerMap . forEachEndpoint ( func ( ep  * endpoint )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 10:13:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											if  ! keep . Contains ( ep . publicKey )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 22:25:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												c . peerMap . deleteEndpoint ( ep ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 19:39:20 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-28 11:53:37 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-06 10:18:12 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 20:45:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// discokeys might have changed in the above. Discard unused info. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									for  dk  :=  range  c . discoInfo  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-27 16:35:34 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  ! c . peerMap . knownPeerDiscoKey ( dk )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 20:45:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											delete ( c . discoInfo ,  dk ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-06 10:18:12 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-25 11:04:52 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 10:13:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  devPanicf ( format  string ,  a  ... any )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  testenv . InTest ( )  ||  envknob . CrashOnUnexpected ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										panic ( fmt . Sprintf ( format ,  a ... ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  logEndpointCreated ( n  tailcfg . NodeView )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . logf ( "magicsock: created endpoint key=%s: disco=%s; %v" ,  n . Key ( ) . ShortString ( ) ,  n . DiscoKey ( ) . ShortString ( ) ,  logger . ArgWriter ( func ( w  * bufio . Writer )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-14 10:19:52 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  regionID  :=  n . HomeDERP ( ) ;  regionID  !=  0  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 10:13:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											code  :=  c . derpRegionCodeLocked ( regionID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  code  !=  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												code  =  "("  +  code  +  ")" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											fmt . Fprintf ( w ,  "derp=%v%s " ,  regionID ,  code ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-11 13:08:47 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										for  _ ,  a  :=  range  n . AllowedIPs ( ) . All ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 10:13:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											if  a . IsSingleIP ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												fmt . Fprintf ( w ,  "aip=%v " ,  a . Addr ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												fmt . Fprintf ( w ,  "aip=%v " ,  a ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-11 13:08:47 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										for  _ ,  ep  :=  range  n . Endpoints ( ) . All ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 10:13:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											fmt . Fprintf ( w ,  "ep=%v " ,  ep ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												tailcfg: add Endpoint, EndpointType, MapRequest.EndpointType
Track endpoints internally with a new tailcfg.Endpoint type that
includes a typed netaddr.IPPort (instead of just a string) and
includes a type for how that endpoint was discovered (STUN, local,
etc).
Use []tailcfg.Endpoint instead of []string internally.
At the last second, send it to the control server as the existing
[]string for endpoints, but also include a new parallel
MapRequest.EndpointType []tailcfg.EndpointType, so the control server
can start filtering out less-important endpoint changes from
new-enough clients. Notably, STUN-discovered endpoints can be filtered
out from 1.6+ clients, as they can discover them amongst each other
via CallMeMaybe disco exchanges started over DERP. And STUN endpoints
change a lot, causing a lot of MapResposne updates. But portmapped
endpoints are worth keeping for now, as they they work right away
without requiring the firewall traversal extra RTT dance.
End result will be less control->client bandwidth. (despite negligible
increase in client->control bandwidth)
Updates tailscale/corp#1543
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2021-04-12 13:24:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  logEndpointChange ( endpoints  [ ] tailcfg . Endpoint )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-31 15:29:04 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . logf ( "magicsock: endpoints changed: %s" ,  logger . ArgWriter ( func ( buf  * bufio . Writer )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										for  i ,  ep  :=  range  endpoints  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  i  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												buf . WriteString ( ", " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												tailcfg: add Endpoint, EndpointType, MapRequest.EndpointType
Track endpoints internally with a new tailcfg.Endpoint type that
includes a typed netaddr.IPPort (instead of just a string) and
includes a type for how that endpoint was discovered (STUN, local,
etc).
Use []tailcfg.Endpoint instead of []string internally.
At the last second, send it to the control server as the existing
[]string for endpoints, but also include a new parallel
MapRequest.EndpointType []tailcfg.EndpointType, so the control server
can start filtering out less-important endpoint changes from
new-enough clients. Notably, STUN-discovered endpoints can be filtered
out from 1.6+ clients, as they can discover them amongst each other
via CallMeMaybe disco exchanges started over DERP. And STUN endpoints
change a lot, causing a lot of MapResposne updates. But portmapped
endpoints are worth keeping for now, as they they work right away
without requiring the firewall traversal extra RTT dance.
End result will be less control->client bandwidth. (despite negligible
increase in client->control bandwidth)
Updates tailscale/corp#1543
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2021-04-12 13:24:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											fmt . Fprintf ( buf ,  "%s (%s)" ,  ep . Addr ,  ep . Type ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-24 08:09:30 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-31 15:29:04 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-24 08:09:30 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-24 09:41:57 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// Bind returns the wireguard-go conn.Bind for c. 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-16 08:44:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// See https://pkg.go.dev/golang.zx2c4.com/wireguard/conn#Bind 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-24 09:41:57 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  Bind ( )  conn . Bind  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  c . bind 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// connBind is a wireguard-go conn.Bind for a Conn. 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-02 18:36:24 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// It bridges the behavior of wireguard-go and a Conn. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// wireguard-go calls Close then Open on device.Up. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// That won't work well for a Conn, which is only closed on shutdown. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// The subsequent Close is a real close. 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-24 09:41:57 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								type  connBind  struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									* Conn 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									mu      sync . Mutex 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									closed  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-07-26 14:39:52 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// This is a compile-time assertion that connBind implements the wireguard-go 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// conn.Bind interface. 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-16 08:44:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								var  _  conn . Bind  =  ( * connBind ) ( nil ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// BatchSize returns the number of buffers expected to be passed to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// the ReceiveFuncs, and the maximum expected to be passed to SendBatch. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// See https://pkg.go.dev/golang.zx2c4.com/wireguard/conn#Bind.BatchSize 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 17:58:14 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * connBind )  BatchSize ( )  int  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// TODO(raggi): determine by properties rather than hardcoding platform behavior 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									switch  runtime . GOOS  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									case  "linux" : 
							 
						 
					
						
							
								
									
										
										
										
											2023-03-28 15:37:11 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  conn . IdealBatchSize 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 17:58:14 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-24 09:41:57 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// Open is called by WireGuard to create a UDP binding. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// The ignoredPort comes from wireguard-go, via the wgcfg config. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// We ignore that port value here, since we have the local port available easily. 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-16 08:44:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// See https://pkg.go.dev/golang.zx2c4.com/wireguard/conn#Bind.Open 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-24 09:41:57 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * connBind )  Open ( ignoredPort  uint16 )  ( [ ] conn . ReceiveFunc ,  uint16 ,  error )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  ! c . closed  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  nil ,  0 ,  errors . New ( "magicsock: connBind already open" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . closed  =  false 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-14 08:09:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									fns  :=  [ ] conn . ReceiveFunc { c . receiveIPv4 ( ) ,  c . receiveIPv6 ( ) ,  c . receiveDERP } 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-20 12:14:19 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  runtime . GOOS  ==  "js"  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										fns  =  [ ] conn . ReceiveFunc { c . receiveDERP } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-24 09:41:57 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// TODO: Combine receiveIPv4 and receiveIPv6 and receiveIP into a single 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// closure that closes over a *RebindingUDPConn? 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-20 12:57:10 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  fns ,  c . LocalPort ( ) ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-24 09:41:57 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// SetMark is used by wireguard-go to set a mark bit for packets to avoid routing loops. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// We handle that ourselves elsewhere. 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-16 08:44:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// See https://pkg.go.dev/golang.zx2c4.com/wireguard/conn#Bind.SetMark 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-24 09:41:57 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * connBind )  SetMark ( value  uint32 )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-02 18:36:24 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// Close closes the connBind, unless it is already closed. 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-16 08:44:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// See https://pkg.go.dev/golang.zx2c4.com/wireguard/conn#Bind.Close 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-24 09:41:57 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * connBind )  Close ( )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  c . closed  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . closed  =  true 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-16 08:42:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// Close the [eventbus.Client]. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  c . eventClient  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . eventClient . Close ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-24 09:41:57 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// Unblock all outstanding receives. 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-02 14:24:51 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . pconn4 . Close ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . pconn6 . Close ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-29 10:57:54 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  c . closeDisco4  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . closeDisco4 . Close ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  c . closeDisco6  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . closeDisco6 . Close ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-24 09:47:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  c . eventClient  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . eventClient . Close ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-24 09:41:57 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// Send an empty read result to unblock receiveDERP, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// which will then check connBind.Closed. 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-14 13:43:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// connBind.Closed takes c.mu, but c.derpRecvCh is buffered. 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-24 09:41:57 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . derpRecvCh  <-  derpReadResult { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-16 08:44:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// isClosed reports whether c is closed. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * connBind )  isClosed ( )  bool  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-24 09:41:57 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  c . closed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// Close closes the connection. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// Only the first close does anything. Any later closes return nil. 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  Close ( )  error  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-14 16:51:17 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  c . closed  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-18 13:32:04 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-17 18:54:03 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . closing . Store ( true ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-19 15:29:50 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  c . derpCleanupTimerArmed  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . derpCleanupTimer . Stop ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 09:52:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . stopPeriodicReSTUNTimerLocked ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-19 22:15:41 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . portMapper . Close ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-12 17:04:57 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . portMapperLogfUnregister ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-02 09:31:25 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 22:25:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . peerMap . forEachEndpoint ( func ( ep  * endpoint )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-30 13:48:32 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										ep . stopAndReset ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 19:39:20 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-08 16:50:31 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . closed  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . connCtxCancel ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-23 14:12:23 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . closeAllDerpLocked ( "conn-close" ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-02 18:36:24 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// Ignore errors from c.pconnN.Close. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// They will frequently have been closed already by a call to connBind.Close. 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-02 14:24:51 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . pconn6 . Close ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . pconn4 . Close ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-23 19:07:24 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  c . closeDisco4  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . closeDisco4 . Close ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  c . closeDisco6  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . closeDisco6 . Close ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-04 09:36:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Wait on goroutines updating right at the end, once everything is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// already closed. We want everything else in the Conn to be 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// consistently in the closed state before we release mu to wait 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// on the endpoint updater & derphttp.Connect. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									for  c . goroutinesRunningLocked ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . muCond . Wait ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-02 17:49:56 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  pinger  :=  c . getPinger ( ) ;  pinger  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										pinger . Close ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-25 17:20:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									deregisterMetrics ( c . metrics ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-02 18:36:24 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  nil 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-04 09:36:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  goroutinesRunningLocked ( )  bool  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  c . endpointsUpdateActive  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-14 13:07:46 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// The goroutine running dc.Connect in derpWriteChanOfAddr may linger 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// and appear to leak, as observed in https://github.com/tailscale/tailscale/issues/554. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// This is despite the underlying context being cancelled by connCtxCancel above. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// To avoid this condition, we must wait on derpStarted here 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// to ensure that this goroutine has exited by the time Close returns. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// We only do this if derpWriteChanOfAddr has executed at least once: 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// on the first run, it sets firstDerp := true and spawns the aforementioned goroutine. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// To detect this, we check activeDerp, which is initialized to non-nil on the first run. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  c . activeDerp  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-04 09:36:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										select  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										case  <- c . derpStarted : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											return  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-27 13:03:22 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-04 09:36:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  false 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 09:52:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  shouldDoPeriodicReSTUNLocked ( )  bool  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-15 15:10:45 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  c . networkDown ( )  ||  c . homeless  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-10-06 15:22:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 09:52:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  len ( c . peerSet )  ==  0  ||  c . privateKey . IsZero ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// If no peers, not worth doing. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// Also don't if there's no key (not running). 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-25 14:19:12 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  f  :=  c . idleFunc ;  f  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										idleFor  :=  f ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-14 12:49:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  debugReSTUNStopOnIdle ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-25 14:19:12 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											c . logf ( "magicsock: periodicReSTUN: idle for %v" ,  idleFor . Round ( time . Second ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-26 13:59:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  idleFor  >  sessionActiveTimeout  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-11 17:53:21 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											if  c . controlKnobs  !=  nil  &&  c . controlKnobs . ForceBackgroundSTUN . Load ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 09:52:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
												// Overridden by control. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												return  true 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-25 14:19:12 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 09:52:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											return  false 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-25 14:19:12 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  true 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-28 13:41:18 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-07-09 10:01:50 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  onPortMapChanged ( )  {  c . ReSTUN ( "portmap-changed" )  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-12 20:10:11 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// ReSTUN triggers an address discovery. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// The provided why string is for debug logging only. 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-23 18:50:55 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// If Conn.staticEndpoints have been updated, calling ReSTUN will also result in 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// the new endpoints being advertised. 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-12 20:10:11 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  ReSTUN ( why  string )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-27 13:03:22 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  c . closed  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// raced with a shutdown. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2022-04-22 10:40:49 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									metricReSTUNCalls . Add ( 1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-27 16:26:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// If the user stopped the app, stop doing work. (When the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// user stops Tailscale via the GUI apps, ipn/local.go 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// reconfigures the engine with a zero private key.) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// This used to just check c.privateKey.IsZero, but that broke 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-25 14:29:55 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// some end-to-end tests that didn't ever set a private 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-27 16:26:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// key somehow. So for now, only stop doing work if we ever 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// had a key, which helps real users, but appeases tests for 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// now. TODO: rewrite those tests to be less brittle or more 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// realistic. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  c . privateKey . IsZero ( )  &&  c . everHadKey  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . logf ( "magicsock: ReSTUN(%q) ignored; stopped, no private key" ,  why ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-27 10:19:05 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-27 13:03:22 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  c . endpointsUpdateActive  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  c . wantEndpointsUpdate  !=  why  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-03 20:39:45 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											c . dlogf ( "[v1] magicsock: ReSTUN: endpoint update active, need another later (%q)" ,  why ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-13 08:55:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											c . wantEndpointsUpdate  =  why 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . endpointsUpdateActive  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										go  c . updateEndpoints ( why ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-18 10:55:25 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-28 10:28:44 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// listenPacket opens a packet listener. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// The network must be "udp4" or "udp6". 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-24 20:08:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  listenPacket ( network  string ,  port  uint16 )  ( nettype . PacketConn ,  error )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-03-06 15:35:50 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									ctx  :=  context . Background ( )  // unused without DNS name to resolve 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  network  ==  "udp4"  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-12 18:23:22 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										ctx  =  sockstats . WithSockStats ( ctx ,  sockstats . LabelMagicsockConnUDP4 ,  c . logf ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-03-06 15:35:50 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-12 18:23:22 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										ctx  =  sockstats . WithSockStats ( ctx ,  sockstats . LabelMagicsockConnUDP6 ,  c . logf ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-03-06 15:35:50 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 23:33:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									addr  :=  net . JoinHostPort ( "" ,  fmt . Sprint ( port ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 22:26:25 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  c . testOnlyPacketListener  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-24 20:08:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  nettype . MakePacketListenerWithNetIP ( c . testOnlyPacketListener ) . ListenPacket ( ctx ,  network ,  addr ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-10 14:26:04 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-17 16:01:41 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  nettype . MakePacketListenerWithNetIP ( netns . Listener ( c . logf ,  c . netMon ) ) . ListenPacket ( ctx ,  network ,  addr ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-10 14:26:04 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-27 14:40:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// bindSocket initializes rucPtr if necessary and binds a UDP socket to it. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// Network indicates the UDP socket type; it must be "udp4" or "udp6". 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// If rucPtr had an existing UDP socket bound, it closes that socket. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// The caller is responsible for informing the portMapper of any changes. 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-22 13:00:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// If curPortFate is set to dropCurrentPort, no attempt is made to reuse 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// the current port. 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-02 14:24:51 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  bindSocket ( ruc  * RebindingUDPConn ,  network  string ,  curPortFate  currentPortFate )  error  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-31 13:05:07 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  debugBindSocket ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . logf ( "magicsock: bindSocket: network=%q curPortFate=%v" ,  network ,  curPortFate ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-27 14:40:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// Hold the ruc lock the entire time, so that the close+bind is atomic 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// from the perspective of ruc receive functions. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									ruc . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  ruc . mu . Unlock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-08 15:48:49 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-09-06 12:16:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  runtime . GOOS  ==  "js"  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-04 16:32:16 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										ruc . setConnLocked ( newBlockForeverConn ( ) ,  "" ,  c . bind . BatchSize ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-06 12:16:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-09-14 12:49:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  debugAlwaysDERP ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-13 16:01:37 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . logf ( "disabled %v per TS_DEBUG_ALWAYS_USE_DERP" ,  network ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-04 16:32:16 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										ruc . setConnLocked ( newBlockForeverConn ( ) ,  "" ,  c . bind . BatchSize ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-13 16:01:37 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-27 14:40:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// Build a list of preferred ports. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Best is the port that the user requested. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Second best is the port that is currently in use. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// If those fail, fall back to 0. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									var  ports  [ ] uint16 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-03 21:51:02 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  port  :=  uint16 ( c . port . Load ( ) ) ;  port  !=  0  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-22 13:00:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										ports  =  append ( ports ,  port ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-27 14:40:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-22 13:00:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  ruc . pconn  !=  nil  &&  curPortFate  ==  keepCurrentPort  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-27 14:40:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										curPort  :=  uint16 ( ruc . localAddrLocked ( ) . Port ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										ports  =  append ( ports ,  curPort ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									ports  =  append ( ports ,  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Remove duplicates. (All duplicates are consecutive.) 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-12 19:14:04 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									ports  =  slices . Compact ( ports ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-27 14:40:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-31 13:05:07 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  debugBindSocket ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . logf ( "magicsock: bindSocket: candidate ports: %+v" ,  ports ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-07-24 20:08:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									var  pconn  nettype . PacketConn 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-27 14:40:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									for  _ ,  port  :=  range  ports  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// Close the existing conn, in case it is sitting on the port we want. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										err  :=  ruc . closeLocked ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  err  !=  nil  &&  ! errors . Is ( err ,  net . ErrClosed )  &&  ! errors . Is ( err ,  errNilPConn )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											c . logf ( "magicsock: bindSocket %v close failed: %v" ,  network ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-27 14:40:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										// Open a new one with the desired port. 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 23:33:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										pconn ,  err  =  c . listenPacket ( network ,  port ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-08 15:48:49 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-27 14:40:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											c . logf ( "magicsock: unable to bind %v port %d: %v" ,  network ,  port ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											continue 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-08 15:48:49 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-05 18:12:02 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  c . onPortUpdate  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											_ ,  gotPortStr ,  err  :=  net . SplitHostPort ( pconn . LocalAddr ( ) . String ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												c . logf ( "could not parse port from %s: %w" ,  pconn . LocalAddr ( ) . String ( ) ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												gotPort ,  err  :=  strconv . ParseUint ( gotPortStr ,  10 ,  16 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													c . logf ( "could not parse port from %s: %w" ,  gotPort ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
													c . onPortUpdate ( uint16 ( gotPort ) ,  network ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 15:49:59 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										trySetSocketBuffer ( pconn ,  c . logf ) 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												wgengine/magicsock: disable SIO_UDP_NETRESET on Windows
By default, Windows sets the SIO_UDP_CONNRESET and SIO_UDP_NETRESET
options on created UDP sockets. These behaviours make the UDP socket
ICMP-aware; when the system gets an ICMP message (e.g. an "ICMP Port
Unreachable" message, in the case of SIO_UDP_CONNRESET), it will cause
the underlying UDP socket to throw an error. Confusingly, this can occur
even on reads, if the same UDP socket is used to write a packet that
triggers this response.
The Go runtime disabled the SIO_UDP_CONNRESET behavior in 3114bd6, but
did not change SIO_UDP_NETRESET–probably because that socket option
isn't documented particularly well.
Various other networking code seem to disable this behaviour, such as
the Godot game engine (godotengine/godot#22332) and the Eclipse TCF
agent (link below). Others appear to work around this by ignoring the
error returned (anacrolix/dht#16, among others).
For now, until it's clear whether this ends up in the upstream Go
implementation or not, let's also disable the SIO_UDP_NETRESET in a
similar manner to SIO_UDP_CONNRESET.
Eclipse TCF agent: https://gitlab.eclipse.org/eclipse/tcf/tcf.agent/-/blob/master/agent/tcf/framework/mdep.c
Updates #10976
Updates golang/go#68614
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: I70a2f19855f8dec1bfb82e63f6d14fc4a22ed5c3
											 
										 
										
											2024-07-26 14:35:03 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										trySetUDPSocketOptions ( pconn ,  c . logf ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-11 09:34:51 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-27 14:40:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										// Success. 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-31 13:05:07 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  debugBindSocket ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											c . logf ( "magicsock: bindSocket: successfully listened %v port %d" ,  network ,  port ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-04 16:32:16 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										ruc . setConnLocked ( pconn ,  network ,  c . bind . BatchSize ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-28 10:36:54 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  network  ==  "udp4"  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-26 08:06:06 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											c . health . SetUDP4Unbound ( false ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-28 10:36:54 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-27 14:40:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Failed to bind, including on port 0 (!). 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Set pconn to a dummy conn whose reads block until closed. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// This keeps the receive funcs alive for a future in which 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// we get a link change and we can try binding again. 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-04 16:32:16 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									ruc . setConnLocked ( newBlockForeverConn ( ) ,  "" ,  c . bind . BatchSize ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-28 10:36:54 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  network  ==  "udp4"  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-26 08:06:06 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . health . SetUDP4Unbound ( true ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-28 10:36:54 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-27 14:40:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  fmt . Errorf ( "failed to bind any ports (tried %v)" ,  ports ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-06-22 13:00:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								type  currentPortFate  uint8 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								const  ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									keepCurrentPort  =  currentPortFate ( 0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									dropCurrentPort  =  currentPortFate ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// rebind closes and re-binds the UDP sockets. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// We consider it successful if we manage to bind the IPv4 socket. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  rebind ( curPortFate  currentPortFate )  error  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-02 14:24:51 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  err  :=  c . bindSocket ( & c . pconn6 ,  "udp6" ,  curPortFate ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . logf ( "magicsock: Rebind ignoring IPv6 bind failure: %v" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-22 13:00:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  err  :=  c . bindSocket ( & c . pconn4 ,  "udp4" ,  curPortFate ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  fmt . Errorf ( "magicsock: Rebind IPv4 failed: %w" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-19 22:15:41 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . portMapper . SetLocalPort ( c . LocalPort ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-18 21:21:46 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . UpdatePMTUD ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-22 13:00:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// Rebind closes and re-binds the UDP sockets and resets the DERP connection. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// It should be followed by a call to ReSTUN. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  Rebind ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-04-22 10:40:49 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									metricRebindCalls . Add ( 1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-22 13:00:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  err  :=  c . rebind ( keepCurrentPort ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-02 11:09:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . logf ( "%v" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-22 13:00:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-09 14:21:36 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
											
												all: convert more code to use net/netip directly
    perl -i -npe 's,netaddr.IPPrefixFrom,netip.PrefixFrom,' $(git grep -l -F netaddr.)
    perl -i -npe 's,netaddr.IPPortFrom,netip.AddrPortFrom,' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPPrefix,netip.Prefix,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPPort,netip.AddrPort,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IP\b,netip.Addr,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPv6Raw\b,netip.AddrFrom16,g' $(git grep -l -F netaddr. )
    goimports -w .
Then delete some stuff from the net/netaddr shim package which is no
longer neeed.
Updates #5162
Change-Id: Ia7a86893fe21c7e3ee1ec823e8aba288d4566cd8
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2022-07-25 21:14:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									var  ifIPs  [ ] netip . Prefix 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-18 14:26:58 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  c . netMon  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										st  :=  c . netMon . InterfaceState ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-28 18:01:50 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										defIf  :=  st . DefaultRouteInterface 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										ifIPs  =  st . InterfaceIPs [ defIf ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . logf ( "Rebind; defIf=%q, ips=%v" ,  defIf ,  ifIPs ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-10 10:04:42 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-27 10:19:05 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-01 04:01:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  len ( ifIPs )  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . maybeCloseDERPsOnRebind ( ifIPs ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 00:31:48 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . resetEndpointStates ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-09 22:25:31 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 19:39:20 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// resetEndpointStates resets the preferred address for all peers. 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-09 22:25:31 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// This is called when connectivity changes enough that we no longer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// trust the old routes. 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 00:31:48 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  resetEndpointStates ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-09 22:25:31 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 22:25:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . peerMap . forEachEndpoint ( func ( ep  * endpoint )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 19:39:20 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										ep . noteConnectivityChange ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-30 12:22:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// packIPPort packs an IPPort into the form wanted by WireGuard. 
							 
						 
					
						
							
								
									
										
										
											
												all: convert more code to use net/netip directly
    perl -i -npe 's,netaddr.IPPrefixFrom,netip.PrefixFrom,' $(git grep -l -F netaddr.)
    perl -i -npe 's,netaddr.IPPortFrom,netip.AddrPortFrom,' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPPrefix,netip.Prefix,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPPort,netip.AddrPort,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IP\b,netip.Addr,g' $(git grep -l -F netaddr. )
    perl -i -npe 's,netaddr.IPv6Raw\b,netip.AddrFrom16,g' $(git grep -l -F netaddr. )
    goimports -w .
Then delete some stuff from the net/netaddr shim package which is no
longer neeed.
Updates #5162
Change-Id: Ia7a86893fe21c7e3ee1ec823e8aba288d4566cd8
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2022-07-25 21:14:09 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  packIPPort ( ua  netip . AddrPort )  [ ] byte  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-24 20:08:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									ip  :=  ua . Addr ( ) . Unmap ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-30 12:22:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									a  :=  ip . As16 ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									ipb  :=  a [ : ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  ip . Is4 ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										ipb  =  ipb [ 12 : ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									b  :=  make ( [ ] byte ,  0 ,  len ( ipb ) + 2 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									b  =  append ( b ,  ipb ... ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-14 18:07:28 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									b  =  append ( b ,  byte ( ua . Port ( ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									b  =  append ( b ,  byte ( ua . Port ( ) >> 8 ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-30 12:22:42 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  b 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-16 08:44:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// ParseEndpoint implements conn.Bind; it's called by WireGuard to connect to an endpoint. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// See https://pkg.go.dev/golang.zx2c4.com/wireguard/conn#Bind.ParseEndpoint 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-31 22:37:23 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  ParseEndpoint ( nodeKeyStr  string )  ( conn . Endpoint ,  error )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-28 11:07:25 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									k ,  err  :=  key . ParseNodePublicUntyped ( mem . S ( nodeKeyStr ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-30 16:45:36 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-31 22:37:23 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  nil ,  fmt . Errorf ( "magicsock: ParseEndpoint: parse failed on %q: %w" ,  nodeKeyStr ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-30 16:45:36 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 19:39:20 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  c . closed  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-30 21:26:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										return  nil ,  errConnClosed 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 19:39:20 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-01 17:53:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									ep ,  ok  :=  c . peerMap . endpointForNodeKey ( k ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-31 16:55:22 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// We should never be telling WireGuard about a new peer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// before magicsock knows about it. 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-01 17:53:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										c . logf ( "[unexpected] magicsock: ParseEndpoint: unknown node key=%s" ,  k . ShortString ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  nil ,  fmt . Errorf ( "magicsock: ParseEndpoint: unknown peer %q" ,  k . ShortString ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-31 13:25:58 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 19:39:20 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-08-31 16:55:22 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  ep ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-05 14:16:58 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-27 14:40:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  newBlockForeverConn ( )  * blockForeverConn  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c  :=  new ( blockForeverConn ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . cond  =  sync . NewCond ( & c . mu ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  c 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-23 14:12:23 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// simpleDur rounds d such that it stringifies to something short. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  simpleDur ( d  time . Duration )  time . Duration  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  d  <  time . Second  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  d . Round ( time . Millisecond ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  d  <  time . Minute  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  d . Round ( time . Second ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  d . Round ( time . Minute ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-24 08:09:30 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-01 19:28:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// UpdateNetmapDelta implements controlclient.NetmapDeltaUpdater. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  UpdateNetmapDelta ( muts  [ ] netmap . NodeMutation )  ( handled  bool )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									for  _ ,  m  :=  range  muts  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										nodeID  :=  m . NodeIDBeingMutated ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										ep ,  ok  :=  c . peerMap . endpointForNodeID ( nodeID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										switch  m  :=  m . ( type )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										case  netmap . NodeMutationDERPHome : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											ep . setDERPHome ( uint16 ( m . DERPRegion ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										case  netmap . NodeMutationEndpoints : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											ep . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											ep . setEndpointsLocked ( views . SliceOf ( m . Endpoints ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											ep . mu . Unlock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-10 17:31:14 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										case  netmap . NodeMutationCap : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											ep . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											ep . relayCapable  =  capVerIsRelayCapable ( m . Cap ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											ep . mu . Unlock ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-01 19:28:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-08-23 12:13:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// UpdateStatus implements the interface nede by ipnstate.StatusBuilder. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// This method adds in the magicsock-specific information only. Most 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// of the status is otherwise populated by LocalBackend. 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-25 22:57:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  UpdateStatus ( sb  * ipnstate . StatusBuilder )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-25 15:38:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									sb . MutateSelfStatus ( func ( ss  * ipnstate . PeerStatus )  { 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												tailcfg: add Endpoint, EndpointType, MapRequest.EndpointType
Track endpoints internally with a new tailcfg.Endpoint type that
includes a typed netaddr.IPPort (instead of just a string) and
includes a type for how that endpoint was discovered (STUN, local,
etc).
Use []tailcfg.Endpoint instead of []string internally.
At the last second, send it to the control server as the existing
[]string for endpoints, but also include a new parallel
MapRequest.EndpointType []tailcfg.EndpointType, so the control server
can start filtering out less-important endpoint changes from
new-enough clients. Notably, STUN-discovered endpoints can be filtered
out from 1.6+ clients, as they can discover them amongst each other
via CallMeMaybe disco exchanges started over DERP. And STUN endpoints
change a lot, causing a lot of MapResposne updates. But portmapped
endpoints are worth keeping for now, as they they work right away
without requiring the firewall traversal extra RTT dance.
End result will be less control->client bandwidth. (despite negligible
increase in client->control bandwidth)
Updates tailscale/corp#1543
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
											 
										 
										
											2021-04-12 13:24:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										ss . Addrs  =  make ( [ ] string ,  0 ,  len ( c . lastEndpoints ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										for  _ ,  ep  :=  range  c . lastEndpoints  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											ss . Addrs  =  append ( ss . Addrs ,  ep . Addr . String ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-25 15:38:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
										if  c . derpMap  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-23 12:13:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											if  reg ,  ok  :=  c . derpMap . Regions [ c . myDerp ] ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
												ss . Relay  =  reg . RegionCode 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-25 15:38:40 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-27 20:25:25 +00:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-12-19 10:23:47 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  sb . WantPeers  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . peerMap . forEachEndpoint ( func ( ep  * endpoint )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											ps  :=  & ipnstate . PeerStatus { InMagicSock :  true } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											ep . populatePeerStatus ( ps ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											sb . AddPeer ( ep . publicKey ,  ps ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-25 22:57:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-10 11:26:57 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									c . foreachActiveDerpSortedLocked ( func ( node  int ,  ad  activeDerp )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// TODO(bradfitz): add a method to ipnstate.StatusBuilder 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// to include all the DERP connections we have open 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// and add it here. See the other caller of foreachActiveDerpSortedLocked. 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-25 22:57:46 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-11-28 15:59:33 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// SetStatistics specifies a per-connection statistics aggregator. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// Nil may be specified to disable statistics gathering. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  SetStatistics ( stats  * connstats . Statistics )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . stats . Store ( stats ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-27 16:26:52 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-11-15 15:10:45 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// SetHomeless sets whether magicsock should idle harder and not have a DERP 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// home connection active and not search for its nearest DERP home. In this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// homeless mode, the node is unreachable by others. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  SetHomeless ( v  bool )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . homeless  =  v 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  v  &&  c . myDerp  !=  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										oldHome  :=  c . myDerp 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . myDerp  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . closeDerpLocked ( oldHome ,  "set-homeless" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  ! v  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										go  c . updateEndpoints ( "set-homeless-disabled" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-07-03 11:06:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								const  ( 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-03 12:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// sessionActiveTimeout is how long since the last activity we 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 22:20:31 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// try to keep an established endpoint peering alive. 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 09:52:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// It's also the idle time at which we stop doing STUN queries to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// keep NAT mappings alive. 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-05 11:28:08 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									sessionActiveTimeout  =  45  *  time . Second 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-03 12:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// upgradeInterval is how often we try to upgrade to a better path 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// even if we have some non-DERP route that works. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									upgradeInterval  =  1  *  time . Minute 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// heartbeatInterval is how often pings to the best UDP address 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// are sent. 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-05 11:28:08 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									heartbeatInterval  =  3  *  time . Second 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-03 12:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-07-03 11:06:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// trustUDPAddrDuration is how long we trust a UDP address as the exclusive 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// path (without using DERP) without having heard a Pong reply. 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-05 11:28:08 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									trustUDPAddrDuration  =  6500  *  time . Millisecond 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-03 12:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// goodEnoughLatency is the latency at or under which we don't 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// try to upgrade to a better path. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									goodEnoughLatency  =  5  *  time . Millisecond 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-19 15:29:50 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 09:52:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// endpointsFreshEnoughDuration is how long we consider a 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// STUN-derived endpoint valid for. UDP NAT mappings typically 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// expire at 30 seconds, so this is a few seconds shy of that. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									endpointsFreshEnoughDuration  =  27  *  time . Second 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-03 11:06:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-10-19 05:10:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// Constants that are variable for testing. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								var  ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// pingTimeoutDuration is how long we wait for a pong reply before 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// assuming it's never coming. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									pingTimeoutDuration  =  5  *  time . Second 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// discoPingInterval is the minimum time between pings 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// to an endpoint. (Except in the case of CallMeMaybe frames 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// resetting the counter, as the first pings likely didn't through 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// the firewall) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									discoPingInterval  =  5  *  time . Second 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-21 17:09:35 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// wireguardPingInterval is the minimum time between pings to an endpoint. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Pings are only sent if we have not observed bidirectional traffic with an 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// endpoint in at least this duration. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									wireguardPingInterval  =  5  *  time . Second 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-19 05:10:38 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-08-12 20:12:56 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// indexSentinelDeleted is the temporary value that endpointState.index takes while 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-25 22:20:31 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// a endpoint's endpoints are being updated from a new network map. 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-12 20:12:56 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								const  indexSentinelDeleted  =  - 1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-05-02 17:49:56 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// getPinger lazily instantiates a pinger and returns it, if it was 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// already instantiated it returns the existing one. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  getPinger ( )  * ping . Pinger  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  c . wgPinger . Get ( func ( )  * ping . Pinger  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  ping . New ( c . connCtx ,  c . dlogf ,  netns . Listener ( c . logf ,  c . netMon ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-06 20:39:23 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// DebugPickNewDERP picks a new DERP random home temporarily (even if just for 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// seconds) and reports it to control. It exists to test DERP home changes and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// netmap deltas, etc. It serves no useful user purpose. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  DebugPickNewDERP ( )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									dm  :=  c . derpMap 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  dm  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  errors . New ( "no derpmap" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  c . netInfoLast  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  errors . New ( "no netinfo" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									for  _ ,  r  :=  range  dm . Regions  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  r . RegionID  ==  c . myDerp  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . logf ( "magicsock: [debug] switching derp home to random %v (%v)" ,  r . RegionID ,  r . RegionCode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										go  c . setNearestDERP ( r . RegionID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										ni2  :=  c . netInfoLast . Clone ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										ni2 . PreferredDERP  =  r . RegionID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										c . callNetInfoCallbackLocked ( ni2 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  errors . New ( "too few regions" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-04 12:02:59 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  DebugForcePreferDERP ( n  int )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . logf ( "magicsock: [debug] force preferred DERP set to: %d" ,  n ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . netChecker . SetForcePreferredDERP ( n ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 15:49:59 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// portableTrySetSocketBuffer sets SO_SNDBUF and SO_RECVBUF on pconn to socketBufferSize, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// logging an error if it occurs. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  portableTrySetSocketBuffer ( pconn  nettype . PacketConn ,  logf  logger . Logf )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-01 04:01:00 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  runtime . GOOS  ==  "plan9"  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// Not supported. Don't try. Avoid logspam. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 15:49:59 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									if  c ,  ok  :=  pconn . ( * net . UDPConn ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										// Attempt to increase the buffer size, and allow failures. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  err  :=  c . SetReadBuffer ( socketBufferSize ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											logf ( "magicsock: failed to set UDP read buffer size to %d: %v" ,  socketBufferSize ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										if  err  :=  c . SetWriteBuffer ( socketBufferSize ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
											logf ( "magicsock: failed to set UDP write buffer size to %d: %v" ,  socketBufferSize ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-07-02 10:48:13 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// derpStr replaces DERP IPs in s with "derp-". 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  derpStr ( s  string )  string  {  return  strings . ReplaceAll ( s ,  "127.3.3.40:" ,  "derp-" )  } 
							 
						 
					
						
							
								
									
										
										
										
											2020-09-03 15:45:41 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// epAddrEndpointCache is a mutex-free single-element cache, mapping from 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// a single [epAddr] to a single [*endpoint]. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								type  epAddrEndpointCache  struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									epAddr  epAddr 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									gen     int64 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									de      * endpoint 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-18 15:27:44 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 20:45:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// discoInfo is the info and state for the DiscoKey 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// in the Conn.discoInfo map key. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// Note that a DiscoKey does not necessarily map to exactly one 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// node. In the case of shared nodes and users switching accounts, two 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// nodes in the NetMap may legitimately have the same DiscoKey.  As 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// such, no fields in here should be considered node-specific. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								type  discoInfo  struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// discoKey is the same as the Conn.discoInfo map key, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// just so you can pass around a *discoInfo alone. 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-25 14:29:55 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// Not modified once initialized. 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-29 14:27:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									discoKey  key . DiscoPublic 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 20:45:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// discoShort is discoKey.ShortString(). 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-25 14:29:55 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// Not modified once initialized; 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 20:45:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									discoShort  string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-10-29 14:27:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// sharedKey is the precomputed key for communication with the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// peer that has the DiscoKey used to look up this *discoInfo in 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Conn.discoInfo. 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-25 14:29:55 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// Not modified once initialized. 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-29 14:27:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									sharedKey  key . DiscoShared 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 20:45:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Mutable fields follow, owned by Conn.mu: 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// lastPingFrom is the src of a ping for discoKey. 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									lastPingFrom  epAddr 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-15 20:45:33 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// lastPingTime is the last time of a ping for discoKey. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									lastPingTime  time . Time 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-13 18:51:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								var  ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricNumPeers      =  clientmetric . NewGauge ( "magicsock_netmap_num_peers" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricNumDERPConns  =  clientmetric . NewGauge ( "magicsock_num_derp_conns" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-04-22 10:40:49 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									metricRebindCalls      =  clientmetric . NewCounter ( "magicsock_rebind_calls" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricReSTUNCalls      =  clientmetric . NewCounter ( "magicsock_restun_calls" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricUpdateEndpoints  =  clientmetric . NewCounter ( "magicsock_update_endpoints" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-13 18:51:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// Sends (data or disco) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricSendDERPQueued       =  clientmetric . NewCounter ( "magicsock_send_derp_queued" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricSendDERPErrorChan    =  clientmetric . NewCounter ( "magicsock_send_derp_error_chan" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricSendDERPErrorClosed  =  clientmetric . NewCounter ( "magicsock_send_derp_error_closed" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricSendDERPErrorQueue   =  clientmetric . NewCounter ( "magicsock_send_derp_error_queue" ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-25 17:20:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									metricSendUDP              =  clientmetric . NewAggregateCounter ( "magicsock_send_udp" ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-13 18:51:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									metricSendUDPError         =  clientmetric . NewCounter ( "magicsock_send_udp_error" ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-25 17:20:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									metricSendDERP             =  clientmetric . NewAggregateCounter ( "magicsock_send_derp" ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-16 08:34:25 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									metricSendDERPError        =  clientmetric . NewCounter ( "magicsock_send_derp_error" ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-13 18:51:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Data packets (non-disco) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricSendData             =  clientmetric . NewCounter ( "magicsock_send_data" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricSendDataNetworkDown  =  clientmetric . NewCounter ( "magicsock_send_data_network_down" ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-25 17:20:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									metricRecvDataPacketsDERP  =  clientmetric . NewAggregateCounter ( "magicsock_recv_data_derp" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricRecvDataPacketsIPv4  =  clientmetric . NewAggregateCounter ( "magicsock_recv_data_ipv4" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricRecvDataPacketsIPv6  =  clientmetric . NewAggregateCounter ( "magicsock_recv_data_ipv6" ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-13 18:51:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// Disco packets 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-07 08:10:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									metricSendDiscoUDP                =  clientmetric . NewCounter ( "magicsock_disco_send_udp" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricSendDiscoDERP               =  clientmetric . NewCounter ( "magicsock_disco_send_derp" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricSentDiscoUDP                =  clientmetric . NewCounter ( "magicsock_disco_sent_udp" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricSentDiscoDERP               =  clientmetric . NewCounter ( "magicsock_disco_sent_derp" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricSentDiscoPing               =  clientmetric . NewCounter ( "magicsock_disco_sent_ping" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricSentDiscoPong               =  clientmetric . NewCounter ( "magicsock_disco_sent_pong" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricSentDiscoPeerMTUProbes      =  clientmetric . NewCounter ( "magicsock_disco_sent_peer_mtu_probes" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricSentDiscoPeerMTUProbeBytes  =  clientmetric . NewCounter ( "magicsock_disco_sent_peer_mtu_probe_bytes" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricSentDiscoCallMeMaybe        =  clientmetric . NewCounter ( "magicsock_disco_sent_callmemaybe" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricRecvDiscoBadPeer            =  clientmetric . NewCounter ( "magicsock_disco_recv_bad_peer" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricRecvDiscoBadKey             =  clientmetric . NewCounter ( "magicsock_disco_recv_bad_key" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricRecvDiscoBadParse           =  clientmetric . NewCounter ( "magicsock_disco_recv_bad_parse" ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-13 18:51:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricRecvDiscoUDP                  =  clientmetric . NewCounter ( "magicsock_disco_recv_udp" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricRecvDiscoDERP                 =  clientmetric . NewCounter ( "magicsock_disco_recv_derp" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricRecvDiscoPing                 =  clientmetric . NewCounter ( "magicsock_disco_recv_ping" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricRecvDiscoPong                 =  clientmetric . NewCounter ( "magicsock_disco_recv_pong" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricRecvDiscoCallMeMaybe          =  clientmetric . NewCounter ( "magicsock_disco_recv_callmemaybe" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricRecvDiscoCallMeMaybeBadNode   =  clientmetric . NewCounter ( "magicsock_disco_recv_callmemaybe_bad_node" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricRecvDiscoCallMeMaybeBadDisco  =  clientmetric . NewCounter ( "magicsock_disco_recv_callmemaybe_bad_disco" ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-03-24 19:11:48 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									metricRecvDiscoDERPPeerNotHere      =  clientmetric . NewCounter ( "magicsock_disco_recv_derp_peer_not_here" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricRecvDiscoDERPPeerGoneUnknown  =  clientmetric . NewCounter ( "magicsock_disco_recv_derp_peer_gone_unknown" ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-16 08:34:25 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// metricDERPHomeChange is how many times our DERP home region DI has 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// changed from non-zero to a different non-zero. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricDERPHomeChange  =  clientmetric . NewCounter ( "derp_home_change" ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-29 10:57:54 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-25 22:28:37 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// metricDERPHomeNoChangeNoControl is how many times our DERP home 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// region did not change because we didn't have an active connection to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// the control server. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricDERPHomeNoChangeNoControl  =  clientmetric . NewCounter ( "derp_home_no_change_no_control" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// metricDERPHomeFallback is how many times we picked a DERP fallback. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricDERPHomeFallback  =  clientmetric . NewCounter ( "derp_home_fallback" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// metricDERPStaleCleaned is how many times we closed a stale DERP connection. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricDERPStaleCleaned  =  clientmetric . NewCounter ( "derp_stale_cleaned" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-08-29 10:57:54 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									// Disco packets received bpf read path 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-21 19:40:03 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									//lint:ignore U1000 used on Linux only 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-29 10:57:54 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									metricRecvDiscoPacketIPv4  =  clientmetric . NewCounter ( "magicsock_disco_recv_bpf_ipv4" ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-21 19:40:03 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									//lint:ignore U1000 used on Linux only 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-29 10:57:54 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									metricRecvDiscoPacketIPv6  =  clientmetric . NewCounter ( "magicsock_disco_recv_bpf_ipv6" ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-07 08:10:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// metricMaxPeerMTUProbed is the largest peer path MTU we successfully probed. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricMaxPeerMTUProbed  =  clientmetric . NewGauge ( "magicsock_max_peer_mtu_probed" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// metricRecvDiscoPeerMTUProbesByMTU collects the number of times we 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// received an peer MTU probe response for a given MTU size. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// TODO: add proper support for label maps in clientmetrics 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricRecvDiscoPeerMTUProbesByMTU  syncs . Map [ string ,  * clientmetric . Metric ] 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-23 09:37:32 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// metricUDPLifetime* metrics pertain to UDP lifetime probing, see type 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// probeUDPLifetime. These metrics assume a static/default configuration for 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// probing (defaultProbeUDPLifetimeConfig) until we disseminate 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// ProbeUDPLifetimeConfig from control, and have lifetime management (GC old 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									// metrics) of clientmetrics or similar. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricUDPLifetimeCliffsScheduled              =  newUDPLifetimeCounter ( "magicsock_udp_lifetime_cliffs_scheduled" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricUDPLifetimeCliffsCompleted              =  newUDPLifetimeCounter ( "magicsock_udp_lifetime_cliffs_completed" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricUDPLifetimeCliffsMissed                 =  newUDPLifetimeCounter ( "magicsock_udp_lifetime_cliffs_missed" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricUDPLifetimeCliffsRescheduled            =  newUDPLifetimeCounter ( "magicsock_udp_lifetime_cliffs_rescheduled" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricUDPLifetimeCyclesCompleted              =  newUDPLifetimeCounter ( "magicsock_udp_lifetime_cycles_completed" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricUDPLifetimeCycleCompleteNoCliffReached  =  newUDPLifetimeCounter ( "magicsock_udp_lifetime_cycle_complete_no_cliff_reached" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricUDPLifetimeCycleCompleteAt10sCliff      =  newUDPLifetimeCounter ( "magicsock_udp_lifetime_cycle_complete_at_10s_cliff" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricUDPLifetimeCycleCompleteAt30sCliff      =  newUDPLifetimeCounter ( "magicsock_udp_lifetime_cycle_complete_at_30s_cliff" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									metricUDPLifetimeCycleCompleteAt60sCliff      =  newUDPLifetimeCounter ( "magicsock_udp_lifetime_cycle_complete_at_60s_cliff" ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-13 18:51:24 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								) 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-07 08:10:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-01-23 09:37:32 -08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// newUDPLifetimeCounter returns a new *clientmetric.Metric with the provided 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// name combined with a suffix representing defaultProbeUDPLifetimeConfig. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  newUDPLifetimeCounter ( name  string )  * clientmetric . Metric  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									var  sb  strings . Builder 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									for  _ ,  cliff  :=  range  defaultProbeUDPLifetimeConfig . Cliffs  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										sb . WriteString ( fmt . Sprintf ( "%ds" ,  cliff / time . Second ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									sb . WriteString ( fmt . Sprintf ( "_%ds" ,  defaultProbeUDPLifetimeConfig . CycleCanStartEvery / time . Second ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  clientmetric . NewCounter ( fmt . Sprintf ( "%s_%s" ,  name ,  sb . String ( ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-07 08:10:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  getPeerMTUsProbedMetric ( mtu  tstun . WireMTU )  * clientmetric . Metric  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									key  :=  fmt . Sprintf ( "magicsock_recv_disco_peer_mtu_probes_by_mtu_%d" ,  mtu ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									mm ,  _  :=  metricRecvDiscoPeerMTUProbesByMTU . LoadOrInit ( key ,  func ( )  * clientmetric . Metric  {  return  clientmetric . NewCounter ( key )  } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  mm 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-15 18:14:20 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-25 14:50:39 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// GetLastNetcheckReport returns the last netcheck report, returning nil if a recent one does not exist. 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-15 18:14:20 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  GetLastNetcheckReport ( ctx  context . Context )  * netcheck . Report  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-25 14:50:39 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									return  c . lastNetCheckReport . Load ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-04-15 18:14:20 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-03 13:24:26 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-05-10 10:30:10 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// SetLastNetcheckReportForTest sets the magicsock conn's last netcheck report. 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-03 13:24:26 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// Used for testing purposes. 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-10 10:30:10 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( c  * Conn )  SetLastNetcheckReportForTest ( ctx  context . Context ,  report  * netcheck . Report )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c . lastNetCheckReport . Store ( report ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-03 13:24:26 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-08 20:31:16 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// lazyEndpoint is a wireguard conn.Endpoint for when magicsock received a 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// non-disco (presumably WireGuard) packet from a UDP address from which we 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// can't map to a Tailscale peer. But Wireguard most likely can, once it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// decrypts it. So we implement the conn.PeerAwareEndpoint interface 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// from https://github.com/tailscale/wireguard-go/pull/27 to allow WireGuard 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// to tell us who it is later and get the correct conn.Endpoint. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								type  lazyEndpoint  struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									c    * Conn 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
									src  epAddr 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-08 20:31:16 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								var  _  conn . PeerAwareEndpoint  =  ( * lazyEndpoint ) ( nil ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								var  _  conn . Endpoint  =  ( * lazyEndpoint ) ( nil ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( le  * lazyEndpoint )  ClearSrc ( )            { } 
							 
						 
					
						
							
								
									
										
										
											
												wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)
This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.
The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.
Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.
Updates tailscale/corp#27502
Updates tailscale/corp#29326
Signed-off-by: Jordan Whited <jordan@tailscale.com>
											 
										 
										
											2025-06-06 09:46:29 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( le  * lazyEndpoint )  SrcIP ( )  netip . Addr    {  return  le . src . ap . Addr ( )  } 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-08 20:31:16 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								func  ( le  * lazyEndpoint )  DstIP ( )  netip . Addr    {  return  netip . Addr { }  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( le  * lazyEndpoint )  SrcToString ( )  string  {  return  le . src . String ( )  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( le  * lazyEndpoint )  DstToString ( )  string  {  return  "dst"  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( le  * lazyEndpoint )  DstToBytes ( )  [ ] byte   {  return  nil  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								func  ( le  * lazyEndpoint )  GetPeerEndpoint ( peerPublicKey  [ 32 ] byte )  conn . Endpoint  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									pubKey  :=  key . NodePublicFromRaw32 ( mem . B ( peerPublicKey [ : ] ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									le . c . mu . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									defer  le . c . mu . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									ep ,  ok  :=  le . c . peerMap . endpointForNodeKey ( pubKey ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									if  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
										return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									le . c . logf ( "magicsock: lazyEndpoint.GetPeerEndpoint(%v) found: %v" ,  pubKey . ShortString ( ) ,  ep . nodeAddr ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
									return  ep 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								}