Configurare un Router-on-a-Stick con VPN su Raspberry Pi 4

Impara a configurare un "Router-on-a-Stick" con un Raspberry Pi 4 e WireGuard. Una guida completa per creare un gateway VPN e instradare il traffico di qualsiasi dispositivo della tua rete.

Condividi
Configurare un Router-on-a-Stick con VPN su Raspberry Pi 4

Cosa è un Router on a Stick?

In linea generale, un Router on a Stick (o One-Armed Router) è una configurazione di rete in cui un router utilizza una sola interfaccia fisica per gestire il traffico tra più VLAN diverse.

Potete immaginarlo come il router del vostro ISP, ma con una sola porta ethernet. Sarà poi la configurazione di instradamento tra le diverse VLAN a permettere al router di svolgere le sue funzioni.

Avendo una sola porta Ethernet, un Raspberry Pi è perfetto per questo tipo di configurazione.

Raspberry Pi 4

Il compagno perfetto per tante avventure informatiche (e non solo!)

Acquista

Inoltre, ci sono molti dispositivi per cui non è disponibile un client VPN nativo, come ad esempio alcuni NAS e la maggior parte delle Smart TV.

Per questo motivo ho deciso di creare un Router-on-a-Stick con un Raspberry Pi 4, in modo da poterlo utilizzare come gateway VPN per tutti i dispositivi della mia rete che possono beneficiarne.

Lato client, la configurazione è semplicissima: basta impostare come Default Gateway l'indirizzo IP del Raspberry Pi, sarà poi lui stesso ad occuparsi del "lavoro sporco".

Questa modifica si effettua nelle impostazioni di rete del dispositivo specifico (TV, PC, etc.) o, per un'applicazione più ampia, direttamente nelle impostazioni DHCP del vostro router principale, se permette di specificare un gateway diverso per certi client.

Vediamo insieme come farlo.

Prerequisiti

In questa guida, nello specifico, utilizzerò un Raspberry Pi 4 con 2GB di RAM e configurerò tramite protocollo WireGuard la mia sottoscrizione a Private Internet Access (PIA).

Una configurazione simile si può replicare utilizzando il protocollo OpenVPN, ma ho scelto WireGuard per una questione di performance, dato che il Pi sicuramente non è una scheggia.

Per quanto riguarda la RAM, 2GB sono più che sufficienti per questo tipo di configurazione, ma se prevedete di utilizzare il vostro Raspberry Pi per altri scopi, vi consiglio di optare per il modello con 4GB.

Vi sconsiglio invece di utilizzare un modello da 1GB di RAM, in quanto potreste incappare in colli di bottiglia, specialmente collegando svariati client.

Infine, parlando di abbonamenti VPN, potete utilizzare qualsiasi provider che supporti WireGuard o OpenVPN.

Alcuni provider (ad esempio PIA, come vedremo più avanti) sono un po' schizzinosi e richiedono una configurazione manuale, mentre altri forniscono un file di configurazione già pronto all'uso.

Personalmente consiglio PIA per il prezzo molto più concorrenziale, soprattutto se si sceglie un piano pluriennale (al momento €70 per 40 mesi di abbonamento).

Inoltre PIA è uno dei pochi provider VPN ad offrire Port Forwarding per il P2P ed ha una No-Log policy certificata.

SPONSORED

Non sai quale Provider VPN scegliere? Segui il mio referral link per abbonarti a PIA ed ottenere ulteriori 30 giorni gratuiti all'acquisto di un abbonamento!

Abbonati a Private Internet Access

Installazione

Vediamo insieme come installare e configurare il nostro Router on a Stick.

  • Come primissima cosa, aggiorniamo il sistema operativo
sudo apt update && sudo apt dist-upgrade -y
  • Adesso possiamo installare wireguard e iptables-persistent, quest'ultimo necessario per rendere permanenti le regole di instradamento che andremo ad impostare
sudo apt install wireguard iptables-persistent -y
  • Modifichiamo il file /etc/sysctl.conf
sudo nano /etc/sysctl.conf
  • Sostituiamo la riga net.ipv4.ip_forward preesistente con questa
net.ipv4.ip_forward=1
❓
Il mio file è vuoto, che faccio?
Niente di cui preoccuparsi! In questo caso, possiamo tranquillamente aggiungere la riga e salvare il file.
  • Applichiamo la modifica
