Mohamed Elashri

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:

  • SSID match for home (HomeNetworkI, HomeNetworkII) or CERN (CERN, eduroam, etc.).
  • Default gateway check for known CERN subnets (yes, that big 137.138.0.0/16 world and a couple of friends).
  • Search domain hints from the system resolver (anything ending in cern.ch is a pretty loud clue).

Policy is even simpler:

  • Home SSIDs → DHCP DNS (use the router provided).
  • CERN signals → use 137.138.16.5 and 137.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 --dns shows my router as the effective default resolver, and dig example.com reports SERVER: 192.168.x.1#53 (or whatever my gateway is).
  • At CERN, scutil --dns includes cern.ch search domains and the default resolver block points to 137.138.16.5 or 137.138.17.5. dig will show one of those answering.
  • Elsewhere, dig shows 9.9.9.9 unless 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.