IPsec was een goed idee. Leg de versleuteling op de netwerklaag, onder alles, en elk protocol dat over IP loopt erft vertrouwelijkheid en integriteit zonder dat het iets hoeft te weten. Geen bibliotheek om te linken. Geen certificaat per applicatie. Niets herschrijven aan wat je al hebt uitgeleverd. Het pakket vertrekt beschermd en komt beschermd aan, en de routers ertussen vervoeren het zonder te weten of te willen weten wat erin zit.

Dat ontwerp rust op één aanname, en die staat in de standaard in plaats van dat hij wordt geïmpliceerd: het adres van een pakket identificeert de machine waar het vandaan kwam. Een security association wordt opgezocht op het bestemmingsadres, het protocolnummer en de SPI1. De Authentication Header gaat verder en ondertekent de IP-header zelf, bron en bestemming inbegrepen2. Voor IPsec is het adres geen routeringsmetadata. Het is onderdeel van de identiteit en onderdeel van de integriteitscontrole.

Daarna heeft deze branche dertig jaar besteed aan het wegnemen van het adres.

Eerst NAT, om een kantoor achter één lijn te laten passen. Toen carrier-grade NAT, om enkele honderden huizen achter één adres te laten passen, omdat IPv6 aanzetten werk was en een doos kopen inkoop — wat het hele onderwerp is van We Zijn Nooit Zonder Adressen Geraakt. We Zijn Zonder Moeite Geraakt. en dat doe ik hier niet nog eens over. Wat voor deze post telt, is het gevolg. Precies het ene ding waarop IPsec gebouwd is, levert het moderne toegangsnetwerk niet meer.

Dus werd IPsec opgelapt. Verpak het versleutelde pakket in UDP zodat een vertaler een poort heeft om te herschrijven. Zet de checksum op nul zodat niemand hem opnieuw controleert. Stuur elke twintig seconden een pakket van één byte, voor altijd, zodat een tabel in andermans apparatuur niet vergeet dat je bestaat. Haal de identiteit van het adres af en hang hem aan een naam. Geef de Authentication Header op, want die kan een herschreven header per constructie niet overleven. En als een hotel UDP blokkeert, verpak het geheel er ook nog eens in TCP bij3.

Elk daarvan is een echte, gestandaardiseerde, door leveranciers ondersteunde oplossing. Samen zijn ze een protocol dat overeind wordt gehouden door zijn eigen steigers. En die steigers zijn het argument: je stut niet een kwart eeuw lang iets omdat het in de kern gezond is.

De conclusie waar ik op uitgekomen ben, is dat IPsec volledig uitgefaseerd hoort te worden. Niet bijgeschaafd, niet opnieuw voorgesteld met betere cijfers, niet bewaard voor site-to-site omdat dat stuk nog werkt. Uitgefaseerd, met datums, zoals PPTP tien jaar eerder had moeten gebeuren dan het moment waarop iemand er eindelijk aan toekwam. Wat volgt is het bewijs, de diagrammen, de leveranciersdocumentatie die dit alles in hun eigen woorden zegt, en — omdat de meesten die dit lezen die dingen maandag toch draaiend moeten houden — een werkbare methode om IPsec-storingen intussen te diagnosticeren.

Wat het je werkelijk kost, in tickets

Vóór de standaarden hier de rekening, in de volgorde waarin je hem tegenkomt.

De tunnel valt op de klok uit. Elk uur, of elke acht uur, of na twintig minuten zonder verkeer. Hij komt terug zodra iemand een bestand opent, dus de helft van de gebruikers meldt het nooit en de andere helft meldt het als “het VPN is traag”. Niemand heeft iets veranderd.

Twee mensen in hetzelfde huis kunnen niet allebei verbinden. De tweede komt op, de eerste valt eruit. Ze bellen apart naar de servicedesk, dus de tickets komen elkaar nooit tegen en veertien dagen lang ziet niemand het patroon.

Kleine dingen werken en grote dingen blijven hangen. Inloggen werkt. Teams werkt. Ping werkt. Een bestand kopiëren stokt elke keer op dezelfde plek, en een grote pagina in een interne applicatie blijft staan tot hij verloopt.

De tunnel staat en er gaat geen verkeer doorheen. Beide kanten zeggen “established”. Beide kanten zijn tevreden over zichzelf. Er beweegt niets.

Van buiten komt er niets binnen. Site-to-site naar het filiaal dat naar een glasvezel-altnet is overgestapt komt niet meer tot stand in de richting waarin dat vroeger ging, en niemand kan zeggen waarom, alleen dat “hun IP is veranderd”.

QoS aanzetten heeft de versleuteling gesloopt. Iemand heeft spraak geprioriteerd, en nu gooit de andere kant pakketten weg als replays.

Geen van deze gevallen is een configuratiefout in de gewone zin. Elk ervan is IPsec dat het netwerk tegenkomt zoals het nu is. De rest van deze post is het waarom, op volgorde, en hoe je aantoont welk geval jij hebt.

IPsec wordt niet door het netwerk gedragen. Het ís het netwerk.

Begin bij wat het was, want het ontwerp is werkelijk goed en de storingen krijgen alleen daartegen betekenis.

ESP is geen protocol dat over TCP of UDP loopt. Het is een transportprotocol, IP-protocolnummer 50, direct op IP, in precies dezelfde plek waar TCP en UDP zitten. AH is protocol 51. Geen van beide heeft een poortveld, want geen van beide heeft er een nodig: op het internet waarvoor IPsec ontworpen is, benoemt het bestemmingsadres al precies één machine, en de SPI in de ESP-header benoemt welke security association op die machine. Adres plus protocol plus SPI. Dat drietal is de opzoeking1.

Het ontwerp zoals gespecificeerd: het adres benoemt de machine, dus zijn er geen poorten nodig en kan elke kant beginnenIPsec zoals gespecificeerd: het adres is de identiteitHost A203.0.113.10Routerssturen alleen doorHost B198.51.100.7elke kantkan beginnenWat de machine verlaatbuitenste IP-headersrc 203.0.113.10 naar 198.51.100.7protocol50 = ESPSPI4 Bvolgnummer4 Bversleutelde payloadjouw pakket, onderweg onleesbaarICV16 BOpzoeking van de association = bestemmingsadres + protocol + SPI. Nergens een poortveld, want er is er geen nodig.Drie aannames van dit ontwerp, in 1995 alle drie waar:Het adres op het pakket is de machine. Niets in het pad herschrijft een header. Elke kant is te bellen.De Authentication Header gaat verder en ondertekent de buitenste header zelf, bron en bestemming inbegrepen,zodat een ontvanger kan bewijzen dat de adressen onderweg niet zijn aangeraakt.Niet op schaal. De ESP-overhead hangt af van het cijfer; hier AES-GCM in tunnelmodus over IPv4.
Het ontwerp zoals het gespecificeerd is. ESP zit als protocol 50 direct op IP, zonder poorten, omdat het ze niet nodig heeft — het bestemmingsadres benoemt de host en de SPI benoemt de association daarop. AH ondertekent de IP-header zelf. Beide kanten houden een echt, bereikbaar adres, elk van beide kan het gesprek beginnen, en niets in het midden hoeft de payload te begrijpen.

Kijk wat dat oplevert. Geen handshake-poort om bloot te stellen, geen sessielaag om fout te doen, geen applicatie die mee moet doen. Elk van beide kanten kan beginnen. Het midden van het netwerk is dom, en dat is precies wat het midden van een netwerk moet zijn. Een router stuurt protocol 50 door zoals hij protocol 6 doorstuurt, en dat hij de payload niet kan lezen is het doel en geen beperking.

Een schoon ontwerp. En tegelijk, in 2026, de beschrijving van een internet dat de meesten die dit lezen niet kunnen kopen.

Toen zette iemand in elk pad een vertaler

Een NAT herschrijft het bronadres, en vaak de bronpoort, zodat meerdere machines één adres delen. Meer doet het niet. Tegen IPsec is dat bijna een volledige sloop, en de IETF was eerlijk genoeg om er een heel document over te publiceren dat de stukken opsomt: RFC 3715, IPsec-Network Address Translation (NAT) Compatibility Requirements4. Zestien aparte onverenigbaarheden. Dit zijn de belangrijke.

AH is klaar, per constructie. In de eigen woorden van RFC 3715: “Since the AH header incorporates the IP source and destination addresses in the keyed message integrity check, NAT or reverse NAT devices making changes to address fields will invalidate the message integrity check.”4 — de AH-header neemt bron- en bestemmingsadres op in de integriteitscontrole, dus elke adreswijziging maakt die ongeldig. Daar is geen oplossing voor, en die zou er ook nooit komen. Een protocol dat de header ondertekent komt niet door een doos wiens hele taak het herschrijven van de header is. AH is niet omzeild. Het is opgegeven.

Er zijn geen poorten om te vertalen. Een NAT die poortvertaling doet heeft een poort nodig. ESP heeft er geen. Cisco schrijft het onomwonden in de Catalyst-configuratiehandleiding: “If PAT found a legislative IP address and port, it would drop the Encapsulating Security Payload (ESP) packet.”5 Het pakket wordt niet op beleid afgewezen. Het wordt weggegooid omdat de doos nergens heeft om te schrijven wat hij moet schrijven.

De identiteit past niet meer bij het pakket. Opnieuw uit RFC 3715: “Where IP addresses are used as identifiers in Internet Key Exchange Protocol (IKE) Phase 1 or Phase 2, modification of the IP source or destination addresses by NATs or reverse NATs will result in a mismatch between the identifiers and the addresses in the IP header.”4 — worden adressen als identificatie gebruikt, dan klopt na de vertaling de identificatie niet meer met de header. Een identiteitsschema dat machines bij adres benoemt overleeft geen apparaat dat machines beroepshalve hernoemt.

Twee machines kunnen dezelfde SPI kiezen. De SPI wordt door de ontvanger gekozen en hoeft alleen bij hem uniek te zijn. Zet twee hosts achter één adres en de vertaler heeft twee associations zonder iets om ze uit elkaar te houden.

Van buiten kan niets beginnen. Een NAT bouwt zijn tabel op uit uitgaande pakketten. Er is geen uitgaand pakket tot iemand begint, en op een NAT-lijn kan alleen de binnenkant beginnen. De halve symmetrie van het protocol is weg.

Eén vertaler in het pad breekt vijf dingen tegelijk, en elke oplossing kost ietsEén vertaler in het pad, en vijf dingen breken tegelijkHost192.0.2.20Vertalerherschrijft bron naar 203.0.113.5Gateway198.51.100.7van deze kant kan niets beginnenWat het herschrijven vernietigt1De ondertekende header klopt niet meer.AH dekt bron- en bestemmingsadres, dus deintegriteitscontrole faalt per constructie. Er is geen oplossing. AH is via een vertaler simpelweg onbruikbaar.2Er is geen poort om te herschrijven.ESP is IP-protocol 50 en heeft geen poortveld, dus eenvertaler die poortvertaling doet heeft niets om mee te werken en gooit het pakket weg.3De identiteit past niet meer bij het pakket.De sleuteluitwisseling benoemde de peer bij adres.Het adres in de header is nu van iemand anders.4Twee hosts kunnen dezelfde SPI kiezen.De ontvanger kiest hem en garandeert alleen dat hijbij hemzelf uniek is, dus heeft de vertaler twee associations die hij niet kan onderscheiden.5De halve symmetrie is weg.De tabel wordt uit uitgaande pakketten opgebouwd, dus alleen de binnenkant kan beginnen.Het compromis, en wat elk onderdeel ervan kostVerpak het hele ESP-pakket in UDP op poort 4500, zodat de vertaler iets begrijpt.Geef de Authentication Header volledig op, want niets kan hem redden.Zet de UDP-checksum op nul, want over herschreven adressen zou hij alleen falen.Haal de identiteit van het adres af en hang hem aan een naam die de peer claimt.Stuur elke twintig seconden één byte, voor altijd, zodat andermans apparatuur je niet vergeet.Het werkt. Dat wordt niet betwist. Het argument is dat niets gezonds vijf concessies nodig heeft voor één doos.
Dezelfde tunnel met één vertaler in het pad. Vijf dingen breken tegelijk: de ondertekende header klopt niet meer, er is geen poort voor de vertaler om te herschrijven, de identiteit klopt niet meer met het bronadres, twee hosts kunnen dezelfde SPI kiezen, en van buiten kan niemand een gesprek beginnen. De rij eronder is wat de branche eraan gedaan heeft — en elke oplossing is iets dat is opgegeven.

De oplossing was echt, en elk onderdeel ervan heeft iets gekost

NAT-traversal werkt. Dat wordt niet betwist en ik doe ook niet alsof. Ik heb genoeg tunnels door genoeg NAT’s gedraaid. Wat ik vastgelegd wil hebben is de rekening, want die wordt elke dag door iedereen betaald en bijna niemand specificeert hem.

Het mechanisme is RFC 3948: detecteer tijdens de sleuteluitwisseling een vertaler, en stop dan het hele ESP-pakket in een UDP-datagram op poort 4500 zodat de vertaler iets heeft dat hij begrijpt6. Cisco’s beschrijving van het wire-formaat is precies: na versleuteling worden “a UDP header and a non-IKE marker (which is 8 bytes in length) are inserted between the original IP header and ESP header”5 — een UDP-header en een acht byte lange niet-IKE-markering tussen de oorspronkelijke IP-header en de ESP-header gezet. Die van Juniper is korter en zegt hetzelfde: “NAT-T encapsulates both IKE and ESP traffic within UDP with port 4500 used as both the source and destination port.”7

Nu de gespecificeerde rekening.

De Authentication Header is weg. Niet beleefd afgeschaft. Onbruikbaar. RFC 8221 zegt inmiddels helder dat ESP samen met AH NOT RECOMMENDED is8, en de eerlijke reden is dat het ene dat AH deed en ESP niet doet, precies het ene is dat NAT vernietigt.

De UDP-checksum wordt opzettelijk op nul gezet. RFC 3948 eist het: met herschreven adressen zou een daarover berekende checksum falen, dus het antwoord van de standaard is hem niet meer te berekenen. “If the protocol header after the ESP header is a UDP header, set the checksum field to zero in the UDP header.”6 Een laag foutdetectie weggehaald zodat een laag adresherschrijving blijft werken.

