Contenuti

VPN server con wireguard

Wireguard è un tool per creare VPN, moderno, sicuro e performante. Vediamo come creare un server VPN a cui inoltrare tutto il traffico.

prerequisiti

Avremo bisogno di un server con caratteristiche minime:

  • 1 core
  • 512mb di RAM (funziona anche con meno, ma vediamo di essere ragionevoli)
  • 5GB di disco
  • banda!
  • linux con un kernel recente

In particolare bisogna prestare attenzione alla banda: se si ha la fortuna di avere una connessione ad internet veloce, diciamo >100mbit, dovremo assicurarci di avere almeno la stessa banda sul server.

Ad oggi, possiamo noleggiare un VPS con queste caratteristiche per meno di 5€/mese.

In questa guida, verranno considerati i seguenti sistemi operativi:

  • Ubuntu Server 20.04
  • Debian 10 Buster

definizioni

Useremo queste convenzioni:

  • Rete del tunnel: 192.168.199.1/24
  • IP del server: 192.168.199.1
  • IP dei client: da 192.168.199.2 in avanti
  • IP esterno del server: 11.22.33.44
  • interfaccia esterna del server: eth0

setup del server

Per semplicità, supponiamo di partire da un server nuovo, a cui abbiamo accesso come utente root.

Se stiamo usando Debian Buster, bisogna innanzitutto abilitare i backports:

1# echo "deb http://deb.debian.org/debian buster-backports main" \
2| tee /etc/apt/sources.list.d/debian-backports.list && apt update

Sempre per Debian Buster, opzionalmente possiamo installare un kernel più recente:

1# apt install linux-image-5.7.0-0.bpo.2-amd64

Ora possiamo procedere ad installare un po' di pacchetti:

1# apt install wireguard iptables resolvconf qrencode unattended-upgrades unbound

Wireguard ha bisogno di una chiave pubblica e di una chiave privata per ogni membro della connessione, quindi creiamo una coppia di chiavi per il server:

1# wg genkey | tee /root/server.privkey
2sL1UKqiqMraaQarCy7UIUpkQnpgzR6Gm+L1RCgp2TEM=
3
4# cat /root/server.privkey | wg pubkey | tee /root/server.pubkey
5UgvmsCnMWWW9XAHNbc6+lkbCLSF5Mt3b85A4PrG4mRE=

Per semplificare la configurazione, useremo un tool di wireguard che si chiama wg-quick: questo ci permette di gestire la configurazione di ogni interfaccia di wireguard in un file; inoltre, si occuperà di gestire indirizzi IP e routing ad ogni attivazione/disattivazione dell’interfaccia. In questo file di configurazione verranno salvate le chiavi pubbliche e gli indirizzi IP di ogni altro membro della VPN. Cominciamo con il crere il file di configurazione (il nome del file DEVE essere [nome_interfaccia].conf) e popolarlo:

 1# touch /etc/wireguard/wg0.conf
 2
 3# cat /etc/wireguard/wg0.conf
 4[Interface]
 5Address = 192.168.199.1/24
 6SaveConfig = true
 7ListenPort = 51194
 8PrivateKey = sL1UKqiqMraaQarCy7UIUpkQnpgzR6Gm+L1RCgp2TEM=
 9
