Posted on 10-05-2015 11:48 AM
Is anyone out there successfully blocking your Macs from joining specific wireless networks? We have a public guest network and a hidden production network and would like to block workstations from connecting to our guest network and force them to our prod network.
Posted on 10-05-2015 12:21 PM
We are using a configuration profile to force the computers to default to one network. You could restrict the PreferencePane for Network and hide the icon using something like:
/usr/libexec/PlistBuddy -c 'Delete :menuExtras:1' ~/Library/Preferences/com.apple.systemuiserver.plist
killall SystemUIServer
Posted on 10-05-2015 12:27 PM
@rhoward That doesn't work for us. We only want them to not join our guest wireless when at the office. These are mostly laptops, and thus travel, and we would want to allow access to network controls to be able to join wifi when off-premises/travel/etc.
Posted on 10-05-2015 12:31 PM
Most effective way to do something like this would be with a NAC based solution, but that's a large-ish project to implement. We've been working with a NAC vendor here for similar functionality, and compliance checking for our corporate Wi-Fi, for close to a year now, and we're only now getting to the full deployment stage, so, lots of testing to do with any NAC solution.
Another possible way would be to have a LaunchDaemon monitor network changes, have the script check to see if the current Wi-Fi connection is on your Guest network and if so, drop the connection and force a connection back to the regular Wi-Fi AP name. And if necessary, delete any saved network setting (preferred wireless networks) from the Mac.
Posted on 10-05-2015 12:53 PM
We have an extension attribute that records SSID's and then policy to delete networks we do not want users to use.
Posted on 10-05-2015 02:18 PM
@jrwilcox Would you be willing to share the extension attribute and the script (I imagine you use a script) to remove the unwanted networks via policy?
Posted on 10-05-2015 02:21 PM
You could run a policy / launchD to check the current SSID against a banned SSID, and if they match disassociate the user and remove the SSID from Preferred Networks.
It won't stop users manually re joining the network, but if you run it on a fairly regular basis I'm sure they will soon get bored / won't notice its switched back to the corporate network.
Here's an example that produces a CLI Tool that you can run, would need some checking for production but should work as a PoC. It will disassociate them, remove the SSID from Preferred Networks at which point the Mac will simply revert to the next best network in its preferred networks list / profile.
TJH:bin tom$ sudo /Users/tom/Library/Developer/Xcode/DerivedData/bannedWifi-faxfdmfmywrgllbkuccsxyxygkts/Build/Products/Debug/bannedWifi "Premier Inn Ultimate Wi-Fi" Current SSID is Premier Inn Ultimate Wi-Fi Banned SSID is Premier Inn Ultimate Wi-Fi Disconnecting from Banned SSID Removing from Preferred Networks 0 TJH:bin tom$
//
// main.swift
// bannedWifi
//
// Created by Thomas Holbrook on 05/10/2015.
// Copyright © 2015 Thomas Holbrook. All rights reserved.
//
// Banned WiFi CLI App
// Bored in a hotel with SSID "Premier Inn Ultimate Wi-Fi"
import Cocoa
import CoreWLAN
import Foundation
let iface = CWWiFiClient.sharedWiFiClient().interface()?.interfaceName
func getCurrentSsid() -> String?
{
//We should check wifi if up here!
return CWWiFiClient.sharedWiFiClient().interface()!.ssid()
}
func getBannedSsid() -> String?
{
//We should check that this argument exists, and if not return a help?
return Process.arguments[1]
}
//Whats our current SSID?
let currentSSID = (getCurrentSsid())
print("Current SSID is " + (currentSSID)!)
//What Banned SSID have we been passed?
let bannedSSID = (getBannedSsid())
print("Banned SSID is " + (bannedSSID)!)
//Check if our current SSID is banned?
if currentSSID == bannedSSID {
//If its a banned SSID diconnect the client
print("Disconnecting from Banned SSID")
CWWiFiClient.sharedWiFiClient().interface()!.disassociate()
//Use networksetup to remove the prefered network entry
let taskCheck = NSTask()
taskCheck.launchPath = "/usr/sbin/networksetup"
taskCheck.arguments = ["-removepreferredwirelessnetwork",iface!,bannedSSID!]
let pipe = NSPipe()
taskCheck.standardOutput = pipe
taskCheck.launch()
taskCheck.waitUntilExit()
print(taskCheck.terminationStatus)
}
else
{
print("Allowed SSID Doing Nothing")
}
Maybe a launchd to watch /etc/resolve so it runs on network changes for a more responsive block?
Posted on 10-05-2015 03:09 PM
I've had success in the past with actually defining the guest network in the Configuration Profile with "auto join" unchecked but adding manual proxy settings for an imaginary proxy server. So, yes, someone could connect manually, but they would get no Internet, and very, very few folks would know to look in the proxy settings to troubleshoot, they'd just give up. At one point at a school, the reverse proxy pointed to an old Xserve and would bring up a page explaining that the use of the guest network with student iPads was forbidden, and then iOS at that time would switch back to the working network automatically within a few seconds of finding no Internet connectivity. It was pretty cool. Not sure if that all would work with the modern Mac OS X, but at least the first part is worth a try, very simple to set up.
Posted on 10-05-2015 03:48 PM
I made a similar solution here: https://jamfnation.jamfsoftware.com/discussion.html?id=13347
But basically, as outlined above, the only real solution is to detect and disconnect. There doesn't seem to be any active way to block the ability to connect to it in the first place.
Posted on 10-06-2015 04:59 AM
Here is our Extension Attribute:
#!/bin/bash
# WiFi_Info.sh
#
#
# Created by James Wilcox on 5/4/15.
#
#
# obtain en number for airport device
#
en=$(networksetup -listallhardwareports | egrep -A 2 "(AirPort|Wi-Fi)" | grep Device | awk '{print $2}')
#
# return list of SSID's in use
#
SSID=$(networksetup -listpreferredwirelessnetworks $en)
echo "<result>$(echo -e "${SSID[@]}" | sed -e 's/^ *//' -e $'s/ / /' )</result>"
We then have a script that is generalized because we actually have 3 SSID'd that should not be used by District owned devices.
#!/bin/bash
# WiFi_Info.sh
#
#
# Created by James Wilcox on 5/4/15.
#
#
# obtain en number for airport device
#
en=$(networksetup -listallhardwareports | egrep -A 2 "(AirPort|Wi-Fi)" | grep Device | awk '{print $2}')
#
# remove SSID passed in 4
#
networksetup -removepreferredwirelessnetwork "$en" "$4"
Posted on 10-06-2015 05:09 AM
So I should have probably prefaced that I am already searching for workstations that trust our guest network, and remediating as needed. And that we're only concerned about laptops since our iMacs obviously have build in ethernet ports, which we take advantage of. Given 99.9% of our laptops are newer, I made a generalization about en0 being the default wifi port.
#!/bin/sh
wifi=`networksetup -listpreferredwirelessnetworks en0 | grep 'GuestWireless' || echo "No"`
echo "<result>$wifi</result>"
And then cleaning up with
#!/bin/sh
networksetup -removepreferredwirelessnetwork en0 GuestWireless
exit 0
But i think it gets to the point that it's H.A.R.D. to block an SSID without doing some major dancing, or trying to cheat the system with a false positive. A second additional bit of info going is that our workstations get bound to our guest by our local tech support (we're 60K winboxes and only a few hundred macs - so our frontline guys skew windows and "struggle" supporting macs). Tricking the system wouldn't work since they come by when there's a support ticket about wireless issues and join the only network they see, which is our guest network. The answer to that is training, I know.
Last point, I need to get better at searching the JAMF pages. Looks like lots of people have worked at this same issue, but in my haste, I didn't come across some of the things that others have already worked on. Some of you guys have great looking solutions that I would have loved to borrow leverage in my work.
Posted on 10-06-2015 12:44 PM
@easyedc I think you might be able accomplish this with a Configuration profile. Essentially, what you'd do is configure a profile for the SSID you want, but fill in the required security settings with incorrect information.
In this example, I set an SSID, pick a security type, and then pick a bad certificate name that will never show up (unless the cert presented by the wireless controller is called "blahblahblah"). Then when the computer tries to connect to it, it will have a wireless configuration profile looking for that cert but it won't be there.
Just a note, I have not tested this, this is just an idea.
Posted on 10-06-2015 01:29 PM
@easyedc I updated the code for the little util to contain some error checking, and combined it with a launchD that triggers it when the WiFi changes, and in testing it works well as soon as i switch WiFi networks or power on /off it triggers and then around 10 seconds later disconnects and moves onto another SSID in my preferred list with the SSID having been removed from Preferred Networks.
Like you i track and remove bad SSID's through extension attributes, but it would be nice to implement something a little 'quicker'.
//
// main.swift
// bannedWifi
//
// Created by Thomas Holbrook on 05/10/2015.
// Copyright © 2015 Thomas Holbrook. All rights reserved.
//
// Banned WiFi CLI App
// Bored in a hotel with SSID "Premier Inn Ultimate Wi-Fi"
import Cocoa
import CoreWLAN
import Foundation
let iface = CWWiFiClient.sharedWiFiClient().interface()?.interfaceName
// Argument parsing Errors.
let arguments = Process.arguments
let currentSSID = CWWiFiClient.sharedWiFiClient().interface()?.ssid()
let executableName = NSString(string: Process.arguments.first!).pathComponents.last!
func usage() {
print("")
print("Usage:")
print(" (executableName) <banned_ssid> <wait_time>")
print("")
print(" (executableName) checks the current SSID against banned SSID")
print("")
print("wait_time defines the amount of time we wait for WiFi to settle before executing the check")
print("")
print("Where a match is found the client is disassociated and the SSID removed from Prefered Networks")
print("")
print("Example - bannedSSID "Tom Tom" 30")
print("")
print("Thomas Holbrook - The software is provided "as is", without warranty of any kind")
print("")
}
//Wait for Wireless to settle.
if arguments.count == 3 {
var delay = UInt32(arguments[2])
sleep(delay!)
}
if arguments.contains("-help") || arguments.contains("-h") {
usage()
exit(0)
}
else if arguments.count == 1 {
usage()
exit(0)
}
else if arguments.count == 2 {
usage()
exit(0)
}
else if arguments.count > 3 {
usage()
exit(0)
}
else if currentSSID == nil {
print("Wifi Not Connected to SSID")
exit(0)
}
let bannedSSID = arguments[1]
let delay = arguments[2]
print("Current SSID is " + currentSSID!)
print("Banned SSID is " + bannedSSID)
//Check if our current SSID is banned?
if currentSSID! == bannedSSID {
//If its a banned SSID diconnect the client
print("Disconnecting from Banned SSID")
CWWiFiClient.sharedWiFiClient().interface()!.disassociate()
//Use networksetup to remove the prefered network entry
print("Removing from Preferred Networks")
let taskCheck = NSTask()
taskCheck.launchPath = "/usr/sbin/networksetup"
taskCheck.arguments = ["-removepreferredwirelessnetwork",iface!,bannedSSID]
let pipe = NSPipe()
taskCheck.standardOutput = pipe
taskCheck.launch()
taskCheck.waitUntilExit()
print(taskCheck.terminationStatus)
}
else
{
print("Allowed SSID Doing Nothing")
}
//The End
exit(0)
Here is the launchD:
/Library/LaunchDaemons/uk.co.tomholbrook.bannedSSID.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>uk.co.tomholbrook.bannedSSID</string>
<key>LowPriorityIO</key>
<true/>
<key>ProgramArguments</key>
<array>
<string>./usr/local/j24/bannedSSID</string>
<string>Premier Inn Ultimate Wi-Fi</string>
<string>30</string>
</array>
<key>WatchPaths</key>
<array>
<string>/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist</string>
</array>
</dict>
</plist>