WireGuard installeren op een eigen VPS
Leer WireGuard configureren op uw Linux VPS. Wij behandelen key generation, wg0.conf en het oplossen van handshake failures en IP forwarding problemen.
Wat u bouwt
Een WireGuard VPN op een eigen server vereist ongeveer veertig regels configuratie: één key pair, één interface bestand, één sysctl, één NAT regel en één firewall uitzondering. De installatie is eenvoudig. Daarom richt deze handleiding zich voornamelijk op veelvoorkomende problemen: key permissions, AllowedIPs, forwarding en DNS.
WireGuard is een Layer 3 tunnel in de kernel. Het is sinds Linux 5.6 onderdeel van de mainline kernel. Ubuntu 24.04 en Debian 13 leveren het daarom standaard zonder externe module. Er is geen cipher negotiation, geen certificate authority en geen gebruikersnaam/wachtwoord stap: een peer bestaat uit een public key plus de IP addresses die die key mag gebruiken. Pakketten die de MAC check niet halen, worden zonder antwoord gedropt. Hierdoor reageert de port niet op scans. Het nadeel is dat er geen auth server bestaat; toegang intrekken betekent een peer verwijderen op de server.
Controleer eerst de virtualisatie
WireGuard vereist een kernel waarin een module geladen kan worden. Op een KVM VPS werkt dit direct. Bij container-virtualisatie die de host-kernel deelt — zoals OpenVZ of LXC — mislukt het eerste commando met RTNETLINK answers: Operation not supported. In dat geval wordt de wireguard-go userspace-implementatie gebruikt. Controleer dit eerst met sudo modprobe wireguard && echo ok.
Genereer keys zonder lekken
Een /etc/wireguard/server.key die voor iedereen leesbaar is, is gelijk aan geen enkele VPN. De standaard umask 077 && wg genkey | sudo tee ...-regel is onbetrouwbaar, omdat sudo een eigen umask toepast op het bestand dat tee aanmaakt. Stel de mode expliciet in.
sudo apt update && sudo apt install -y wireguard nftables
sudo install -d -m 700 /etc/wireguard
sudo sh -c 'umask 077; wg genkey > /etc/wireguard/server.key'
sudo sh -c 'wg pubkey < /etc/wireguard/server.key > /etc/wireguard/server.pub'
sudo chmod 600 /etc/wireguard/server.keyGenereer het client-paar op dezelfde manier. wg genpsk voegt een optionele pre-shared key toe, bestaande uit één regel in elke config.
De serverinterface: /etc/wireguard/wg0.conf
[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = <contents of /etc/wireguard/server.key>
[Peer]
PublicKey = <laptop public key>
PresharedKey = <psk, optional>
AllowedIPs = 10.8.0.2/32chmod 600 dit; een waarschuwing bij het opstarten dat het bestand wereldwijd toegankelijk is, betekent dat u deze stap hebt overgeslagen. Address is het adres van de server binnen de tunnel en bevat de maskering van het volledige VPN-subnet. Kies een bereik dat niet in de praktijk voorkomt — 192.168.1.0/24 botst met de helft van de thuishome-routers waar uw clients achter zitten, waardoor de tunnel de lokale route stilletjes verliest.
De AllowedIPs van een peer aan de server-zijde is een /32, het enige tunneladres dat de client bezit. Als u twee peers hetzelfde allowed IP geeft, verplaatst de configuratie zich naar de laatst geconfigureerde peer en stopt de eerste met het ontvangen van verkeer zonder dat er een foutmelding wordt weergegeven. Laat SaveConfig leeg, anders overschrijft wg-quick down dit bestand op basis van de actuele status.
Verander de box in een router
Een Linux-server laat pakketten vallen die niet aan hemzelf zijn gericht. Forwarding en source NAT zijn standaard niet ingeschakeld.
printf 'net.ipv4.ip_forward = 1\nnet.ipv6.conf.all.forwarding = 1\n' \
| sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl --system
sysctl net.ipv4.ip_forwardEen kale sysctl -w werkt tot de volgende reboot en stopt daarna zonder melding. NAT heeft de egress interface nodig — de NIC die verbinding maakt met het internet, niet wg0. Ga niet uit van eth0; bepaal uw eigen interface met ip route show default, aangezien huidige images namen zoals enp1s0 of ens3 gebruiken.
Firewall: de poort en het doorstuurpad
Eén nftables bestand regelt zowel filtering als NAT. Gebruik /etc/nftables.conf — dit verwijdert de huidige regelset volledig. Sla dit over op een systeem dat al door ufw of Docker wordt beheerd.
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority filter; policy drop;
ct state established,related accept
iif lo accept
tcp dport 22 accept
udp dport 51820 accept
}
chain forward {
type filter hook forward priority filter; policy drop;
ct state established,related accept
iifname "wg0" oifname "enp1s0" accept
}
}
table ip nat {
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
ip saddr 10.8.0.0/24 oifname "enp1s0" masquerade
}
}Pas dit toe met sudo systemctl enable --now nftables en houd een tweede SSH-sessie open: een typefout in de SSH-regel in policy drop zorgt ervoor dat u de toegang tot uw eigen server verliest. Let op wat de forward chain niet toestaat — wg0 tot wg0. Peers bereiken het internet, maar niet elkaar; voeg iifname "wg0" oifname "wg0" accept toe voor een peer-to-peer VPN. Dezelfde chain bepaalt wat een peer mag aanraken op de server zelf. Dit is belangrijk wanneer de machine ook dient als een remote development box die Claude Code in tmux uitvoert en u die zijde niet publiekelijk wilt blootstellen.
Op een ufw-systeem: ufw allow 51820/udp, DEFAULT_FORWARD_POLICY="ACCEPT" in /etc/default/ufw, en een *nat POSTROUTING MASQUERADE regel bovenaan /etc/ufw/before.rules.
Gebruik systemd voor de configuratie
sudo systemctl enable --now wg-quick@wg0
sudo wg showwg-quick maakt de interface aan, voegt de adressen toe en installeert routes afgeleid van AllowedIPs. enable --now is de cruciale stap: handmatige configuratie via wg-quick up wg0 gaat verloren na een herstart. Kernel-updates vereisen bovendien een herstart.
De clientconfiguratie, en de instelling die iedereen fout doet
[Interface]
PrivateKey = <laptop private key>
Address = 10.8.0.2/32
DNS = 10.8.0.1
[Peer]
PublicKey = <server public key>
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25AllowedIPs vervult twee verschillende functies tegelijkertijd. Het verwarren van deze functies is de oorzaak van de meeste WireGuard-verwarring.
Voor uitgaand verkeer is het een routingtabel. Een pakket waarvan het doeladres overeenkomt met de AllowedIPs van een peer, wordt versleuteld en naar die peer verzonden. 0.0.0.0/0, ::/0 stuurt al het verkeer door de tunnel — een full tunnel, waarbij de server als default route dient. Een split tunnel is een beperktere lijst: AllowedIPs = 10.8.0.0/24, 10.20.0.0/16 bevat VPN-verkeer plus één privaat netwerk achter de server, terwijl de rest zijn lokale route behoudt. Deze beperkte lijst zorgt ervoor dat u services volledig van het publieke internet kunt afsluiten — een private Nextcloud-instantie op een VPS die aan het tunneladres is gekoppeld, of de nested-virtualisation lab VM's die op hetzelfde systeem draaien, blijven bereikbaar voor peers en onzichtbaar voor de rest.
Voor inkomend verkeer is het een access-control list. Een gedecodeerd pakket van een peer waarvan het bronadres niet in de AllowedIPs van die peer staat, wordt gedropt. Daarom vermeldt de server 10.8.0.2/32 voor de laptop: een vermelding van 0.0.0.0/0 zou die client in staat stellen elk adres in de tunnel te spoofen.
PersistentKeepalive is bedoeld voor clients achter NAT, waarbij de router de UDP-mapping alleen openhoudt zolang er pakketten worden verzonden. Wanneer de verbinding verloopt, kan de server de client niet meer bereiken. PersistentKeepalive = 25 houdt de mapping open — stel dit in op de client, niet op een server met een publiek IP.
DNS, en het lek dat niemand opmerkt
Met AllowedIPs = 0.0.0.0/0 en geen DNS = regel behoudt de client de resolver die via het lokale netwerk is verkregen — de router van het café op 192.168.1.1. Die route is specifieker dan de standaardroute. Hierdoor verlaten DNS-queries de lokale link in cleartext, terwijl de rest van het verkeer via de tunnel gaat. Het verkeer is privé; de lijst met namen niet.
Er zijn twee betrouwbare opties. Wijs DNS toe aan een publieke resolver (DNS = 9.9.9.9). De queries gaan dan via de tunnel en verlaten het netwerk via uw server, hoewel die resolver de queries nog steeds ziet. Of gebruik unbound of dnsmasq gekoppeld aan 10.8.0.1, stel DNS = 10.8.0.1 in, en voeg udp dport 53 iifname "wg0" accept toe aan de input chain. Als u die regel instelt zonder een resolver te gebruiken, vindt er geen resolutie plaats.
Op Linux-clients past wg-quick DNS toe via resolvconf; als deze ontbreekt, krijgt u resolvconf: command not found. Installeer openresolv, of stel PostUp = resolvectl dns %i 10.8.0.1 in op een systemd-resolved client.
Peers toevoegen en verwijderen zonder de tunnel te verbreken
Het herstarten van de interface om een gebruiker toe te voegen, verbreekt de verbinding met alle actieve gebruikers. Voeg de [Peer] block toe aan wg0.conf en herlaad vervolgens de peer set.
sudo bash -c 'wg syncconf wg0 <(wg-quick strip wg0)'wg-quick strip toont de configuratie zonder de wg-quick-only keys (Address, DNS, PostUp). Met syncconf wordt het verschil doorgevoerd terwijl lopende sessies actief blijven. Alleen peers worden bijgewerkt: een gewijzigde Address vereist nog steeds een volledige down/up actie. Gebruik sudo wg set wg0 peer <public key> remove om een peer in te trekken. Verwijder daarna de block uit het bestand, anders wordt deze bij de volgende reload opnieuw geladen.
Foutmodi, met de strings die u zult zien
Handshake wordt nooit voltooid. wg show vermeldt de peer zonder latest handshake, en de client logt:
Handshake for peer 1 (10.0.0.10:51820) did not complete after 5 seconds, retrying (try 2)Er komt niets aan, of er wordt niets geaccepteerd. Controleer de volgende punten: staat UDP 51820 open in de VPS-firewall én in de firewall van uw provider (een aparte instelling in de meeste panels); is het Endpoint adres en de poort correct; zijn de keys correct uitgewisseld. De key in de [Peer] block van de client moet de publieke key van de server zijn, en vice versa — het plakken van een private key, of de eigen publieke key van de client, veroorzaakt precies dit symptoom. sudo tcpdump -ni any udp port 51820 op de server laat zien of er überhaupt pakketten aankomen. Het kernel-module logt standaard niets; WireGuard-berichten verschijnen in dmesg pas nadat u dynamic debug (echo module wireguard +p | sudo tee /sys/kernel/debug/dynamic_debug/control) heeft ingeschakeld. Wanneer dit is ingeschakeld, verschijnt een key-mismatch als een invalid-MAC drop.
Handshake werkt, geen internet. ping 10.8.0.1 slaagt, maar ping 1.1.1.1 geeft een timeout: forwarding of NAT ontbreekt. Controleer of sysctl net.ipv4.ip_forward 1 leest, en controleer vervolgens de counters terwijl de client pings uitvoert met sudo nft list ruleset of sudo iptables -t nat -L POSTROUTING -n -v. Nul pakketten op de masquerade rule betekent dat de egress interface naam onjuist is; een stijgende counter zonder antwoorden wijst op de forward chain policy.
Internet werkt, namen werken niet. ping 1.1.1.1 slaagt en curl https://example.com geeft Could not resolve host terug. De DNS regel ontbreekt, of vermeldt een resolver die onbereikbaar is via de tunnel.
Sommige HTTPS-sites hangen. SSH en ping werken goed; grote pagina's blijven hangen. Dit is path MTU: de tunnel voegt overhead toe, en een tussenliggende verbinding laat de te grote pakketten vallen zonder een ICMP-bericht terug te sturen. Verlaag MTU in de client [Interface] — probeer 1420, dan 1380, dan 1280.
Interface weigert te starten. Address already in use betekent dat een ander proces UDP 51820 gebruikt. Cannot find device wg0 na een mislukte up betekent meestal dat de configuratie is geweigerd; lees journalctl -u wg-quick@wg0 -n 50.
Migreren vanaf Streisand of OpenVPN
Streisand wordt niet meer onderhouden en het repository is gearchiveerd. Het draaien van een VPN op verouderde automatisering vormt een langzaam beveiligingsrisico. Er is geen mogelijkheid voor een in-place upgrade. De PKI van OpenVPN is niet compatibel: WireGuard gebruikt geen certificaten, geen CA en heeft geen vervaldatum, waardoor elke client een nieuw key pair ontvangt.
Migreer parallel — WireGuard op UDP 51820 kan naast OpenVPN op 1194 op dezelfde machine draaien. Installeer wg0, verplaats clients één voor één, en stop daarna de oude service. Het gebruikersnaam/wachtwoord- en revocation-model van OpenVPN wordt niet overgenomen; als u accounts of een audit trail nodig heeft, moet u dit boven WireGuard implementeren.
Backups, upgrades, and what strains at scale
/etc/wireguard is de server. Maak een backup (sudo tar czf wg-backup.tgz -C /etc wireguard, mode 600, buiten de machine bewaard) en u kunt binnen enkele minuten een nieuwe VPS opbouwen. Als u de private key van de server verliest, moet elke client-configuratie opnieuw worden uitgegeven, omdat clients de public key van de server gebruiken voor verificatie. Upgrades zijn een standaard apt upgrade plus een reboot voor kernel-updates, en wg-quick@wg0 start automatisch opnieuw op als u dit heeft ingeschakeld.
De status per peer is klein en de cryptografie draait in de kernel. De limiet wordt daarom bepaald door de CPU en de bandbreedte van uw VPS, in plaats van door instellingen in deze configuratie. Meet dit met iperf3 over de tunnel in plaats van te vertrouwen op gepubliceerde gegevens. De uitdaging bij schaalvergroting is het beheer. Elke peer heeft een uniek tunnel IP nodig. Handmatig zestig [Peer] blocks bewerken leidt tot fouten zoals dubbele AllowedIPs: genereer de configuraties met een script. Eén server is één UDP endpoint en één single point of failure. WireGuard ondersteunt geen clustering; redundantie vereist een tweede server met eigen keys. Key rotation blijft handmatig, dus houd bij wie welke key bezit en hoe u een key intrekt.
Dit alles vereist een Linux-machine waar u controle over heeft: een publiek IP, een kernel waarin u een module kunt laden, en een firewall waar u volledige controle over heeft.
FAQ
Waarom wordt de WireGuard handshake nooit voltooid?
wg show die een peer zonder latest handshake vermeldt, betekent dat pakketten niet aankomen of niet worden geaccepteerd. Controleer UDP 51820 in de firewall van de VPS en de aparte netwerkfirewall van uw provider. Bevestig de Endpoint host en poort. Controleer of de keys niet zijn verwisseld; het [Peer] blok van de client moet de public key van de server bevatten. sudo tcpdump -ni any udp port 51820 op de server laat zien of er überhaupt pakketten aankomen; dmesg rapporteert alleen WireGuard handshake-fouten nadat u dynamic debug (echo module wireguard +p | sudo tee /sys/kernel/debug/dynamic_debug/control) heeft ingeschakeld. Een mismatch in de keys verschijnt dan als een invalid-MAC drop.
De tunnel is verbonden maar ik heb geen internet. Wat ontbreekt er?
ping 10.8.0.1 die werkt terwijl ping 1.1.1.1 een timeout geeft, wijst op forwarding of NAT. Bevestig dat sysctl net.ipv4.ip_forward 1 leest en dat dit is ingesteld in /etc/sysctl.d/, en niet alleen met een sysctl -w die na een reboot verdwijnt. Controleer vervolgens of de masquerade-regel de juiste egress interface gebruikt uit ip route show default — enp1s0 of ens3, zelden eth0.
Heb ik de DNS = regel nodig in mijn client config?
Bij een full tunnel zonder DNS = regel behoudt de client de resolver van het lokale netwerk. Deze queries worden in cleartext over de lokale link verzonden, terwijl de rest via de tunnel gaat. Wijs DNS toe aan een publieke resolver, of draai unbound/dnsmasq gebonden aan 10.8.0.1 en open poort udp dport 53 iifname "wg0" in de input chain.
Wat controleert AllowedIPs precies?
Het heeft twee functies. Voor uitgaand verkeer is het een routing tabel: verkeer dat overeenkomt met de AllowedIPs van een peer wordt versleuteld en naar die peer verzonden. Voor inkomend verkeer is het een access-control list: een gedecodeerd pakket waarvan de bron buiten de AllowedIPs van die peer valt, wordt gedropt. Daarom vermeldt de serverzijde een /32 per client, terwijl de clientzijde mogelijk 0.0.0.0/0 vermeldt.
Werkt WireGuard op elke VPS?
Op een KVM VPS werkt het met de in-kernel module zonder extra instellingen. Bij container-virtualisatie die de host kernel deelt, zoals OpenVZ of LXC, faalt modprobe wireguard met Operation not supported. De fallback is de wireguard-go userspace implementatie. Voer sudo modprobe wireguard && echo ok uit voordat u iets anders doet.