10# systemctl enable wg-quick@wg0
11
12# wg-quick up wg0
13[#] ip link add wg0 type wireguard
14[#] wg setconf wg0 /dev/fd/63
15[#] ip -4 address add 192.168.199.1/24 dev wg0
16[#] ip link set mtu 1420 up dev wg0
17
18# wg
19interface: wg0
20  public key: UgvmsCnMWWW9XAHNbc6+lkbCLSF5Mt3b85A4PrG4mRE=
21  private key: (hidden)
22  listening port: 51194

Mettiamo un secondo da parte il server e vediamo il client.

setup del client (linux)

Sul client dobbiamo replicare gli stessi comandi del server, con alcune piccole differenze: chiaramente la coppia di chiavi sarà differente, e non avremo un indirizzo IP ed una porta per la ricezione delle connessioni in quanto la connessione sarà solo in uscita.

Supponendo di utilizzare una Ubuntu 20.04:

 1# sudo apt install wireguard resolvconf
 2
 3# wg genkey | tee ~/server.privkey
 4AGrgj2nh5T/3VMddrno/FIOgiotgKVQ9ydjw2AHzbno=
 5
 6# cat ~/server.privkey | wg pubkey | tee ~/server.pubkey
 77c0uRl/F4jcpEPLOTA8zs0vcpQ3lTiljYbWb2QmJ11M=
 8
 9# sudo touch /etc/wireguard/wg0.conf
10
11# sudo tee /etc/wireguard/wg0.conf <<EOF
12[Interface]
13SaveConfig = true
14PrivateKey = AGrgj2nh5T/3VMddrno/FIOgiotgKVQ9ydjw2AHzbno=
15Address = 192.168.199.2/32
16DNS = 192.168.199.1
17
18[Peer]
19PublicKey = phoJ2IBLJXEjaJJXzcEM6TGidh/rGxCdpXvKOP0HK0E=
20Endpoint = 11.22.33.44:51194
21AllowedIPs = 0.0.0.0/0
22# AllowedIPs = 192.168.199.0/24
23PersistentKeepalive = 20
24EOF
25
26# sudo systemctl enable wg-quick@wg0
27
28# sudo wg-quick up wg0
29[#] ip link add wg0 type wireguard
30[#] wg setconf wg0 /dev/fd/63
31[#] ip -4 address add 192.168.199.2/32 dev wg0
32[#] ip link set mtu 1420 up dev wg0
33[#] ip -4 route add 0.0.0.0/0 dev wg0

Ricapitolando, il client ha impostato un indirizzo IP singolo (/32) ed un DNS. Nella sezione [Peer] indica il server al quale connettersi e su che porta (si può usare anche un FQDN), oltre alla chiave pubblica per certificarne l’identità e decrittare il traffico.

La riga AllowedIPs indica quali indirizzi IP vengono inoltrati sul tunnel, in questo caso tutti. Di conseguenza, quando la VPN sarà attiva, sarà impossibile vedere la rete locale (ed ogni altra rete non raggiungibile dal server VPN) e tutto il traffico passerà dalla VPN.

configurazione del client sul server

Il server deve essere istruito per accettare le connessioni dal client:

 1# wg set wg0 peer 7c0uRl/F4jcpEPLOTA8zs0vcpQ3lTiljYbWb2QmJ11M= \
 2allowed-ips 192.168.199.2
 3
 4# wg
 5interface: wg0
 6  public key: UgvmsCnMWWW9XAHNbc6+lkbCLSF5Mt3b85A4PrG4mRE=
 7  private key: (hidden)
 8  listening port: 51194
 9  fwmark: 0xca6c
10
11peer: 7c0uRl/F4jcpEPLOTA8zs0vcpQ3lTiljYbWb2QmJ11M=
12  endpoint: 3.4.5.6:51820
13  allowed ips: 192.168.199.2/32
14  latest handshake: 39 seconds ago
15  transfer: 7.20 MiB received, 6.63 MiB sent
16
17# wg-quick save wg0
18[#] wg showconf wg0

L’ultimo comando serve per salvare immediatamente la configurazione nel file /etc/wireguard/wg0.conf.

Abbiamo ancora bisogno di un paio di ritocchi: masquerading e DNS.

Masquerading (e forwarding)

Il traffico che arriva dalla VPN wireguard, al momento, arriva sul server e viene scartato. Bisogna abilitare il forwarding:

1# echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/99-forwarding.conf
2
3# sysctl -w net.ipv4.ip_forward=1

Creiamo anche delle regole sul firewall per gestire il traffico:

1# iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
2# iptables -A FORWARD -i wg0 -j ACCEPT
3# iptables -P FORWARD DROP
4# iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Eccole spiegate:

  • il traffico da inoltrare, relativo a connessioni già attive, viene accettato ed inoltrato
  • il traffico da inoltrare, in arrivo dalla VPN viene accettato
  • ogni altro traffico da inoltrare, non gestito da altre regole, viene scartato
  • il traffico in uscita sulla porta eth0 del server viene nattato (masquerading)

Rendiamo permanenti le modifiche:

1# iptables-save > /etc/iptables.up.rules
2
3# cat > /etc/network/if-pre-up.d/iptables <<EOF
4#!/bin/sh
5/sbin/iptables-restore < /etc/iptables.up.rules
6EOF
7
8# chmod +x /etc/network/if-pre-up.d/iptables

DNS

Il client utilizza il server DNS presente sul server, che quindi andiamo a configurare:

 1# cat > /etc/unbound/unbound.conf.d/custom.conf <<EOF
 2interface: 0.0.0.0
 3access-control: 192.168.199.0/24 allow
 4access-control: 127.0.0.1/8 allow
 5
 6forward-zone:
 7        name: "."
 8        forward-addr: 9.9.9.9
 9        forward-addr: 1.1.1.2
10EOF
11
12# service unbound restart

Semplicemente abilitiamo il server DNS su TUTTE le interfacce, ma accettiamo le richieste solo dalla VPN e da localhost; ogni richiesta viene inoltrata ai DNS di quad9 e cloudflare.

TODO

  • filtraggio malware/pubblicità
  • istruzioni anche per Windows ed OSX?