Tunnel Doctor
Diagnoses and fixes Tailscale conflicts with proxy/VPN tools (Shadowrocket, Clash, Surge, OrbStack/Docker) on macOS when SSH, curl, browsers or Docker mysteriously hang.
UtilitiesAdvanced★ 1,323⑂ 212AI score 8/10Last updated: Aug 8, 2026
What it does
When Tailscale runs alongside a TUN-mode proxy on macOS, breakage can happen at several independent layers. This skill separates the layers and points to the exact fix.
- Five conflict layers: route-table hijacking,
http_proxyenv vars, system proxy (browser-only 503), SSHProxyCommanddouble tunneling, and proxy propagation into VM/container runtimes. - Symptom → step lookup table: "tailscale ping works but SSH times out", "browser 503 while curl returns 200", "git push fails intermittently with
failed to begin relaying via HTTP", "RUN apk addfails instantly inside docker build". - TUN measurement contamination guide: explains why
nc -zshowing0.00sor sub-millisecond pings to another continent are fabricated by the TUN, and which metrics (time_appconnect,time_starttransfer) you can still trust. - DNS-specific traps: 198.18.x.x fake-IP hijack, a dead supplemental resolver that stalls
ssh/curlfor ~60s whilenslookupis instant, and DIRECT split-brain where every direct-routed site dies at once. scripts/quick_diagnose.pyautomates NO_PROXY checks, system-proxy exceptions, direct-vs-proxy path split and local TLS trust.
Who it's for
- Developers who SSH into remote dev boxes (Mac Mini, WSL) over Tailscale with a proxy always on.
- Anyone on a proxy-mandatory network whose
docker pull/docker buildkeeps timing out. - Engineers who want evidence-driven network debugging instead of guesswork.
- People stuck on
kex_exchange_identification: Connection closedwhile enabling Tailscale SSH to WSL.
Examples
- Browser-only 503: curl returns 200 but the browser shows 503 on a Tailscale IP → identified as Layer 3 (system proxy), fixed by adding
100.64.0.0/10to Shadowrocket'sskip-proxy. - Only
git pushfails:ssh -T git@github.comsucceeds but push dies with a relaying error → diagnosed as an SSH double tunnel, verified withProxyCommand=none, then migrated tossh.github.com:443. - Broken
docker build: host curl works butRUN apk addfails in under 0.2s → OrbStack transparent proxy clashing with the TUN, fixed via--network hostor adocker.jsonpointing athost.internal.
· · · Install guide · · ·
Install in the Claude app (no terminal)
- Download the ZIP with the button below.
- In Claude, open Settings → Capabilities and turn on 'Code execution and file creation'. (one time)
- Go to Customize → Skills → + → 'Upload a skill' and upload the ZIP.
Install in Claude Code
Let Claude do it — paste this into Claude Code
Install the skill I found on Claude Skill Mart. Copy the tunnel-doctor folder from the GitHub repo daymade/claude-code-skills into my ~/.claude/skills/tunnel-doctor/. When it's done, tell me in one line what this skill can do.
Install with a command instead
git clone https://github.com/daymade/claude-code-skills.git && mkdir -p ~/.claude/skills && cp -r claude-code-skills/tunnel-doctor ~/.claude/skills/⚠ This is a third-party skill. Check the source repository before installing.
- Open a terminal and clone the repository that contains the skill:
git clone https://github.com/daymade/claude-code-skills.git - Create your Claude Code skills directory if it doesn't exist:
mkdir -p ~/.claude/skills - Copy the whole
tunnel-doctorfolder so itsscripts/andreferences/files come along:cp -r claude-code-skills/tunnel-doctor ~/.claude/skills/ - Verify with
ls ~/.claude/skills/tunnel-doctor— you should seeSKILL.md. - Restart Claude Code, then describe your symptom (e.g. "tailscale ping works but SSH times out") to trigger the skill.
- The quick-diagnose helper needs Python 3; check with
python3 --version. - Safety note: several fixes modify routes, DNS settings and Docker daemon config — read each suggested command before running it and back up existing config files.
View source on GitHub ↗License: MIT