gateway: fix funnel-watchdog to probe real public path (b66, interim) - #40
Draft
baron-3dl wants to merge 1 commit into
Draft
gateway: fix funnel-watchdog to probe real public path (b66, interim)#40baron-3dl wants to merge 1 commit into
baron-3dl wants to merge 1 commit into
Conversation
The camp's portal timeouts trace to the gateway VM's CGNAT uplink: a middlebox on its path (on-prem MiniUPnPd/Debian-wheezy router at 192.168.2.1 and/or the carrier CGNAT) flushes long-lived TCP state on a fixed ~34-min timer, regardless of traffic. Measured on 2026-08-11 (enterpriseaiframework-b66): - gateway tailscaled control+DERP resets every 33-36 min for 6+ h (a metronome). - Silent blackhole: a 40-min tcpdump on :443 caught ZERO RSTs; the dying flow just had bytes stuck in Send-Q. NAT-state teardown, not an active reset. - Flows carry packets every 2-13s yet still die on the tick -> keepalives can't prevent it; the flush is scheduled. - workshop (same LAN, same CGNAT egress, same router, same UPnP/offloads/TS ver) had 0 such resets in the same window -> gateway-node-specific, not the uplink as a whole, and not any host config that can be copied over. Each flush drops the public Funnel path; tailscaled usually self-heals in 1-2 min but occasionally wedges. The prior watchdog checked `tailscale status ... offline` -- a signal the fast self-heal almost never trips -- so it fired 0x in 12h while the portal was actually down. This version probes the real public Funnel path (portal via the ingress IPs) every 30s and bounces tailscale only after ~90s of sustained outage, with a 120s cooldown. Verified end-to-end: injected `tailscale down`, watchdog auto-recovered the public portal in 107s. Interim only. The durable fix is to move public ingress off the CGNAT path (replace the router, or a public-IP/Cloudflare-Tunnel ingress with the OIDC-hostname reconfiguration that implies) -- raised as an operator decision on b66. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Root cause (enterpriseaiframework-b66)
Camp portal timeouts + long glm-5.2 stream deaths trace to the gateway VM's CGNAT uplink: a middlebox on its path (the on-prem
MiniUPnPd/Debian-wheezy router at192.168.2.1, and/or the carrier CGNAT) flushes long-lived TCP state on a fixed ~34-min timer, regardless of traffic.Evidence gathered 2026-08-11:
tailscaledcontrol+DERP reset every 33–36 min for 6+ h — a metronome, not random NAT churn.tcpdumpon:443caught zero RSTs; the dying flow just had bytes stuck inSend-Q. NAT-state teardown, not an active reset.Each flush drops the public Funnel path.
tailscaledusually self-heals in 1–2 min but occasionally wedges. The prior watchdog checkedtailscale status … offline— which the fast self-heal almost never trips — so it fired 0× in 12 h while the portal was actually down.This change (interim)
Tracked, corrected watchdog under
deploy/gateway/funnel-watchdog/. Probes the real public Funnel path every 30s; bounces tailscale only after ~90s sustained outage (debounced past normal self-heal), 120s cooldown to avoid thrash.Verified end-to-end: injected
tailscale down, watchdog auto-recovered the public portal in 107s. (Old watchdog would not have fired at all.)Not the durable fix
Does not eliminate the ~34-min blips and cannot save an in-flight stream. It is a safety net for genuine wedges.
Durable fix — operator decision (raised on b66)
The CGNAT uplink cannot hold a connection past ~34 min, so no gateway-local change makes the public path reliable:
gateway.tailcb6ef9.ts.net→ coordinated auth reconfig + CF account/domain (spend/scope).🤖 Generated with Claude Code