› Forums › Network Management › ZeroShell › [Janus / twin Alix2] #8 WiFi on knock + LED + auto-hangup
- This topic is empty.
-
AuthorPosts
-
March 29, 2016 at 7:42 pm #44520
PatrickB
MemberHello.
Today I give you my solution to switch the WiFi of the Alix ON through a request done on the wired LAN, then monitor the access to and switch it back OFF after some minutes idle.
In addition I use the Led #3 to show the active state and the traffic 8)Of course it is interesting as a security feature if you have a mainly wired LAN and punctual use of the WiFi for your smartphone or tablet. Even protected, a permanent Wifi access is a potential entry to silently bypass your firewall and visit your LAN πΏ
Even if you prefer the WiFi permanent, this page may show your some useful tools anyway… π
Prerequisites
We need KnockD, a wonderful utility that you can install through IPKG, as explained in post #2 there:
https://www.zeroshell.org/forum/viewtopic.php?t=5005We need a Knocker to emit the request from any station of your wired LAN. You can find several there:
http://www.zeroflux.org/projects/knock
For instance the native Windows client can be invoked through a little CMD file then you can just have an icon to click on your desktop…We need to drive the Alix Led (I use Led 3), I proposed a solution there:
https://www.zeroshell.org/forum/viewtopic.php?t=5094Using KnockD
Here it is used quite normally π Say that because KnockD can be a handy way to receive and process a “signal” (no parameters) on a machine, to trigger a command that needs root privileges, without the need to install an Apache and dig into CGI, do a “safe” privilege elevation (chroot ?) and even have to open a port !
β‘ For instance, if you need a nice solution to trigger a shutdown or reboot across the LAN…Here we need such a section [ActivateWiFi] in the /opt/etc/knockd.conf:
[options]
# logfile = /var/log/knockd.log
logfile = /dev/null
[Janus-heartbeat]
sequence = 0000:udp,0000:tcp,0000:udp
seq_timeout = 2
command = echo "$(date +'%s')" > /tmp/twin-heartbeat
[ActivateWiFi]
sequence = 12:udp,34:tcp,56:udp,78:udp <
Choose your own secret, of course
seq_timeout = 5
command = bash /opt/bin/switch-and-watch-wifi.sh %IP%NB: In non-debug mode I prefer to suppress KnockD’s logfile and have my own logs done by the commands that it runs. Notably the [Janus-heartbeat], run every minute, would be terrible…
Now switch-and-watch-wifi.sh is invoked with the knocker’s IP in argument whenever you click the icon.
Of course this script must run as a safe singleton. You can do that this way:
# Do not run a second instance of the script in case of concurrent process.
# There is no way to check whether a file exists else create it in a single
# atomic operation, while mkdir is atomic and will take an error if the
# directory already exists.
ZtMutexDir=/tmp/$(basename $0).lock
if ! $(mkdir "$ZtMutexDir" 2>/dev/null); then
echo -e "$(basename $0) is already running !n" ;
exit 1 ;
else
# Ensure that the mutex will be deleted however we end
trap "rm -rf $ZtMutexDir" INT TERM EXIT ;
fiMy version is a bit more complex, using component scripts…
Monitoring the WiFi activity
The statistics counters are perfect for that. I prefer to monitor the incoming traffic counter because normally it is really frozen when nothing is connected, unlike the outgoing counter.
In order to have a correct reactivity of the monitoring (notably the Led), I use the following settings:
# WiFi activation settings:
ZtTrafficPollingInterval=3 # in seconds
ZtDeactivationTimeout=60 # in polling intervals
# The indicator showing the incoming traffic
ZtTrafficIndicator="/sys/class/net/WLAN00/statistics/rx_bytes"
ZtTrafficDelta=50 # in bytesChecking and switching the WiFi interface
This is where it becomes tricky. In my configuration the Wifi is bridged with the wired LAN interface, and in addition the bridge has a second IP (twin Janus system), so the way ‘ifconfig’ handles the wired and WiFi interfaces is a bit different (with/without IP).
For checking the state I wrote a generic tool:
CheckInterface() # $1 = Interface name, $2 = IP
{
ZtState="DOWN"
if [ -z "$2" ]; then
ZtQuery="" ;
ZtMatch="$1" ;
else
ZtQuery="$1" ;
ZtMatch="$2" ;
fi
if [ "$(ifconfig -v $ZtQuery | grep $ZtMatch)" != "" ]; then
ZtState="UP" ;
fi
echo $ZtState
}
Sample calls:
ZtIpStatus=$(CheckInterface "BRIDGE01:00" "192.168.xxx.yyy")
ZtIpStatus=$(CheckInterface "" "WLAN00")Switching the WiFi OFF is trivial, I just restart the network after, as in the main script for the twin Janus system:
ifconfig WLAN00 down
/etc/rc.d/init.d/network restartBut switching the WiFi ON is more complicated. By just doing the same thing:
ifconfig WLAN00 up
/etc/rc.d/init.d/network restart
…the interface is UP, the remote devices manage to initiate a connection, but then the authentication fails π‘To make it work I had to call that in addition (a priori the script that runs when ticking the checkbox “up” for WLAN00):
/root/kerbynet.cgi/scripts/start-wifi norestartI’m very unhappy π₯ with it because this script takes 4s and appears to do tons of things, maybe suitable when the WiFi interface has been created, but probably useless to just switch ON the existing one. But at this time I could not locate the critical statement inside π
β Clues from the Zeroshell designers are welcome ! Thanks a lot.Packing all together
Here is the script where I simplified/removed things out of topic and needing other components.
When clicking (on some PC) the icon to knock, the Led 3 flashes fast for 3-4 seconds then becomes solid when the WiFi is ON. Then every 3s it changes to either fast flashing if there is traffic, or solid if idle. After 3mn idle, the WiFi and the Led both turn OFF. In case of error the Led blinks slowly.
There is also a safety feature consisting in a periodic (cron task) call to the script with argument EnsureWiFiOff. If the WiFi is being monitored at this time, it has no effect since it does not pass the check for singleton. But if the script could have died for any reason, leaving the WiFi ON, this safety feature would switch it back OFF.
The activation and deactivation are logged to a file. In my configuration, it is taken in a periodic reporting email, but this is out of topic.
#!/bin/bash
# switch-and-watch-wifi.sh Uses Bash v.3.2 extensions
#
#
# This script is run by a KNOCKD task when the valid knocking sequence for turning
# the WiFi ON has been received, normally by the LAN Master.
# It switches the WiFi ON then monitors the traffic and flashes the WiFi LED when
# incoming traffic is detected.
# When no more traffic is detected, after a timeout, it switches the WiFi OFF.
#
# This script is also invoked by 'ensure-lan-master.sh' every hour with the special
# parameter "EnsureWiFiOff". If it is not already running, it means that the normal
# process has died, potentially leaving the WiFi active. Then this new instance
# cares of switching it OFF.
#
if [ "$1" == "EnsureWiFiOff" ]; then
ZtEnsureWiFiOff=1 ;
else
ZtKnockerIP="$1" ; # Passed by KNOCKD
if [ "$ZtKnockerIP" == "" ]; then
ZtKnockerIP="unknown" ;
fi ;
fi
# Host name, normalized:
source $(dirname $0)/define-hostname-variants.include.sh
#
# Local settings for the network of Janus1 and Janus2
#
# WiFi activation settings:
ZtTrafficPollingInterval=3 # in seconds
ZtDeactivationTimeout=60 # in polling intervals
# The interfaces and IP addresses
ZtLanWifiInterfaceName="WLAN00"
# The indicator showing the incoming traffic
ZtTrafficIndicator="/sys/class/net/WLAN00/statistics/rx_bytes"
ZtTrafficDelta=50 # in bytes
# WiFi access logfile, consumed by ensure-lan-master.sh
ZtWifiLogFile="wifi-access.log"
#
# DO NOT MODIFY BEYOND (or take a deep breath before :-)
#
# Main directories
ZtOptionPath="/opt/etc"
ZtWorkTempDir="/tmp"
ZtLogPath="/var/log"
# Information used for reporting:
ZtThisScript="$(basename $0)"
ZtLogFile="$ZtLogPath/$ZtWifiLogFile"
DateForLog()
{
echo $(date +'%a %Y/%m/%d %H:%M:%S')
}
#
if [ -z "$BASH" ] || [ $(( (${BASH_VERSINFO[0]} * 100) + ${BASH_VERSINFO[1]} )) -lt 302 ]; then
echo -e "$ZtThisScript: running on Bash 3.2+ is required !n" ;
exit 1 ;
fi
#
source $(dirname $0)/ensure-singleton-process.include.sh
source $(dirname $0)/Alix-leds-and-beep.include.sh
#
CheckInterface() # $1 = Interface name, $2 = IP
{
ZtState="DOWN"
if [ -z "$2" ]; then
ZtQuery="" ;
ZtMatch="$1" ;
else
ZtQuery="$1" ;
ZtMatch="$2" ;
fi
if [ "$(ifconfig -v $ZtQuery | grep $ZtMatch)" != "" ]; then
ZtState="UP" ;
fi
echo $ZtState
}
#
ZtStatus="OK"
if [ -n "$ZtEnsureWiFiOff" ]; then
# If we could come here, it means that the normal (singleton) process died badly !
ZtIpStatus="$(CheckInterface '' $ZtLanWifiInterfaceName)" ;
if [ "$ZtIpStatus" == "UP" ]; then
echo -e "n$(DateForLog) - $Zt1stUpHostName WiFi safety check." >> $ZtLogFile ;
echo -e "- No watcher process '$ZtThisScript' is running," >> $ZtLogFile ;
echo -e "- The WiFi ($ZtLanWifiInterfaceName) is UP !" >> $ZtLogFile ;
echo -e "Deactivating..." >> $ZtLogFile ;
ifconfig $ZtLanWifiInterfaceName down ;
/etc/rc.d/init.d/network restart ;
ZtIpStatus="$(CheckInterface '' $ZtLanWifiInterfaceName)" ;
if [ "$ZtIpStatus" != "DOWN" ]; then
ZtStatus="ERROR" ;
fi ;
echo -e "The WiFi ($ZtLanWifiInterfaceName) is $ZtIpStatus => $ZtStatus" >> $ZtLogFile ;
SetLed 3 off ;
exit 2 ;
fi ;
exit 0 ;
fi
#
echo -e "n$(DateForLog) - $Zt1stUpHostName knocked for WiFi access by $ZtKnockerIP" >> $ZtLogFile
echo -e "$Zt1stUpHostName opens WiFi access..." >> $ZtLogFile
SetLed 3 fast
ifconfig $ZtLanWifiInterfaceName up
/etc/rc.d/init.d/network restart
# echo -e "debug 1 - $(DateForLog)" >> $ZtLogFile
# But it is not enough, in order to avoid authentication failures, we need that too:
/root/kerbynet.cgi/scripts/start-wifi norestart
# echo -e "debug 2 - $(DateForLog)" >> $ZtLogFile
ZtIpStatus="$(CheckInterface '' $ZtLanWifiInterfaceName)"
if [ "$ZtIpStatus" != "UP" ]; then
ZtStatus="ERROR" ;
fi
echo -e "The WiFi ($ZtLanWifiInterfaceName) is $ZtIpStatus => $ZtStatus" >> $ZtLogFile ;
# Start monitoring
if [ "$ZtStatus" == "OK" ]; then
ZtByteCount=$(cat $ZtTrafficIndicator) ;
ZtIdleCount=0 ;
SetLed 3 on ;
ZtLedIsSolid=1 ;
while [ $ZtIdleCount -lt $ZtDeactivationTimeout ]
do
sleep $ZtTrafficPollingInterval ;
ZtNewByteCount=$(cat $ZtTrafficIndicator) ;
if [ $(( $ZtNewByteCount - $ZtByteCount )) -gt $ZtTrafficDelta ]; then
if [ $ZtLedIsSolid -eq 1 ]; then
SetLed 3 fast ;
ZtLedIsSolid=0 ;
fi ;
ZtIdleCount=0 ;
else
if [ $ZtLedIsSolid -eq 0 ]; then
SetLed 3 on ;
ZtLedIsSolid=1 ;
fi ;
ZtIdleCount=$(( $ZtIdleCount + 1 )) ;
fi ;
ZtByteCount=$ZtNewByteCount;
done ;
echo -e "$(DateForLog) - WiFi access idle, deactivate..." >> $ZtLogFile ;
ifconfig $ZtLanWifiInterfaceName down ;
/etc/rc.d/init.d/network restart ;
ZtIpStatus="$(CheckInterface '' $ZtLanWifiInterfaceName)" ;
if [ "$ZtIpStatus" != "DOWN" ]; then
ZtStatus="ERROR" ;
fi ;
echo -e "The WiFi ($ZtLanWifiInterfaceName) is $ZtIpStatus => $ZtStatus" >> $ZtLogFile ;
SetLed 3 off ;
fi
if [ "$ZtStatus" != "OK" ]; then
SetLed 3 slow ;
exit 4 ;
fi
exit 0;It works very fine and my WiFi is now secured this way.
Hope it can help someone.
Ideas for improvements are welcome.
β‘ And notably any input about the mystery of kerby-script start-wifi.Best regards. π
-
AuthorPosts
- You must be logged in to reply to this topic.