Je stuurt nu pakketten om een tabel warm te houden. RFC 3948 definieert een keepalive als één byte, 0xFF, verstuurd als er verder niets is uitgegaan gedurende een instelbaar interval met standaard twintig seconden6. Juniper noemt de reden zonder opsmuk: “Because NAT devices age out stale UDP translations, keepalive messages are required between the peers.”7 Een laptop in de trein die helemaal niets doet, zendt dus elke twintig seconden, voor altijd, omdat een tabel in een doos die van geen van beide kanten is anders vergeet dat hij bestaat. Vermenigvuldig dat met een vloot. Dat is de radio die wakker wordt, de accu die leegloopt, en het mobiele netwerk dat verkeer draagt waarvan het enige doel is vergeten te voorkomen.

Je firewallt nu twee poorten in plaats van één protocol, en Cisco’s eigen beperkingenlijst eist statische vertaalregels voor zowel 500 als 4500 voordat er ook maar iets van werkt5.

En lees de rest van die beperkingenlijst, want daar vertelt de leverancier je de vorm van het ding. Dynamisch NAT-beleid: niet ondersteund. IPv6-verkeer: onverenigbaar met de functie. IPsec en NAT op hetzelfde apparaat: die kunnen niet allebei werken5. Dat is geen configuratiehandleiding. Dat is een lijst van plekken waar de steigers niet komen.

Elegant is er niets aan, en het is ook niemands schuld in het bijzonder. Het is wat er gebeurt als je een laag-3-protocol in leven houdt op een netwerk dat is opgehouden laag 3 te eerbiedigen.

Carrier-grade NAT nam weg wat er over was

Gewoon NAT nam het adres van de machine af en gaf het aan de locatie. De vertaler was nog van jou, dus je kon een poort doorsturen, een mapping vastzetten, een timer verlengen of de concentrator ervoor zetten.

Carrier-grade NAT neemt het adres van de locatie af en geeft het aan enkele honderden vreemden, en de vertaler is van je provider. Alles wat je er vroeger aan kon doen, kan nu niet meer.

En wees duidelijk over wat er werkelijk in het pad staat, want dit is het stuk dat mensen fout hebben. De router in huis doet nog steeds NAT. Die is niet uitgezet. Hij vertaalt je laptop op 192.168.1.20 nog altijd naar het adres dat de lijn houdt — alleen houdt de lijn nu 100.64.12.7, gedeelde ruimte, geen publiek adres. De carrier vertaalt dat vervolgens nog een keer. Het pakket passeert dus twee vertalers voor het het internet bereikt, en dat is het gewone geval, niet iets bijzonders.

Carrier-grade NAT betekent twee vertalingen, twee timers, en bij geen van beide een bereikbaar adresCarrier-grade NAT zijn twee vertalingen, niet éénLaptop192.168.1.20Router in huisvertaling éénDe lijn100.64.12.7Carrier-vertalervertaling twee, naar 203.0.113.9de jouwe, en de enige tabel die je zietdie van hen, gedeeld met enkele honderden huizen, voor jou onzichtbaarniets van internet bereikt een van beide adressenTwee tabellen, twee timers, en de kortste wint.Je keepalive moet die verslaan die van detwee het eerst verloopt, en je kunt er maar één lezen. Die ertoe doet is die je niet kunt zien.Poortdoorsturing werkt en levert niets op.De router stuurt vrolijk een poort door vanaf eenadres dat internet niet bereikt. UPnP en PCP melden succes en openen een deur naar een gang. Daaromis “ik heb 500 en 4500 doorgestuurd en hij komt nog steeds niet op” zo'n veelvoorkomend en misleidend ticket.De responderrol is weg.Twee filialen op consumentenglasvezel kunnen elkaar helemaal niet bellen.Iets in het midden moet ze voorstellen, en nu hang je aan een bedrijf dat je nooit koos.Identiteit kan niet het adres zijn.Meerdere abonnees komen aan als één adres, dusis wat ze onderscheidt niet het veld dat IPsec zou gebruiken. En er is een gepubliceerd plafond:op de grotere SRX-platformen noemt Juniper hoogstens 1.000 tunnels per vertaald adres.De snelste bevestiging kost niets: lees het WAN-adres in de router. Begint het met 100.64, dan is dat degedeelde ruimte uit RFC 6598, zit je achter CGNAT, en is de halve instellingenpagina decoratie.Een zakelijke lijn met een echt vast adres heeft één vertaling en een bereikbaar eindpunt. Dat is wat demaandelijkse meerprijs je echt verkoopt: wat elke machine vroeger voor niets had.
Het pakket wordt twee keer vertaald: één keer door de router in huis, één keer door de carrier. Geen van beide adressen die het houdt is van buiten bereikbaar. Dat betekent twee mappingtabellen met twee onafhankelijke timers waarvan er maar één voor jou zichtbaar is, poortdoorsturing die slaagt en niets oplevert, helemaal geen responderrol meer, en een peeridentiteit die geen adres meer kan zijn.

Je zit achter dubbel NAT, en maar één van de tabellen is van jou. Twee vertalingen betekent twee mappingtabellen, twee verouderingstimers en twee kansen dat de mapping verdwijnt. Je keepalive moet die verslaan die het eerst verloopt, en je kunt er precies één lezen. Erger nog, de twee grijpen in elkaar: de router in huis heeft mogelijk eigen ideeën over IPsec en probeert te helpen met een application gateway, zodat de bronpoort die je client denkt te gebruiken niet die is die het huis verlaat, en ook niet die is die de carrier verlaat.

Poortdoorsturing werkt nog steeds, en levert helemaal niets op. Dit is het ticket dat de meeste tijd opeet. Iemand stuurt UDP 500 en 4500 door op de thuisrouter, de router accepteert het, de instellingenpagina zegt dat de regel actief is — en niets kan hem gebruiken, want hij stuurt door vanaf een adres dat het internet niet kan bereiken. UPnP en PCP gedragen zich net zo: de client vraagt om een mapping, de router verleent die, en de poort opent op een gang. Alles meldt succes en niets werkt. De doos vertelt je wat je horen wilt.

De snelste manier om het te beslechten kost niets. Lees het WAN-adres in de router. Begint dat met 100.64, dan is dat de gedeelde ruimte die in RFC 6598 is gereserveerd, zit je achter carrier-grade NAT, en is de halve instellingenpagina decoratie.

De responderrol bestaat niet meer. Een apparaat achter CGNAT kan niet de kant zijn die iemand belt. Site-to-site tussen twee filialen op consumentenglasvezel — normaal, goedkoop, en precies wat een klein bedrijf wil — vereist dat minstens één kant een echt adres houdt, of een derde partij in het midden die ze aan elkaar voorstelt. Die derde partij is een bedrijf waarvan je nu afhankelijk bent omdat je provider je geen adres wilde geven.

De timer is van iemand anders. RFC 4787 zegt NAT-beheerders dat een UDP-mapping “MUST NOT expire in less than two minutes”, en beveelt vijf of meer aan9. Dat is de ondergrens en het advies, geen belofte, en wat jouw carrier werkelijk doet kun je niet nakijken. Als zodanig houdt de keepalive op een afstelknop te zijn. Hij is dragend, op een timer die je raadt.

De identiteit van je peer kan niet zijn adres zijn. Meerdere abonnees bereiken de andere kant als één adres. Wat de concentrator ook gebruikt om ze uit elkaar te houden, het is niet de IP-header — en juist die zou IPsec gebruiken.

Er is een harde bovengrens, en de leveranciers publiceren hem. Juniper legt voor SRX5400, SRX5600 en SRX5800 vast: “the total number of tunnels from a given public translated IP cannot exceed 1000 tunnels”7. Lees dat als beheerder en niet als specificatieregel. Je VPN-concentrator heeft een limiet per gedeeld adres, het delen wordt gedaan door een carrier waarmee je geen contract hebt, en hoe dicht je bij die limiet zit hangt af van hoeveel van je gebruikers toevallig achter dezelfde zitten. Er is geen teller om in te kijken. Er is alleen de dag waarop het voor sommigen begint te falen en voor anderen niet.

Alles in dit hoofdstuk vloeit voort uit één beslissing die dit land genomen heeft en bleef nemen. Die zaak heb ik elders volledig uitgeschreven en herhaal ik niet. Het punt is hier smaller: de kernaanname van IPsec is door het toegangsnetwerk geschrapt, en IPsec leeft sindsdien van noodoplossingen.

En het IPv6-only-netwerk redt het ook niet

Hier moet ik eerlijk zijn tegen mijn eigen betoog, want het voor de hand liggende antwoord op alles hierboven is: goed, geef dan elke machine een echt IPv6-adres en IPsec werkt weer zoals gespecificeerd.

Dat klopt, tussen twee kanten die er allebei een hebben. Dat is niet het netwerk waar de meeste mensen op zitten.

De IPv6-only-toegangsnetwerken die werkelijk bestaan, mobiel voorop, bereiken het IPv4-internet via NAT64, en dat is in de gewone zin helemaal geen NAT. Het is een protocolvertaler, die een IPv6-pakket herschrijft tot een IPv4-pakket. En RFC 6146 benoemt wat het vervoert, en benoemt wat het niet vervoert, zonder enige dubbelzinnigheid:

“The current specification only defines how stateful NAT64 translates unicast packets carrying TCP, UDP, and ICMP traffic. Multicast packets and other protocols, including the Stream Control Transmission Protocol (SCTP), the Datagram Congestion Control Protocol (DCCP), and IPsec, are out of the scope of this specification.”10

IPsec, bij naam, buiten het bereik. En pakketten die iets buiten die lijst dragen “SHOULD be discarded”10.

Op een IPv6-only-telefoon of -laptop die een IPv4-concentrator wil bereiken — en dat zijn de meeste concentratoren — wordt natief ESP dus niet door een firewall weggegooid of door een vertaler verminkt. Het wordt om te beginnen nooit vervoerd. De vertaler doet precies wat zijn standaard hem voorschrijft.

Het antwoord van de branche daarop is onvermijdelijk nog een laag: 464XLAT, dat het apparaat een lokale IPv4-stack geeft en twee keer vertaalt, uit IPv4 en terug, zodat wat NAT64 niet kan dragen toch werkt11. Het staat al op de lijst met aanbouwsels in de IPv6-post en ik ga het niet opnieuw beargumenteren. Wat hier het vermelden waard is, is de vorm: een protocol dat in 2004 op NAT brak, breekt ook op de vertaling die in 2011 voor de IPv6-overgang is gebouwd, en beide keren is het antwoord het in iets anders te verpakken.

Dat is de toets die een protocol in 2026 moet doorstaan. Werkt het op het netwerk dat mensen werkelijk hebben — achter het gedeelde adres van een carrier, op een IPv6-only-mobielnetwerk, door een hotel dat alleen TCP 443 doorlaat? Alles dat op een UDP-poort gebouwd is doorstaat alle drie zonder dat je het hoeft te zeggen. IPsec heeft voor elk een andere noodoplossing nodig, en voor de derde bovendien TCP-encapsulatie3.

Geen poorten betekent ook geen tweede lijn

Hier een storing die niets met NAT te maken heeft, puur modern is, en bijna geen aandacht krijgt.

Routers en switches verdelen verkeer over parallelle paden. Link aggregation, equal-cost multipath: die werken hetzelfde, door het vijftal te hashen. Bronadres, bestemmingsadres, protocol, bronpoort, bestemmingspoort. ESP heeft geen poorten. Elk pakket van een tunnel tussen dezelfde twee adressen hasht dus identiek, en de hele tunnel landt op één lid van de bundel, hoeveel je er ook gekocht hebt.

Twee 10G-lijnen en één IPsec-tunnel geven je 10G. Vier geven je 10G. De apparatuur werkt precies zoals ontworpen.

De noodoplossing heeft de gebruikelijke vorm. Sommig silicium kan in plaats daarvan op de SPI hashen, want elke SPI benoemt één association en dus één stroom, maar dat is een functie die je gekocht moet hebben en niet iets dat je kunt aannemen van een pad dat niet van jou is. Er loopt een IETF-concept waarvan het enige doel is ESP in nog een UDP-header te verpakken zodat gewone routers het kunnen hashen, en het zegt in één zin waarom: “Although the ESP SPI field within the IPsec packets can be used as the load-balancing key, but it cannot be used by legacy switches and routers.”12 De probleemstelling is net zo onomwonden over wat mensen in plaats daarvan doen: “Many cloud service providers allow customers to establish multiple IPsec VPN tunnels in parallel to enable ECMP and increase aggregate bandwidth. However, this approach is not ideal, as each tunnel typically requires its own public IP address, leading to higher public IP consumption and increased operational overhead.”12

Laat dat even bezinken. De aanbevolen manier om een versleutelde verbinding sneller te maken, is er meerdere bouwen, elk met een verbrand publiek IPv4-adres — tijdens een adressenschaarste — omdat het protocol geen poortnummer heeft om op te hashen. Een op UDP gebouwde tunnel krijgt multipath intussen gratis, van apparatuur die vijftien jaar geleden is uitgeleverd, omdat hij een poort heeft zoals al het andere op het moderne internet.

Dat is geen erfenisprobleem dat vanzelf uitdooft. Dat is een levende grens voor nieuwbouw, vandaag, bij precies de snelheden die mensen nu kopen.

De MTU-belasting, en wie hem betaalt

Elke tunnel kost bytes. IPsec kost er meer dan de meeste, en de manier waarop het faalt als het krap wordt is de ergste soort storing: onregelmatig, afhankelijk van de grootte, en onzichtbaar voor elke test die je als eerste draait.

