dockerised wireguard tunnel

Το παρόν αποτελεί αναδιατύπωση του μπλόγκ πόστ μου εδώ
Αλλα και του channel post μου εδώ

Προετοιμασία

Το docker setup προ απαιτεί το wireguard kernel module , μια ανοιχτή udp port στο ρούτερ, ενα public subdomain , port forward την wireguard port στην lan IP του rasberry στις ρυθμίσεις του ρούτερ .

→ “Φορτώνουμε” το wireguard kernel module

modprobe wireguard

→ Βεβαιωνόμαστε ότι θα φορτώνει κατά το boot

δημιουργούμε ένα config file:

sudo nano /etc/modules-load.d/wireguard.conf

προσθέτουμε το module name

wireguard

ελέγχουμε την κατάσταση των kernel modules , ψάχνοντας για το wireguard

lsmod |grep wireguard

Ελέγχουμε αν το systemd service φορτώνει το module:

systemctl status systemd-modules-load.service

Αντιγράφουμε το proccess id
e.g.

Main PID: 210 (code=exited, status=0/SUCCESS) PID = 210

status=0/SUCCESS σημαίνει οτι το systemd φόρτωσε το module επιτυχημένα

διπλό ελέγχουμε

journalctl -b _PID=210

systemd-modules-load[210]: Inserted module ‘wireguard’

Forword ipv4

sudo nano /etc/sysctl.d/ipv4_forwarding.conf

προσθέτουμε

net.ipv4.ip_forward=1

ελέγχουμε

sysctl net.ipv4.ip_forward

Δυο λόγια για το key pair του wireguard

Tο docker run δημιουργεί έτοιμα προς χρήση server config και client configs καθώς και σετ private/public keys για τον server και τους client

Τα παραπάνω αρχεία βρίσκονται στο path/to/appdata/ το οποίο path το ορίζουμε ως volume env var e.g. -v /home/user/wireguard:/config

Το Client config βρίσκεται στο path/to/appdata/config/peer1/peer1.png ως αρχείο εικόνας png και κειμένου path/to/appdata/config/peer1/peer1.conf
o φάκελος του client επίσης περιέχει το private key “privatekey-peer1” και το public key “publickey-peer1” και το preshare key “presharedkey-peer1”

Το server config βρίσκεται στο path/to/appdata/config/wg0.conf και ο φακελος server περιέχει τo public key "publickey-server " και private key “privatekey-server” του server

Τα private key είναι ιδιωτικά.
Του server μένει στον server και του client μένει στον client
Tα config έχουν δύο section interface και peer

τα config ειναι της μορφής

client:

[Interface]
Address = 10.13.13.2
PrivateKey = blahblahblah1=
ListenPort = 51000
DNS = 10.13.13.1

[Peer]
PublicKey = blahblahblah2=
PresharedKey = blahblahblah3=
Endpoint = my.ddns.domain.com:51000
AllowedIPs = 0.0.0.0/0, ::/0

server:

[Interface]
Address = 10.13.13.1
ListenPort = 51000
PrivateKey = blahblahblah4
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth+ -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth+ -j MASQUERADE

[Peer]
# peer1
PublicKey = blahblahblah5
PresharedKey = blahblahblah6
AllowedIPs = 10.13.13.2/32

Βάζοντας τις κατάλληλες παραμέτρους μπορείς να συνδέσεις τα δυο τους και να συνδεθείς από το ένα στο άλλο

Το docker run θα μας τα δώσει έτοιμα προς χρήση

Το client config το εισάγουμε στον android client σκαναρωντας το qr code στο path/to/appdata/config/peer1/peer1.png
Μπορούμε να εμφανίσουμε το qr code στο terminal με
docker exec -it wireguard /app/show-peer 1
Διαφορετικά μπορούμε να μεταφέρουμε το config στη συσκευη και να το κάνυμε import

Η λογική των wireguard config

  • Στο public key field του peer section του server εισάγουμε το public key του client

  • Στο public key field του peer section του client εισάγουμε το public key του server

  • Στο PresharedKey field τόσο του server και του client βάζουμε το PresharedKey απο το φάκελο του client. Το συγκεκριμένο κλειδί είναι optional και παρέχει επιπλέον ασφάλεια

  • Στο Endpoint field του peer section του client εισάγουμε το την public ip του server και την port στην οποία “ακουει” e.g. αν έχουμε το dynamic dns domain wire-test.duckdns.org θα βάλουμε αυτό στο συγκεκριμένο πεδίο wire-test.duckdns.org:5000

  • Στο DNS field του interface section του client βάζουμε την wireguard subnet address του σέρβερ e.g. 10.13.13.1 όπως φαίνεται στο Address field του interface section του server

  • Το AllowedIPs fiend του peer section τoυ client είναι το πιο ενδιαφέρον πεδίο γιατί από αυτό μπορούμε να ρυθμίσουμε αν ο client θα μπορεί να συνδεθεί μόνο στη συγκεκριμένη συσκευή στην οποία τρέχει ο server π.χ. για remote ssh ή σε όλο του subnet σε όλες δλδ τις συσκευές του local LAN σά να είμαι δλδ συνδεδεμένος στο wifi του σπιτιού

Σύνδεση σε όλο το subnet AllowedIPs = 0.0.0.0/0, ::/0

