Skip to content

fix(intercept): resolve bridge's own lookups without the tunnel it's redialing - #20

Merged
vercel-eddie merged 2 commits into
mainfrom
eddie/bridge-dns-reconnect
Nov 10, 2026
Merged

vercel-eddie merged 2 commits into
mainfrom
eddie/bridge-dns-reconnect

Conversation

@vercel-eddie

Copy link
Copy Markdown
Collaborator

Problem

When an intercept's gRPC connection to the proxy drops, it never comes back, and every DNS lookup in the container fails until the bridge is torn down.

The redial goes resolvePod → K8s API → aws eks get-token → STS, so it needs real DNS. The _bridge group's RETURN rule (551b34d) was meant to give it that. Since #9, though, /etc/resolv.conf names only 127.0.0.1. So bridge's own lookups still reach the DNS server that asks the tunnel, and with --forward-domains "*" that includes the API server. The redial can't resolve the cluster it's redialing, and it fails forever:

lookup 357A8D7E….gr7.us-east-2.eks.amazonaws.com on 127.0.0.1:53: server misbehaving
tunnel DNS resolution for 357a8d7e….gr7.us-east-2.eks.amazonaws.com: ResolveDNSQuery RPC: … waiting for connections to become ready

This takes down vercel/api's Devbox E2E, which bridges api-devbox and subscriber-devbox into staging. In runs 42716374698 and 42136406829, both bridges lost their connection within 35s of each other. DNS then failed about 12,000 times with no recovery, and about 70 tests failed (getaddrinfo EAI_AGAIN vercel.com, S3, DynamoDB, ElastiCache…).

Change

  • Bypass DNS for bridge's own group. A second DNS server on a random loopback port that only asks the original nameserver, over TCP so the UDP redirect can't loop it. The _bridge group's UDP :53 is redirected to it instead of RETURN. The app's lookups are unchanged: they still go through the tunnel, with no fallback around it.
  • Replace a dead pooled port-forward. dialerPool handed a cached portforward.Dialer back forever, even after its SPDY connection closed. So once DNS works, every redial to the same pod would still fail. It now replaces a dialer whose CloseChan() has fired.

Validation

  • New e2e TestBridgeResolvesWhileTunnelIsDown runs intercept under sg _bridge (as the feature does) and stops the proxy. Then it checks two things: bridge's group still resolves a name only the container's own Docker DNS knows, and root (the app) doesn't. On main it fails with Can't find witness: No answer, the same as CI. With this change it passes.
  • Unit tests for the iptables ordering (the _bridge rule comes before the general redirect, with no RETURN) and for replacing a closed pooled dialer.

🤖 Generated with Claude Code

vercel-eddie and others added 2 commits November 9, 2026 16:02
…redialing

When the gRPC connection to the proxy drops, the k8spf redial needs real
DNS: resolvePod → K8s API → aws eks get-token → STS. The _bridge group was
meant to skip the DNS redirect for this, but since /etc/resolv.conf names
only 127.0.0.1, its lookups still reached the DNS server that asks the
tunnel. With --forward-domains "*" that includes the API server itself, so
every redial failed and the intercept never recovered: all DNS in the
container stayed SERVFAIL until it was torn down.

- Start a bypass DNS server that only asks the original nameserver, and
  redirect the _bridge group's UDP :53 to it instead of RETURN. The app's
  lookups still go through the tunnel, with no fallback around it.
- Replace a pooled SPDY port-forward dialer once its connection closes.
  The pool handed the dead one back forever, so redials would fail even
  with DNS working.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…'t apply

GitHub runners give containers an Azure search domain, and busybox nslookup
then queries only witness.<domain>.internal.cloudapp.net.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel-eddie
vercel-eddie marked this pull request as ready for review November 10, 2026 01:00
@vercel-eddie
vercel-eddie merged commit c39101f into main Nov 10, 2026
6 checks passed
@vercel-eddie
vercel-eddie deleted the eddie/bridge-dns-reconnect branch November 10, 2026 01:00
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.

1 participant