Wat elke tunnel per pakket uitgeeft voordat je gegevens erin gaanBytes weg voordat je gegevens beginnen, op schaalheaders, per pakkettotaalNatief ESPtunnel, AES-GCMIP20ESP8IV8trailer + tag1854 BESP in UDPpoort 4500, voor NATIP20UDP8ESP8IV8trailer + tag1862 BL2TP/IPsecAES-CBC, NAT-TIP20UDP8ESP8IV16UDP8L2TP6PPP4trailer + tag1888 BPPTPGRE, protocol 47IP20GRE16PPP4helemaal geen integriteitstag40 BWireGuardéén UDP-poortIP20UDP8header16tag1660 BDe gearceerde blokken zijn de prijs van andermans vertaler.In de L2TP-rij zitten er drievan binnen de versleuteling: een tweede UDP-header, een sessielaag, en de framing van een inbelmodem.PPTP is het goedkoopst omdat het niets beschermt.De 40 byte kopen geen integriteitscontrole, en MS-CHAPv2werd in 2012 teruggebracht tot één DES-bewerking. Goedkoop is niet de maat. Wat de bytes kopen is de maat.Telkens één doorgerekende configuratie, over IPv4. De exacte cijfers hangen af van cijfer, modus en adresfamilie.
Bytes die op elk pakket opgaan voordat er iets van jouw gegevens in gaat, telkens één doorgerekende configuratie. Natief ESP is sober. Het voor NAT verpakken kost er acht meer. L2TP/IPsec draagt binnen de versleuteling een UDP-header, een L2TP-header en een PPP-header — inbel-framing, versleuteld, in 2026. PPTP oogt goedkoop omdat het helemaal geen integriteitscontrole draagt, en dat is precies het probleem ermee.

Reken het voor één configuratie door in plaats van te zwaaien. ESP in tunnelmodus over IPv4 met AES-GCM: 20 byte buitenste IP-header, 8 ESP-header, 8 nonce, minimaal 2 trailer, 16 integriteitswaarde. 54 byte voordat er iets van je pakket in gaat. Verpak het voor NAT-traversal en de UDP-header maakt er 62 van. Op een pad van 1500 byte blijft 1438 over, en zodra er ergens ervoor PPPoE op 1492 loopt zit je er weer onder.

En dan het stuk dat er een storing van maakt in plaats van een rekensom. Een verzender komt er alleen achter dat een pakket te groot was doordat er een ICMP-fout terugkomt — Fragmentation Needed bij IPv4, Packet Too Big bij IPv6. Gooit iets in het pad die fouten weg, dan komt de verzender er nooit achter en blijft hij pakketten sturen die blijven sterven. Dat is het klassieke zwarte gat: de handshake komt erdoor omdat handshakes klein zijn, en de overdracht blijft hangen omdat overdrachten dat niet zijn.

Cisco onderhoudt hierover sinds het GRE-en-IPsec-tijdperk een heel document, en het is nog altijd een van de betere verklaringen van dit samenspel in wiens bibliotheek dan ook13. Het moet onderhouden worden omdat mensen ICMP in zijn geheel blijven blokkeren en zich dan afvragen waarom tunnels zich vreemd gedragen.

De twee helften van dat betoog heb ik al uitgeschreven en ze gelden hier zonder herhaling: welke ICMP-berichten dragend zijn en welk niet, in Ping: het diagnosegereedschap dat een heleboel meer opent, en hoe je de precieze hop vindt die je verkeer opeet, in De firewall is elf hops ver. De korte versie voor deze post: de fouten zijn het mechanisme, echo niet, en een grensbeleid dat heel ICMP weggooit heeft je VPN gesloopt op een manier die het VPN aangerekend wordt.

En je eigen quality of service kan het slopen

Nog eentje, want die pakt goede ingenieurs die het juiste doen.

ESP draagt een volgnummer en de ontvanger houdt een replayvenster van standaard 64 pakketten op Cisco-platformen14. Prioriteer nu spraak op de verzendende router. Low latency queueing doet wat je vroeg en herschikt pakketten ten opzichte van de volgorde waarin ze versleuteld zijn. Valt een pakket bij aankomst buiten het venster, dan gooit de andere kant het weg als replay, en de teller die oploopt is een beveiligingsteller.

Cisco’s eigen woorden: “Certain QoS features, such as Low Latency Queueing (LLQ), could cause IPsec packet delivery to become out-of-order and dropped by the receiving endpoint due to a replay check failure.”14 Hun antwoord is het venster te verbreden naar 1024 waar het platform dat toelaat, of een uitbreiding met meerdere volgnummerruimtes te nemen die QoS-klassen op gescheiden volgnummerruimtes binnen één association afbeeldt14.

Dus: een standaardfunctie van je eigen netwerk aanzetten sloopt je eigen tunnel, en het middel is nog een protocoluitbreiding. Dezelfde vorm als alles hierboven.

L2TP: inbel-framing, versleuteld, in 2026

L2TP is geen beveiligingsprotocol en heeft dat nooit beweerd. RFC 2661 is een tunnelprotocol om PPP-sessies te vervoeren, gepubliceerd in 1999, zonder eigen vertrouwelijkheid — de eigen beveiligingsparagraaf verwijst je voor bescherming op pakketniveau naar IPsec15. Die koppeling is RFC 3193, en het resultaat is de stapel uit het diagram hierboven: een buitenste IP-header, een UDP-header voor NAT-traversal, ESP, dan binnen de versleuteling nog een UDP-header op poort 1701, een L2TP-header en een PPP-header.

PPP. De framing van inbelmodems, vervoerd in een versleutelde tunnel, over het internet, in 2026, omdat L2TP daar nu eenmaal voor geschreven is.

Reken uit wat dat kost aan een voorbeeld — buitenste IP 20, UDP 8, ESP-header en IV 24, binnenste UDP 8, L2TP 6, PPP 4, trailer en waarde 18 — en je geeft ongeveer 88 byte per pakket uit om gegevens te verplaatsen die natief ESP voor 54 verplaatst. Vierendertig byte, op elk pakket, voor een sessielaag die niets toevoegt wat je wilde en een verbindingslaag die voor een telefoonlijn ontworpen is.

De overhead is nog het minste.

Het vermenigvuldigt het NAT-probleem in plaats van het te delen. L2TP/IPsec gebruikt gewoonlijk ESP in transportmodus, de modus waar NAT het meeste pijn doet, en het bekende resultaat is dat veel implementaties twee clients achter één adres helemaal niet ondersteunen. Twee mensen in één huis, of veertig in één kantoor, of enkele honderden achter het gedeelde adres van een carrier. De andere kant ziet één adres en kan de sessies niet uit elkaar houden, dus vervangt de tweede verbinding de eerste. Dat is het ticket van bovenaan deze post, en het is in niemands product een fout — het is het identiteit-via-adres-probleem dat aankomt op de plek waar de meeste mensen het tegenkomen.

En in het veld wordt het meestal uitgerold met één gedeeld geheim voor iedereen. Doordat het geheim in het clientprofiel wordt gezet en met de installatie-instructies wordt uitgedeeld, staat de pre-shared key in het onboardingdocument, op de wikipagina, in de e-mail aan nieuwe collega’s, en op elke laptop die ooit het pand verliet. Het is geen tweede factor. Het is een wachtwoord dat de gateway tegenover niemand in het bijzonder authenticeert en dat nog nooit gewisseld is.

L2TP is geen protocol dat slecht verouderd is. Het is een protocol dat vanaf dag één het verkeerde vervoerde, en aan IPsec is vastgeschroefd om goed te maken wat het helemaal niet kon.

PPTP was nooit veilig, en wordt nog steeds verkocht

PPTP verdient twee alinea’s, geen hoofdstuk, en krijgt ze alleen omdat mensen het nog steeds uitleveren.

Het was nooit een standaard. RFC 2637 is Informational. Een opgeschreven leveranciersprotocol, niets dat de IETF ooit heeft aanbevolen. Het vervoert PPP in GRE, IP-protocol 47, dat net als ESP geen poorten heeft, dus het heeft in elke NAT op het pad een eigen uitzonderingsbehandeling nodig — het vinkje “PPTP passthrough”, dat op heel veel thuisrouters precies één sessie tegelijk ondersteunt.

De beveiliging eindigde publiekelijk in 2012. Marlinspike en Hulton lieten zien dat de beveiliging van MS-CHAPv2 zich ongeacht de wachtwoordlengte terugbrengt tot één DES-bewerking, bouwden chapcrack om de handshake eruit te halen, en koppelden dat aan een kraakdienst die de sleutel binnen een dag voor twintig dollar teruggaf — een slaagkans van 100 %, geen waarschijnlijkheid16. Hun conclusie was dat PPTP-verkeer als onversleuteld beschouwd moet worden. Apple stemde met de voeten en haalde PPTP in 2016 uit de ingebouwde client van macOS Sierra en iOS 10, en publiceert de waarschuwing nog steeds17.

Tien jaar later is PPTP nog altijd een menu-item op routers die dit jaar verkocht worden, nog altijd in handleidingen van leveranciers, nog altijd wat iemand aanzet omdat het de enige is die meteen werkt. Het werkt meteen omdat het de klus niet doet.

Alles wat zich IPsec-VPN noemt

“IPsec-VPN” is geen protocol. Het is een familie, en de lengte van de lijst hieronder is het argument, want geen twee producten implementeren dezelfde deelverzameling, en in de gaten tussen die deelverzamelingen woont elke interopklus die je ooit gehaat hebt.

OnderdeelWat het toevoegtWaar het staat
ESP, IP-protocol 50De versleuteling en integriteit zelfRFC 4303 — actueel18
AH, IP-protocol 51Integriteit ook over de IP-headerRFC 4302 — door NAT onbruikbaar2
IKEv1De oorspronkelijke sleuteluitwisselingAfgeschaft, RFC’s op Historic gezet19
IKEv2De huidige sleuteluitwisselingRFC 729620
IPComp, IP-protocol 108Comprimeert voor het versleutelen, met eigen associationsRFC 317321
PF_KEY v2Een kernel-API zodat een daemon de sleutels kan ladenRFC 236722
NAT-traversalVerpakt ESP in UDP 4500 zodat een vertaler ermee overweg kanRFC 3947 / 39486
TCP-encapsulatieVoor netwerken die ook UDP blokkerenRFC 9329, vervangt RFC 82293
IKEv2-fragmentatieOmdat de sleuteluitwisseling zelf de MTU ontgroeid isRFC 738323
MOBIKEZodat de tunnel een adreswisseling overleeftRFC 455524
Dead peer detectionEen hartslag, want verder zegt niets het jeRFC 370625
XAUTHGebruikersauthenticatie — wachtwoord, token, RADIUSNooit een RFC. Verlopen concept, 200126
Mode-ConfigGeeft de client adres, DNS en routesOok nooit een RFC26
L2TP/IPsecVervoert PPP in de tunnelRFC 2661 + RFC 319327
GRE of VTI over IPsecGeeft je een routeerbare interface om een protocol op te draaienLeveranciersarchitectuur op ESP
DMVPNmGRE plus NHRP plus IPsec, zodat spokes elkaar vindenLeveranciersarchitectuur, NHRP RFC 233228
GETVPNGroepssleutels, helemaal zonder tunnel per paarGDOI, RFC 640729
PPTPWat IPsec moest vervangenRFC 2637 — Informational, nooit een standaard30

Kijk nu naar de twee vetgedrukte regels, want dat zijn de regels die je moeten tegenhouden.

Bijna twee decennia lang was de normale manier om een gebruiker op een zakelijk IPsec-VPN aan te melden XAUTH — je gebruikersnaam en wachtwoord, je token, je RADIUS-server — met Mode-Config dat de client zijn adres, DNS-servers en routes geeft. Samen zijn ze de hele ervaring van toegang op afstand. Elke “Cisco IPsec”-client, elk VPN-pictogram in een balk, elke aansluitinstructie.

Geen van beide is een standaard. XAUTH was een individueel internetconcept dat in 2001 verliep en gearchiveerd werd zonder ooit een RFC te worden26. De opgegeven reden is het lezen waard, want daar legt een commissie uit waarom het zijn werk niet wilde doen: het concept legt vast dat de IPSRA-werkgroep geen protocol zou aanvaarden dat ISAKMP of IKE uitbreidt, en dat de IPsec-werkgroep alles weigerde wat met toegang op afstand te maken had26. Het meest uitgerolde deel van het meest uitgerolde VPN-protocol bleef dus dakloos, werd toch door elke leverancier naar eigen lezing van een verlopen concept geïmplementeerd, en aan miljoenen gebruikers uitgeleverd.

IKEv2 heeft beide uiteindelijk rechtgezet, en dat mag gezegd worden: de authenticatie ging naar EAP en de configuratiepayloads voor de client kwamen in de kernspecificatie20. Maar lees de jaartallen. De meest gebruikte functie van het meest gebruikte VPN-protocol liep ongeveer een decennium op een verlopen concept voordat er überhaupt een standaard was, en de geïnstalleerde basis draaide daarna nog jaren door op de conceptversie. Een protocolfamilie krijgt geen krediet voor het uiteindelijk standaardiseren van het deel dat iedereen toch al gebruikte.

Dat is de familie die je draait. Een deel ervan is Standards Track en actueel. Een deel is Historic. Een deel is nooit iets geworden. En een product waarvan het datablad “IPsec-VPN” zegt, heeft je ongeveer niets verteld over welke van deze achttien dingen het kan — en daarom kost twee ervan aan elkaar knopen veertien dagen, een spreadsheet met proposals en een telefoontje naar iemand die het eerder gedaan heeft.

Het Fisher-Price OS (Windows) heeft nooit echt samengewerkt

Dit is het stuk waar iemand zegt dat het probleem eigenlijk Linux is, dus doen we het met bronnen.

Standaard verbindt de Windows-client helemaal niet met een IPsec-server die achter NAT staat. Niet “heeft moeite”. Weigert. De oplossing is een registerwaarde met de naam AssumeUDPEncapsulationContextOnSendRule onder HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PolicyAgent, op 1 gezet als de server achter een vertaler staat of op 2 als beide kanten dat doen, op elke client en op de server, gevolgd door een herstart31. Microsofts eigen woorden: “By default, Windows Vista and Windows Server 2008 don’t support Internet Protocol security (IPsec) network address translation (NAT) Traversal (NAT-T) security associations to servers that are located behind a NAT device.”31

