Mac OS X Wi-Fi Preferred Network Management

Rule4 Blog
4 min readSep 21, 2019

--

Update 5/14/21: Well, there’s a much easier way to do this, at least in Big Sur. You’ll need to know the SSID, your network interface name, and the network security type. With that, you should be able to run:

networksetup -removepreferredwirelessnetwork en0 "<SSID_NAME>"
networksetup -addpreferredwirelessnetworkatindex en0 "<SSID_NAME>" 0 WPA2

Given the credentials are decoupled from the network and in your Keychain, it probably works for versions prior to Big Sur. Simplicity FTW!

Invariably while away from the office, you find yourself needing to connect to a wireless network. Maybe you join the ubiquitous network presented by an equally ubiquitous coffee shop chain, or perhaps you have a cable/DSL subscription with a large Internet provider that gives you access to some form of hotspot network as a value-add. Whatever the reason, you need some bytes and you need ’em now, so you connect to the often abysmally performant network.

All the great networks.

Quick note: This isn’t a guide on safe network selection, verification, and VPN use, but don’t forget to take suitable precautions when and if you have to connect to low-trust networks.

Whatever network you connected to, assuming it’s the first time you’ve connected on a Mac, you’ve likely just set a new highest priority network in your preferred network list. You can manage this to a degree by disabling the option to remember networks the system has joined, and also by disabling auto-join for particular networks. But more often than not, even knowing that setting is available, I find it’s preferable to remember networks and deal with connection preference issues than to seek out access information for a network each time.

Your excursion into the wide world complete, you find yourself back in your office or home, and you eventually realize (after too many minutes of puzzling over some specific failed connection and many mumbles of “Why isn’t this working?”) that you’re connected not to the network in your location, but instead to the network you opportunistically used out in the wild that blankets the country with the same SSID. Various other forms of this problem might exist, including centrally managed configuration deployment and conflicts, temporary guest or alternative network use in the vicinity of your primary network, or any other scenario that puts you in a position where a network other than your expected network ends up higher on your priority list.

This isn’t a complex problem, and it takes seconds to correct it once you realize what’s happening. But, it’s annoying. There should be some way to programmatically manage this, or a way to apply an absolute priority value for a network that overrides implicit prioritization based on adding new networks, but that doesn’t seem to exist. The networksetup command gives us hope:

networksetup -addpreferredwirelessnetworkatindex 1 <your_ssid>

Only to shatter the hope just as quickly (it’s a literal add, as opposed to an add or an update):

** Error: The amount of parameters was not correct.

The parameter requirements are defined in the help:

Usage: networksetup -addpreferredwirelessnetworkatindex <device name> <network> <index> <security type> [password]Add wireless network named <network> to preferred list for <device name> at <index>. For security type, use OPEN for none, WPA for WPA Personal, WPAE for WPA Enterprise, WPA2 for WPA2 Personal, WPA2E for WPA2 Enterprise, WEP for plain WEP, and 8021XWEP for 802.1X WEP. If a password is included, it gets stored in the keychain.

So while you can list preferred networks (networksetup -listpreferredwirelessnetworks <interface>), you can’t change priorities. Weak. It’s even more of a pain if you’re trying to manage a fleet of Macs and users are able to manage their own network additions.

One Network To Rule Them All

The script below is intended to solve this problem using a combination of various tools and command chaining to perform the file content manipulation that reorders the network list. I make no claim that it’s the most efficient method :). A few help notes and useful script background (let’s assume you name the script mac_wipri):

  • The preferred network list is stored in the global /Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist file, and will require administrative rights to edit with the script.
  • The network preferences file is XML (and thus fairly parsable with tools such as Xpath), and the script uses some relative navigation between parent and sibling elements based on identifiable elements/values and resulting value extraction.
  • Put the script in /usr/local/sbin/, ensuring permissions are set to 540 to allow execution and no editing, e.g.:
sudo chmod 540 /usr/local/sbin/mac_wipri
  • Because it’s modifying a protected file, you’ll need to ensure it runs with administrative privileges. Add a sudoers file entry to support running this script without prompting for a password so that you can schedule it via cron. Change <user> to your username.
<user> (ALL) = (root) NOPASSWD: /usr/local/sbin/mac_wipri
  • Edit your crontab (generally via crontab -e) and add and entry to update your preferences file on whatever schedule you prefer. This example will move the “Foxes Rock” network to the top of the list every 30th minute past every hour from 6 a.m. through 5 p.m. Mon-Fri:
*/30 6-17 * * 1-5 sudo /usr/local/sbin/mac_wipri "Foxes Rock"

Preferred Network Change Script

Single-file script to move an existing SSID to the top of the preferred network list

Hopefully there are enough comments that you can walk through the script and get an understanding of what’s happening. That said, comments and questions are always welcome.

Written by Paul Nelson.

Interested in what us foxes are doing? Follow @mrpnelson and @rule4 on Twitter.

--

--

Rule4 Blog

Rule4. Cybersecurity and emerging technology expertise for every organization.