This adds a new ListenPacket function on tsnet.Server
which acts mostly like `net.ListenPacket`.
Unlike `Server.Listen`, this requires listening on a
specific IP and does not automatically listen on both
V4 and V6 addresses of the Server when the IP is unspecified.
To test this, it also adds UDP support to tsdial.Dialer.UserDial
and plumbs it through the localapi. Then an associated test
to make sure the UDP functionality works from both sides.
Updates #12182
Signed-off-by: Maisem Ali <maisem@tailscale.com>
Updates https://github.com/tailscale/corp/issues/15802.
On iOS exclusively, this PR adds logic to use a split DNS configuration in more cases, with the goal of improving battery life. Acting as the global DNS resolver on iOS should be avoided, as it leads to frequent wakes of IPNExtension.
We try to determine if we can have Tailscale only handle DNS queries for resources inside the tailnet, that is, all routes in the DNS configuration do not require a custom resolver (this is the case for app connectors, for instance).
If so, we set all Routes as MatchDomains. This enables a split DNS configuration which will help preserve battery life. Effectively, for the average Tailscale user who only relies on MagicDNS to resolve *.ts.net domains, this means that Tailscale DNS will only be used for those domains.
This PR doesn't affect users with Override Local DNS enabled. For these users, there should be no difference and Tailscale will continue acting as a global DNS resolver.
Signed-off-by: Andrea Gottardo <andrea@tailscale.com>
Palo Alto reported interpreting hairpin probes as LAND attacks, and the
firewalls may be responding to this by shutting down otherwise in use NAT sessions
prematurely. We don't currently make use of the outcome of the hairpin
probes, and they contribute to other user confusion with e.g. the
AirPort Extreme hairpin session workaround. We decided in response to
remove the whole probe feature as a result.
Updates #188
Updates tailscale/corp#19106
Updates tailscale/corp#19116
Signed-off-by: James Tucker <james@tailscale.com>
Palo Alto firewalls have a typically hard NAT, but also have a mode
called Persistent DIPP that is supposed to provide consistent port
mapping suitable for STUN resolution of public ports. Persistent DIPP
works initially on most Palo Alto firewalls, but some models/software
versions have a bug which this works around.
The bug symptom presents as follows:
- STUN sessions resolve a consistent public IP:port to start with
- Much later netchecks report the same IP:Port for a subset of
sessions, most often the users active DERP, and/or the port related
to sustained traffic.
- The broader set of DERPs in a full netcheck will now consistently
observe a new IP:Port.
- After this point of observation, new inbound connections will only
succeed to the new IP:Port observed, and existing/old sessions will
only work to the old binding.
In this patch we now advertise the lowest latency global endpoint
discovered as we always have, but in addition any global endpoints that
are observed more than once in a single netcheck report. This should
provide viable endpoints for potential connection establishment across
a NAT with this behavior.
Updates tailscale/corp#19106
Signed-off-by: James Tucker <james@tailscale.com>
In this commit I updated the Ipv6 range we use to generate Control D DOH ip, we were using the NextDNSRanges to generate Control D DOH ip, updated to use the correct range.
Updates: #7946
Signed-off-by: Kevin Liang <kevinliang@tailscale.com>
In a configuration where the local node (ip1) has a different IP (ip2)
that it uses to communicate with a peer (ip3) we would do UDP flow
tracking on the `ip2->ip3` tuple. When we receive the response from
the peer `ip3->ip2` we would dnat it back to `ip3->ip1` which would
then not match the flow track state and the packet would get dropped.
To fix this, we should do flow tracking on the `ip1->ip3` tuple instead
of `ip2->ip3` which requires doing SNAT after the running filterPacketOutboundToWireGuard.
Updates tailscale/corp#19971, tailscale/corp#8020
Signed-off-by: Maisem Ali <maisem@tailscale.com>
It was documented as such but seems to have been dropped in a
refactor, restore the behavior. This brings down the time it
takes to run a single integration test by 2s which adds up
quite a bit.
Updates tailscale/corp#19786
Signed-off-by: Maisem Ali <maisem@tailscale.com>
This adds a new bool that can be sent down from control
to do jailing on the client side. Previously this would
only be done from control by modifying the packet filter
we sent down to clients. This would result in a lot of
additional work/CPU on control, we could instead just
do this on the client. This has always been a TODO which
we keep putting off, might as well do it now.
Updates tailscale/corp#19623
Signed-off-by: Maisem Ali <maisem@tailscale.com>
This plumbs a packet filter for jailed nodes through to the
tstun.Wrapper; the filter for a jailed node is equivalent to a "shields
up" filter. Currently a no-op as there is no way for control to
tell the client whether a peer is jailed.
Updates tailscale/corp#19623
Co-authored-by: Andrew Dunham <andrew@du.nham.ca>
Signed-off-by: Maisem Ali <maisem@tailscale.com>
Change-Id: I5ccc5f00e197fde15dd567485b2a99d8254391ad
Now that tsdial.Dialer.UserDial has been updated to honor the configured routes
and dial external network addresses without going through Tailscale, while also being
able to dial a node/subnet router on the tailnet, we can start using UserDial to forward
DNS requests. This is primarily needed for DNS over TCP when forwarding requests
to internal DNS servers, but we also update getKnownDoHClientForProvider to use it.
Updates tailscale/corp#18725
Signed-off-by: Nick Khyl <nickk@tailscale.com>
This refactors the peerConfig struct to allow storing more
details about a peer and not just the masq addresses. To be
used in a follow up change.
As a side effect, this also makes the DNAT logic on the inbound
packet stricter. Previously it would only match against the packets
dst IP, not it also takes the src IP into consideration. The beahvior
is at parity with the SNAT case.
Updates tailscale/corp#19623
Co-authored-by: Andrew Dunham <andrew@du.nham.ca>
Signed-off-by: Maisem Ali <maisem@tailscale.com>
Change-Id: I5f40802bebbf0f055436eb8824e4511d0052772d
We'd like to use tsdial.Dialer.UserDial instead of SystemDial for DNS over TCP.
This is primarily necessary to properly dial internal DNS servers accessible
over Tailscale and subnet routes. However, to avoid issues when switching
between Wi-Fi and cellular, we need to ensure that we don't retain connections
to any external addresses on the old interface. Therefore, we need to determine
which dialer to use internally based on the configured routes.
This plumbs routes and localRoutes from router.Config to tsdial.Dialer,
and updates UserDial to use either the peer dialer or the system dialer,
depending on the network address and the configured routes.
Updates tailscale/corp#18725
Fixes#4529
Signed-off-by: Nick Khyl <nickk@tailscale.com>
While debugging a failing test in airplane mode on macOS, I noticed
netcheck logspam about ICMP socket creation permission denied errors.
Apparently macOS just can't do those, or at least not in airplane
mode. Not worth spamming about.
Updates #cleanup
Change-Id: I302620cfd3c8eabb25202d7eef040c01bd8a843c
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
To aid in debugging exactly what's going wrong, instead of the
not-particularly-useful "dns udp query: context deadline exceeded" error
that we currently get.
Updates #3786
Updates #10768
Updates #11620
(etc.)
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: I76334bf0681a8a2c72c90700f636c4174931432c
So that we can use this for additional, non-NAT configuration without it
being confusing.
Updates #cleanup
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: I1658d59c9824217917a94ee76d2d08f0a682986f
This was a holdover from the older, pre-BART days and is no longer
necessary.
Updates #cleanup
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: I71b892bab1898077767b9ff51cef33d59c08faf8
Updates tailscale/corp#18960
Tests in corp called us using the wrong logging calls. Removed.
This is logged downstream anyway.
Signed-off-by: Jonathan Nobels <jonathan@tailscale.com>
Updates tailscale/corp#18960
iOS uses Apple's NetworkMonitor to track the default interface and
there's no reason we shouldn't also use this on macOS, for the same
reasons noted in the comments for why this change was made on iOS.
This eliminates the need to load and parse the routing table when
querying the defaultRouter() in almost all cases.
A slight modification here (on both platforms) to fallback to the default
BSD logic in the unhappy-path rather than making assumptions that
may not hold. If netmon is eventually parsing AF_ROUTE and able
to give a consistently correct answer for the default interface index,
we can fall back to that and eliminate the Swift dependency.
Signed-off-by: Jonathan Nobels <jonathan@tailscale.com>
Certain device drivers (e.g. vxlan, geneve) do not properly handle
coalesced UDP packets later in the stack, resulting in packet loss.
Updates #11026
Signed-off-by: Jordan Whited <jordan@tailscale.com>
In prep for most of the package funcs in net/interfaces to become
methods in a long-lived netmon.Monitor that can cache things. (Many
of the funcs are very heavy to call regularly, whereas the long-lived
netmon.Monitor can subscribe to things from the OS and remember
answers to questions it's asked regularly later)
Updates tailscale/corp#10910
Updates tailscale/corp#18960
Updates #7967
Updates #3299
Change-Id: Ie4e8dedb70136af2d611b990b865a822cd1797e5
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
... in prep for merging the net/interfaces package into net/netmon.
This is a no-op change that updates a bunch of the API signatures ahead of
a future change to actually move things (and remove the type alias)
Updates tailscale/corp#10910
Updates tailscale/corp#18960
Updates #7967
Updates #3299
Change-Id: I477613388f09389214db0d77ccf24a65bff2199c
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
The goal is to move more network state accessors to netmon.Monitor
where they can be cheaper/cached. But first (this change and others)
we need to make sure the one netmon.Monitor is plumbed everywhere.
Some notable bits:
* tsdial.NewDialer is added, taking a now-required netmon
* because a tsdial.Dialer always has a netmon, anything taking both
a Dialer and a NetMon is now redundant; take only the Dialer and
get the NetMon from that if/when needed.
* netmon.NewStatic is added, primarily for tests
Updates tailscale/corp#10910
Updates tailscale/corp#18960
Updates #7967
Updates #3299
Change-Id: I877f9cb87618c4eb037cee098241d18da9c01691
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This has been a TODO for ages. Time to do it.
The goal is to move more network state accessors to netmon.Monitor
where they can be cheaper/cached.
Updates tailscale/corp#10910
Updates tailscale/corp#18960
Updates #7967
Updates #3299
Change-Id: I60fc6508cd2d8d079260bda371fc08b6318bcaf1
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
I'm working on moving all network state queries to be on
netmon.Monitor, removing old APIs.
Updates tailscale/corp#10910
Updates tailscale/corp#18960
Updates #7967
Updates #3299
Change-Id: If0de137e0e2e145520f69e258597fb89cf39a2a3
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This adds a health.Tracker to tsd.System, accessible via
a new tsd.System.HealthTracker method.
In the future, that new method will return a tsd.System-specific
HealthTracker, so multiple tsnet.Servers in the same process are
isolated. For now, though, it just always returns the temporary
health.Global value. That permits incremental plumbing over a number
of changes. When the second to last health.Global reference is gone,
then the tsd.System.HealthTracker implementation can return a private
Tracker.
The primary plumbing this does is adding it to LocalBackend and its
dozen and change health calls. A few misc other callers are also
plumbed. Subsequent changes will flesh out other parts of the tree
(magicsock, controlclient, etc).
Updates #11874
Updates #4136
Change-Id: Id51e73cfc8a39110425b6dc19d18b3975eac75ce
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Previously it was both metadata about the class of warnable item as
well as the value.
Now it's only metadata and the value is per-Tracker.
Updates #11874
Updates #4136
Change-Id: Ia1ed1b6c95d34bc5aae36cffdb04279e6ba77015
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This moves most of the health package global variables to a new
`health.Tracker` type.
But then rather than plumbing the Tracker in tsd.System everywhere,
this only goes halfway and makes one new global Tracker
(`health.Global`) that all the existing callers now use.
A future change will eliminate that global.
Updates #11874
Updates #4136
Change-Id: I6ee27e0b2e35f68cb38fecdb3b2dc4c3f2e09d68
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
If this happens, it results in us pessimistically closing more
connections than might be necessary, but is more correct since we won't
"miss" a change to the default route interface and keep trying to send
data over a nonexistent interface, or one that can't reach the internet.
Updates tailscale/corp#19124
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: Ia0b8b04cb8cdcb0da0155fd08751c9dccba62c1a
-Move Android impl into interfaces_android.go
-Instead of using ip route to get the interface name, use the one passed in by Android (ip route is restricted in Android 13+ per termux/termux-app#2993)
Follow-up will be to do the same for router
Fixestailscale/corp#19215Fixestailscale/corp#19124
Signed-off-by: kari-ts <kari@tailscale.com>
This ensures that we close the underlying connection(s) when a major
link change happens. If we don't do this, on mobile platforms switching
between WiFi and cellular can result in leftover connections in the
http.Client's connection pool which are bound to the "wrong" interface.
Updates #10821
Updates tailscale/corp#19124
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: Ibd51ce2efcaf4bd68e14f6fdeded61d4e99f9a01
This wasn't previously handling the case where an interface in s2 was
removed and not present in s1, and would cause the Equal method to
incorrectly return that the states were equal.
Updates tailscale/corp#19124
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: I3af22bc631015d1ddd0a1d01bfdf312161b9532d
It should've been deleted in 11ece02f52.
Updates #9040
Change-Id: If8a136bdb6c82804af658c9d2b0a8c63ce02d509
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
At least in userspace-networking mode.
Fixes#11361
Change-Id: I78d33f0f7e05fe9e9ee95b97c99b593f8fe498f2
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
We were being too aggressive when deciding whether to write our NRPT rules
to the local registry key or the group policy registry key.
After once again reviewing the document which calls itself a spec
(see issue), it is clear that the presence of the DnsPolicyConfig subkey
is the important part, not the presence of values set in the DNSClient
subkey. Furthermore, a footnote indicates that the presence of
DnsPolicyConfig in the GPO key will always override its counterpart in
the local key. The implication of this is important: we may unconditionally
write our NRPT rules to the local key. We copy our rules to the policy
key only when it contains NRPT rules belonging to somebody other than us.
Fixes https://github.com/tailscale/corp/issues/19071
Signed-off-by: Aaron Klotz <aaron@tailscale.com>
This removes a potentially increased boot delay for certain boot
topologies where they block on ExecStartPre that may have socket
activation dependencies on other system services (such as
systemd-resolved and NetworkManager).
Also rename cleanup to clean up in affected/immediately nearby places
per code review commentary.
Fixes#11599
Signed-off-by: James Tucker <james@tailscale.com>
At least in the case of dialing a Tailscale IP.
Updates #4529
Change-Id: I9fd667d088a14aec4a56e23aabc2b1ffddafa3fe
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Updates #7946
[@bradfitz fixed up version of #8417]
Change-Id: I1dbf6fa8d525b25c0d7ad5c559a7f937c3cd142a
Signed-off-by: alexelisenko <39712468+alexelisenko@users.noreply.github.com>
Signed-off-by: Alex Paguis <alex@windscribe.com>
The netcheck package and the magicksock package coordinate via the
health package, but both sides have time based heuristics through
indirect dependencies. These were misaligned, so the implemented
heuristic aimed at reducing DERP moves while there is active traffic
were non-operational about 3/5ths of the time.
It is problematic to setup a good test for this integration presently,
so instead I added comment breadcrumbs along with the initial fix.
Updates #8603
Signed-off-by: James Tucker <james@tailscale.com>
We now allow some more ICMP errors to flow, specifically:
- ICMP parameter problem in both IPv4 and IPv6 (corrupt headers)
- ICMP Packet Too Big (for IPv6 PMTU)
Updates #311
Updates #8102
Updates #11002
Signed-off-by: James Tucker <james@tailscale.com>
This implementation uses less memory than tempfork/device,
which helps avoid OOM conditions in the iOS VPN extension when
switching to a Tailnet with ExitNode routing enabled.
Updates tailscale/corp#18514
Signed-off-by: Percy Wegmann <percy@tailscale.com>
I was running all tests while preparing a recent stable release, and
this was failing because my computer is connected to a fairly large
tailnet.
```
--- FAIL: TestGetRouteTable (0.01s)
routetable_linux_test.go:32: expected at least one default route;
...
```
```
$ ip route show table 52 | wc -l
1051
```
Updates #cleanup
Signed-off-by: Anton Tolchanov <anton@tailscale.com>
This test could hang because the subprocess was blocked on writing to
the stdout pipe if we find the address we're looking for early in the
output.
Updates #cleanup
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: I68d82c22a5d782098187ae6d8577e43063b72573
The `stack.PacketBufferPtr` type no longer exists; replace it with
`*stack.PacketBuffer` instead.
Updates #8043
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: Ib56ceff09166a042aa3d9b80f50b2aa2d34b3683
When reverse path filtering is in strict mode on Linux, using an exit
node blocks all network connectivity. This change adds a warning about
this to `tailscale status` and the logs.
Example in `tailscale status`:
```
- not connected to home DERP region 22
- The following issues on your machine will likely make usage of exit nodes impossible: [interface "eth0" has strict reverse-path filtering enabled], please set rp_filter=2 instead of rp_filter=1; see https://github.com/tailscale/tailscale/issues/3310
```
Example in the logs:
```
2024/02/21 21:17:07 health("overall"): error: multiple errors:
not in map poll
The following issues on your machine will likely make usage of exit nodes impossible: [interface "eth0" has strict reverse-path filtering enabled], please set rp_filter=2 instead of rp_filter=1; see https://github.com/tailscale/tailscale/issues/3310
```
Updates #3310
Signed-off-by: Anton Tolchanov <anton@tailscale.com>
Tailscaled becomes inoperative if the Tailscale Tunnel wintun adapter is abruptly removed.
wireguard-go closes the device in case of a read error, but tailscaled keeps running.
This adds detection of a closed WireGuard device, triggering a graceful shutdown of tailscaled.
It is then restarted by the tailscaled watchdog service process.
Fixes#11222
Signed-off-by: Nick Khyl <nickk@tailscale.com>
The WinTun adapter may have been removed by the time we're closing
the dns.windowsManager, and its associated interface registry key might
also have been deleted. We shouldn't use winutil.OpenKeyWait and wait
for the interface key to appear when performing a cleanup as a part of
the windowsManager shutdown.
Updates #11222
Signed-off-by: Nick Khyl <nickk@tailscale.com>
If a client socket is remotely lost but the client is not sent an RST in
response to the next request, the socket might sit in RTO for extended
lengths of time, resulting in "no internet" for users. Instead, timeout
after 10s, which will close the underlying socket, recovering from the
situation more promptly.
Updates #10967
Signed-off-by: James Tucker <james@tailscale.com>
We don't need a log line every time defaultRoute is read in the good
case, and we now only log default interface updates that are actually
changes.
Updates #3363
Signed-off-by: James Tucker <james@tailscale.com>
Setting a user timeout will be a more practical tuning knob for a number
of endpoints, this provides a way to set it.
Updates tailscale/corp#17587
Signed-off-by: James Tucker <james@tailscale.com>
This fixes an infinite loop caused by the configuration of
systemd-resolved on Amazon Linux 2023 and how that interacts with
Tailscale's "direct" mode. We now drop the Tailscale service IP from the
OS's "base configuration" when we detect this configuration.
Updates #7816
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: I73a4ea8e65571eb368c7e179f36af2c049a588ee
These are functionally the same as the "urn:schemas-upnp-org" services
with a few minor changes, and are still used by older devices. Support
them to improve our ability to obtain an external IP on such networks.
Updates #10911
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: I05501fad9d6f0a3b8cf19fc95eee80e7d16cc2cf
This no longer results in a nil pointer exception when we get a valid
UPnP response with no supported clients.
Updates #10911
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: I6e3715a49a193ff5261013871ad7fff197a4d77e
The prefix has space for 32-bit site IDs, but the validateViaPrefix
function would previously have disallowed site IDs greater than 255.
Fixestailscale/corp#16470
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: I4cdb0711dafb577fae72d86c4014cf623fa538ef
Add a standalone server for STUN that can be hosted independently of the
derper, and factor that back into the derper.
Fixes#8434Closes#8435Closes#10745
Signed-off-by: James Tucker <james@tailscale.com>
To make it easier to correlate the starting/ending log messages.
Updates #cleanup
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: I2802d53ad98e19bc8914bc58f8c04d4443227b26
Updates #8022
Updates #6075
On iOS, we currently rely on delegated interface information to figure out the default route interface. The NetworkExtension framework in iOS seems to set the delegate interface only once, upon the *creation* of the VPN tunnel. If a network transition (e.g. from Wi-Fi to Cellular) happens while the tunnel is connected, it will be ignored and we will still try to set Wi-Fi as the default route because the delegated interface is not getting updated as connectivity transitions.
Here we work around this on the Swift side with a NWPathMonitor instance that observes the interface name of the first currently satisfied network path. Our Swift code will call into `UpdateLastKnownDefaultRouteInterface`, so we can rely on that when it is set.
If for any reason the Swift machinery didn't work and we don't get any updates, here we also have some fallback logic: we try finding a hardcoded Wi-Fi interface called en0. If en0 is down, we fall back to cellular (pdp_ip0) as a last resort. This doesn't handle all edge cases like USB-Ethernet adapters or multiple Ethernet interfaces, but it is good enough to ensure connectivity isn't broken.
I tested this on iPhones and iPads running iOS 17.1 and it appears to work. Switching between different cellular plans on a dual SIM configuration also works (the interface name remains pdp_ip0).
Signed-off-by: Andrea Gottardo <andrea@tailscale.com>
If the epoch that we see during a Probe is less than the existing epoch,
it means that the gateway has either restarted or reset its
configuration, and an existing mapping is no longer valid. Reset any
saved mapping(s) if we detect this case so that a future
createOrGetMapping will not attempt to re-use it.
Updates #10597
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: Ie3cddaf625cb94a29885f7a1eeea25dbf6b97b47
When the portable Monitor creates a winMon via newOSMon, we register
address and route change callbacks with Windows. Once a callback is hit,
it starts a goroutine that attempts to send the event into messagec and returns.
The newly started goroutine then blocks until it can send to the channel.
However, if the monitor is never started and winMon.Receive is never called,
the goroutines remain indefinitely blocked, leading to goroutine leaks and
significant memory consumption in the tailscaled service process on Windows.
Unlike the tailscaled subprocess, the service process creates but never starts
a Monitor.
This PR adds a check within the callbacks to confirm the monitor's active status,
and exits immediately if the monitor hasn't started.
Updates #9864
Signed-off-by: Nick Khyl <nickk@tailscale.com>
Run `staticcheck` with `U1000` to find unused code. This cleans up about
a half of it. I'll do the other half separately to keep PRs manageable.
Updates #cleanup
Signed-off-by: Andrew Lytvynov <awly@tailscale.com>
This logs additional information about what mapping(s) are obtained
during the creation process, including whether we return an existing
cached mapping.
Updates #10597
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: I9ff25071f064c91691db9ab0b9365ccc5f948d6e
Currently, we get the "likely home router" gateway IP and then iterate
through all IPs for all interfaces trying to match IPs to determine the
source IP. However, on many platforms we know what interface the gateway
is through, and thus we don't need to iterate through all interfaces
checking IPs. Instead, use the IP address of the associated interface.
This better handles the case where we have multiple interfaces on a
system all connected to the same gateway, and where the first interface
that we visit (as iterated by ForeachInterfaceAddress) isn't also the
default internet route.
Updates #8992
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: I8632f577f1136930f4ec60c76376527a19a47d1f
Instead of taking the first UPnP response we receive and using that to
create port mappings, store all received UPnP responses, sort and
deduplicate them, and then try all of them to obtain an external
address.
Updates #10602
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: I783ccb1834834ee2a9ecbae2b16d801f2354302f
This uses the fact that we've received a frame from a given DERP region
within a certain time as a signal that the region is stil present (and
thus can still be a node's PreferredDERP / home region) even if we don't
get a STUN response from that region during a netcheck.
This should help avoid DERP flaps that occur due to losing STUN probes
while still having a valid and active TCP connection to the DERP server.
RELNOTE=Reduce home DERP flapping when there's still an active connection
Updates #8603
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: If7da6312581e1d434d5c0811697319c621e187a0
Previously, we would select the first WANIPConnection2 (and related)
client from the root device, without any additional checks. However,
some routers expose multiple UPnP devices in various states, and simply
picking the first available one can result in attempting to perform a
portmap with a device that isn't functional.
Instead, mimic what the miniupnpc code does, and prefer devices that are
(a) reporting as Connected, and (b) have a valid external IP address.
For our use-case, we additionally prefer devices that have an external
IP address that's a public address, to increase the likelihood that we
can obtain a direct connection from peers.
Finally, we split out fetching the root device (getUPnPRootDevice) from
selecting the best service within that root device (selectBestService),
and add some extensive tests for various UPnP server behaviours.
RELNOTE=Improve UPnP portmapping when multiple UPnP services exist
Updates #8364
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: I71795cd80be6214dfcef0fe83115a5e3fe4b8753
Unfortunately in the test we can't reproduce the failure seen
in the real system ("SOAP fault: UPnPError")
Updates https://github.com/tailscale/tailscale/issues/8364
Signed-off-by: Denton Gentry <dgentry@tailscale.com>
Before this fix, LikelyHomeRouterIP could return a 'self' IP that
doesn't correspond to the gateway address, since it picks the first
private address when iterating over the set interfaces as the 'self' IP,
without checking that the address corresponds with the
previously-detected gateway.
This behaviour was introduced by accident in aaf2df7, where we deleted
the following code:
for _, prefix := range privatev4s {
if prefix.Contains(gateway) && prefix.Contains(ip) {
myIP = ip
ok = true
return
}
}
Other than checking that 'gateway' and 'ip' were private IP addresses
(which were correctly replaced with a call to the netip.Addr.IsPrivate
method), it also implicitly checked that both 'gateway' and 'ip' were a
part of the *same* prefix, and thus likely to be the same interface.
Restore that behaviour by explicitly checking pfx.Contains(gateway),
which, given that the 'ip' variable is derived from our prefix 'pfx',
ensures that the 'self' IP will correspond to the returned 'gateway'.
Fixes#10466
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: Iddd2ee70cefb9fb40071986fefeace9ca2441ee6
Config.singleResolverSet returns true if all routes have the same resolvers,
even if the routes have no resolvers. If none of the routes have a specific
resolver, the default should be used instead. Therefore, check for more than
0 instead of nil.
Signed-off-by: Ryan Petris <ryan@petris.net>
This prevents running more than one recursive resolution for the same
hostname in parallel, which can use excessive amounts of CPU when called
in a tight loop. Additionally, add tests that hit the network (when
run with a flag) to test the lookup behaviour.
Updates tailscale/corp#15261
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: I39351e1d2a8782dd4c52cb04b3bd982eb651c81e
An EmbeddedAppConnector is added that when configured observes DNS
responses from the PeerAPI. If a response is found matching a configured
domain, routes are advertised when necessary.
The wiring from a configuration in the netmap capmap is not yet done, so
while the connector can be enabled, no domains can yet be added.
Updates tailscale/corp#15437
Signed-off-by: James Tucker <james@tailscale.com>
The other IP types don't appear to be imported anymore, and after a scan
through I couldn't see any substantial usage of other representations,
so I think this TODO is complete.
Updates #cleanup
Signed-off-by: James Tucker <james@tailscale.com>
As of 2023-11-27, the official IP addresses for b.root-servers.net will
change to a new set, with the older IP addresses supported for at least
a year after that date. These IPs are already active and returning
results, so update these in our recursive DNS resolver package so as to
be ready for the switchover.
See: https://b.root-servers.org/news/2023/05/16/new-addresses.htmlFixes#9994
Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: I29e2fe9f019163c9ec0e62bdb286e124aa90a487
It seems to be implicated in a CPU consumption bug that's not yet
understood. Disable it until we understand.
Updates tailscale/corp#15261
Change-Id: Ia6d0c310da6464dda79a70fc3c18be0782812d3f
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Endeavour OS, at least, uses NetworkManager 1.44.2 and does
not use systemd-resolved behind the scenes at all. If we
find ourselves in that situation, return "direct" not
"systemd-resolved"
Fixes https://github.com/tailscale/tailscale/issues/9687
Signed-off-by: Denton Gentry <dgentry@tailscale.com>