Twee dingen daarover. Ten eerste heeft Microsoft de NAT-traversalstandaard die het weigert te gebruiken mede geschreven. Hun naam staat op RFC 3947 en RFC 39486. Ten tweede is de pagina die je zegt het register te bewerken voor het laatst herzien in februari 202631. Twintig jaar later is een registeringreep op elk eindpunt nog altijd het antwoord, en wordt het nog altijd als antwoord onderhouden.

En lees de zin die Microsoft er direct boven zet: “If you must use IPsec for communication, use public IP addresses for all servers that you can connect to from the Internet.”31

Dat is deze hele post, in de documentatie van de leverancier. Zet IPsec niet achter NAT. Geef elke machine een echt adres. Ze hebben het opgeschreven, en daarna heeft de branche twee decennia het tegenovergestelde gedaan en het verschil in rekening gebracht.

Bij NAT houdt het niet op. Lees wat een opensourcegateway moet vastleggen om een Windows-client te accepteren.

  • Het gatewaycertificaat heeft een extended key usage nodig die hiervoor en voor niets anders bestaat. serverAuth, OID 1.3.6.1.5.5.7.3.1, plus IP Security IKE Intermediate, OID 1.3.6.1.5.5.8.2.232. Je CA moet geleerd worden een OID uit te geven waarvan de meeste gereedschappen nog nooit gehoord hebben, anders faalt de verbinding op een beleidsfout zonder bruikbare melding.
  • Een tweede registerwaarde is nodig voordat de client fatsoenlijke cryptografie aanbiedt. strongSwan documenteert het toevoegen van NegotiateDH2048_AES256 onder Rasman\Parameters om AES-256-CBC en een 2048-bits groep te krijgen33. Lees dat andersom, want zo telt het: zonder registeringreep is het standaardaanbod zwakker dan dat.
  • Door de server gestart hersleutelen wordt door clients achter NAT geweigerd, en de gedocumenteerde noodoplossing is hersleutelen op de gateway uit te zetten en de client te laten beginnen33.
  • Standaard IKEv2-uitbreidingen ontbreken simpelweg — geen IKE-omleiding, geen meervoudige authenticatierondes33.

Niets daarvan is een fout van Linux. Elk punt is een opensourceproject dat opschrijft wat het moet doen om tegemoet te komen aan de lezing die één leverancier geeft aan een standaard die die leverancier mede geschreven heeft.

Dat is het patroon, en het is dertig jaar oud. PPTP was Microsofts protocol, als Informational opgeschreven en nooit gestandaardiseerd30. MS-CHAPv2 en MPPE waren Microsofts authenticatie en versleuteling, en beide zijn in het openbaar gebroken16. SSTP is een Microsoft-tunnel die niemand anders termineert. DirectAccess was IPsec, en was aan beide kanten Windows bij ontwerp — en is inmiddels afgeschaft en wordt verwijderd, waarbij klanten naar Always On VPN worden geduwd34. Geen daarvan is ooit een protocol geweest waarbij de rest van ons elkaar halverwege kon treffen. Het was een protocol waar je je bij aansloot, en draaide je aan beide kanten niet het juiste besturingssysteem, dan kreeg je de registeringreep, de rare OID en de pagina met noodoplossingen.

Dus zeg ik het onomwonden, het is tenslotte mijn blog. Het Fisher-Price OS (Windows) is in een open protocolstapel nooit een echte gelijke geweest, want daar was het nooit voor bedoeld. Het verbergt de machine voor de persoon die hem gebruikt, en wel als ontwerpdoel, en een stapel die je niet kunt zien is een stapel die je niet interoperabel kunt maken. Als dat het enige besturingssysteem is dat je ooit beheerd hebt, zullen de hoofdstukken hierboven over kerneltellers en meelezen op de lijn als een vreemde taal geklonken hebben, en dát is het gat — geen voorkeur, een gat.

Niets daarvan hoeft de lezer iets te kosten. Elke diagnose in deze post draait vanaf elke Unix in het netwerk, gericht op wat kapot is, en het maakt haar volstrekt niet uit wat er aan de andere kant draait. En als dat besturingssysteem het enige is dat je hebt, draagt het diagnosedeel hieronder ook zijn eigen gereedschap — de capture, de twee cmdlets en de foutcodes met wat elk daarvan werkelijk zegt. Een kapotte tunnel moet maandag toch gerepareerd worden. De vervanger waar ik aan het eind voor pleit heeft dan één client, die zich op elk platform hetzelfde gedraagt, dat platform inbegrepen — voor het eerst in dertig jaar geldt dat voor een VPN.

Het afschaffingsdossier leest als een overlijdensbericht

Zet de noodoplossingen opzij en lees gewoon wat de standaardisatieorganen deze familie door de jaren heen hebben aangedaan. Geen mening. Eisniveaus, in gepubliceerde RFC’s.

WatWaar het nu staatBron
IKEv1Afgeschaft; RFC 2407, 2408 en 2409 op Historic gezetRFC 9395, 202319
DES in ESPMUST NOTRFC 82218
3DES in ESPSHOULD NOTRFC 82218
HMAC-MD5-96MUST NOTRFC 82218
ESP samen met AHNOT RECOMMENDEDRFC 82218
ESP met alleen versleutelingOnveilig aangetoond, en in 2007 in de praktijk gebrokenDegabriele en Paterson35
IPsec op een IPv6-nodeVan MUST naar SHOULD verlaagdRFC 6434, 201136
PPTPNooit een standaard; alleen InformationalRFC 263730

De één-na-laatste regel is die welke ik voor zou leggen aan iedereen die mij vertelt dat IPsec prima is en dat het netwerk het probleem is. IPv6 schreef IPsec oorspronkelijk voor — het was het beveiligingsverhaal, vastgelegd in de node requirements. In 2011 bedacht de IETF zich: “Previously, IPv6 mandated implementation of IPsec and recommended the key management approach of IKE. This document updates that recommendation by making support of the IPsec Architecture a SHOULD for all IPv6 nodes.”36

Zelfs de adresfamilie die IPsec alles teruggegeven zou hebben wat NAT wegnam, is vijftien jaar geleden opgehouden het te eisen. Dat is niet het netwerk dat IPsec in de steek laat. Dat zijn de mensen die het netwerk ontworpen hebben en besloten dat het het gebod niet verdiend had.

De complexiteit werd in 1999 gesignaleerd, schriftelijk

Niets hiervan is wijsheid achteraf, en juist dat maakt het het opschrijven waard.

In 1999 kregen Niels Ferguson en Bruce Schneier de opdracht IPsec te beoordelen. Hun rapport is kort, helder en de moeite waard om helemaal te lezen. Het opent met “IPsec was a great disappointment to us. Given the quality of the people that worked on it and the time that was spent on it, we expected a much better result.”37 Het benoemt de oorzaak: “Our main criticism of IPsec is its complexity. IPsec contains too many options and too much flexibility; there are often several ways of doing the same or similar things. This is a typical committee effect.”37

En het deed drie aanbevelingen die nu lezen als een lijst van dingen die toch gebeurd zijn, twintig jaar te laat en op de harde manier:

  • Schaf de transportmodus af. “We therefore recommend that transport mode be eliminated.”37 De transportmodus is de modus die L2TP/IPsec gebruikt, en de modus waar NAT het meeste pijn doet.
  • Schaf AH af. “We conclude that eliminating transport mode allows the elimination of the AH protocol as well, without loss of functionality.”37 NAT heeft het in plaats daarvan afgeschaft, om een slechtere reden.
  • Sta versleuteling zonder authenticatie nooit toe. Ze waarschuwden dat beheerders “will be quite likely to configure ESP for only encryption, believing that it provides security” — ESP zeer waarschijnlijk alleen op versleuteling zouden zetten, in de overtuiging dat dat beveiliging oplevert37.

Acht jaar later hield dat laatste punt op een waarschuwing te zijn. Degabriele en Paterson publiceerden aanvallen die “break any RFC-compliant implementation of IPsec making use of encryption-only ESP” — elke RFC-conforme implementatie breken die ESP met alleen versleuteling gebruikt, uit louter de cijfertekst, en waarvoor niet meer nodig is dan verkeer meelezen en pakketten injecteren35. De voorspelling stond acht jaar in het publieke dossier en de standaard stond de configuratie nog steeds toe.

Het oordeel uit dat rapport van 1999 is de zin waar ik telkens op terugkom: “We have found serious security weaknesses in all major components of IPsec. As always in security, there is no prize for getting 90% right; you have to get everything right.”37

Nog twee gegevens, en dan laat ik het erbij.

Logjam, 2015. Het team erachter scande een steekproef van 1 % van IPv4 op IKE en vond dat 86,1 % van de IKEv1- en 91,0 % van de IKEv2-servers de 1024-bits Oakley-groep 2 ondersteunde, en dat 66,1 % van de geprofileerde IKEv1-servers die prefereerde. Hun conclusie: voorberekening tegen een tweede 1024-bits groep “would allow decryption of traffic to 66% of IPsec VPNs”, en de gepubliceerde inlichtingendocumenten over VPN-exploitatie zijn “consistent with having achieved such a break”38. Cryptografische wendbaarheid, waar IPsec het meeste van heeft, is de reden dat bijna iedereen vijftien jaar op dezelfde zwakke groep bleef zitten.

CVE-2016-1287. Een bufferoverloop in de IKEv1- en IKEv2-code op Cisco ASA, bereikbaar door geprepareerde UDP-pakketten te sturen, met code-uitvoering op afstand vóór authenticatie39. Denk aan waar die doos staat. Het is het apparaat dat je bewust aan het hele internet hebt blootgesteld, waarop het meest optierijke protocol van het hele park draait, met een fragmentassembler voor de parser, en dat de sleutels tot alles daarachter houdt. De complexiteit waar Ferguson en Schneier voor waarschuwden is geen abstractie. Het is aanvalsoppervlak, op de ene machine die je nergens achter kunt zetten.

Het diagnosticeren zolang je het nog draait

Je kunt dit niet vanmiddag allemaal uitzetten, dus hier is hoe je eraan werkt. Dit is de methode, in de volgorde die het minste kost, met wat elk resultaat werkelijk betekent.

Zes manieren waarop het het opgeeft, op de plek in het pad waar elk gebeurtWaar elke storing echt zitClientbeleid en routesThuisroutervertaling éénCarriervertaling tweeHet internetfilters en MTUGatewayselectors en identiteit1234561Helemaal niets op de lijn.Het verkeer heeft IPsec nooit bereikt. Stop met zoeken bij de crypto.ip xfrm policyen de route, en wat de hostfirewall doet.2Poort 500 beide kanten op, 4500 nooit.NAT-traversal is niet onderhandeld.tcpdump -ni eth0 'udp port 500 or udp port 4500 or ip proto 50'Kaal ESP overleeft dat niet.3Sterft na inactiviteit, leeft op bij gebruik.Een mapping is bij een van de twee vertalers verlopen.Je keepalive verliest van een timer die je niet kunt lezen. Verkort hem en vertrouw de standaard niet.4Uitgaande teller stijgt, inkomende vlak.ESP sterft onderweg in één richting.ip -s xfrm stateaan beide kanten, zoek dan de hop die het opeet.5Inloggen gaat, grote overdrachten hangen.Path MTU, en de ICMP-fouten komen niet terug.ping -M do -s 1400stapsgewijs omlaag, klem dan de segmentgrootte en repareer de ICMP-regel.6Beide kanten zeggen up, er gaat niets door.Traffic selectors, beleid of routering — niet de sleutels.En heeft een tweede gebruiker de eerste eruit gegooid, dan is het peeridentiteit, geen capaciteit.Eén opname aan de grens van dertig seconden beantwoordt de eerste drie. Doe dat voordat je een console opent.
De zes storingen in de volgorde waarin je erop test, met het symptoom, de controle en wat het antwoord betekent. Elke regel is een andere laag van de stapel die het opgeeft, en de eerste drie worden beantwoord door dertig seconden naar de lijn te kijken — en dat is waarom je daarmee begint en niet eindigt.

Kijk eerst naar de lijn, niet naar de console

Beide consoles vertellen je wat ze geloven. De lijn vertelt je wat er gebeurd is. Eén opname aan de grens, dertig seconden, beantwoordt de eerste drie vragen tegelijk:

tcpdump -ni eth0 'udp port 500 or udp port 4500 or ip proto 50 or ip6 proto 50'
  • Helemaal niets uitgaand — het probleem zit vóór IPsec: routering, beleid, of een hostfirewall. Stop met zoeken bij de cryptografie.
  • Alleen uitgaand, niets terug — je pakketten gaan weg en hun antwoorden komen niet aan. Filtering onderweg, een dode peer, of de andere kant wijst stil af.
  • UDP 500 beide kanten op maar 4500 verschijnt nooit — NAT-traversal is niet onderhandeld. Of een kant heeft het uit staan, of de detectie is mislukt.
  • Protocol 50 op de lijn terwijl één kant achter NAT zit — de onderhandeling besloot dat er geen vertaler was terwijl die er wel is. Dat komt nooit meer goed.

De fout bij de sleuteluitwisseling lezen

IKEv2 vertelt je waarom het geweigerd heeft, en de notify-namen zijn specifiek genoeg om er alleen al op te diagnosticeren. Het helpt om eerst de vorm van de hele uitwisseling voor je te hebben, want elke notify hieronder hoort bij een bepaalde sport daarvan.