Σύνδεση μόνο στον σέρβερ:
Εισάγουμε την local lan IP της συσκευής στην οποία τρέχει σέρβερ e.g. 192.168.1.24 μαζί με την wireguard subnet address του σέρβερ e.g. 10.13.13.1 όπως φαίνεται στο Address field του interface section του server
AllowedIPs = 192.168.1.24/32 , 10.13.13.1/32

  • Στο AllowedIPs fiend του peer section τoυ server εισάγουμε την wireguard subnet address του client όπως φαίνεται στο Address field του interface section του client

  • Το ListenPort field του interface section του server ειναι η udp port στην οποία ακούει το wireguard . Την ορίζουμε ως env var sto docker run και την “ανοίγουμε” στο ρούτερ και την κάνουμε prt forword στη συσκευη που τρέχει ο server

  • Τα Address field του interface section τόσο του server όσο και του client ειναι η ip address του καθε ενα στο wireguard subnet (το εσωτερικό του wireguard οχι του LAN)

  • Τα PrivateKey field του interface section τόσο του server όσο και του client όπως φαίνονται στα privatekey-peer1 και privatekey-server

  • Tα PostUp και PostDown fields του interface section του server ειναι τα iptables όπως τα δημιουργεί το docker run .

Setup
Docker & docker-compose

Το linuxserver Wireguard Docker image μπορεί να δεχτεί αρκετές enviromental variables

docker run -d \
  --name=wireguard \
  --cap-add=NET_ADMIN \
  --cap-add=SYS_MODULE \
  -e PUID=1000 \
  -e PGID=1000 \
  -e TZ=Europe/Athens \
  -e SERVERURL=wireguard.domain.com `#optional` \
  -e SERVERPORT=51820 `#optional` \
  -e PEERS=1 `#optional` \
  -e PEERDNS=auto `#optional` \
  -e INTERNAL_SUBNET=10.13.13.0 `#optional` \
  -e ALLOWEDIPS=0.0.0.0/0 `#optional` \
  -e LOG_CONFS=true `#optional` \
  -p 51820:51820/udp \
  -v /path/to/appdata/config:/config \
  -v /lib/modules:/lib/modules `#optional` \
  --sysctl="net.ipv4.conf.all.src_valid_mark=1" \
  --restart unless-stopped \
  lscr.io/linuxserver/wireguard:latest
  • name = Το όνομα που θα έχει το container
  • cap-add = Tα Docker containers ειναι “unprivileged” προσθέτουμε Linux capabilities γιατί το wireguard χρειάζεται να έχει πρόσβαση στα network interfaces και τα kernel modules
  • PUID και PGID Το docker τρέχει σαν root που σημαίνει οτι οι διαδικασίες μέσα στα container επίσης τρέχουν σαν ρουτ και είναι owned απο τον root . Οποτε δημιουργούμε το container ως τον default χρήστη και οχι τον ρουτ
  • TZ = ζώνη ώρας
  • SERVERURL = To domain name από το οποίο συνδέεσαι στο raspberry (τη συσκευή στην οποία τρέχει ο σερβερ)
  • SERVERPORT = ειναι η udp port στην οποία ακούει το wireguard . Την ορίζουμε ως env var sto docker run και την “ανοίγουμε” στο ρούτερ και την κάνουμε prt forword στη συσκευη που τρέχει ο server
  • PEERS = Πολύ σημαντική παράμετρος . Αυτή μας καθορίζει αν το container θα τρέχει σε server mode , δημιουργώντας και τα αντίστοιχα config . Μπορούμε να δημιουργήσουμε περισσότερα απο ένα peer (clients δλδ) χωριζοντάς τα με κόμμα αν θέλουμε να τα ονομάσουμε ή απλα να δώσουμε έναν αριθμό και να τα ονομάσει μόνο του.

Αν θέλουμε να τρέξουμε το conttainer σε client mode δέν συμπληρώνουμε αυτη την παράμετρο , εχoυμε έτοιμο το client config το οποίο αντιγράφουμε στη διαδρομή `/config/wg0.conf και έπειτα τρέχουμε το container

  • PEERDNS = auto Απαραίτητο σε server mode
  • INTERNAL_SUBNET = Το εσωτερικό subnet του wireguard
  • ALLOWEDIPS = Καθορίζει το AllowedIPs fiend του peer section τoυ client όπως περιγράυτικε πιο πάνω
  • LOG_CONFS=true/false Αν τα qr codes θα εμφανίζοντε στο docker log ή όχι
  • /path/to/appdata/config:/config Περιέχει τα private public keys , τα server client configs etc
  • /lib/modules Κάνει mount τα kernel modules του host στο container .
  • sysctl = απαιτείτε για το networking του wireguard σε kernel level . Απαραίτητο σε clinet mode
7 «Μου αρέσει»

Ποια είναι η ανάγκη να τρέξει το wireguard σε OS virtualization (docker)?

Το μοναδικό που μπορώ να σκεφτώ είναι για να ενώσεις δύο private cloud δίκτυα, αλλά σε τέτοιες περιπτώσεις σου δίνουν τα ίδια τα clouds λύσεις.

1 «Μου αρέσει»

η ευκολία
copy paste το docker run
σκαναρεις το qr και είσαι μέσα

πέραν τούτου σου εξηγώ ενα ενα τα field των section
και πως να φορτώσεις το κερνελ μοντουλ

αν και το ποστ στοχεύει τον μη τεχνικό χρήστη μπορείς με αυτο να φτιάξεις wireguard config στο χέρι χωρίς docker

1 «Μου αρέσει»

Το comment μου ήταν ξεκάθαρα για πληροφοριακους λόγους. Τύπου μήπως χάνω κάτι πρακτικό εγώ. Π.χ. έχει νόημα να τρέχεις ένα microservice σε dockers για να μπορείς να κάνεις spin off νέα instances όταν έχεις την ανάγκη.

Σε ευχαριστώ πολύ για την απάντηση σου

2 «Μου αρέσει»