sudo sysctl -p
❓
Cosa abbiamo fatto?
Modificando il file sysctl.conf, che contiene le opzioni di configurazione del kernel "persistenti" al boot, abbiamo abilitato la funzione di IP Forwarding sul nostro sistema operativo. Quindi, il nostro Raspberry adesso può inoltrare sull'interfaccia VPN i pacchetti che riceve dalla LAN.
  • Modifichiamo le regole del nostro firewall iptables aggiungendo un paio di policy relative a wg0, l'interfaccia utilizzata da WireGuard
sudo iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE
sudo iptables -A FORWARD -i eth0 -o wg0 -j ACCEPT
sudo iptables -A FORWARD -i wg0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o eth0 -j DROP
sudo netfilter-persistent save

Nel dettaglio:

  1. sudo iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE abilita il NAT sull'interfaccia wg0, in modo che tutti i client appaiano come il Raspberry agli occhi della VPN
  2. sudo iptables -A FORWARD -i eth0 -o wg0 -j ACCEPT quando un pacchetto entra dall'interfaccia eth0 e deve andare sull'interfaccia wg0, accetta il traffico
  3. sudo iptables -A FORWARD -i wg0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT questa regola è relativa al return traffic, cioè permette la comunicazione nel verso contrario (dalla VPN alla LAN) solamente per connessioni già stabilite. Questo evita l'ingresso tramite VPN verso la nostra LAN
  4. sudo iptables -A FORWARD -i eth0 -o eth0 -j DROP questo è il nostro Kill-Switch. Se il tunnel VPN dovesse venire chiuso (per mano nostra o per altro motivo) il traffico dei client proverebbe a passare da eth0 ad eth0, col rischio di uscire in chiaro su internet. Per evitarlo, questa regola indica di bloccare i pacchetti che provano a transitare sulla eth0.
  5. sudo netfilter-persistent save salva le regole che abbiamo appena aggiunto

Adesso siamo pronti a configurare la nostra utenza di PIA per collegarci in VPN

Configurazione

Come anticipato, PIA è uno di quei provider un po' "schizzinosi" sull'utilizzo del protocollo WireGuard senza passare dal loro client ufficiale. Tuttavia, abbiamo la soluzione.

Il progetto GitHub pia-wg è una utility in Python che, inserendo le nostre credenziali PIA e specificando un Server VPN, può estrarre per noi il file di configurazione da dare in pasto al client VPN.

Vediamo come fare

  • Installiamo le dipendenze software
sudo apt install git wireguard-tools openresolv python3-venv -y
  • Cloniamo il progetto da GitHub
git clone https://github.com/djtroyal/pia-wg
  • Spostiamoci nella cartella che abbiamo appena clonato
cd pia-wg
  • Creiamo un Virtual Environment di Python per eseguire il programma
python3 -m venv venv
  • Installiamo i requisiti di Python per il progetto
./venv/bin/pip install -r requirements.txt
  • Rendiamo eseguibile lo script auto-generate-config.sh
chmod +x auto-generate-config.sh
  • Modifichiamo il file .env
nano .env
  • Indichiamo i nostri dati
    • PIA_user → il nostro username di PIA (in genere, inizia con la lettera p)
    • PIA_pass → la password del nostro utente PIA
    • region → il nome, così come visualizzato sul client ufficiale di PIA, del server VPN per cui scaricare la configurazione. Ad esempio, "IT Milano"
region = ""
PIA_user = ""
PIA_pass = ""
  • Adesso possiamo eseguire lo script ed ottenere il nostro file
./auto-generate-config.sh

Lo script ha ora generato, in questa cartella, un file PIA-wg.conf che contiene tutte le informazioni necessarie al nostro client VPN per connettersi.

  • Spostiamo il file in /etc/wireguard/ e rinominiamo in wg0.conf, per farlo riconoscere in automatico al client VPN
sudo cp PIA-wg.conf /etc/wireguard/wg0.conf
  • Adesso possiamo finalmente testare la connessione via VPN
sudo wg-quick up wg0
  • Se non abbiamo ricevuto errori, possiamo controllare con quale indirizzo IP stiamo uscendo su internet
curl icanhazip.com