De IKEv2-uitwisseling stap voor stap, en welke storing op welke stap woontElke stap van de uitwisseling, en de storing die erop woontClientachter een vertalerGatewayecht adresWat hier misgaatIKE_SA_INIT-verzoek — UDP 500niets terug — 809 ERROR_VPN_TIMEOUTIKE_SA_INIT-antwoord — UDP 500NO_PROPOSAL_CHOSEN, INVALID_KE_PAYLOADNAT gezien, beide kanten naar 4500geen omschakeling — proto 50 sterft bij de vertalerIKE_AUTH — UDP 4500, versleuteldte groot, fragment weg, hertransmissie, time-outIKE_AUTH-antwoord — CHILD_SA aangemaaktAUTHENTICATION_FAILED — 13801, 13806ESP in UDP 4500 — jouw verkeerTS_UNACCEPTABLE — up, en er beweegt nietskeepalive — 1 byte per 20 s, voor altijdgeen keepalive — invoer verloopt bij stilteDe omschakeling is het scharnier.Erboven is alles UDP 500. Eronder is alles UDP 4500. Gebeurt de omschakeling nooit, dan stop je protocol 50in een vertaler die niets heeft om te herschrijven, en het komt nooit terug.De groottefout woont op één sport.IKE_AUTH draagt de certificaatketen en is daarmee het enige grote bericht hier. Een vooraf gedeelde sleutel die welverbindt waar een certificaat dat niet doet, is een verloren fragment, geen slecht certificaat.Aangemaakt is niet hetzelfde als werkend.De child-associatie kan bestaan en toch niets dragen, als de twee kanten het oneens zijn over welk verkeer zij dekt.Elke storing in de rechterkolom wordt bij de client als time-out gemeld, wat het ook werkelijk was.
De uitwisseling van het eerste pakket tot de vaste toestand, met de storing die op elke stap woont. De omschakeling van 500 naar 4500 is het scharnier: erboven is alles één poort, eronder een andere, en gebeurt de omschakeling nooit, dan stop je protocol 50 in een vertaler die het niet kan dragen. IKE_AUTH is hier het enige grote bericht, en daarom kan een vooraf gedeelde sleutel verbinden waar een certificaat dat niet doet — dat is een verloren fragment, geen slecht certificaat.
NotifyWat het werkelijk betekentWaar je kijkt
NO_PROPOSAL_CHOSENGeen van de aangeboden combinaties van cijfer/integriteit/DH/PRF is de andere kant acceptabelBeide proposal-lijsten; verwacht aan één kant een afgeschaft algoritme
INVALID_KE_PAYLOADDiffie-Hellman-groep komt niet overeen — jij bood één groep aan, hij wil een andereDe DH-groep, het eerste in het proposal
AUTHENTICATION_FAILEDSleutel, certificaat of identiteit fout — een afwijkende pre-shared key, een verlopen certificaat, of een ID dat de peer niet verwachtDe identiteit, niet alleen het geheim
TS_UNACCEPTABLEDe traffic selectors overlappen niet — je vroeg subnetten te beschermen die de peer niet beschermtDe selectorconfiguratie aan beide kanten
INVALID_SPIEr kwam een pakket aan voor een association die niet meer bestaat, meestal na een eenzijdige herstartOf één kant hersleuteld is of herstart

Junipers handleiding voor fase 2 zegt over de meest voorkomende hetzelfde: “no proposal chosen” betekent dat het apparaat “did not accept any of the IKE Phase 2 proposals that the peer sent”, en de oplossing is een wederzijds acceptabel proposal en geen herhaalde herstart40.

Op strongSwan de toestand van alles in één commando:

swanctl --list-sas                 # what is established, and what it negotiated
swanctl --log                      # the negotiation as it happens

Op Cisco show crypto ikev2 sa en show crypto ipsec sa, met debug crypto ikev2 als het niet omhoog komt41. Op Junos show security ike security-associations en show security ipsec security-associations, met de onderhandeling in show log kmd-logs42.

Is NAT-traversal eigenlijk wel onderhandeld?

Dit is de controle die mensen overslaan, en hij verklaart een groot deel van “vanaf kantoor werkt het en van thuis niet”.

Elke kant stuurt hashes van de adressen en poorten waarvan hij denkt dat ze in het spel zijn. Komt de hash die de andere kant uit het ontvangen pakket berekent niet overeen met die jij stuurde, dan zit er een vertaler tussen, en gaan beide kanten over op UDP 4500. Faalt de detectie — één kant heeft traversal uit staan, of iets in het midden verminkt de uitwisseling — dan gaan beide kanten verder met kaal ESP, dat de vertaler niet overleeft.

Dus: zie poort 4500 in de opname, uit beide richtingen, of er vindt geen traversal plaats. Neem het woord van de console er niet voor aan.

Controleer daarna of de keepalive echt loopt en of het interval korter is dan waarop je carrier mappings laat verouderen. De standaard is twintig seconden6; de ondergrens van de standaard voor NAT-beheerders is twee minuten9; wat jouw specifieke carrier doet, zie je niet. Sterft de tunnel na inactiviteit en leeft hij op bij verkeer, dan is dit het elke keer.

De kerneltellers die bijna niemand leest

Onder Linux houdt de transformatielaag een volledige uitsplitsing van fouten bij, en dat is de snelste manier om van “het werkt niet” een concrete oorzaak te maken. De tellers zijn door de kernel zelf gedocumenteerd43.

cat /proc/net/xfrm_stat        # error counters, by cause
ip -s xfrm state               # per-SA packet and byte counters
ip xfrm policy                 # what should be protected, and in which direction

Het leest beter als pad dan als lijst. Het pakket gaat door vijf stadia, en elk daarvan heeft zijn eigen teller:

Vijf stadia, en de teller die noemt waar je pakket stierfVolg één pakket, en laat de teller het stadium noemen waar het stierfJouw policywordt dit verkeer beschermd?XfrmOutPolBlockje gooit het zelf weg, met opzet, in beleidJouw associatieversleutelen, verzegelen, nummerenXfrmOutNoStatesbeleid matchte, geen associatie om het te dragenHet padvertaler, MTU, filtersniets hoogt op, aan geen van beide kantenhier wonen NAT, MTU en filtering, en geen enkele teller ziet er iets vanHun associatiebestemming + protocol + SPIXfrmInNoStates · XfrmInStateProtoError · XfrmInStateSeqErrorhet kwam aan en de cryptografie kwam niet uit: verkeerde SPI, verkeerde sleutel, buiten vensterHun policyhoorde dit beschermd te zijn?XfrmInTmplMismatch · XfrmInNoPolsde cryptografie was goed, het beleid was het oneens dat het zo hoordeStadium drie is het stadium zonder teller.Alles wat een kwart eeuw vertaling dit protocol heeft aangedaan gebeurt daar, en de transformatielaag ziet er aangeen van beide kanten één pakket van. Dat is precies waarom een capture vóór een console komt.Stadium vier en vijf zijn tegengestelde storingen.Vier betekent dat de cryptografie niet uitkwam. Vijf betekent dat die wel uitkwam, en iets het oneens was of het zohoorde. Ze worden bijna altijd in de verkeerde volgorde bekeken, want vijf lijkt een cryptostoring en is dat niet.De tellernamen zijn die van Linux. Op Junos lees je dezelfde stadia uit show security ipsec statistics; op hetFisher-Price OS (Windows) uit Get-NetIPsecQuickModeSA en het logboek van Windows Firewall met geavanceerde beveiliging.
Vijf stadia, en de teller die noemt waar je pakket stierf. Stadium drie is het enige zonder enige teller — de vertaler, de MTU en elk filter ertussen wonen daar, en de transformatielaag ziet er aan geen van beide kanten één pakket van. Dat is het hele argument om eerst een capture te pakken en pas daarna een console. Stadium vier en vijf zijn tegengestelde storingen en worden bijna altijd in de verkeerde volgorde bekeken.

Kijk welke beweegt terwijl de storing optreedt:

TellerBeschrijving van de kernelWat het op de dag zelf betekent
XfrmInNoStates“No state is found i.e. Either inbound SPI, address, or IPsec protocol at SA is wrong”Hun pakketten komen aan voor een association die jij niet hebt — meestal een eenzijdig hersleutelen of een herstart
XfrmInStateSeqError“Sequence error i.e. Sequence number is out of window”Herschikking of gedoe met het replayvenster; zie het QoS-samenspel hierboven
XfrmInStateProtoError“Transformation protocol specific error e.g. SA key is wrong”De sleutels lopen uiteen — de association overleefde een hersleuteling aan slechts één kant
XfrmInTmplMismatch“No matching template for states e.g. Inbound SAs are correct but SP rule is wrong”De association klopt en het beleid niet
XfrmInNoPols“No policy is found for states e.g. Inbound SAs are correct but no SP is found”Er komt beschermd verkeer aan waarvan niemand om bescherming vroeg
XfrmOutPolBlock“Policy discards”Je gooit het zelf weg, met opzet, in het beleid
XfrmOutNoStates“No state is found”Verkeer trof beleid zonder association om het te dragen — de tunnel kwam nooit op

XfrmInTmplMismatch en XfrmInNoPols zijn de twee die je op het zicht moet kennen, want beide betekenen dat de cryptografie klopt en het beleid niet, en dat is het tegenovergestelde van waar iedereen het eerst kijkt.

Het zegt “up” en er beweegt niets

Beide kanten opgezet, geen verkeer. Lees de tellers per association in beide richtingen:

ip -s xfrm state
  • Uitgaande bytes stijgen, inkomende vlak — je versleutelt en verstuurt, en er komt niets terug. Of jouw ESP bereikt hen niet, of dat van hen bereikt jou niet. Vraag de andere kant om hun uitgaande teller; stijgt die ook, dan sterven de pakketten onderweg en is de volgende vraag waar, en dat is een TTL-vraag en geen cryptovraag.
  • Beide vlak — er wordt niets aan de tunnel aangeboden. Routering of beleid, geen IPsec. Bij route-based: controleer of de route echt naar de tunnelinterface wijst; bij policy-based: controleer de selectors.
  • Beide stijgen, applicaties nog steeds stuk — het is de tunnel niet. Ga kijken wat er aan de overkant staat.

Junipers advies voor dit geval volgt hetzelfde instinct in hun taal: stijgt alleen de uitgaande pakketteller van de sessie, bevestig dan bij de peer of het verkeer überhaupt ontvangen wordt44.

Kleine dingen werken, grote blijven hangen

MTU. Het is altijd MTU. De test duurt tien seconden:

ping -M do -s 1400 10.0.0.1      # inside the tunnel, do-not-fragment set
ping -M do -s 1300 10.0.0.1      # step down until it succeeds

Waar het begint te lukken vertelt je de werkelijk bruikbare grootte. Laat TCP het daarna zelf uitzoeken door de aangekondigde segmentgrootte op het pad te klemmen in plaats van te hopen dat elke ICMP-fout de reis overleeft:

nft add rule inet filter forward tcp flags syn tcp option maxseg size set rt mtu

En los ook de onderliggende oorzaak op, en dat is bijna altijd een te brede ICMP-regel aan een grens ergens. Gooi echo weg als je wilt. Ik heb elders betoogd dat het dat verdient. Maar hou Fragmentation Needed en Packet Too Big. Die zijn het mechanisme, geen vriendelijkheid.

Het valt op de klok uit

Klok de storingen. Het interval benoemt de oorzaak vanzelf.

  • Een vaste periode die overeenkomt met een ingestelde lifetime — hersleutelen. De association verloopt en de vervangende onderhandeling faalt of loopt in een race. Controleer de lifetimes aan beide kanten; afwijkende waarden zijn normaal en prima, maar een harde lifetime aan de ene kant die korter is dan de zachte van de andere levert precies dit op.
  • Na een periode zonder verkeer, terug bij het eerste gebruik — een NAT-mapping is verlopen. Keepalive-interval, of het ontbreken ervan.
  • Dead peer detection breekt hem af terwijl de verbinding in orde is — de sondes gaan verloren in plaats van dat de peer dood is, vaak omdat de sondes het enige verkeer zijn en de mapping allang weg is.

De tweede gebruiker gooit de eerste eruit

Twee peers bereiken de concentrator vanaf één adres en authenticeren zich als dezelfde identiteit. De gateway heeft de keuze tussen de oude association behouden en vervangen, en een gangbare standaard is vervangen. De tweede verbinding wint dus en de eerste sterft in stilte.

Geef elke peer een werkelijk unieke identiteit in plaats van een adres of een gedeelde naam, en stel de gateway zo in dat hij meerdere associations vanaf één adres behoudt in plaats van er één per peer aan te nemen. Test het dan op de enige manier die telt: twee clients, één adres, tegelijk. Heeft je acceptatietest nooit twee gebruikers achter één NAT gehad, dan heb je juist het geval niet getest waar de meeste van je gebruikers in zitten.

Dezelfde storingen, op het Fisher-Price OS (Windows)

Elke controle hierboven draait vanaf een Unix-machine, en als je er een in dat netwerk hebt, gebruik hem dan, want hij vertelt je sneller de waarheid en het kan hem niets schelen wat er aan de andere kant draait. Maar een hoop lezers hebben een client die niet verbindt, een besturingssysteem dat de machine bewust voor hen verbergt, en verder niets om naar te kijken. Dus hier dezelfde methode nog eens, in dezelfde volgorde, met het gereedschap dat dat systeem werkelijk meelevert.

Kijk naar de lijn. Er is geen tcpdump, maar er is een capture. Start hem verhoogd, reproduceer de storing, stop hem:

netsh wfp capture start cab=on file=ipsec
netsh wfp capture stop

Dat schrijft een .cab. Daarin zit het spoor van wat het filterplatform en de sleuteluitwisseling werkelijk deden terwijl het misging, en dat is meer dan een van beide consoles wil toegeven. Voor live meekijken in plaats van een archief schrijft dezelfde commandofamilie met file=- naar de console: netsh wfp show state “Displays the current state of WFP and IPsec”, en netsh wfp show ikeevents “Displays recent Internet Key Exchange (IKE) epoch events matching the specified parameters”, gefilterd op één peer45.

netsh wfp show state file=-
netsh wfp show ikeevents remoteaddr=203.0.113.5 file=-

show ikeevents is hier het dichtst bij het uitwisselingslogboek dat elke andere stack ongevraagd schrijft. Goed om te weten dat het er is. Anders geeft de interface je een getal van drie cijfers en verder niets, en zit je een sleuteluitwisseling te diagnosticeren op gevoel.

Lees de associaties, en lees ze allebei. De tegenhangers van ip -s xfrm state en swanctl --list-sas zijn twee cmdlets, en de scheiding daartussen is de hele diagnose:

Get-NetIPsecMainModeSA
Get-NetIPsecQuickModeSA

