Check routing tables quickly with netstat -nr
Last week my Docker containers suddenly lost internet on my MacBook while I was tethered to a hotel Wi-Fi + VPN. DNS looked fine, but pings to 8.8.8.8 hung.
The culprit turned out to be a rogue default route left behind by the VPN client.
netstat -nr exposed it in two seconds.
$ netstat -nr
Routing tables
Internet:
Destination Gateway Flags Netif Expire
default 172.20.0.1 UGSc utun3
default 192.168.1.1 UGSc en0
127.0.0.1 127.0.0.1 UH lo0
192.168.1.0/24 link#4 U en0
How to read those columns
| Column | What it tells you | How I used it |
|---|---|---|
| Destination | Network or host the rule matches. default = “everything not matched elsewhere.” |
I immediately saw two defaults—bad sign. |
| Gateway | Next hop for that destination. | 172.20.0.1 came from the VPN adapter; should have disappeared when I disconnected. |
| Flags | U = route up, G = via gateway, S = static, C = cloned, etc. | Both defaults had UGSc, so the system could pick either—hello packet limbo. |
| Netif | Interface sending the traffic (en0, utun3, lo0, …). |
The bad route pointed to utun3 (VPN tunnel) instead of en0 (Wi-Fi). |
| Expire | Seconds until the ARP entry ages out (blank for static). | Not critical here, but useful when chasing ARP/ND cache issues. |
Why the -n matters
The -n switch skips DNS and reverse-lookup delays, so routes pop up instantly—crucial when you're half-connected.
Fixing my issue
# delete the stale VPN route
sudo route delete default 172.20.0.1
A quick re-run of netstat -nr showed a single healthy default pointing at 192.168.1.1 on en0, and Docker traffic flowed again.
When netstat isn't around
- Modern Linux:
ip route showgives an even terser view.
default via 192.168.1.1 dev wlan0 proto dhcp metric 100 - Fallback:
route -nstill works almost everywhere.