Leds on based on ping through specific interface, possible?

hey there everyone, i have been trying to experiment with led's on my device. standard i have all internet traffic going through my wireguard provider, which works well. i currently have enabled in luci a configuration that if data is received on the wireguard interface, a red led blinks. this seems to work well.
However i would like to control the blue led to go on when data is received through the wan interface. but the problem is, that the wan interface is connected to the bridge of my ISP, so it is always receiving data. How do i make it check for actual internet access, but ONLY through the wan interface, ignoring the standard firewall settings that traffic has to go through the wireguard interface?
This would allow me to both check if the device has internet access, and allow me to check if the wireguard interface is working.

Preferably with some blinking of the leds, but im not picky.

Thanks if anyone can help with this!

This is the script I've written for my use case, which takes into account interface:

INTERFACE=$(uci -q get network.wan.device)
TARGETS=$(uci -q get network.wan.dns)
TARGET=${TARGETS%% *}

[ -z $INTERFACE -o -z $TARGET ] && exit 1

switch_leds() {
    echo none > /sys/class/leds/$1/trigger
    echo 0 > /sys/class/leds/$1/brightness

    echo switch0 > /sys/class/leds/$2/trigger
    echo link tx rx > /sys/class/leds/$2/mode
    echo 15 > /sys/class/leds/$2/speed_mask
    echo 2 > /sys/class/leds/$2/port_mask
}

if ping -q -4 -I $INTERFACE -c 1 -W 10 $TARGET > /dev/null 2>&1; then
    switch_leds "amber:wan" "green:wan"
else
    switch_leds "green:wan" "amber:wan"
fi
1 Like

Thanks! Where do we have to enter this script?
Can you tell me a bit what it does and what to change for my setup, except led paths.

I run it from crontab; once every minute.

* * * * * sh /etc/wan_leds.sh

As for what it does and what to change, you will have to go through the script yourself and add/remove/replace lines to suit your needs. The script is very small and should be pretty obvious what each line is doing, no programming knowledge required.

If you want the LED to shutdown when there is no internet access and blink on data transfer when there is internet access, you probably want to split the switch_leds function into two separate functions, wan_led_on and wan_led_off. wan_led_off should contain the first two lines of switch_leds and wan_led_on the rest, but corrected to your setup, as port 2 might not be your WAN port.

Thank you a lot, this already gives me a good start.
i am going to put the script in a file in /etc/wan_leds.sh, make it executable, make a cron job and experiment around. my idea is that im going to use 2 scripts then, because i need one for WAN if it can ping the internet through it, and one for the wireguard interface i made if it can ping the internet through it. Only have two led's though, that are in the same location (so both blue and red on combine into purple)

would this work? @Cthulhu88
I made it more simple based on reading what you got there. don't wanna break anything by executing scripts without a double check, seeing people sometimes brick the router... probably not possible to do so by playing with led brightness but idk.

So if both the wireguard interface (with name surfshark) can get a ping response from google, and the wan interface can, then blue led goes on permanently. if both of these are not true, then check if only the wan interface can reach google at 8.8.8.8. if yes, the red led goes on permanently, blue goes out. if neither can (wireguard could never if wan has no internet) then led stays out.

if ping -q -4 -I wan -c 1 -W 5 8.8.8.8 > /dev/null 2>&1; && ping -q -4 -I surfshark -c 1 -W 10 8.8.8.8 > /dev/null 2>&1; then
echo 255 > /sys/class/leds/blue:system/brightness
echo 0 > /sys/class/leds/red:system/brightness

else

if ping -q -4 -I wan -c 1 -W 5 8.8.8.8 > /dev/null 2>&1; then
echo 255 > /sys/class/leds/red:system/brightness
echo 0 > /sys/class/leds/blue:system/brightness

else

echo 0 > /sys/class/leds/red:system/brightness
echo 0 > /sys/class/leds/blue:system/brightness

fi

There are both syntax and logical errors in your script.

ping -q -4 -I "this must be the wan interface as shown in network.wan.device" -c 1 -W 5 8.8.8.8 > /dev/null 2>&1
wan_status=$?
ping -q -4 -I "this must be the wireguard interface as shown in network.surfshark.device" -c 1 -W 5 8.8.8.8 > /dev/null 2>&1
wg_status=$?

if [ -z $wan_status -a -z $wg_status ]; then
    echo 255 > /sys/class/leds/blue:system/brightness
    echo 0 > /sys/class/leds/red:system/brightness
elif [ -z $wan_status ]; then
    echo 255 > /sys/class/leds/red:system/brightness
    echo 0 > /sys/class/leds/blue:system/brightness
else
    echo 0 > /sys/class/leds/red:system/brightness
    echo 0 > /sys/class/leds/blue:system/brightness
fi

I would avoid probing google though. Probably the largest privacy violator around.

1 Like

what do you suggest? simply pinging isnt giving google much data about me?
i tried to execute "uci -q get network.wan.dns" and it returned nothing in a cmd window, thats why i swapped to google.