Main mode is de sleuteluitwisseling. Quick mode draagt de pakketten. Microsoft zegt het verband gewoon hardop: “There is only one main mode SA between a pair of computers, but there can be many quick mode SAs”46. Main mode aanwezig met quick mode leeg is dus dezelfde storing als een staande IKE_SA zonder CHILD_SA eronder, en het betekent hetzelfde: de twee kanten werden het eens over hoe ze praten en vervolgens niet over wat er beschermd wordt. Kijk naar de traffic selectors, niet naar de algoritmen.

Lees de logboeken, op de twee plekken waar ze zich verstoppen. Storingen op verbindingsniveau landen in het Toepassingenlogboek onder de bron RasClient, en Microsofts eigen opmerking over het lezen ervan is het nuttige deel: “All error messages return the error code at the end of the message”47. Dat getal is de diagnose, en de volgende sectie zegt wat de getallen betekenen. Beleids- en filterbeslissingen landen ergens heel anders, onder Logboeken van toepassingen en services, in de kanalen van Windows Firewall met geavanceerde beveiliging. Twee logboeken, twee teams, één storing.

Verzamel het netjes als je moet escaleren. Het ondersteunde pakket is TSS — TSS.ps1 -Scenario NET_VPN op de client, TSS.ps1 -Scenario NET_RAS op de server, gestart voordat je de storing reproduceert en daarna gestopt48. Leer het voordat iemand erom vraagt.

Als hij op Verbinden blijft staan en dan afloopt

Dit is de storing die de tickets vult, en het woord in de fout is een leugen. Begin met het benoemen van de code. De code is precies, ook als het bericht nergens op slaat.

Een verbindings-time-out is een van drie dingen, en geen daarvan is een klokWat de client een time-out noemt, en wat het werkelijk wasDe client zegt: tijd verlopen809, 718, 828, 930, 638 — vijf codes, één woord, en geen daarvan is een klokHet is een van drie dingen, en één test zegt je welkEr kwam niets aanhet geval stilteTest: capture bij de client — vertrekt UDP 500 en komt er niets terug?Filtering in het pad, of NAT-traversal nooit onderhandeld, dus 4500 is nooit verstuurd.Kwam aan, te groothet geval fragmentTest: verbindt een vooraf gedeelde sleutel waar een certificaat dat niet doet?IKE_AUTH draagt de keten, fragmenteert daardoor, en het fragment wordt in het pad weggegooid.Nooit de tunnelhet geval verkeerde laagTest: logt de gateway op dezelfde seconde een authenticatiefout?930 is RADIUS. 812 is de authenticatiemethode. 13801 en 13806 zijn certificaten.Geen van de drie is een timer.De time-out verlengen is het enige waartoe de interface je uitnodigt, en het enige dat er nog nooiteen van heeft opgelost. Het woord staat er omdat de meldende laag niet ver genoeg ziet om meer te zeggen.Test in die volgorde. De eerste kost dertig seconden capture, de tweede één verbindingspoging, de derde een logboek.
Vijf foutcodes dragen het woord timeout en geen ervan is een klok. Het is een van drie dingen, en één test scheidt ze: een capture zegt of er überhaupt iets terugkwam, één verbindingspoging met een vooraf gedeelde sleutel zegt of de certificaatuitwisseling simpelweg te groot was om aan te komen, en het logboek van de gateway zegt of de tunnel ooit het probleem was. Test in die volgorde, want dat is ook de volgorde van wat ze kosten.
CodeNaam in raserror.hWat er werkelijk gebeurde
809ERROR_VPN_TIMEOUTEr kwam helemaal niets terug. De door Microsoft genoemde oorzaak: “the UDP 500 or 4500 ports on the VPN server or firewall are blocked”47 — maar blocked dekt drie verschillende dingen en maar één daarvan is een verbodsregel. Meestal is 4500 nooit verstuurd, omdat NAT-traversal nooit onderhandeld is, of staat de helper die het vroeger droeg uit. Lees verder voordat je om een firewallwijziging vraagt
789ERROR_OAKLEY_GENERAL_PROCESSING“The L2TP connection attempt failed because the security layer encountered a processing error during initial negotiations” — de inloggegevens of de certificaten, niet het netwerk
718ERROR_PPP_TIMEOUTHet IPsec-deel werkte. PPP in de L2TP-tunnel kreeg geen antwoord
828ERROR_IDLE_TIMEOUT“The connection was terminated because of idle timeout” — een instelling aan de serverkant, met opzet
930ERROR_AUTH_SERVER_TIMEOUTRADIUS antwoordde niet op tijd. Heeft niets met IPsec te maken
638ERROR_REQUEST_TIMEOUTDe algemene. Behandel hem als geen informatie en ga naar de lijn

Elk daarvan komt uit Microsofts eigen foutenlijst49. Lees 809 nu nog eens. Hij heet ERROR_VPN_TIMEOUT, en de gedocumenteerde oorzaak is een geblokkeerde poort. De client loopt niet af omdat de overkant traag is. Hij loopt af omdat de overkant stil is, en stilte is de enige storingsvorm die een protocol zonder poorten en zonder zichtbare handshake kan melden.

Wees wel voorzichtig met het woord blocked, want het draagt meer dan het aankan. Drie verschillende dingen dragen het, en maar één daarvan is een verbodsregel.

Er heeft nooit iemand 4500 gestuurd. NAT-traversal is niet onderhandeld, dus de client bleef ESP spreken, en ESP geeft een vertaler niets om te herschrijven. De standaardinstelling van dat platform is op zichzelf al genoeg reden: zonder de registerwaarde vormt het helemaal geen NAT-T-associatie met een server achter een vertaler31. 4500 is dus niet geblokkeerd. Het is nooit geprobeerd.

De helper die dat vroeger wegpoetste, staat uit. Firewalls en thuisrouters dragen helpers per protocol — IPsec passthrough op consumentenapparatuur, en de hele familie application-layer gateways erachter — die een protocol lezen dat NAT niet aankan en het pad terug ervoor openzetten. Op Linux is de automatische vorm daarvan vanaf kernel 4.7 standaard uitgezet “for security reasons”, met sindsdien het advies om een helper bewust met een regel aan te hangen of helemaal niet; onder de gedekte helpers zit die voor PPTP50.

En ze uitzetten was de juiste keuze. Een helper is een stuk van je firewall dat een payload leest en daarna op grond van wat het las een gat slaat. NAT Slipstreaming is de rekening daarvoor: een browser die een pagina bezoekt, verkeer zo gevormd dat de SIP- of H.323-helper van de router het als een gesprek leest, en een gat door de NAT — in de versie van 2021 naar elk intern adres, niet alleen naar de machine die de pagina laadde51. Helpers uitzetten sluit dat. Het legt ook je IPsec stil. Allebei waar tegelijk, en het tweede is geen argument om het eerste terug te draaien.

Wat opnieuw deze post in het klein is. Het protocol werkte alleen omdat kastjes in het midden verkeer lazen dat hen niet aanging en namens dat protocol gaten openzetten, en de branche heeft het afgelopen decennium volkomen terecht besloten daarmee te stoppen.

Werk de oorzaken dus in deze volgorde af, het goedkoopste eerst.

Eén: er komt niets terug. Capture aan de clientkant, of vraag het de gateway. Gaat UDP 500 eruit en komt er niets terug, dan is het filtering of bereikbaarheid, en geen enkele timer lost dat op. Gaat 500 beide kanten op en verschijnt 4500 nooit, dan is NAT-traversal niet onderhandeld. En zit een van beide kanten achter een vertaler, dan ben je terug bij de registerwaarde van eerder in deze post: AssumeUDPEncapsulationContextOnSendRule, 1 of 2, op beide machines, daarna opnieuw opstarten31. Zonder die waarde weigert de client bij ontwerp, en meldt dat als een time-out.

Twee: het antwoord is te groot om aan te komen. Deze kost hele middagen. Certificaatauthenticatie maakt de tweede uitwisseling groot, want die draagt een keten, en een grote uitwisseling fragmenteert. De fragmenten worden weggegooid door dezelfde tussenkastjes als al het andere in deze post, de client verstuurt opnieuw in hetzelfde gat, en dan geeft hij het op en zegt time-out. Het teken is op zichzelf al de diagnose: een vooraf gedeelde sleutel verbindt wel en een certificaat niet. Dat is geen certificaatstoring. Dat is een groottestoring, want de uitwisseling met een vooraf gedeelde sleutel is klein genoeg om te passen. Gestandaardiseerde IKEv2-fragmentatie bestaat precies hiervoor23, en strongSwan legt vast wanneer dit platform het kreeg: “IKEv2 fragmentation is supported since the v1803 release of Windows 10 and Windows Server”33. Iets ouders, of een gateway met fragmentatie uit, en je vertrouwt op een pad dat een gefragmenteerd UDP-datagram draagt. Een hoop paden doen dat niet.

Drie: hij verbindt en valt dan op de klok uit. Klok het. Sterft hij na een vaste periode zonder verkeer, dan is dat 828 en is het configuratie, geen storing — -IdleDisconnectSeconds op de server, met -SALifeTimeSeconds, -MMSALifeTimeSeconds en -SADataSizeForRenegotiationKilobytes als de drie andere klokken die een sessie kunnen beëindigen52. Die laatste beëindigt hem op volume in plaats van op tijd, en daarom kan een sessie betrouwbaar sterven tijdens een grote bestandskopie en nooit tijdens een dag e-mail. En sterft hij bij het hersleutelen met de client achter NAT, dan is dat de gedocumenteerde interop-storing van eerder: de client weigert een door de server gestart hersleutelen met Microsoft-fout 13863, en het antwoord aan de gatewaykant is ermee ophouden en de client het laten doen33.

Vier: het is de tunnel helemaal niet. 930 is RADIUS. 812 is een authenticatiemethode die de server niet accepteerde47. 13801 en 13806 zijn certificaten — verkeerd uitgebreid sleutelgebruik, verlopen, ontbrekende root, of een servernaam die niet bij het onderwerp van het certificaat past47. De tunnelonderhandeling was in alle vier de gevallen in orde, en als je de middag aan algoritmen besteedt vind je er geen enkele van.

Dit is wat je uit die tabel mee moet nemen. Zes foutcodes, vijf ervan met het woord timeout in de naam, en geen enkele is werkelijk een time-out. Het zijn een geblokkeerde poort, een verloren fragment, een beleidsbeslissing en een RADIUS-server, allemaal met hetzelfde woord om, want de laag die de storing meldt ziet te weinig van wat er gebeurde om iets nuttigers te zeggen. De timer verlengen lost er geen een op, en de timer verlengen is precies waar de interface je toe uitnodigt.

Wat je in plaats daarvan moet draaien

Ik ga niet doen alsof de vervanger exotisch is. Hij zit in de kernel en dat al jaren.

WireGuard is één UDP-poort, één sleutel per peer, geen onderhandeling over cijfers en helemaal geen protocolwendbaarheid. Het standpunt van de auteur daarover is bewust en uitgesproken: “It intentionally lacks cipher and protocol agility. If holes are found in the underlying primitives, all endpoints will be required to update. As shown by the continuing torrent of SSL/TLS vulnerabilities, cipher agility increases complexity monumentally.”53 Die ene beslissing schrapt NO_PROPOSAL_CHOSEN, INVALID_KE_PAYLOAD, downgrade-aanvallen en de bevinding van Logjam in één keer, want er valt niets te onderhandelen en niets te verlagen.

Het is ook eerlijk over de prijs, en ik ook: geen wendbaarheid betekent dat je op de dag dat een primitief valt de hele vloot bijwerkt in plaats van één configuratieregel om te zetten. Dat zijn echte beheerkosten en het zijn de juiste om te betalen.

De rest sluit bijna punt voor punt aan op de lijst hierboven. Een UDP-poort hebben betekent dat NAT en CGNAT het als elke andere stroom behandelen, en dat ECMP en link aggregation het als elke andere stroom hashen. Roaming is ingebouwd in plaats van erop geschroefd — een geauthenticeerd pakket van een nieuw adres verplaatst het eindpunt van de peer, dus een telefoon die van wifi naar mobiel gaat onderhandelt niets opnieuw. Op een niet-geauthenticeerd pakket antwoordt het niets, dus een scanner vindt een gesloten poort waar IPsec hem een concentrator zou bieden om mee te praten. En het past in minder dan 4.000 regels code53, tegenover een stapel die een heel document nodig heeft om zijn zestien onverenigbaarheden met één tussendoos op te sommen.

Qua prestaties mat het simpelweg sneller dan beide IPsec-configuraties waartegen het getest werd: 1.011 Mbit/s tegen 881 en 825, met lagere latentie53. Ik zou een protocol niet uitfaseren op grond van een benchmark. Ik noem het omdat het laatste argument dat voor IPsec overblijft meestal prestaties is, en dat klopt ook niet.

Om een persoon bij een applicatie te krijgen — in plaats van een netwerk bij een netwerk — is het antwoord helemaal geen tunnel. Identiteit aan de voordeur, de applicatie daardoorheen gepubliceerd, niets gerouteerd. Dat heb ik met Proxmox en Cloudflare Access uitgebouwd in Zero-Trust-VDI zonder de cloudrekening, en het relevante punt hier is dat wie drie interne applicaties nodig heeft geen route naar je hele park nodig heeft.

En zeg het stille deel hardop over hardware. Ja, er zijn netwerkkaarten en ASIC’s met ESP-offload, en dat is een echt argument voor IPsec op specifieke apparatuur bij specifieke snelheden. Het is een argument over silicium dat iemand je al verkocht heeft, niet over de juistheid van het protocol. Als zodanig veroudert het, en snel. PPTP heeft precies zo overleefd, precies zolang als het vinkje bestond.

Het netjes uitfaseren

Uitfaseren is een plan met datums, geen gevoel. Dit is het plan waar ik mijn naam aan zou verbinden.

Stop nu met nieuwe IPsec-uitrollen. Niet “alternatieven verkiezen”. Stoppen. Elke nieuwe tunnel is een tunnel die iemand later moet migreren, en die vandaag gebouwd worden draaien in 2035 nog steeds als niemand deze week nee zegt.