(in alternativa, anche un traceroute può darci questa informazione)

Step successivi

configurazioni avanzate

Avvio Automatico

Adesso che abbiamo configurato iptables ed il client wireguard, possiamo connetterci

sudo wg-quick up wg0

e disconnetterci

sudo wg-quick down wg0

dalla VPN.

Tuttavia, per non dover effettuare questa operazione manualmente, possiamo sfruttare il servizio wg-quick del client di WireGuard per tirare su la connessione all'avvio del sistema operativo.

Per farlo, ci basta attivare il servizio che è già stato predisposto dall'installazione:

sudo systemctl enable wg-quick@wg0

Notifiche in Caso Di Disconnessione

Nel caso in cui il client WireGuard dovesse perdere la connessione, è molto importante essere informati per poter controllare cosa è andato storto.

Se avete installato un endpoint di Apprise API, potete utilizzare uno script per essere avvertiti automaticamente.

Non sai cosa sia Apprise API? Segui la mia guida per installare il tuo personale centralinista smart!

Apprise - come inviare notifiche verso qualsiasi servizio di messaggistica
Scopri Apprise, lo strumento che unifica tutte le tue notifiche. Invia messaggi a email, Telegram, Slack e decine di altri servizi con una singola chiamata API. Semplifica i tuoi script, risparmia tempo e centralizza la gestione degli avvisi in un unico posto.

Ho scritto un piccolo script in Bash proprio a questo scopo, ed è ovviamente possibile integrarlo con altri sistemi di notifica, se necessario.

  • Creiamo il file check_wg.sh (potete crearlo dove preferite, ma ricordatevi il path perchè ci servirà nella configurazione della schedulazione)
nano check_wg.sh
  • Incolliamo lo script
#!/bin/bash

# PARAMETRI
TAG=""
CONFIG="apprise"
NOME=""
APPRISE_API_URL="http://indirizzo.ip.di.apprise:porta/notify/$CONFIG"


# Dati JSON per la notifica
JSON='{
  "tag": ["$TAG"],
  "title": "WireGuard VPN assente",
  "body": "Attenzione: $NOME ha perso la connessione WireGuard!",
  "config": "$CONFIG"
}'

# Verifica se l'interfaccia wg0 è "up"
if ! wg show wg0 > /dev/null 2>&1; then
  # Richiesta POST per invio notifica
  curl -X POST \
    -F "title=WireGuard VPN assente" \
    -F "body=Attenzione: $NOME ha perso la connessione WireGuard!" \
    -F "tags=$TAG" \
    "$APPRISE_API_URL"
fi
  • Personalizziamolo coi parametri relativi alla nostra installazione (sezione PARAMETRI):
    • TAG: il tag di Apprise da utilizzare per instradare la notifica
    • CONFIG: il nome della configurazione di Apprise da caricare (di default "apprise")
    • NOME: il "friendly name" del vostro Raspberry, come viene scritto nella notifica (ad esempio, potete chiamarlo "Raspberry VPN")
    • APPRISE_API_URL: qui indichiamo Indirizzo IP e Porta del nostro endpoint di Apprise
  • Rendiamo eseguibile lo script
sudo chmod +x check_wg.sh
  • Proviamo ad eseguirlo per assicurarci che non siano presenti errori
sh check_wg.sh
  • Per testare l'invio delle notifiche, possiamo tirare giù la VPN manualmente
sudo wg-quick down wg0
  • Eseguiamo nuovamente lo script. Adesso dovremmo ricevere una notifica ai canali impostati
sh check_wg.sh
  • Infine, se tutto è andato a buon fine, possiamo programmarne l'esecuzione periodica tramite crontab
sudo crontab -e
  • Aggiungiamo la seguente riga per eseguire lo script ogni 5 minuti
*/5 * * * * /path/assoluto/script/check_wg.sh
‼️
ATTENZIONE
Fate attenzione ad indicare il path completo allo script che abbiamo creato.

Split Tunneling

Lo Split Tunneling è la tecnica che permette di scegliere quali dati inviare tramite la VPN e quali lasciare viaggiare sulla rete locale. Questo meccanismo può agire -nel più semplice dei casi- a seconda della subnet di destinazione ma, a seconda del risultato che si vuole ottenere, si può filtrare per applicazione, protocollo o anche per IP sorgente.

