My boring Blog

Home page di Mauro Frigerio

Wake-on-LAN da Guacamole in docker

24-07-2022 Tempo di lettura 3 minuti article

Il servizio Guacamole permette di lanciare un pacchetto “Wake on LAN” (WOL) prima di collegarsi alla macchina con VNC o RDP. Purtroppo per impostazione di default di Docker, le reti configurate come bridge non permettono di inviare in uscita i pacchetti broadcast (anche se diretti a una subnet specifica). Questo impedisce l’utilizzo di WOL e Guacamole. Resta la possibilità di configurare il container guacd sulla rete host, ma questa soluzione ha problemi di sicurezza.

Cercando in rete ho trovato questo post dal quale ho sfruttato lo script. Io mi sono limitato a descrivere meglio i passaggi da eseguire.

Prima di tutto

Nel post si propone di usare uno script presente su Github, ma per poterlo eseguire prima si deve installare un pacchetto:

sudo apt install jq -y

Poi è possibile scaricare lo script in locale e renderlo eseguibile

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

chmod +x configure_docker_networks_for_wol.sh

Prima di lanciarlo si deve modificare DOCKER_NETWORK con il proprio valore, nel mio caso guacd è collegato alla rete net_guacamole_db.

Attenzione

Se la rete è stata creata con docker-compose si deve aggiungere un suffisso.

Con il comando seguente è possibile visualizzare tutte le reti configurate in docker:

sudo docker network ls

Dopo aver modificato e salvato lo script è possibile eseguirlo e riavviare il computer.

sudo ./configure_docker_networks_for_wol.sh

sudo reboot

Come testare

Si può aprire Wireshark su un computer collegato alla rete e catturare il traffico di rete. Basta applicare il filtro udp.port==9 per visualizzare solo i pacchetti WOL.

Creare un container di test collegato alla rete scelta in precedenza

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

In Portainer cambiare la rete alla quale è collegato il container e aprire la console (si deve scegliere l’opzione /bin/sh).

Installare awake e inviare alcuni pacchetti WOL di test. Se tutto funziona è possibile ricevere i pacchetti su Wireshark.

pip3 install awake

awake -b 192.168.3.255 aa:bb:cc:dd:ee:ff    #192.68.3.255 è l'indirizzo broadcast del mio subnet

Copy of the 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

Credits Foto di Steve Buissinne da Pixabay