Doe toegang op afstand eerst, want daar komt elke storing uit deze post het hardst aan: het CGNAT, het gedeelde adres, de keepalives, de tweede gebruiker in hetzelfde huis, het MTU-gat op een willekeurig hotelnetwerk. Het is ook het makkelijkst te verplaatsen, want de eindpunten worden beheerd en de wijziging is een client.

Daarna site-to-site over het publieke internet, dezelfde problemen met minder eindpunten en een onderhoudsvenster.

Bewaar voor het laatst de tunnels waarvan je niet beide kanten bezit: een partner, een toezichthouder, de managed service van een carrier. Die bewegen als het contract beweegt, en hoe je ze in beweging krijgt staat in het volgende punt.

Koop geen apparatuur meer waarvan de enige tunnel IPsec is. Zet het in de aanbesteding. Een regel die om een moderne, poortgebaseerde, roamingvaste tunnel vraagt, is een regel die een leverancier beantwoordt of niet, en zo verliest het argument van de geïnstalleerde basis uiteindelijk. Dat argument is het enige dat dit alles in leven houdt, en het wordt alleen door inkoop verslagen.

Schrijf op welke tunnels er over zijn en waarom, en zet op elk een datum. Een protocol waar tien jaar niemand van was, is hoe PPTP tot 2026 gekomen is. Een inventarisatie met datums is het verschil tussen iets uitfaseren en het alleen maar niet leuk vinden.

Als je het nog steeds uitrolt, mag je jezelf dan IT-professional noemen?

Dat is een echte vraag, en ik ga hem eerlijk beantwoorden, want het is de vraag waar de rest van deze post naartoe loopt.

Het hangt af van of je het weet. En weten overkomt je niet. Zorgen dat je het weet, is het werk.

Als je dit jaar een nieuwe IPsec-toegang op afstand neerzet en je kunt niet uit je hoofd zeggen waarom ESP geen poorten heeft, wat een woonlijn achter carrier-grade NAT ermee doet, waarom een NAT64-netwerk het helemaal niet draagt, of waar dat ene byte per twintig seconden eigenlijk voor is — dan nee. Hierin niet, nog niet. Je kiest geen protocol. Je herhaalt een vorm, want de vorige zag er zo uit en niemand in de kamer vroeg waarom — jij ook niet. Het falen is niet het gat. Iedereen heeft gaten. Het falen is bouwen over een gat dat je nooit bent gaan dichten. Als zodanig krijgt degene die het in 2035 erft een decennium aan tickets die allemaal te vermijden waren op de dag dat jij het tekende.

En ik geef het de juiste naam, want de beleefde versie gaat al twintig jaar rond en heeft niets veranderd. Wie een protocol uitrolt dat hij niet kan uitleggen, is geen engineer. Die is een volger. Die leest kaartjes voor — de referentiearchitectuur van de leverancier, het laatste wijzigingsverzoek, een tekening die iemand in 2014 maakte en die sindsdien niemand heeft geopend — en leest ze voor met echte overtuiging, en achter het optreden zit geen begrip. Van buiten ziet dat er precies uit als vakmanschap. Het blijft er ook precies uitzien als vakmanschap, tot de eerste storing die de kaartjes niet dekken, en vanaf dat moment is het het enige in de kamer dat ertoe doet.

De kaartjes zijn ook de reden dat dit protocol er nog is. Niemand stond in 2026 bij een whiteboard IPsec inhoudelijk te verdedigen. Het werd opnieuw uitgerold omdat het op het kaartje stond, en het kaartje is geschreven door een leverancier wiens belang is dat je de doos blijft kopen die het termineert. Zo overleeft iets zijn eigen overlijdensbericht met twintig jaar — niet door verdedigd te worden, maar door zich nooit één keer te hoeven verantwoorden in een kamer waar iemand het verschil zou merken.

En dit wordt hardop gezegd. In de kamer, op het moment zelf — niet achteraf op de gang gemompeld. Wie het woord professional naast zijn naam zet, krijgt met dat woord de uitnodiging om bevraagd te worden, en vragen is niet onbeleefd. Bevraagd worden en een antwoord hebben is het hele verschil tussen het woord en een visitekaartje.

Het telt het zwaarst als je ervoor betaalt. Een adviesbureau, een MSP, de professional-services-tak van een leverancier, de integrator op het raamcontract — wat je koopt is oordeelsvermogen, en oordeelsvermogen is het enige dat je bij levering niet kunt keuren. Keur het dus vooraf. Vraag waarom dit protocol en niet een ander. Vraag wat ermee gebeurt op een lijn achter carrier-grade NAT, op een IPv6-only mobiel netwerk, op een pad dat stilletjes fragmenten weggooit. Vraag welke daarvan ze zelf hebben meegemaakt en wat ze toen deden. Je weet binnen twee minuten of je iets verteld krijgt of wordt voorgelezen, en twee minuten is een flink goedkopere test dan vier jaar tickets. En als het antwoord uit kaartjes bestaat en je tekent toch, dan is dat ook een besluit — het is alleen net van hen naar jou verhuisd.

Kun je dat allemaal wél zeggen en rol je het toch uit omdat een toezichthouder het bij naam voorschrijft, omdat de apparatuur van de partner niets anders termineert, of omdat de vervanger in het budget van volgend jaar staat en dit in maart moet werken — dan ja, uiteraard, en dan doe je je werk goed. Randvoorwaarden zijn echt, en ik heb om ergere heen gebouwd. Wat de twee scheidt is niet het protocol op de tekening. Het is of je hebt opgeschreven waarom, en of er een datum naast staat.

De onverdedigbare positie is de middelste. Genoeg weten om er ongemakkelijk van te worden, en het toch bouwen omdat niemand je dwong het te verantwoorden. Geen engineering. Gewoonte, met een wijzigingsnummer erop — en precies zo belandde L2TP op een datasheet die dit jaar gedrukt is.

Stel jezelf die vraag dus vóór de aanbesteding sluit, niet erna. Professional is geen woord over welke protocollen je kent. Het is een woord over of je het gekozen protocol hardop kunt verdedigen, tegenover iemand die de storingsvormen kent. Kun je dat, rol dan uit wat de randvoorwaarden eisen en slaap prima. Kun je dat niet, dan heb je net gevonden wat je vanavond gaat lezen, en dat is geen belediging. Iedereen was ooit een volger, zonder uitzondering, ik ook. Wat niet te verdedigen is, is ervoor kiezen er een te blijven en dat een loopbaan noemen.

Een goed idee mag ook voorbij zijn

Ik wil recht doen aan IPsec, want dat verdient het.

Het was het juiste instinct. Beveiliging hoort laag in de stapel, waar alles het erft en geen enkele applicatie vertrouwd hoeft te worden om het goed te doen. De association aan het adres binden was in 1995 geen fout — het adres was de machine, en daarop bouwen was juist. De mensen die het schreven waren serieuze mensen met een echt probleem, en uitgerekend het WireGuard-artikel zegt het het best: de gelaagdheid van IPsec is deugdelijk, alles zit op de juiste plek, tot academische perfectie toe53.

En toen bewoog de grond. Niet omdat IPsec iets fout deed, maar omdat deze branche besloot dat adressen een te beheren kostenpost waren in plaats van iets dat elke machine krijgt, en vijfentwintig jaar vertaling bouwde om het alternatief te ontlopen. IPsec werd stilletjes het fundament ontnomen, en in plaats van dat toe te geven hebben we ondersteund. UDP-encapsulatie. Toen keepalives. Toen TCP-encapsulatie voor de netwerken die UDP blokkeren. Toen nog een UDP-header zodat een router iets vindt om op te hashen. Elke oplossing op zich redelijk; de stapel ervan is een protocol dat overeind wordt gehouden door mensen die betaald worden om het overeind te houden.

Dat is het deel dat woede verdient, en het gaat eigenlijk helemaal niet over IPsec. Onze branche is heel goed in dingen onderhouden en heel slecht in ze beëindigen. Onderhoud is factureerbaar, begroot, bemenst en veilig. Uitfaseren is een beslissing die iemand moet tekenen, met zijn naam eronder, en zonder directe beloning. Dus leefde PPTP veertien jaar voort na het bewijs van zijn waardeloosheid, wordt L2TP nog steeds geleverd op dozen die dit jaar verkocht worden, en bleef IKEv1 nog een decennium na zijn Historic-status tunnels onderhandelen. Niet omdat iemand ze verdedigde. Maar omdat niemand ooit verplicht was ze te beëindigen.

Er is geen prijs voor 90 % goed. Ferguson en Schneier schreven dat in 1999 over IPsec, en wat er sindsdien gebeurd is, zijn dertig jaar waarin de branche de laatste 10 % elke keer op een nieuwe manier fout deed en de pleister een oplossing noemde.

