Posted on 11-10-2016 07:09 AM
A few years back, I was in a school within a community with a large cluster of open WiFi networks. The problem we had was students dropping off the filtered School WiFi and connecting to one of the neighborhood networks.
To address this issue, I created a script to ensure that students would get kicked off any other network if the school network was available. The attached Flow chart illustrates the logic of the script.
The script is below without any modification from it's original use. Note that in the FlowChart it checks to see if a device was allowed on the internet...and reads that info from a public fileserver..but that's another discussion.
The individual functions line up with the flow chart boxes. The script was triggered using a launchd item (which follows) which triggered on a network change.
#! /bin/bash
#########################################################################
# #
# manage wifi networks #
# #
# #
# #
# Del Brown #
# 2011 #
# delbrown@me.com #
# #
# #
# #
# #
# #
#########################################################################
# Define Variables Here
# Set the approved Wireless Network Name(s) in the WifiWhitelist variable
WifiWhitelist="Lyman_Moore_MS Lincoln_MS King_MS ProjectOffice"
# Set the Location of the AccessList file which determines if student is allowed internet access
#AccessCheck="http://www.delbrown.net/mlti/AccessList"
AccessCheck="http://staff.portlandschools.org/brownde/mlti/AccessList"
########################### DO NOT MODIFY BELOW THIS LINE ###############################
#check for current WiFi name
MyWifi=`networksetup -getairportnetwork Airport | awk '{print $4}'`
WifiAvailable=`/System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport -s | awk '{print $1}'`
# This can also be based on the serial number if you wish
#Asset=`ioreg -l | grep IOPlatformSerialNumber | sed 's/"//g' | awk '{print $4}'`
Asset=`nvram asset-tag | awk '{print $2}'` #this is where I have stored the Asset Tag Info
# Check for Access
Access=`curl -sf $AccessCheck | grep -i $Asset | awk '{print $2}'`
# Get Working Directory
WorkDir=`dirname "$0"`
# End of Variable Definitions
########################### Functions ###########################
disconnect ()
{
# Notify user that the network is not approved and disconnect from the wireless network.
./BigHonkingText $MyWifi is not an approved Network
/System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport -z
exit 1
}
atSchool ()
{
# test to see if the Asset is at school by scanning for school networks and see if one is the school
for ScannedNetworks in $WifiAvailable
do
for SchoolNetwork in $WifiWhitelist
do
if [ "$SchoolNetwork" == "$ScannedNetworks" ]
then
AssetAtSchool="Yes"
return
fi
done
done
AssetAtSchool="No"
return
}
onSchoolNetwork ()
{
# test to see if the school network has been joined.
# Call the disconnect function if a network outside of school is joined
for AllowedID in $WifiWhitelist
do
if [ "$AllowedID" == "$MyWifi" ]
then # Asset is on the school network
exit 1
fi
done
disconnect
exit 2
}
checkAccess ()
{
# look up the list to see if home access has been turned off
Access=`curl -sf $AccessCheck | grep -i $Asset | awk '{print $2}'`
}
########################### End Functions ############################
# Change to Working Directory
cd "$WorkDir"
# Is the Asset at school?
atSchool
if [ $AssetAtSchool == "Yes" ]
then
# Is the Asset on the School Network
onSchoolNetwork
fi
# If we get here then the computer is at home...or cannot connect to the school network
# Is the student allowed on the internet at home?
checkAccess
if [ "$Access" == "No" ]
then
disconnect
fi
# Everything is good and we can exit
echo "Everything is A-OK"
exit 1
Net manage plist follows:
<?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>net.delbrown.NetManage</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/delbrown.net/bin/NetManage</string>
</array>
<key>WatchPaths</key>
<array>
<string>/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist</string>
</array>
</dict>
</plist>
Posted on 11-10-2016 07:15 AM
@delbrown might want to edit your post or repost so the script shows up properly. Looks like you pasted the script outside of the "grave" ticks that mark it as a script.
Posted on 11-10-2016 07:31 AM
I can see this coming in hand with some students using their phones as hotspots for our school.
I do have one issue that seems to be coming up with this section:
Asset=`nvram asset-tag | awk '{print $2}'` #this is where I have stored the Asset Tag Info
It is giving me this error when I attempt to run the script:
bash-3.2$
Asset=nvram asset-tag | awk '{print $2}'
#this is where I have stored the Asset Tag Info
nvram: Error getting variable - 'asset-tag': (iokit/common) data was not found
Posted on 11-10-2016 07:35 AM
Thanks @stevewood. I figured it out after I viewed it again.
Posted on 11-10-2016 07:38 AM
@jjones That part references a variable in nvram where I used to store the devices asset tag to make it persistent after imaging. This was part of the "Other Discussion"
Posted on 11-21-2016 09:49 AM
After looking at the unfinished nature of my original script. I found a little time and updated my original script to simplify the option and work on the updated macOS available. This script is ready to go. Just create a valid Launchd action and run the following:
#!/bin/bash
# Monitor and Manage WiFi Networks
# Del Brown
# 11/21/16
# delonline@icloud.com
#
# Begin Variable Definitions
#Replace WIFINAME with your school WiFi. Leaving it empty will disconnect from any network.
WifiWhitelist="WIFINAME"
# End of Variable Definitions
# Begin Function Declarations
connect ()
{
for SchoolNetwork in $WifiWhitelist
do
#loop through whitelist and connect to whitelisted network found
echo " Available Network ""$SchoolNetwork"
networksetup -setairportnetwork en0 "$SchoolNetwork" &>/dev/null
done
}
disconnect ()
{
echo "Time to disconnect"
# send disconnect command to en0
/System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport -z
#exit 1
}
onSchoolNetwork ()
{
# test to see if the school network has been joined. You can either use the networksetup command or the airport utility for this
MyWifi=`networksetup -getairportnetwork en0 | awk '{print $4}'`
#MyWifi=`/System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport --getinfo | grep " SSID" | awk '{print $2}'`
# Call the disconnect function if a network outside of school is joined
for AllowedID in $WifiWhitelist
do
if [ "$AllowedID" == "$MyWifi" ]
then # Asset is on the school network
echo "I am connected to the School Network ""$AllowedID"
exit 1
fi
done
echo "Device is not connected to School Network so disconnect and reconnect to the school"
disconnect
connect
exit
}
atSchool ()
{
WifiAvailable=`/System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport -s | awk '{print $1}'`
# test to see if the Asset is at school by scanning for school networks and see if one is the school
for ScannedNetworks in $WifiAvailable
do
for SchoolNetwork in $WifiWhitelist
do
if [ "$SchoolNetwork" == "$ScannedNetworks" ]
then
AssetAtSchool="Yes"
echo "The Device is at school"
return
fi
done
done
AssetAtSchool="No"
echo "asset is not at school so we don't care and we'll exit"
exit
}
# End Function Declarations
#########################
#program starts here
atSchool
onSchoolNetwork
Posted on 11-29-2016 10:27 AM
@delbrown Thanks! You just saved me some work.
Posted on 03-01-2017 07:38 AM
OK, @delbrown , this looks exactly like what I need, but my complete lack of scripting knowledge is making this a challenge. I'd love some help if you have time! I get that I have to change the Wifi whitelist name to our student network name, but after that, I have no idea what pieces to copy, what pieces I need to edit...I've successfully pushed out some really basic scripts via Casper Remote, like the one that requires them to authenticate with admin credentials to turn off the wifi, but that was a one-line script I just had to copy/paste. :)
Posted on 03-01-2017 11:27 AM
@lizmowens If you look at the original post by @delbrown at the top of this thread, you'll see that he shows both the .sh script that manages the WiFi settings (although the one you want to use is further down in the thread) and the .plist LaunchAgent that will trigger the script when the AirPort preferences file changes. You need to modify those for your environment and then create a package in Composer you can deploy to your student machines.
Search on Jamf Nation for LaunchAgent to find info on that topic.
You may also find this site useful: lauchd info
This is a very useful app for dealing with LaunchAgents/LaunchDaemons: LaunchControl
Posted on 11-18-2019 03:47 PM
Thanks! amazing script, any ideas how can I modify the script if my SSID have a whitespace? e.g "STUDENT WIFI"
I tried to use
or just but it doesn't seem to work
Posted on 12-09-2019 09:05 AM
@j.tanudjaja I'm working on the same issue. I've made the following changes:
WifiDevice=$(networksetup -listnetworkserviceorder | grep 'Wi-Fi' | grep 'Device' | cut -d ":" -f3 | rev | cut -c 2- | rev | awk '{$2=$2}$1')
MyWifi=$(networksetup -getairportnetwork $WifiDevice | cut -d ":" -f2 | awk '{$2=$2}$1')
This gets the currently connected SSID. I need WifiDevice as some computers use en0 while others use en1.
WifiAvailable=$("/System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport" -s | cut -d ":" -f1 | cut -d ")" -f2 | awk '{$2=$2}$1' | rev | cut -c 4- | rev | sort | uniq)
This gets a list of SSIDs and removes leading/trailing spaces and duplicates.
As we have multiple SSIDs, with spaces, that devices can connect to I'm looking into using an array for the WifiWhitelist. Should just need a change in the atSchool () function to work.
Posted on 12-10-2019 12:41 PM
I've made modifications to Del Brown's script to support spaces in the SSIDs. Next is to force connection to a saved network profile while at school but that can wait for now.
#! /bin/bash
#########################################################################
# #
# manage wifi networks #
# #
# #
# #
# Del Brown #
# 2011 #
# delbrown@me.com #
# #
# #
# #
# #
# #
#########################################################################
# Modified to support SSIDs with spaces BMull 10-Dec-2019
# Define Variables Here
# Set the approved Wireless Network Name(s) in the WifiWhitelist variable
# As we have spaces in SSIDs will use an array
declare -a WifiWhitelist
WifiWhitelist=("SSID 1" "SSID 2" "SSID 3" "SSID4")
########################### DO NOT MODIFY BELOW THIS LINE ###############################
#check for current WiFi name
WifiDevice=$(networksetup -listnetworkserviceorder | grep 'Wi-Fi' | grep 'Device' | cut -d ":" -f3 | rev | cut -c 2- | rev | awk '{ gsub(/^[ ]+|[ ]+$/, ""); print }')
MyWifi=$(networksetup -getairportnetwork $WifiDevice | cut -d ":" -f2 | awk '{ gsub(/^[ ]+|[ ]+$/, ""); print }')
# Needed below to work with SSIDs with spaces in arrays; MUST be after WifiDevice/MyWifi or will get an error
SAVEIFS=$IFS
IFS=$(echo -en "
")
apPath="/System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources"
declare -a WifiAvailable
WifiAvailable=( $("$apPath/airport" -s | cut -d ":" -f1 | cut -d ")" -f2 | awk '{ gsub(/^[ ]+|[ ]+$/, ""); print }' | rev | cut -c 4- | rev | sort | uniq | tr "
" "
") )
# Get Working Directory
WorkDir=$(dirname "$0")
# End of Variable Definitions
########################### Functions ###########################
disconnect ()
{
# Notify user that the network is not approved and disconnect from the wireless network.
./BigHonkingText "$MyWifi is not an approved Network"
$apPath/airport -z
}
atSchool ()
{
# test to see if the Asset is at school by scanning for school networks and see if one is the school
for ScannedNetworks in "${WifiAvailable[@]}"
do
for SchoolNetwork in "${WifiWhitelist[@]}"
do
if [ "$ScannedNetworks" == "$SchoolNetwork" ]
then
AssetAtSchool="Yes"
return
fi
done
done
AssetAtSchool="No"
return
}
onSchoolNetwork ()
{
# test to see if the school network has been joined.
# Call the disconnect function if a network outside of school is joined
for AllowedID in "${WifiWhitelist[@]}"
do
if [ "$AllowedID" == "$MyWifi" ]
then # Asset is on the school network
IFS=$SAVEIFS
exit 0
fi
done
disconnect
IFS=$SAVEIFS
exit 2
}
########################### End Functions ############################
# Change to Working Directory
cd "$WorkDir" || return
# Is the Asset at school?
atSchool
if [ "$AssetAtSchool" == "Yes" ]
then
echo "Asset is at School..."
# Is the Asset on the School Network
onSchoolNetwork
fi
# If we get here then the computer is at home...or cannot connect to the school network
# Everything is good and we can exit
echo "Everything is A-OK"
IFS=$SAVEIFS
exit 1
Posted on 09-08-2020 04:49 PM
Could someone please help with this? like @lizmowens I'm a little lost ... I copied the script with our own WiFiWhitelist variables and converted the plist using plutil and put it in /Library/LaunchAgents yet it doesn't seem to work. My apologies, I'm such a novice with this stuff