Skip to content

fix(wg): rate-limit DISCO PONG replies once a direct path is trusted - #64

Merged
fudio101 merged 1 commit into
mainfrom
fix/issue-43-disco-pong-rate-limit
Aug 19, 2026
Merged

fix(wg): rate-limit DISCO PONG replies once a direct path is trusted#64
fudio101 merged 1 commit into
mainfrom
fix/issue-43-disco-pong-rate-limit

Conversation

@fudio101

Copy link
Copy Markdown
Collaborator

Summary

Adapted from dj-oyu/microlink@bde4bff (issue #43, piece 4 of 4) — hand-ported against process_disco_ping() since dj-oyu's pre-refactor disco_process_packet() no longer exists in this fork's layout.

Once a peer has a trusted direct path, the remote tailscaled peer sends NAT-keepalive PINGs roughly every few seconds. This fork was answering every single one with a 3-path PONG (direct reply + all LAN endpoints + DERP relay) — pure waste once the path is established. Now rate-limited to 1/5s per peer via a new last_pong_sent_ms field, gated on has_direct_path so it still answers immediately while searching (no direct path yet) or on the very first reply, since that's what establishes the path in the first place.

This closes out issue #43's remaining bundle. The other 3 pieces needed no code change:

Closes #43

Test plan

  • No automated tests (hardware-in-the-loop only, per CLAUDE.md) — needs on-device verification: establish a direct path between two nodes, confirm PONG replies drop to ~1/5s cadence instead of matching every incoming PING, and that the direct path stays trusted (no spurious fallback to DERP from the reduced PONG traffic).
  • Reviewed for field/struct compatibility (has_direct_path, ml_get_time_ms() — both already used identically elsewhere in this file).
  • Verified no overlap with the still-running investigation into issue DERP backpressure/reconnect-storm fixes: busy-loop, TCP_NODELAY, reader/writer split (mined from Csontikka/microlink) #35's remaining DERP retry/watchdog pieces (this PR only touches ml_wg_mgr.c's DISCO ping handler, not ml_derp.c).

Adapted from dj-oyu/microlink@bde4bff (issue #43, piece 4 of 4) --
hand-ported against process_disco_ping() since dj-oyu's pre-refactor
disco_process_packet() no longer exists in this fork's layout.

Once a peer has a trusted direct path, the remote tailscaled peer
sends NAT-keepalive PINGs roughly every few seconds. This fork was
answering every single one with a 3-path PONG (direct reply + all LAN
endpoints + DERP relay) -- pure waste once the path is established.
Now rate-limited to 1/5s per peer via a new last_pong_sent_ms field,
gated on has_direct_path so it still answers immediately while
searching (no direct path yet) or on the very first reply, since
that's what establishes the path in the first place.

This closes out issue #43's remaining bundle. The other 3 pieces
needed no code change:
- TAI64N: superseded by upstream PR #22's absorption (6a4447c).
- DERP->direct re-handshake trilogy (a30160a, eb3dce0, c505539):
  investigated, not needed. wireguardif_connect() already forces an
  immediate handshake and wireguardif_connect_derp() already exists
  (landed via #34/#42). update_peer_addr() already retargets a peer's
  ip/port on every valid decrypted packet regardless of transport, so
  an established session's keypair keeps working transport-agnostically
  across a DERP->direct switch -- exactly what the trilogy's own final
  commit independently concludes. Issue #33's already-landed NAT-rebind
  logic implements the same reasoning with an added data-liveness
  safety net the trilogy never had.
- LOCK_TCPIP_CORE no-op -> tcpip_try_callback: investigated, not
  needed. This fork's WG RX (direct + DERP) funnels through a single
  wg_rx_queue consumed only by wg_mgr task -- no concurrent caller of
  wireguardif_network_rx() ever exists to race. Same architectural
  class as issue #31's resolution.

Closes #43

Co-authored-by: Adrian.Nguyen-Qualgo <tansolo.barn@gmail.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@fudio101
fudio101 merged commit ac9e156 into main Aug 19, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Adapt dj-oyu/microlink fixes: TAI64N replay-after-reboot, DERP-to-direct re-handshake, LOCK_TCPIP_CORE no-op, DISCO PONG rate-limiting

2 participants