www.zeroshell.org Forum Index www.zeroshell.org
Linux Distribution for server and embedded devices
 
 SearchSearch  RegisterRegister  UsergroupsUsergroups 
 ProfileProfile  Log inLog in  Log in to check your private messagesPrivate Message 

[Janus / twin Alix2] #8 WiFi on knock + LED + auto-hangup

 
Post new topic   Reply to topic    www.zeroshell.org Forum Index -> ZeroShell
View previous topic :: View next topic  
Author Message
PatrickB



Joined: 03 Nov 2012
Posts: 43

PostPosted: Tue Mar 29, 2016 7:42 pm    Post subject: [Janus / twin Alix2] #8 WiFi on knock + LED + auto-hangup Reply with quote

Hello.

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 Cool

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 Evil or Very Mad

Even if you prefer the WiFi permanent, this page may show your some useful tools anyway... Wink

Prerequisites

We need KnockD, a wonderful utility that you can install through IPKG, as explained in post #2 there:
http://www.zeroshell.org/forum/viewtopic.php?t=5005

We 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:
http://www.zeroshell.org/forum/viewtopic.php?t=5094

Using KnockD

Here it is used quite normally Laughing 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 !
Arrow 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:
Code:
[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:
Code:
# 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 ;
fi

My 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:
Code:
# 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 bytes

Checking 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:
Code:
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 restart


But 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 Mad

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 norestart

I'm very unhappy Crying or Very sad 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 Sad
Exclamation 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.

Code:

#!/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.
Arrow And notably any input about the mystery of kerby-script start-wifi.

Best regards. Very Happy
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    www.zeroshell.org Forum Index -> ZeroShell All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group