Nel nostro caso, può far comodo distinguere il traffico interno da quello destinato all'esterno, e far uscire in VPN solo il traffico verso internet.

Se non abbiamo modificato manualmente le tabelle di routing del nostro Raspberry Pi, il traffico destinato alla subnet di cui fa parte il Raspberry Pi sta già bypassando la VPN. Tuttavia, se avete altre subnet interne, dovrete aggiungere una rotta statica permanente per ciascuna. Vediamo come fare:

‼️
ATTENZIONE
I seguenti comandi funzionano solo se usate dhcpcd come gestore. Se invece utilizzate NetworkManager o systemd-networkd, dovrete utilizzare i comandi specifici della vostra soluzione.
  • Modifichiamo il file /etc/dhcpcd.conf
sudo nano /etc/dhcpd.conf
  • Aggiungiamo in fondo al file una riga seguendo questo formato
static route=x.x.x.x/xx via indirizzo.IP.del.router
🗒️
ESEMPIO
Per raggiungere la rete 192.168.1.0 con subnet mask 255.255.255.0 tramite il router 192.168.1.1:
static route=192.168.1.0/24 via 192.168.1.1
  • Una volta aggiunte tutte le rotte necessarie, riavviamo il servizio dhcpcd per applicare le modifiche
sudo systemctl restart dhcpcd

Auto-rinnovo Del File Di Configurazione

Un ultima cosa: a differenza del client nativo di PIA, quando vengono cambiate alcune configurazioni lato server VPN, il nostro client WireGuard non aggiornerà automaticamente il file di configurazione wg0.conf.

Di conseguenza, può darsi che ogni tanto il Tunnel VPN cada e rimanga giù finché, manualmente, non andremo a rigenerare il file di configurazione. Per ovviare a questo problema, ho creato un altro script che si occupa di:

  1. Disattivare la VPN
  2. Rigenerare il file di configurazione
  3. Spostarlo nella cartella di configurazione di WireGuard
  4. Riattivare la VPN

Impostando questo script per l'avvio ad intervalli regolari, possiamo dimenticarci di dover aggiornare il file di configurazione manualmente, al costo di qualche pacchetto perso durante la sostituzione del file.

Se siete interessati, questo è lo script update-wg.sh:

#!/bin/bash

# Costante: percorso della directory pia-wg
PIAWG_PATH="/path/alla/cartella/pia-wg"

# 1. Disattiva la VPN (WireGuard)
echo "Disattivo WireGuard (wg0)..."
wg-quick down wg0

# 2. Va nella directory pia-wg ed esegue lo script di autogenerazione
echo "Mi sposto nella cartella pia-wg ed eseguo auto-generate-config.sh..."
cd "$PIAWG_PATH" || exit 1
./auto-generate-config.sh

# 3. Controlla che il file PIA-wg.conf sia stato generato
if [ ! -f "$PIAWG_PATH/PIA-wg.conf" ]; then
    echo "Errore: il file di config non è stato generato!"
    exit 2
fi

# 4. Copia il nuovo config nella directory WireGuard
echo "Copio PIA-wg.conf in wg0.conf..."
cp "$PIAWG_PATH/PIA-wg.conf" /etc/wireguard/wg0.conf
chmod 600 /etc/wireguard/wg0.conf

# 5. Riattiva la VPN
echo "Avvio WireGuard (wg0)..."
wg-quick up wg0

echo "Script concluso!"

Ricordatevi poi di renderlo eseguibile

chmod +x update-wg.sh

Ed infine di programmarlo con crontab

sudo crontab -e

Per esempio, ogni 6 ore

0 */6 * * * /path/assoluto/di/update-wg.sh

Conclusioni

Ora che abbiamo creato il nostro personalissimo Router VPN, possiamo configurare i nostri client affinché lo utilizzino come Default Gateway.

Come sempre, il limite è la vostra immaginazione.

Volendo è possibile infatti personalizzare questa configurazione per creare un ponte VPN site-to-site tra due reti, oppure ancora sfruttare la scheda WiFi del vostro Raspberry Pi per usarlo come Router VPN da usare in viaggio.

Qualsiasi sia il vostro obiettivo, sono felice che siate arrivati in fondo a questa guida.

Alla prossima!