My boring Blog

Mauro Frigerio blog

Wake-on-LAN from Guacamole in docker

24-07-2022 3 min read Article

The Guacamole service allows a “Wake on LAN” (WOL) packet to be launched before connecting to the machine with VNC or RDP. Unfortunately, by Docker’s default setting, networks configured as bridge do not allow broadcast packets (even if directed to a specific subnet) to be sent out. This prevents the use of WOL and Guacamole. There remains the option of configuring the guacd container on the host network, but this solution has security issues.

Searching the web, I found this post from which I exploited the script. I merely described in more detail the steps to be performed.

First of all

The post suggests using a script from Github, but in order to run it first, a package must be installed:

sudo apt install jq -y

Then you can download the script locally and make it executable

wget https://github.com/dhutchison/container-images/raw/master/homebridge/configure_docker_networks_for_wol.sh

chmod +x configure_docker_networks_for_wol.sh

Before launching it you have to change the value of DOCKER_NETWORK with your own value, in my case guacd is connected to net_guacamole_db.

Warning

If the network was created with docker-compose you have to add a suffix.

With the following command you can view all networks configured in docker:

sudo docker network ls

After editing and saving the script you can run it and restart the computer.

sudo ./configure_docker_networks_for_wol.sh

sudo reboot

How to test

You can open Wireshark on a computer connected to the network and capture network traffic. Just apply the udp.port==9 filter to display only WOL packets.

Create a test container connected to the network chosen above

sudo docker run --name testcontainer -d -it python:3-alpine

In Portainer change the network to which the container is connected and open the console (you have to choose the /bin/sh option).

Install awake and send some test WOL packets. If everything works you can receive the packets on Wireshark.

pip3 install awake

awake -b 192.168.3.255 aa:bb:cc:dd:ee:ff    #192.68.3.255 is the broadcast address of my subnet

Copia dello script

https://github.com/dhutchison/container-images/blob/master/homebridge/configure_docker_networks_for_wol.sh

#!/bin/bash

##############
#
# This script will set the required kernel network settings to 
# allow broadcast traffic to be sent from a docker network
# to another network.
# 
# This sets using both "sysctl -w" as well as configuring a file in
# "/etc/sysctl.d/" so the change will persist a reboot. 
#
##############

# The name of the network the docker container will be connected to
DOCKER_NETWORK=traefik-backend

# Disable the setting to ignore echo broadcasts
sudo sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=0
echo '# Disable the setting to ignore echo broadcasts' | sudo tee /etc/sysctl.d/97-docker-broadcast.conf
echo 'net.ipv4.icmp_echo_ignore_broadcasts=0' | sudo tee -a /etc/sysctl.d/97-docker-broadcast.conf

# Enabling broadcast forwarding for "all" interfaces, 
# although it seems this needs used in combination with specific interfaces
sudo sysctl -w net.ipv4.conf.all.bc_forwarding=1
echo '# Enabling broadcast forwarding for "all" interfaces' | sudo tee -a /etc/sysctl.d/97-docker-broadcast.conf
echo 'net.ipv4.conf.all.bc_forwarding=1' | sudo tee -a /etc/sysctl.d/97-docker-broadcast.conf


# Find the subnet for the docker network
subnet=$(docker network inspect "$DOCKER_NETWORK" | jq --raw-output .[0].IPAM.Config[0].Subnet)

if [ ! -z subnet ]; then

    echo "Got subnet $subnet"

    # Find the network interface
    interface=$(ip route | grep "$subnet" | cut -d ' ' -f3)

    if [ ! -z interface ]; then
        echo "Got interface $interface"

        # Check the setting value to check we are substituting correctly
        sudo sysctl -w net.ipv4.conf.${interface}.bc_forwarding=1
        echo '# Check the setting value to check we are substituting correctly' | sudo tee -a /etc/sysctl.d/97-docker-broadcast.conf
        echo "net.ipv4.conf.${interface}.bc_forwarding=1" | sudo tee -a /etc/sysctl.d/97-docker-broadcast.conf
    else
        echo "Could not determine the network interface for $subnet"
    fi
else
    echo "Could not determine the subnet for $DOCKER_NETWORK"
fi

Crediti Foto di Steve Buissinne da Pixabay