Wat dit bouwt
Eén instantie die WireGuard draait, elke cliënt een privé IPv4-adres geeft, een gerouteerd IPv6-adres uit je eigen /48, en een resolver die in de tunnel leeft zodat DNS-query's nooit een andere route nemen dan de rest van het verkeer. De firewall is standaard-drop in beide richtingen. Doorsturen is alleen ingeschakeld voor de tunnelinterface, en alleen uitgaand.
Getest op een R-4 in AMS-01 met Debian 13. WireGuard is single-flow en kernel-side, dus meer cores leveren niets op totdat je meerdere gigabits per seconde duwt. Wat veel meer uitmaakt is de locatie: kies de locatie die het dichtst bij je eigenlijke positie ligt, want elke milliseconde die je hier toevoegt, voeg je toe aan elk pakket.
Voordat je begint
- Een geïmplementeerde instantie en root via SSH.
- De add-on IPv6 /48 ingeschakeld in het paneel. De bijgeleverde /64 werkt voor een enkele cliënt, maar per-cliënt-subnetten uit een enkele /64 betekent neighbour discovery proxven, en dat is een hobby in plaats van een configuratie.
- Een hostnaam die naar de instantie wijst. Hieronder wordt overal
vpn.example.comgebruikt. - Elk
2001:db8:-adres hier is documentatieruimte. Vervang het prefix door dat op je instantiepagina wordt getoond.
1. Pakketten en kernelinstellingen
apt update && apt full-upgrade -y
apt install -y wireguard-tools nftables unbound qrencode
ip -br linkDat laatste commando print de naam van je naar buiten gerichte interface. Op onze KVM-images is dat ens3; als de jouwe verschilt, vervang het dan hieronder overal. Nu de kernel:
cat > /etc/sysctl.d/99-wireguard.conf <<EOF
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.ens3.accept_ra = 2
net.ipv4.conf.all.rp_filter = 1
EOF
sysctl --systemDe accept_ra = 2-regel is degene die men vergeet. Het inschakelen van IPv6-doorsturen zorgt ervoor dat de kernel stopt met het accepteren van routeradvertenties, de standaardroute verdwijnt binnen tien minuten en de machine wordt donker via v6 terwijl hij nog via v4 antwoordt. Door het op twee te zetten, blijf je advertenties accepteren op een doorsturende host.
2. Sleutels
install -d -m 700 /etc/wireguard
umask 077
wg genkey | tee /etc/wireguard/server.key | wg pubkey > /etc/wireguard/server.pub
wg genkey | tee /etc/wireguard/laptop.key | wg pubkey > /etc/wireguard/laptop.pub
wg genpsk > /etc/wireguard/laptop.pskDe pre-shared key is niet optioneel in deze build. Het kost niets, het is één regel in elke config, en het is het verschil tussen een tunnel die vandaag slechts veilig is en een die veilig blijft tegen een aanvaller die nu verkeer opneemt om later te decoderen.
3. De serverinterface
Schrijf /etc/wireguard/wg0.conf en plak de sleutelinhoud waar gemarkeerd:
[Interface]
Address = 10.7.0.1/24, 2001:db8:1a2b:7::1/64
ListenPort = 51820
PrivateKey = <contents of /etc/wireguard/server.key>
MTU = 1420
[Peer]
# laptop
PublicKey = <contents of /etc/wireguard/laptop.pub>
PresharedKey = <contents of /etc/wireguard/laptop.psk>
AllowedIPs = 10.7.0.2/32, 2001:db8:1a2b:7::2/128Aan de serverkant is AllowedIPs een routingtabel, geen machtigingslijst. Geef elke peer precies de adressen die hij bezit en niets breder, anders vechten twee cliënten om dezelfde route en stopt de verliezer eenvoudigweg met het ontvangen van pakketten.
chmod 600 /etc/wireguard/wg0.conf4. Een resolver in de tunnel
Cliënten naar een publieke resolver verwijzen, maakt een groot deel van het doel ongedaan. Unbound is al geïnstalleerd; geef het /etc/unbound/unbound.conf.d/tunnel.conf:
server:
interface: 10.7.0.1
interface: 2001:db8:1a2b:7::1
access-control: 10.7.0.0/24 allow
access-control: 2001:db8:1a2b:7::/64 allow
do-ip6: yes
prefetch: yes
hide-identity: yes
hide-version: yes
qname-minimisation: yesUnbound zal niet starten voordat de tunnel bestaat, omdat die adressen nog niet actief zijn. Sequenceer het goed in plaats van ertegen te vechten:
systemctl edit unbound[Unit]
[email protected]
[email protected]5. De firewall
Vervang /etc/nftables.conf volledig:
flush ruleset
table inet filter {
chain input {
type filter hook input priority filter; policy drop;
ct state established,related accept
ct state invalid drop
iif lo accept
ip protocol icmp accept
ip6 nexthdr icmpv6 accept
tcp dport 22 accept
udp dport 51820 accept
iifname "wg0" udp dport 53 accept
iifname "wg0" tcp dport 53 accept
}
chain forward {
type filter hook forward priority filter; policy drop;
ct state established,related accept
iifname "wg0" oifname "ens3" accept
iifname "wg0" oifname "wg0" drop
}
chain output {
type filter hook output priority filter; policy accept;
}
}
table ip nat {
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
ip saddr 10.7.0.0/24 oifname "ens3" masquerade
}
}Let op wat ontbreekt: er is geen NAT-tabel voor IPv6. Cliënten gaan uit met hun eigen adres uit je /48, wat de hele reden is om de /48 in de eerste plaats te nemen. De iifname "wg0" oifname "wg0" drop-regel stopt peers die elkaar bereiken, wat je wilt tenzij je bewust een mesh bouwt.
systemctl enable --now nftables
nft list ruleset | head -206. Start het
systemctl enable --now wg-quick@wg0
systemctl restart unbound
wg show wg07. De cliënt
[Interface]
PrivateKey = <contents of /etc/wireguard/laptop.key>
Address = 10.7.0.2/24, 2001:db8:1a2b:7::2/64
DNS = 10.7.0.1
MTU = 1420
[Peer]
PublicKey = <contents of /etc/wireguard/server.pub>
PresharedKey = <contents of /etc/wireguard/laptop.psk>
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25Voor een telefoon, zet dat om in een QR-code op de server en fotografeer de terminal:
qrencode -t ansiutf8 < /root/laptop.confOp een Debian- of Ubuntu-cliënt heeft de DNS =-regel openresolv geïnstalleerd nodig, anders print wg-quick een waarschuwing en laat stilletjes je oude resolver op zijn plaats. Dat is de meest voorkomende oorzaak van een tunnel die perfect werkt en elke lookup lekt.
Verifieer het
Vier controles, in volgorde. Alles wat faalt, vertelt je naar welke stap je terug moet.
# on the server, after connecting the client
wg show wg0 latest-handshakes
wg show wg0 transferEen handshake-timestamp binnen de laatste twee minuten en niet-null tellers in beide richtingen betekenen dat zowel de cryptografie als de routing in orde zijn.
# on the client
ping -c3 10.7.0.1
ping -c3 2001:db8:1a2b:7::1
dig @10.7.0.1 paragonvps.com AAAA +shortHet derde commando bewijst dat de tunnelresolver antwoordt. Als het een time-out geeft, is unbound gestart voordat wg0 bestond; herstart het. De laatste controle is de enige die bewijst dat je verkeer vertrekt waar je denkt dat het vertrekt, en die heeft een tweede machine nodig. Elke andere instantie in de vloot volstaat, in elke stad:
# on the second instance
nc -lv 9101
# on the client, tunnel up
curl -m5 -4 http://second.example.com:9101/
curl -m5 -6 http://second.example.com:9101/De luisteraar print het bronadres van elke verbinding. Je v4-poging moet aankomen vanaf de WireGuard-server, omdat die gemaskeerd is. De v6-poging moet aankomen vanaf het eigen tunneladres van de cliënt binnen je /48, onveranderd, wat gerouteerd betekent en geproxied niet.
Wanneer het misgaat
| Symptoom | Oorzaak | Fix |
|---|---|---|
| Handshake slaagt, geen verkeer passeert | Doorsturen uit, of de forward-chain laat vallen | sysctl net.ipv4.ip_forward en lees dan de forward-chain opnieuw |
| Kleine verzoeken prima, grote downloads hangen | MTU en padontdekking | Zet beide configs op MTU = 1380 en probeer opnieuw |
| IPv6 sterft ongeveer tien minuten na opstarten | Doorsturen doodde routeradvertenties | accept_ra = 2 op de naar buiten gerichte interface |
| DNS lost buiten de tunnel op | Cliënt negeerde DNS = | Installeer openresolv op de cliënt |
| Alles weg na een herstart | Eenheden nooit ingeschakeld | systemctl enable wg-quick@wg0 nftables unbound |
Vanaf hier zijn de logische volgende stappen een tweede endpoint in een andere regio en een monitoring-stack die je vertelt wanneer een ervan stopt met antwoorden. Beide worden elders behandeld in de gidsen; de netwerkpagina legt uit wat de edge met je verkeer doet voordat het je bereikt.