thanks for fixing the script!

For one, it allows them to build a fairly reliable alive hosts list with minimal effort.
network.wan.dns won't return anything if you don't have dns servers manually set for the wan interface.

I would recommend a host that is alive 99% of the time, replies to ICMP echo requests and specially one that doesn't have such an "evil" track record.
Since leds aren't essential to the operation of the router and disruption won't cause any issues, you can use openwrt.org for one.

1 Like

I got internet back today, was down for some days, and noticed the script was not working.
I fixed it by asking Grok on X what was wrong with it.

So if anyone want to have the same functionality for a VPN interface like wireguard, here is the final script needed:

# Ping WAN interface
ping -q -4 -I wan -c 1 -W 4 1.1.1.1 > /dev/null 2>&1
wan_status=$?

# Ping VPN interface
ping -q -4 -I surfshark -c 1 -W 4 1.1.1.1 > /dev/null 2>&1
wg_status=$?

# Check status and set LEDs
if [ $wan_status -eq 0 ] && [ $wg_status -eq 0 ]; then
    echo 255 > /sys/class/leds/blue:system/brightness
    echo 0 > /sys/class/leds/red:system/brightness
elif [ $wan_status -eq 0 ]; then
    echo 255 > /sys/class/leds/red:system/brightness
    echo 255 > /sys/class/leds/blue:system/brightness
else
    echo 255 > /sys/class/leds/red:system/brightness
    echo 0 > /sys/class/leds/blue:system/brightness
fi

The IP 1.1.1.1 is from cloudflare, which is very reliable and doesn't breach privacy like google does.

Thanks again @Cthulhu88!

EDIT:
And remember to make the script work by calling for it in a cronjob (in luci's interface it's at system > scheduled tasks.
I added the path of the script multiple times with a sleep, so it checks every 6 seconds or so and updated the LED. (because with cronjobs you cannot use a script per x amount of seconds)

* * * * * sh /etc/wan_leds.sh
* * * * * ( sleep 6 ; sh /etc/wan_leds.sh )
* * * * * ( sleep 12 ; sh /etc/wan_leds.sh )
* * * * * ( sleep 18 ; sh /etc/wan_leds.sh )
* * * * * ( sleep 24 ; sh /etc/wan_leds.sh )
* * * * * ( sleep 30 ; sh /etc/wan_leds.sh )
* * * * * ( sleep 36 ; sh /etc/wan_leds.sh )
* * * * * ( sleep 42 ; sh /etc/wan_leds.sh )
* * * * * ( sleep 48 ; sh /etc/wan_leds.sh )
* * * * * ( sleep 54 ; sh /etc/wan_leds.sh )

Right, -z doesn't work for -z 0, only if empty or unset.

Your crontabs can overlap, if the sum of the blocking time (via timeout) exceeds 6 seconds. If you want to execute it more than once every minute, use a loop, /proc/uptime and sleep.

INTERFACE_WAN="this must be the wan interface as shown in network.wan.device"
INTERFACE_WG="this must be the wireguard interface as shown in network.surfshark.device"
TARGET="target address"
TIMEOUT=5
DELAY=6

while true; do
    start=$(awk '{ sub(/\..*/, "") } { print }' /proc/uptime)

    if ping -q -4 -I $INTERFACE_WAN -c 1 -W $TIMEOUT $TARGET > /dev/null 2>&1; then
        if ping -q -4 -I $INTERFACE_WG -c 1 -W $TIMEOUT $TARGET > /dev/null 2>&1; then
            echo 0 > /sys/class/leds/red:system/brightness
            echo 255 > /sys/class/leds/blue:system/brightness
        else
            echo 0 > /sys/class/leds/blue:system/brightness
            echo 255 > /sys/class/leds/red:system/brightness
        fi
    else
        echo 0 > /sys/class/leds/red:system/brightness
        echo 0 > /sys/class/leds/blue:system/brightness
    fi

    end=$(awk '{ sub(/\..*/, "") } { print }' /proc/uptime)

    delay=$((DELAY - (end - start)))

    [ $delay -gt 0 ] && sleep $delay
done

Then add it to /etc/rc.local instead of crontab, sh script.sh & or ./script.sh &.

Other than using a loop and sleep, these are the things that I've changed:

  • Don't bother pinging the wireguard interface if the WAN ping failed.
  • Turn off the previous LED before turning on the next one.

Also, I've noticed you're turning both LEDs on when only the WAN interface is successful. I am assuming this is an error on your part, but if my assumption is wrong, just change the value for the new code.

The watchcat package ( https://openwrt.org/docs/guide-user/advanced/watchcat ) combines a similar shell script with a service.
The guide page doesn't list it, but there is a run_script mode: https://github.com/openwrt/packages/blob/master/utils/watchcat/files/watchcat.sh#L262-L265
The problem is, the script is only called after ping has failed for X amount of seconds, making it harder to customize your LEDs through it.

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.