My Lazy DNS Auto-Switch on macOS (Home vs CERN)
I wanted my macOS device to quietly use the home router’s DNS when I am on my home Wi-Fi network, But because CERN IT don't like anyone to use external DNS and as a rules' follower I don't want to try to circumvent that. So I want to switch to CERN’s DNS when I am connected to CERN network, but use 9.9.9.9 on other networks (If I'm not using a VPN or tailscale). But I get tired of clicking through System Settings and remembering to undo a manual change after I leave. So I thought, why not automate it? I came up with a simple solution that works well for my needs, and I thought I would share it in case it helps someone else.
The idea is simple: a tiny script runs as a LaunchAgent. It detects where I am and sets DNS for the active network service. Detection uses a few signals:
SSIDmatch for home (HomeNetworkI,HomeNetworkII) or CERN (CERN,eduroam, etc.).- Default gateway check for known CERN subnets (yes, that big
137.138.0.0/16world and a couple of friends). - Search domain hints from the system resolver (anything ending in
cern.chis a pretty loud clue).
Policy is even simpler:
- Home
SSIDs→ DHCP DNS (use the router provided). - CERN signals → use
137.138.16.5and137.138.17.5. - Everything else →
9.9.9.9.
Why not a profile or MDM? Because I bounce between home, CERN, and odd coffee-shop/Airport Wi-Fi, and I do not want profiles fighting with VPNs or split-DNS. A tiny script is honest, it sets exactly what I want right now, then gets out of the way.
How it works at runtime?
The LaunchAgent triggers on login, on network changes, and on a short interval (which is probably overkilling but why not?). The script figures out the default interface (typically en0), maps that to the corresponding Network Service (e.g., “Wi-Fi”), then decides a target DNS based on the signals above and applies it with networksetup. If DNS is already correct, it does nothing. If a VPN tries to be bossy, I can still let it win for work cases; the script is not a firewall, it is just a polite nudge toward the right default.
What I will see when it flips correctly:
- At home,
scutil --dnsshows my router as the effective default resolver, anddig example.comreportsSERVER: 192.168.x.1#53(or whatever my gateway is). - At CERN,
scutil --dnsincludescern.chsearch domains and the default resolver block points to137.138.16.5or137.138.17.5.digwill show one of those answering. - Elsewhere,
digshows9.9.9.9unless some VPN overrides it for a scoped domain.
I am not pasting the full script here because it is a bit longer than a blog snippet deserves, but it is just a Bash file. Grab the exact version I use (with SSID list, CERN CIDRs, and a couple of debug lines) from this gist.
The setup is quick, put the script in ~/.local/bin/ssid-dns.sh, make it executable, drop the plist in ~/Library/LaunchAgents/, and launchctl load it. If you want to test without installing, just run the script and then check: scutil --dns | sed -n '1,80p' and dig example.com | grep '^;; SERVER:'. When you roam between home, CERN, and the outside world, it should quietly keep the resolver sane.
I hope this would help someone else who have this annoyance.