Een goed idee mag ook voorbij zijn. Weten wanneer je moet ophouden iets te onderhouden is een vaardigheid, en het is die waarin dit vak het slechtst is. Iemand moet degene zijn die zegt dat een protocol zijn leven gehad heeft, de datum opschrijft en de gevolgen draagt van degene te zijn geweest die het zei. Anders sturen we in 2040 nog elke twintig seconden een pakket van één byte, om een tabel warm te houden in een doos die niet van ons is, op een netwerk dat ons onze adressen afnam en ons ervoor liet betalen.


  1. RFC 4301 — Security Architecture for the Internet Protocol, december 2005. Definieert de security association en het drietal waarop hij wordt opgezocht: bestemmingsadres, beveiligingsprotocol en SPI. ↩︎ ↩︎

  2. RFC 4302 — IP Authentication Header, december 2005. De integriteitscontrole van AH dekt de onveranderlijke velden van de IP-header, bron- en bestemmingsadres inbegrepen. ↩︎ ↩︎

  3. RFC 9329 — TCP Encapsulation of Internet Key Exchange Protocol (IKE) and IPsec Packets, november 2022, vervangt RFC 8229. Bestaat omdat tussendozen op publieke netwerken UDP blokkeren. ↩︎ ↩︎ ↩︎

  4. RFC 3715 — IPsec-Network Address Translation (NAT) Compatibility Requirements, maart 2004. Zestien opgesomde onverenigbaarheden, waaronder: “Since the AH header incorporates the IP source and destination addresses in the keyed message integrity check, NAT or reverse NAT devices making changes to address fields will invalidate the message integrity check.” en “Where IP addresses are used as identifiers in Internet Key Exchange Protocol (IKE) Phase 1 or Phase 2, modification of the IP source or destination addresses by NATs or reverse NATs will result in a mismatch between the identifiers and the addresses in the IP header.” ↩︎ ↩︎ ↩︎

  5. Cisco — Configuring IPsec NAT-Traversal, Security Configuration Guide, Cisco IOS XE 17.15.x (Catalyst 9300 Switches). “If PAT found a legislative IP address and port, it would drop the Encapsulating Security Payload (ESP) packet”; de UDP-header en een acht byte lange niet-IKE-markering worden tussen de buitenste IP-header en de ESP-header gezet; de beperkingenlijst noemt statische regels voor poort 500 en 4500, geen ondersteuning voor dynamisch NAT-beleid, geen IPv6, en dat IPsec en NAT niet allebei op hetzelfde apparaat kunnen werken. ↩︎ ↩︎ ↩︎ ↩︎

  6. RFC 3948 — UDP Encapsulation of IPsec ESP Packets, januari 2005, met de onderhandeling in RFC 3947. Definieert de keepalive als “a one-octet-long payload with the value 0xFF”, verstuurd “if no other packet to the peer has been sent in M seconds. M is a locally configurable parameter with a default value of 20 seconds.”, en eist dat de UDP-checksum op nul gaat: “If the protocol header after the ESP header is a UDP header, set the checksum field to zero in the UDP header.” Microsoft, Cisco, F-Secure, Nortel en SafeNet staan allemaal op de auteurslijsten van RFC 3947 en RFC 3948. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  7. Juniper — Route-Based and Policy-Based VPNs with NAT-T, Junos OS IPsec VPN User Guide. “NAT-T encapsulates both IKE and ESP traffic within UDP with port 4500 used as both the source and destination port”; “Because NAT devices age out stale UDP translations, keepalive messages are required between the peers”; en op SRX5400, SRX5600 en SRX5800: “the total number of tunnels from a given public translated IP cannot exceed 1000 tunnels.” ↩︎ ↩︎ ↩︎

  8. RFC 8221 — Cryptographic Algorithm Implementation Requirements and Usage Guidance for ESP and AH, oktober 2017. ENCR_DES MUST NOT, ENCR_3DES SHOULD NOT, AUTH_HMAC_MD5_96 MUST NOT; ESP samen met AH is NOT RECOMMENDED. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  9. RFC 4787 — Network Address Translation (NAT) Behavioral Requirements for Unicast UDP, januari 2007. REQ-5: “A NAT UDP mapping timer MUST NOT expire in less than two minutes”, met “a default value of five minutes or more for the NAT UDP mapping timer is RECOMMENDED”. ↩︎ ↩︎

  10. RFC 6146 — Stateful NAT64: Network Address and Protocol Translation from IPv6 Clients to IPv4 Servers, april 2011. “The current specification only defines how stateful NAT64 translates unicast packets carrying TCP, UDP, and ICMP traffic. Multicast packets and other protocols, including the Stream Control Transmission Protocol (SCTP), the Datagram Congestion Control Protocol (DCCP), and IPsec, are out of the scope of this specification.” Pakketten met iets anders “SHOULD be discarded”. ↩︎ ↩︎

  11. RFC 6877 — 464XLAT: Combination of Stateful and Stateless Translation, april 2013. Geeft een IPv6-only-apparaat een lokale IPv4-stack zodat verkeer werkt dat NAT64 niet kan dragen. ↩︎

  12. IETF — draft-xu-ipsecme-esp-in-udp-lb, Encapsulating IPsec ESP in UDP for Load-balancing. “Although the ESP SPI field within the IPsec packets can be used as the load-balancing key, but it cannot be used by legacy switches and routers”; “Many cloud service providers allow customers to establish multiple IPsec VPN tunnels in parallel to enable ECMP and increase aggregate bandwidth. However, this approach is not ideal, as each tunnel typically requires its own public IP address, leading to higher public IP consumption and increased operational overhead.” ↩︎ ↩︎

  13. Cisco — Resolve IPv4 Fragmentation, MTU, MSS, and PMTUD Issues with GRE and IPsec. De al lang onderhouden referentie over tunneloverhead, path MTU discovery en wat er stukgaat als de ICMP-fouten niet terugkomen. ↩︎

  14. Cisco — Troubleshoot IPsec Anti-Replay Check Failures. “Certain QoS features, such as Low Latency Queueing (LLQ), could cause IPsec packet delivery to become out-of-order and dropped by the receiving endpoint due to a replay check failure.” Standaardvenster 64 pakketten; 1024 op nieuwere platformen; het andere middel zijn meerdere volgnummerruimtes per association. ↩︎ ↩︎ ↩︎

  15. RFC 2661 — Layer Two Tunneling Protocol “L2TP”, augustus 1999. Een tunnelprotocol voor PPP zonder eigen vertrouwelijkheid op pakketniveau; de beveiligingsparagraaf verwijst naar IPsec. ↩︎

  16. Moxie Marlinspike en David Hulton — Divide and Conquer: Cracking MS-CHAPv2 with a 100% Success Rate, 2012; gereedschap op github.com/moxie0/chapcrack. De beveiliging van MS-CHAPv2 brengt zich ongeacht de wachtwoordlengte terug tot één DES-bewerking; verslag uit die tijd in The Register. Hun conclusie was PPTP-verkeer als onversleuteld te beschouwen. ↩︎ ↩︎

  17. Apple — If you see a “VPN Using PPTP May Not Be Secure” alert. PPTP is in 2016 uit de ingebouwde client van macOS Sierra en iOS 10 gehaald. ↩︎

  18. RFC 4303 — IP Encapsulating Security Payload (ESP), december 2005. IP-protocol 50; de ESP-header draagt de SPI en het volgnummer en heeft geen poortveld. ↩︎

  19. RFC 9395 — Deprecation of the Internet Key Exchange Version 1 (IKEv1) Protocol and Obsolete Cryptographic Algorithms, april 2023. “Internet Key Exchange Version 1 (IKEv1) has been deprecated, and RFCs 2407, 2408, and 2409 have been moved to Historic status.” ↩︎ ↩︎

  20. RFC 7296 — Internet Key Exchange Protocol Version 2 (IKEv2), oktober 2014. De huidige sleuteluitwisseling, en de bron van de notify-namen in de diagnosetabel. ↩︎ ↩︎

  21. RFC 3173 — IP Payload Compression Protocol (IPComp), september 2001. Een eigen IP-protocolnummer en eigen associations, naast ESP onderhandeld. ↩︎

  22. RFC 2367 — PF_KEY Key Management API, Version 2, juli 1998. De kernelinterface waarmee een sleuteldaemon associations installeert. ↩︎

  23. RFC 7383 — IKEv2 Message Fragmentation, november 2014. “This document describes a way to avoid IP fragmentation of large Internet Key Exchange Protocol version 2 (IKEv2) messages.” ↩︎ ↩︎

  24. RFC 4555 — IKEv2 Mobility and Multihoming Protocol (MOBIKE), juni 2006. Laat een opgezette tunnel een adreswisseling overleven. ↩︎

  25. RFC 3706 — A Traffic-Based Method of Detecting Dead Internet Key Exchange (IKE) Peers, februari 2004. ↩︎

  26. draft-beaulieu-ike-xauth — Extended Authentication within IKE (XAUTH). Laatste revisie 02, oktober 2001, status Expired, “Expired & archived”, nooit als RFC gepubliceerd. Het concept legt vast dat het als Informational werd aangeboden omdat “the IPSRA working group will not accept any protocol which extends ISAKMP or IKE, and the IPsec working group refuses to accept any protocols that deal with remote access.” Mode-Config onderging hetzelfde lot. ↩︎ ↩︎ ↩︎ ↩︎

  27. RFC 3193 — Securing L2TP using IPsec, november 2001. Mede geschreven bij Microsoft. ↩︎

  28. RFC 2332 — NBMA Next Hop Resolution Protocol (NHRP), april 1998. Het stuk waarmee DMVPN-spokes elkaar vinden. ↩︎

  29. RFC 6407 — The Group Domain of Interpretation, oktober 2011. Groepssleutels, zoals GETVPN ze gebruikt. ↩︎

  30. RFC 2637 — Point-to-Point Tunneling Protocol (PPTP), juli 1999. Categorie: Informational. Een opgeschreven leveranciersprotocol, nooit een standaard. ↩︎ ↩︎ ↩︎

  31. Microsoft — Configure L2TP/IPsec server behind NAT-T device, KB 926179, voor het laatst herzien op 12 februari 2026. “By default, Windows Vista and Windows Server 2008 don’t support Internet Protocol security (IPsec) network address translation (NAT) Traversal (NAT-T) security associations to servers that are located behind a NAT device”; de DWORD-waarde AssumeUDPEncapsulationContextOnSendRule onder HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PolicyAgent neemt 0 (standaard, kan niet), 1 (server achter NAT) of 2 (beide kanten achter NAT), en de machine moet herstarten. Ook: “If you must use IPsec for communication, use public IP addresses for all servers that you can connect to from the Internet.” ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  32. strongSwan — Windows Certificate Requirements. Het gatewaycertificaat heeft de EKU serverAuth nodig, OID 1.3.6.1.5.5.7.3.1, en de EKU IP Security IKE Intermediate, OID 1.3.6.1.5.5.8.2.2. ↩︎

  33. strongSwan — Windows Clients. Documenteert het toevoegen van de DWORD NegotiateDH2048_AES256 onder Rasman\Parameters voor AES-256-CBC en MODP-2048; de hersleutel-noodoplossing voor clients achter NAT (rekey_time = 0 op de gateway, de client begint); en dat de Windows-client “does not currently support IKE redirection (RFC 5685) and multiple authentication rounds (RFC 4739)”. Daarnaast: “IKEv2 fragmentation is supported since the v1803 release of Windows 10 and Windows Server”, en clients achter NAT weigeren een door de server gestarte CHILD_SA-hersleuteling met Microsoft-fout 13863. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  34. Microsoft — DirectAccess en Remote Access Always On VPN migration overview. DirectAccess is afgeschaft en wordt in een toekomstige versie van Windows Server verwijderd; klanten worden naar Always On VPN verwezen. ↩︎

  35. Jean Paul Degabriele en Kenneth G. Paterson — Attacking the IPsec Standards in Encryption-only Configurations, IEEE Symposium on Security and Privacy, 2007. Aanvallen die “break any RFC-compliant implementation of IPsec making use of encryption-only ESP”, uit louter de cijfertekst, en die niet meer vergen dan verkeer meelezen en pakketten injecteren. ↩︎ ↩︎

  36. RFC 6434 — IPv6 Node Requirements, december 2011. “Previously, IPv6 mandated implementation of IPsec and recommended the key management approach of IKE. This document updates that recommendation by making support of the IPsec Architecture [RFC4301] a SHOULD for all IPv6 nodes.” ↩︎ ↩︎

  37. Niels Ferguson en Bruce Schneier — A Cryptographic Evaluation of IPsec, Counterpane Internet Security, 1999. “IPsec was a great disappointment to us”; “Our main criticism of IPsec is its complexity”; “We therefore recommend that transport mode be eliminated”; “We conclude that eliminating transport mode allows the elimination of the AH protocol as well, without loss of functionality”; en “We have found serious security weaknesses in all major components of IPsec. As always in security, there is no prize for getting 90% right; you have to get everything right.” ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  38. David Adrian e.a. — Imperfect Forward Secrecy: How Diffie-Hellman Fails in Practice, ACM CCS 2015. Voorberekening voor een tweede 1024-bits groep “would allow decryption of traffic to 66% of IPsec VPNs”; 86,1 % van de gescande IKEv1- en 91,0 % van de IKEv2-servers ondersteunde Oakley-groep 2, en 66,1 % van de geprofileerde IKEv1-servers prefereerde die. ↩︎

  39. CVE-2016-1287 en Cisco’s advisory, Cisco ASA Software IKEv1 and IKEv2 Buffer Overflow Vulnerability. Code-uitvoering op afstand vóór authenticatie, bereikt met geprepareerde UDP-pakketten naar de IKE-dienst. ↩︎

  40. Juniper — How to Analyze IKE Phase 2 VPN Status Messages. “No proposal chosen” betekent dat het apparaat “did not accept any of the IKE Phase 2 proposals that the peer sent”. ↩︎

  41. Cisco — Understand and Use Debug Commands to Troubleshoot IPsec en Troubleshoot Common L2L and Remote Access IPsec VPN Issues. ↩︎

  42. Juniper — Troubleshoot a VPN Tunnel That is Down. ↩︎

  43. Linux-kernel — XFRM proc counters. De beschrijvingen in de tabel komen uit de kerneldocumentatie zelf. ↩︎

  44. Juniper — Troubleshoot a VPN That Is Up But Not Passing Traffic. “If only the pkts counter in the out direction of the session is incrementing, then validate with the VPN peer that the traffic is being received.” ↩︎

  45. Microsoft — netsh wfp, Windows Commands. netsh wfp capture start “Starts a capture session for network events processed by WFP” en schrijft standaard wfpdiag.cab; netsh wfp show state “Displays the current state of WFP and IPsec”; netsh wfp show ikeevents “Displays recent Internet Key Exchange (IKE) epoch events matching the specified parameters” en accepteert een filter remoteaddr=. Met file=- schrijft elke show naar de console in plaats van XML. ↩︎

  46. Microsoft — Get-NetIPsecQuickModeSA, module NetSecurity. “There is only one main mode SA between a pair of computers, but there can be many quick mode SAs”, en het monitoren ervan “can provide information about which peers are currently connected to this computer, and which protection suite is protecting the data exchanged between them”. ↩︎

  47. Microsoft — Troubleshoot Always On VPN, laatst herzien op 12 februari 2026. Over het lezen van de clientlogboeken: “look for events labeled RasClient. All error messages return the error code at the end of the message.” Oorzaak van fout 809: “You can encounter this issue when the UDP 500 or 4500 ports on the VPN server or firewall are blocked.” Fout 812 is een verschil in authenticatiemethode tussen het beleid van de server en het profiel van de client. De vier genoemde oorzaken van 13801 zijn een machinecertificaat zonder Server Authentication in het uitgebreide sleutelgebruik, een verlopen RAS-machinecertificaat, een client zonder het rootcertificaat, en een client waarvan de “VPN server name doesn’t match the subjectName value on the server certificate”; 13806 is “IKE can’t find a valid machine certificate”. ↩︎ ↩︎ ↩︎ ↩︎

  48. Microsoft — Guidance for troubleshooting Remote Access (VPN and AOVPN). De ondersteunde verzameling is TSS, verhoogd uitgevoerd: TSS.ps1 -Scenario NET_VPN op de client en TSS.ps1 -Scenario NET_RAS op de server, met de storing gereproduceerd tussen start en stop en de sporen geschreven naar C:\MS_DATA. ↩︎

  49. Microsoft — Routing and Remote Access Error Codes, de codes gedefinieerd in raserror.h. 638 ERROR_REQUEST_TIMEOUT; 718 ERROR_PPP_TIMEOUT; 789 ERROR_OAKLEY_GENERAL_PROCESSING, “The L2TP connection attempt failed because the security layer encountered a processing error during initial negotiations with the remote computer”; 809 ERROR_VPN_TIMEOUT, “The network connection between your computer and the VPN server could not be established because the remote server is not responding”; 828 ERROR_IDLE_TIMEOUT, “The connection was terminated because of idle timeout”; 930 ERROR_AUTH_SERVER_TIMEOUT, “The authentication server did not respond to authentication requests in a timely fashion”. ↩︎

  50. firewalld — Automatic Helper Assignment. “With kernel 4.7 and up the automatic helper assignment in kernel has been turned off by default”, gestuurd door de sysctl onder /proc/sys/net/netfilter/nf_conntrack_helper, en “for the secure use of iptables and connection tracking helpers it is recommended to turn AutomaticHelpers off”. De kernelmelding over de wijziging noemt de reden en de vervanging: de automatische toewijzing “has been turned off for security reasons”, gebruik in plaats daarvan het CT-target. De gedekte helpers zijn onder meer ftp, irc, sip, h323, tftp, snmp en pptp. ↩︎

  51. Samy Kamkar — NAT Slipstreaming, v1 van 31 oktober 2020, v2 van 26 januari 2021 met Ben Seri en Gregory Vishnipolsky van Armis. De aanval misbruikt “the Application Level Gateway (ALG) connection tracking mechanism built into NATs, routers, and firewalls” om “bypass victim NAT and connect directly back to any port on any machine on the network, exposing previously protected/hidden services and systems”. v1 gebruikte de SIP-gateway op poort 5060, v2 H.323 op 1720, waarmee het gat op elke interne host gericht kon worden in plaats van alleen op de machine die de pagina laadde. ↩︎

  52. Microsoft — Set-VpnServerConfiguration, module RemoteAccess. -IdleDisconnectSeconds “Specifies the time, in seconds, after which an idle connection is terminated”; -SALifeTimeSeconds en -MMSALifeTimeSeconds zetten de levensduur van quick mode en main mode; -SADataSizeForRenegotiationKilobytes “Specifies the number of kilobytes that are allowed to transfer using a security association (SA), after which the SA will be renegotiated”. ↩︎

  53. Jason A. Donenfeld — WireGuard: Next Generation Kernel Network Tunnel, NDSS 2017. “It intentionally lacks cipher and protocol agility. If holes are found in the underlying primitives, all endpoints will be required to update. As shown by the continuing torrent of SSL/TLS vulnerabilities, cipher agility increases complexity monumentally”; “implemented for Linux in less than 4,000 lines of code”; “it is important to stress, however, that the layering of IPsec is correct and sound; everything is in the right place with IPsec, to academic perfection”. Metingen: 1.011 Mbit/s tegen 881 en 825 voor twee IPsec-cijfersuites, en 0,403 ms ping tegen 0,501 en 0,508. ↩︎ ↩︎ ↩︎ ↩︎