If the NodeAttrDisableRelayClient node attribute is set, ensures that a node cannot allocate endpoints on a UDP relay server itself, and cannot use newly-discovered paths (via disco/CallMeMaybeVia) that traverse a UDP relay server.
Fixestailscale/corp#30180
Signed-off-by: Dylan Bargatze <dylan@tailscale.com>
Since a [*lazyEndpoint] makes wireguard-go responsible for peer ID, but
wireguard-go may not yet be configured for said peer, we need a JIT hook
around initiation message reception to call what is usually called from
an [*endpoint].
Updates tailscale/corp#30042
Signed-off-by: Jordan Whited <jordan@tailscale.com>
TCP connections are two unidirectional data streams, and if one of these
streams closes, we should not assume the other half is closed as well.
For example, if an HTTP client closes its write half of the connection
early, it may still be expecting to receive data on its read half, so we
should keep the server -> client half of the connection open, while
terminating the client -> server half.
Fixestailscale/corp#29837.
Signed-off-by: Naman Sood <mail@nsood.in>
These were flipped. DstIP() and DstIPBytes() are used internally by
wireguard-go as part of a handshake DoS mitigation strategy.
Updates tailscale/corp#20732
Updates tailscale/corp#30042
Signed-off-by: Jordan Whited <jordan@tailscale.com>
Just make [relayManager] always handle it, there's no benefit to
checking bestAddr's.
Also, remove passing of disco.Pong to [relayManager] in
endpoint.handlePongConnLocked(), which is redundant with the callsite in
Conn.handleDiscoMessage(). Conn.handleDiscoMessage() already passes to
[relayManager] if the txID us not known to any [*endpoint].
Updates tailscale/corp#27502
Signed-off-by: Jordan Whited <jordan@tailscale.com>
A lazyEndpoint may end up on this TX codepath when wireguard-go is
deemed "under load" and ends up transmitting a cookie reply using the
received conn.Endpoint.
Updates tailscale/corp#20732
Updates tailscale/corp#30042
Signed-off-by: Jordan Whited <jordan@tailscale.com>
Inverts the nodeAttrs related to UDP relay client/server enablement to disablement, and fixes up the corresponding logic that uses them. Also updates the doc comments on both nodeAttrs.
Fixestailscale/corp#30024
Signed-off-by: Dylan Bargatze <dylan@tailscale.com>
Cryptokey Routing identification is now required to set an [epAddr] into
the peerMap for Geneve-encapsulated [epAddr]s.
Updates tailscale/corp#27502
Updates tailscale/corp#29422
Updates tailscale/corp#30042
Signed-off-by: Jordan Whited <jordan@tailscale.com>
Changes to our src/address family can trigger blackholes.
This commit also adds a missing set of trustBestAddrUntil when setting
a UDP relay path as bestAddr.
Updates tailscale/corp#27502
Signed-off-by: Jordan Whited <jordan@tailscale.com>
Otherwise we can end up mirroring packets to them forever. We may
eventually want to relax this to direct paths as well, but start with
UDP relay paths, which have a higher chance of becoming untrusted and
never working again, to be conservative.
Updates tailscale/corp#27502
Signed-off-by: Jordan Whited <jordan@tailscale.com>
This was previously hooked around direct UDP path discovery /
CallMeMaybe transmission, and related conditions. Now it is subject to
relay-specific considerations.
Updates tailscale/corp#27502
Signed-off-by: Jordan Whited <jordan@tailscale.com>
Relay handshakes may now occur multiple times over the lifetime of a
relay server endpoint. Handshake messages now include a handshake
generation, which is client specified, as a means to trigger safe
challenge reset server-side.
Relay servers continue to enforce challenge values as single use. They
will only send a given value once, in reply to the first arriving bind
message for a handshake generation.
VNI has been added to the handshake messages, and we expect the outer
Geneve header value to match the sealed value upon reception.
Remote peer disco pub key is now also included in handshake messages,
and it must match the receiver's expectation for the remote,
participating party.
Updates tailscale/corp#27502
Signed-off-by: Jordan Whited <jordan@tailscale.com>
Premature cancellation was preventing the work from ever being cleaned
up in runLoop().
Updates tailscale/corp#27502
Signed-off-by: Jordan Whited <jordan@tailscale.com>
If we acted as the allocator we are responsible for signaling it to the
remote peer in a CallMeMaybeVia message over DERP.
Updates tailscale/corp#27502
Signed-off-by: Jordan Whited <jordan@tailscale.com>
udprelay.Server is lazily initialized when the first request is received
over peerAPI. These early requests have a high chance of failure until
the first address discovery cycle has completed.
Return an ErrServerNotReady error until the first address discovery
cycle has completed, and plumb retry handling for this error all the
way back to the client in relayManager.
relayManager can now retry after a few seconds instead of waiting for
the next path discovery cycle, which could take another minute or
longer.
Updates tailscale/corp#27502
Signed-off-by: Jordan Whited <jordan@tailscale.com>
Any return underneath this select case must belong to a type switch case.
Updates tailscale/corp#27502
Signed-off-by: Jordan Whited <jordan@tailscale.com>
This reverts commit 6a93b17c8cafc1d8e1c52e133511e52ed9086355.
The reverted commit added more complexity than it was worth at the
current stage. Handling delta CapVer changes requires extensive changes
to relayManager datastructures in order to also support delta updates of
relay servers.
Updates tailscale/corp#27502
Signed-off-by: Jordan Whited <jordan@tailscale.com>
nodeBackend now publishes filter and node changes to eventbus topics
that are consumed by magicsock.Conn
Updates tailscale/corp#27502
Updates tailscale/corp#29543
Signed-off-by: Jordan Whited <jordan@tailscale.com>
This enables us to mark nodes as relay capable or not. We don't actually
do that yet, as we haven't established a relay CapVer.
Updates tailscale/corp#27502
Signed-off-by: Jordan Whited <jordan@tailscale.com>
It might complete, interrupting it reduces the chances of establishing a
relay path.
Updates tailscale/corp#27502
Signed-off-by: Jordan Whited <jordan@tailscale.com>
This is simply for consistency with relayManagerInputEvent(), which
should be the sole launcher of runLoop().
Updates tailscale/corp#27502
Signed-off-by: Jordan Whited <jordan@tailscale.com>
relayManager can now hand endpoint a relay epAddr for it to consider
as bestAddr.
endpoint and Conn disco ping/pong handling are now VNI-aware.
Updates tailscale/corp#27502
Updates tailscale/corp#29422
Signed-off-by: Jordan Whited <jordan@tailscale.com>
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>
Fragmented datagrams would be processed instead of being dumped right
away. In reality, thse datagrams would be dropped anyway later so there
should functionally not be any change. Additionally, the feature is off
by default.
Closes#16203
Signed-off-by: Claus Lensbøl <claus@tailscale.com>
Our conn.Bind implementation is updated to make Send() offset-aware for
future VXLAN/Geneve encapsulation support.
Updates tailscale/corp#27502
Signed-off-by: Jordan Whited <jordan@tailscale.com>
relayManager is responsible for disco ping/pong probing of relay
endpoints once a handshake is complete.
Future work will enable relayManager to set a relay endpoint as the best
UDP path on an endpoint if appropriate.
Updates tailscale/corp#27502
Signed-off-by: Jordan Whited <jordan@tailscale.com>
This type improves code clarity and reduces the chance of heap alloc as
we pass it as a non-pointer. VNI being a 3-byte value enables us to
track set vs unset via the reserved/unused byte.
Updates tailscale/corp#27502
Signed-off-by: Jordan Whited <jordan@tailscale.com>
CallMeMaybeVia reception and endpoint allocation have been collapsed to
a single event channel. discoInfo caching for active relay handshakes
is now implemented.
Updates tailscale/corp#27502
Signed-off-by: Jordan Whited <jordan@tailscale.com>
Add new rules to update DNAT rules for Kubernetes operator's
HA ingress where it's expected that rules will be added/removed
frequently (so we don't want to keep old rules around or rewrite
existing rules unnecessarily):
- allow deleting DNAT rules using metadata lookup
- allow inserting DNAT rules if they don't already
exist (using metadata lookup)
Updates tailscale/tailscale#15895
Signed-off-by: Irbe Krumina <irbe@tailscale.com>
Co-authored-by: chaosinthecrd <tom@tmlabs.co.uk>
The event loop removes the need for growing locking complexities and
synchronization. Now we simply use channels. The event loop only runs
while there is active work to do.
relayManager remains no-op inside magicsock for the time being.
endpoints are never 'relayCapable' and therefore endpoint & Conn will
not feed CallMeMaybeVia or allocation events into it.
A number of relayManager events remain unimplemented, e.g.
CallMeMaybeVia reception and relay handshaking.
Updates tailscale/corp#27502
Signed-off-by: Jordan Whited <jordan@tailscale.com>
relayManager will eventually be responsible for handling the allocation
and handshaking of UDP relay server endpoints.
relay servers are endpoint-independent, and Conn must already maintain
handshake state for all endpoints. This justifies a new data structure
to fill these roles.
Updates tailscale/corp#27502
Signed-off-by: Jordan Whited <jordan@tailscale.com>
Conn.handleDiscoMessage() now makes a distinction between relay
handshake disco messages and peer disco messages.
Updates tailscale/corp#27502
Signed-off-by: Jordan Whited <jordan@tailscale.com>
Conn.sendDiscoMessage() now verifies if the destination disco key is
associated with any known peer(s) in a thread-safe manner.
Updates #15844
Signed-off-by: Jordan Whited <jordan@tailscale.com>