De korte versie: WireGuard gebruikt geen TLS en heeft geen onderhandeling met meerdere heen-en-weer-berichten zoals OpenVPN of IPsec/IKEv2. Het gebruikt een vaste, opiniërende cryptografische handshake afgeleid van het Noise Protocol Framework — specifiek het Noise_IK-patroon — die in precies twee berichten wordt afgerond. Beide peers kennen elkaars langetermijn-openbare sleutels van tevoren (statisch geconfigureerd, net zoals SSH-sleutels worden geconfigureerd), dus de taak van de handshake is niet om identiteiten te ontdekken, maar om wederzijds het bezit van de bijbehorende privésleutels te bewijzen en verse symmetrische sessiesleutels met forward secrecy af te leiden. De hele transactie is klein genoeg om in twee UDP-datagrammen van een paar honderd bytes elk te passen. Het gaat sneller dan een TLS-handshake doorgaans doet, en de resulterende sessiesleutels wisselen elke twee minuten gedurende de verbinding.
Waarom een handshake überhaupt bestaat
Twee computers willen privé communiceren over een netwerk dat ze niet beheersen. Het fundamentele cryptografische probleem: voordat ze iets kunnen versleutelen, moeten ze overeenstemming bereiken over een gedeeld geheim dat een aanvaller die het netwerk afluistert niet kan afleiden. Ze moeten ook elkaars identiteit verifiëren — anders kan een aanvaller de andere kant nabootsen en een van de peers misleiden om gegevens naar de aanvaller te versleutelen in plaats van naar de bedoelde ontvanger.
Een handshake lost beide problemen op in een gestructureerde uitwisseling:
- Wederzijdse authenticatie — elke peer toont het bezit van een privésleutel die overeenkomt met een openbare sleutel die de andere partij al vertrouwt. Geen van de peers stuurt de privésleutel zelf ooit door; ze bewijzen alleen dat ze die bezitten door cryptografische bewerkingen uit te voeren die alleen die sleutel kan produceren.
- Forward-secret sleutelafspraak — beide peers genereren verse, tijdelijke ("efemere") sleutelparen voor deze specifieke sessie, wisselen de openbare helften uit en combineren ze met hun langetermijnsleutels om een symmetrische sessiesleutel af te leiden. De efemere sleutels worden na de handshake vernietigd; zelfs als de langetermijnsleutels later worden gestolen, kunnen de eerdere sessiesleutels er niet uit worden gereconstrueerd. Deze eigenschap heet forward secrecy en is de reden waarom eerder verkeer beschermd blijft, zelfs als er in de toekomst een sleutelcompromis plaatsvindt.
- Replay-bescherming instellen — beide peers initialiseren tellers en nonces die voorkomen dat een aanvaller eerder verkeer later kan opvangen en opnieuw kan afspelen.
Verschillende VPN-protocollen implementeren dit anders. OpenVPN doet het via TLS, met meerdere heen-en-weer-berichten, certificaatvalidatie en veel configureerbare cipher suites. IPsec/IKEv2 heeft zijn eigen onderhandelingsprotocol met vergelijkbare complexiteit. WireGuard doet het in twee pakketten, zonder configuratiemogelijkheden, zonder onderhandeling over cipher suites — elke WireGuard-handshake gebruikt dezelfde vaste set cryptografische primitieven. De afweging is opzettelijk: minder complexiteit betekent minder aanvalsoppervlak en eenvoudigere controleerbaarheid, ten koste van nul protocol-niveau flexibiliteit.
Het Noise-framework — wat het is en waarom WireGuard Noise_IK gebruikt
Het Noise Protocol Framework is een specificatie voor het bouwen van cryptografische handshakes. Het is het werk van Trevor Perrin, die ook het Signal Protocol ontwierp dat Signal, WhatsApp en de meeste moderne end-to-end versleutelde berichtenapps beveiligt. Noise is niet één protocol — het is een gereedschapskist van bouwstenen (handshake-"patronen", cryptografische primitieven, afleidingsregels) waarmee een protocolontwerper de exacte handshakevorm kan kiezen die hij nodig heeft en een precieze specificatie krijgt van wat berichten bevatten en welke garanties ze bieden.
Noise-handshakepatronen worden benoemd met twee letters die aangeven wat elke kant van tevoren weet:
- N — geen statische sleutel voor die kant; alleen efemere sleutels worden gebruikt. Anoniem.
- K — de statische sleutel is de andere partij van tevoren "bekend".
- X — de statische sleutel wordt tijdens de handshake verzonden.
- I — de statische sleutel wordt "onmiddellijk" verzonden in het eerste bericht.
Noise_IK betekent: de initiator stuurt hun statische sleutel Onmiddellijk (in het eerste bericht), en de statische sleutel van de responder is de initiator van tevoren Bekend. Dit patroon is ideaal voor het gebruik van WireGuard omdat beide peers elkaars statische sleutels echt van tevoren kennen — ze zijn geconfigureerd in het WireGuard-configuratiebestand. De "IK"-keuze maakt het mogelijk om de volledige handshake in twee berichten af te ronden, het minimaal mogelijke voor wederzijds geverifieerde, forward-secret sleuteluitwisseling.
De volledige specificatie van het Noise-framework is gepubliceerd op noiseprotocol.org en is een van de overzichtelijkere stukken openbare cryptografische engineering — geschreven om controleerbaar te zijn, met formele verificatie van de patronen zelf. WireGuards keuze voor Noise_IK was een bewuste ontwerpkeuze om de analyse van het framework te erven.
Pakket 1: Initiator → Responder
De handshake begint wanneer de initiator (jouw telefoon, jouw laptop, de clientkant) besluit te communiceren met de responder (de VPN-server). Dit gebeurt omdat er verkeer in de wachtrij staat voor de tunnel, of omdat de sessiesleutel is verlopen en een hersleuteling nodig is. De initiator construeert één UDP-pakket dat het volgende bevat:
- Afzenderindex — een willekeurig gekozen 32-bits integer die deze handshake-sessie identificeert. Wordt gebruikt om gelijktijdige handshakes tussen dezelfde peers te onderscheiden.
- Efemere openbare sleutel — een vers gegenereerde Curve25519-openbare sleutel. De bijbehorende privésleutel wordt in het geheugen bewaard door de initiator. Dit is de "E" in het Noise-patroon — de nieuwe efemere sleutel die wordt geïntroduceerd.
- Statische openbare sleutel (versleuteld) — de langetermijn-Curve25519-openbare sleutel van de initiator, maar versleuteld met een sleutel afgeleid van de efemere uitwisseling. Dit is onderdeel van de "I" in IK — de statische sleutel van de initiator wordt in het eerste bericht verzonden, maar is beschermd tegen passieve waarnemers.
- Tijdstempel (versleuteld) — een TAI64N-formaat tijdstempel, versleuteld. Dit is het replay-beschermingsanker: de responder weigert elke handshake met een tijdstempel eerder dan een al geaccepteerd tijdstempel van deze peer. Voorkomt dat een aanvaller een geldig handshake-bericht later opvangt en opnieuw afspeelt.
- MAC-velden — twee korte authenticatoren (mac1, mac2) die bewijzen dat de afzender de openbare sleutel van de responder kent. Het mac2-veld wordt ook gebruikt voor het cookie-reply DoS-mitigatiemechanisme dat in het WireGuard-whitepaper wordt beschreven.
Wat dit pakket bewijst en bereikt: door een verse efemere sleutel op te nemen, verbindt de initiator zich aan de helft van de uiteindelijke sessiesleutel. Door het tijdstempel en de MAC die aan de statische sleutel van de responder zijn gekoppeld op te nemen, toont de initiator aan: "Ik heb in ieder geval de openbare sleutel van de responder" — wat betekent dat een willekeurige buitenstaander niet zomaar nep-handshake-initiaties kan sturen en servermiddelen kan verspillen. Het hele pakket is 148 bytes, past comfortabel in één UDP-datagram en wordt nooit gefragmenteerd.
Een subtiliteit die de moeite waard is om op te merken: de statische openbare sleutel van de initiator is opgenomen maar versleuteld, zodat een passieve waarnemer op het netwerk niet kan identificeren welke client verbinding maakt. Ze kunnen zien dat iemand een WireGuard-handshake initieert naar deze server, maar niet wie. Dit is een privacyeigenschap die initiator identity hiding wordt genoemd, en het is sterker dan wat TLS standaard biedt.
Pakket 2: Responder → Initiator
De responder ontvangt het initiatiepakket, ontsleutelt de statische openbare sleutel van de initiator en zoekt die op in zijn peer-tabel. Als de peer bekend is en het tijdstempel aanvaardbaar is (nieuwer dan het laatste geaccepteerde), genereert de responder zijn eigen efemere sleutelpaar en construeert een antwoordpakket:
- Afzenderindex — de door de responder gekozen 32-bits identifier voor deze sessie.
- Ontvangersindex — teruggestuurd van de initiator, zodat beide kanten het eens zijn over welke sessie dit is.
- Efemere openbare sleutel — de vers gegenereerde efemere openbare sleutel van de responder.
- Leeg versleuteld payload — een geverifieerd maar leeg ciphertext dat bewijst dat de responder de sessiesleutel kan afleiden. Dit is het cryptografische signaal: "Ik heb jouw bericht gelezen en de juiste sleutel berekend".
- MAC-velden — hetzelfde patroon als in het initiatiepakket.
Wanneer de initiator dit antwoord ontvangt, voert hij de bijbehorende sleutelafleiding uit, verifieert dat het geverifieerde lege payload correct wordt ontsleuteld met de afgeleide sleutel, en nu hebben beide kanten onafhankelijk dezelfde symmetrische sessiesleutel bereikt — zonder dat die sleutel ooit het netwerk heeft overgestoken. De sessiesleutel heeft perfecte forward secrecy omdat deze afhankelijk is van beide efemere sleutels (die op het punt staan te worden vernietigd) en beide statische sleutels.
Het antwoordpakket is 92 bytes. De totale handshake — beide pakketten samen — is 240 bytes plus IP/UDP-headers, past in twee UDP-uitwisselingen die in ongeveer één netwerk-RTT worden afgerond (één pakket elke kant op), en produceert een volledig geverifieerde, forward-secret sessie die klaar is om applicatieverkeer te versleutelen. Er is geen certificaatketenvalidatie, geen cipher suite-onderhandeling, geen versievergelijking, geen extensielijst — geen van de dingen die TLS-handshakes gecompliceerd maken.
De sessie die volgt
Zodra de handshake is voltooid, wisselen de twee peers datapakketten uit in een veel eenvoudiger formaat. Elk datapakket bevat:
- Ontvangersindex — de 32-bits sessie-ID die door de ontvanger is toegewezen tijdens de handshake.
- Teller — een 64-bits nonce die met elk verzonden pakket toeneemt. Wordt zowel gebruikt als AEAD-nonce als voor replay-detectie.
- Versleuteld payload — het originele IP-pakket, versleuteld met ChaCha20-Poly1305 met de sessiesleutel en de teller als nonce.
ChaCha20-Poly1305 is een AEAD-constructie (Authenticated Encryption with Associated Data): het versleutelt zowel het payload als produceert een authenticatietag die elke manipulatie detecteert. Als één bit van de ciphertext wordt omgedraaid, mislukt de ontsleuteling en gooit de ontvanger het pakket weg. Er is geen "zachte" faalstand — gemanipuleerde pakketten worden stilzwijgend verwijderd, net als pakketten met de verkeerde teller of verkeerde ontvangersindex.
De ontvanger behoudt een schuivend venster van geaccepteerde tellerwaarden. Pakketten met tellers die binnen het venster vallen en nog niet eerder zijn gezien, worden geaccepteerd; pakketten die onder het venster vallen (te oud) of al zijn gezien, worden geweigerd. Dit biedt anti-replay-bescherming zonder dat de ontvanger elke ooit geziene teller hoeft te onthouden — alleen de meest recente, in een kleine bitmap.
Vanuit het perspectief van het netwerk zien de datapakketten er identiek uit, ongeacht de inhoud van het payload. Het zijn allemaal UDP-pakketten naar hetzelfde server-IP en -poort, met vergelijkbare groottes (het versleutelde payload bewaart de grootte van het onderliggende IP-pakket plus 32 bytes overhead), en geen waarneembaar patroon dat ze onderscheidt. Er is geen SNI, geen certificaatuitwisseling, geen TLS-handshake-dan-data-structuur — alleen ondoorzichtige UDP na de initiële twee-pakket-handshake.
Hersleutelgedrag — elke 2 minuten OF elke 2^60 pakketten
WireGuard roteert sessiesleutels agressief. Het standaard hersleutelbeleid: een nieuwe handshake wordt gestart wanneer de huidige sessie 2 minuten actief is geweest of 2^60 pakketten heeft verzonden, wat eerder optreedt. In de praktijk is de tijdsgrens wat hersleuteling triggert voor de meeste sessies — 2^60 pakketten is een astronomisch groot getal dat geen echte verbinding ooit bereikt.
Waarom 2 minuten? Twee redenen. Ten eerste verbetert frequente hersleuteling de forward secrecy. Elke sessie is versleuteld met een sleutel afgeleid van één specifiek paar efemere sleutels. Hoe korter de sessie, hoe minder gegevens er ooit door één sleutel stromen, zodat zelfs theoretische toekomstige cryptanalytische aanvallen veel sleutels zouden moeten compromitteren om een betekenisvolle hoeveelheid verkeer te lezen. Ten tweede is de hersleuteling onzichtbaar voor de applicatie — de nieuwe handshake vindt plaats op de achtergrond terwijl de oude sessiesleutels nog steeds gegevens versleutelen, en de overstap is naadloos. Beide peers behouden een klein overlapvenster waarin ze pakketten versleuteld met zowel de oude als de nieuwe sleutel accepteren.
De hersleuteling wordt gestart door de peer die als eerste merkt dat de timer afloopt — doorgaans de initiator. Het protocolbericht is dezelfde twee-pakket-handshake die hierboven is beschreven. Vanuit het perspectief van een externe waarnemer zien ze elke twee minuten een kleine golf van extra UDP-pakketten, maar geen waarneembare verandering in de gegevensstroom zelf.
Handshakefases in één oogopslag
De volledige handshake, uitgesplitst per fase, pakket en de cryptografische primitief die het werk doet:
| Fase | Pakket | Wat wordt verzonden | Cryptografische primitief |
|---|---|---|---|
| 1. Initiatie | Initiator → Responder (148 bytes) | Afzenderindex, efemere openbare sleutel, versleutelde statische sleutel, versleuteld tijdstempel, MACs | Curve25519 (ECDH), BLAKE2s (hash/MAC), ChaCha20-Poly1305 (AEAD), HKDF (sleutelafleiding) |
| 2. Antwoord | Responder → Initiator (92 bytes) | Afzenderindex, ontvangersindex, efemere openbare sleutel, leeg versleuteld payload (sleutelbevestiging), MACs | Curve25519 (ECDH), BLAKE2s, ChaCha20-Poly1305, HKDF |
| 3. Datasessie | Beide richtingen, onbeperkt (32 bytes overhead per pakket) | Ontvangersindex, teller, versleuteld IP-pakket | ChaCha20-Poly1305 (AEAD) |
| 4. Hersleuteling (elke 2 min) | Dezelfde twee-pakket-uitwisseling als fases 1+2 | Verse efemere sleutels, nieuwe sessiesleutelafleiding | Dezelfde primitieven |
Er worden vijf cryptografische primitieven gebruikt, geen enkele onderhandelbaar: Curve25519 voor elliptische-curve Diffie-Hellman-sleutelafspraak, ChaCha20 voor symmetrische stroomversleuteling, Poly1305 voor de authenticatietag, BLAKE2s voor de hashfunctie en MAC, en HKDF voor sleutelafleiding. Dit is de "geen flexibiliteit"-ontwerpkeuze: door de primitieven vast te leggen, krimpt het protocoloppervlak dramatisch en wordt de analyse veel beter beheersbaar. De kosten zijn dat als een primitief ooit wordt gebroken, het volledige protocol een nieuwe versie nodig heeft — er is geen inband manier om te upgraden. De weddenschap die WireGuard maakt is dat deze primitieven voldoende bestudeerd zijn dat een plotselinge doorbraak onwaarschijnlijk is.
Wat er mis kan gaan
Cryptografische handshakes hebben bekende faalpatronen. Sommige zijn van toepassing op WireGuard; andere niet. De moeite waard om te begrijpen:
Replay-aanvallen
Het versleutelde tijdstempel in het initiatiepakket voorkomt replays. Als een aanvaller een geldig initiatiepakket opvangt en later opnieuw probeert te versturen, ziet de responder een tijdstempel dat al is geaccepteerd (of een tijdstempel dat ouder is dan het meest recent geaccepteerde) en weigert het pakket. Dit is een van de redenen waarom WireGuard per-peer-status bijhoudt over het meest recente handshake-tijdstempel — het protocol is ervan afhankelijk.
Compromittering van langetermijnsleutels
Als een aanvaller de langetermijn-privésleutel van een peer steelt, kan hij die peer nabootsen in toekomstige handshakes. Hij kan echter eerdere sessies niet ontsleutelen — de efemere sleutels die die sessiesleutels hebben afgeleid, werden na elke handshake vernietigd. Dit is de forward-secrecy-garantie. De mitigatie voor doorlopend risico is het roteren van de langetermijnsleutel (een nieuw paar genereren, de nieuwe openbare sleutel distribueren naar peers) — er is geen protocol-mechanisme om een oude sleutel ongeldig te maken, dus dit moet buiten het protocol om worden gedaan.
NAT-timeout en stille verbindingsdood
WireGuard draait over UDP, wat verbindingsloos is. Netwerkadresvertalers (in je thuisrouter of het netwerk van je ISP) verwijderen UDP-stroomvermeldingen soms na een paar minuten inactiviteit. Wanneer dit gebeurt, kunnen de antwoordpakketten van de responder de initiator niet meer bereiken — de NAT is de mapping vergeten. De mitigatie is de keepalive-instelling (vaak ingesteld op 25 seconden), die een klein heartbeat-pakket van de initiator naar de responder stuurt om de NAT-mapping in stand te houden. Zonder keepalive kunnen inactieve verbindingen stilzwijgend sterven en is een nieuwe handshake nodig om te herstellen.
Denial-of-service via handshake-flood
Een responder onder zware aanval kan veel nep-handshake-initiaties ontvangen, elk waarvan Curve25519-bewerkingen vereist om te verwerken. WireGuard mitigeert dit met het cookie-reply-mechanisme: wanneer de responder onder belasting staat, kan hij eisen dat de initiator een kleine proof-of-work-achtige berekening uitvoert voordat de responder zich verbindt aan een volledige handshake. Het mac2-veld in de handshake-pakketten draagt dit mechanisme. De DoS-weerstand is niet perfect — geen enkel protocol kan dat zijn — maar het is aanzienlijk moeilijker te overstromen dan bijvoorbeeld een niet-geverifieerde TCP-gebaseerde dienst.
Waarom dit er voor VPN-gebruikers praktisch toe doet
De handshake-architectuur heeft concrete voor gebruikers zichtbare voordelen ten opzichte van oudere VPN-protocollen:
- Geen TLS-handshake aan de clientkant — WireGuard valideert geen certificaten, koppelt niet aan een CA, en is niet afhankelijk van het systeemvertrouwensarchief. Dit elimineert een hele klasse aanvallen (gecompromitteerde CA's, fout uitgegeven certificaten) die TLS-gebaseerde VPN's treffen.
- Geen stateful verbinding — het protocol draait over UDP en is verbindingsloos. Er is geen TCP-stijl toestandsmachine die breekt wanneer het netwerk verandert. Een roamend apparaat dat overschakelt van Wi-Fi naar mobiel netwerk hoeft niets opnieuw op te zetten; het begint gewoon pakketten te sturen vanaf het nieuwe IP-adres en de responder accepteert ze.
- Directe roaming — omdat de verbinding wordt geïdentificeerd door de cryptografische sleutels in plaats van het bron-IP-adres, accepteert de responder pakketten van elk bron-IP dat de juiste cryptografische authenticatie produceert. Dit is waarom WireGuard netwerkovergangen op mobiele apparaten veel beter afhandelt dan OpenVPN of IPsec, die vaak opnieuw moeten onderhandelen wanneer het onderliggende IP verandert.
- Klein aanvalsoppervlak — de referentie-implementatie bestaat uit ongeveer 4.000 regels code. OpenSSL heeft meer dan 500.000 regels. Dit is geen eerlijke vergelijking (ze doen verschillende hoeveelheden werk), maar de implicatie is reëel: kleinere code is gemakkelijker te controleren, gemakkelijker formeel te analyseren, en biedt minder kansen voor implementatiefouten die uitgroeien tot kwetsbaarheden.
- Voorspelbare prestaties — elke handshake gebruikt dezelfde primitieven met dezelfde sleutelgroottes. Er is geen snelpad/langzaam-pad-divergentie op basis van onderhandelde cipher suite. De handshake duurt op dezelfde hardware ongeveer evenveel tijd, ongeacht met wie je verbinding maakt.
Voor de afweging met het oudere protocol dat het voor de meeste gebruikers heeft vervangen, zie onze bespreking van WireGuard vs OpenVPN, die de praktische prestatie- en beveiligingsverschillen behandelt. Voor de reden waarom de tunnelingkeuzes van een VPN uitmaken voor wat apps zien, zie wat is split tunneling.
Casper's Cloak gebruikt WireGuard voor alle clientverbindingen, draait de officiële kernel-modus-implementatie op Linux-eindpunten, en levert de standaard userspace-client (gebouwd op de wireguard-go-referentie) op iOS, Android en macOS. De hierboven beschreven handshake is precies wat er gebeurt wanneer je de app aanzet. Hetzelfde Noise_IK-patroon, dezelfde Curve25519/ChaCha20-Poly1305/BLAKE2s/HKDF-primitivenset, dezelfde hersleuteling van 2 minuten, dezelfde handshake van 240 bytes. De bedreigingsbeschermingsfunctie legt DNS-level filtering bovenop de WireGuard-tunnel — de tunnel verzorgt het transport, het filter verzorgt het bestemmingsbeleid.
Voor de volledige protocolspecificatie is het originele WireGuard-whitepaper van Jason Donenfeld de gezaghebbende referentie: wireguard.com/papers/wireguard.pdf. Het paper behandelt de cryptografische constructie, het bedreigingsmodel, de formele analyse en de implementatierationale. Het is een van de beter leesbare stukken moderne protocolomtwerpsliteratuur — de moeite waard om in een uur door te bladeren als je de ontwerpafwegingen bij de bron wilt begrijpen.
Conclusie: de WireGuard-handshake bestaat uit twee pakketten, duurt in de praktijk minder dan 100 milliseconden, verifieert beide peers wederzijds, leidt forward-secret sessiesleutels af en weerstaat elk gangbaar aanvalspatroon (replay, downgrade, identiteitsopenbaarmaking, DoS) by design. Het is een strak, vast, opiniërend protocol, en die opinionering is precies het punt.