mirror of
https://github.com/go-gost/x.git
synced 2026-10-19 16:16:32 +00:00
tun: the registration handshake is not a keepalive option
A tun client registers its device's addresses with the far side's tun
server by sending the handshake frame. That frame is what tells the server
which addresses this device holds, and it is the only thing that can: a
server routes by destination address, so without it the link is one-way —
traffic leaves and nothing comes back.
keepalive() has always sent it unconditionally and returned early when no
period was configured, so the period only ever decided whether it
repeated. The call site did not: it was gated on the udp network or a
configured period, which on a p2p link ("ip") meant no period, no
handshake, no registration at all. That is the shape a p2p hub needs
least — its route table has no TTL to refresh, so the repeat buys nothing
there and the one-shot is the whole of it.
The gate is gone; the handshake always runs. The period keeps its meaning
where it has one: a server reached over UDP is connectionless, so silence
is the only signal that a peer has left, and the repeat is what lets its
route expire.
Found by a user asking why the keepalive switch was needed at all. It was
not, on a p2p hub — and turning it off silently produced the one-way link
the entrypoint's own comment warns about.
This commit is contained in:
+15
-9
@@ -44,16 +44,22 @@ func (h *tunHandler) handleClient(ctx context.Context, conn net.Conn, network st
|
||||
}
|
||||
defer cc.Close()
|
||||
|
||||
// A datagram link needs the keepalive. On the udp network it is the
|
||||
// registration handshake (and runs even without keepalive:true, so
|
||||
// existing configs keep their one-shot registration); on a p2p link
|
||||
// ("ip") it is what registers the route with the peer's tun server.
|
||||
if network == "udp" || h.md.keepAlivePeriod > 0 {
|
||||
iterCtx, iterCancel := context.WithCancel(ctx)
|
||||
defer iterCancel()
|
||||
// The registration handshake always runs. It is how the far side's
|
||||
// tun server learns which addresses this device holds, and it is
|
||||
// the only thing that tells it — a server routes by destination
|
||||
// address, and this is the sole source of that mapping. Without it
|
||||
// the link is one-way: traffic leaves, and nothing can come back.
|
||||
//
|
||||
// A configured keepalive period only decides whether the handshake
|
||||
// then repeats, which matters against a server reached over UDP:
|
||||
// UDP is connectionless, so silence is the only signal that a peer
|
||||
// has left, and a repeat is what lets a route expire. On a p2p link
|
||||
// the period buys nothing — closing the stream says the peer is
|
||||
// gone — so a one-shot is the whole of it there.
|
||||
iterCtx, iterCancel := context.WithCancel(ctx)
|
||||
defer iterCancel()
|
||||
|
||||
go h.keepalive(iterCtx, cc, ips)
|
||||
}
|
||||
go h.keepalive(iterCtx, cc, ips)
|
||||
|
||||
return h.transportClient(ctx, conn, cc, log)
|
||||
}()
|
||||
|
||||
Reference in New Issue
Block a user