✦Engineering

NAT traversal uitgelegd: hoe een P2P-extern bureaublad door je router heen reikt.

Je hebt één openbaar IP-adres en een dozijn apparaten achter je router. Je iPad zit op mobiel internet, drie netwerken verderop. Toch opent een app voor extern bureaublad in minder dan een seconde een directe verbinding van het ene naar het andere — meestal zonder relay ertussen. Zo werkt die magie echt: ICE, STUN, TURN, hole punching en de ongemakkelijke waarheid over symmetrische NAT.

Waarom dit belangrijk is

Stel je een dinsdagochtend voor. Je Mac mini staat thuis achter een router met één openbaar IPv4-adres. Je iPad zit in de trein, op het mobiele netwerk van een provider met eigen lagen van adresvertaling. Tussen de twee apparaten zitten minstens twee NAT's, waarschijnlijk drie. Geen van beide machines is standaard bereikbaar vanaf het open internet.

En toch open je Remio op de iPad, tik je op de Mac en een seconde later kijk je naar je bureaublad. Beeld en invoer lopen rechtstreeks tussen de twee apparaten — geen cloudrelay, geen proxy ertussen die je scherm opnieuw codeert.

De techniek die dit mogelijk maakt heeft een naam — NAT traversal — en een familie van duidelijk gedefinieerde protocollen erachter: STUN, TURN en ICE. Dit zijn dezelfde protocollen die WebRTC gebruikt voor videobellen in de browser, en ze zijn de reden dat elk modern P2P-extern bureaublad kan voorkomen dat je schermframes door het datacenter van een derde moeten. Dit artikel loopt door wat ze elk doen, waarom ze bestaan en hoe ze samen het pad met de laagste latentie vinden tussen twee apparaten die achter routers schuilen.

Het NAT-probleem in 60 seconden

Het internet is ontworpen zodat elk apparaat een eigen, openbaar routeerbaar adres had. Er zijn in de hele ruimte zo'n 4,3 miljard IPv4-adressen — ruim voldoende in 1981, en eind jaren negentig overduidelijk te weinig.

De oplossing was Network Address Translation. Je router krijgt van je provider één openbaar IPv4-adres. Binnen je huis krijgt elk apparaat een privéadres uit een gereserveerd bereik (meestal 192.168.x.x of 10.x.x.x). Wanneer je laptop een pakket verstuurt, herschrijft de router het bronadres naar zijn eigen openbare IP, onthoudt de koppeling en stuurt door. Komt het antwoord terug, dan zoekt de router de koppeling op en herschrijft hij het bestemmingsadres weer naar je laptop.

Precies daarom werken inkomende verbindingen standaard niet. Van buitenaf heeft je laptop geen adres; alleen de router heeft er een. Het pakket van een vreemde naar je-router-openbaar-ip:5060 komt bij een router zonder koppeling en wordt weggegooid.

Voor een P2P-app is dit het hele spel. Beide partijen zitten achter routers die alleen pakketten doorlaten als ze zich herinneren eerst zelf iets naar buiten te hebben gestuurd. Geen van beide kan de ander simpelweg "bellen" — ze moeten met hun routers samenwerken om tijdelijk een pad te openen.

Hole punching: de firewall je weer binnen laten

Dit is de truc. De NAT-tabel van je router werkt met een vijfvoud: bron-IP, bronpoort, bestemmings-IP, bestemmingspoort en protocol. Wanneer je apparaat een uitgaand UDP-pakket naar 1.2.3.4:5678 stuurt, maakt de router een tijdelijke regel: "als er een UDP-pakket van 1.2.3.4:5678 terugkomt naar mijn openbare IP op poort X, stuur het dan door naar dit apparaat op poort Y."

Die regel bestaat een tijdje — meestal 30 tot 60 seconden — en verloopt dan, tenzij iets hem ververst. In dat venster wordt elk pakket van het bestemmingsadres geaccepteerd.

Dit is het sleutelgat dat P2P-apps gebruiken. Als beide partijen elkaars openbare adres kennen, kunnen ze allebei tegelijk één uitgaand UDP-pakket naar de ander sturen. De router van elke kant opent een uitgaande koppeling. Het eerste pakket van elke kant wordt goed mogelijk weggegooid — de andere router heeft zijn koppeling nog niet geopend — maar het tweede pakket kan wel ergens heen. Vanaf dat moment denken beide routers dat ze een gewoon uitgaand gesprek doorsturen, en praten de twee apparaten rechtstreeks met elkaar.

Dit heet UDP hole punching. Het is een klein wonder, goed gedocumenteerd (RFC 5128) en werkt voor de overgrote meerderheid van consumenten-NAT's in het wild. De overige gevallen — symmetrische NAT, CGNAT, bedrijfsfirewalls — zijn de reden dat TURN bestaat.

Hole punching is geen hack. Het is precies het contract waaromheen NAT is ontworpen: een uitgaand pakket geeft inkomende toestemming. P2P-apps sturen dat uitgaande pakket alleen met opzet.

STUN: "wat is mijn openbare adres?"

Hole punching heeft één voorwaarde: elke partij moet haar eigen openbare adres kennen om de ander te kunnen vertellen waarheen pakketten moeten. Dat adres is van binnen het apparaat niet zichtbaar. Je iPad ziet zijn lokale wifi-adres (192.168.1.42). Wat de rest van het internet ziet nadat de router het pakket heeft herschreven, is iets heel anders.

STUN — Session Traversal Utilities for NAT, RFC 5389 — is het kleine protocol dat dit oplost. De werking is bijna beschamend simpel:

  1. De partij stuurt een UDP-pakket naar een openbare STUN-server. (Remio gebruikt voor redundantie zowel de openbare STUN-servers van Cloudflare als die van Google.)
  2. De STUN-server leest het bron-IP en de bronpoort van de lijn — wat per definitie het door NAT vertaalde openbare adres van de partij is.
  3. De STUN-server antwoordt met dat adres als inhoud: "Voor zover ik kan zien, ben jij 203.0.113.42:48291."
  4. De partij weet nu welk adres ze aan de andere kant moet doorgeven.

Dat openbare adres heet in ICE-terminologie een server-reflexive candidate. Het kost vrijwel niets — één rondreis tijdens het opzetten van de verbinding, en geen extra bandbreedte of latentie nadat de verbinding er is. STUN heeft maar één taak: twee partijen aan elkaar voorstellen; zodra ze praten, speelt de STUN-server geen rol meer.

TURN: wanneer hole punching mislukt

Hole punching werkt voor de meeste NAT's, maar niet voor alle. De mislukkingen zijn echt, en een P2P-app die doet alsof ze niet bestaan, kan voor een aanzienlijk deel van de gebruikers simpelweg geen verbinding maken.

De belangrijkste boosdoeners:

Voor deze gevallen is de terugvaloptie TURN — Traversal Using Relays around NAT, RFC 5766. Een TURN-server is een relay die beide partijen kunnen bereiken omdat hij een openbaar adres heeft dat altijd inkomend verkeer accepteert. Elke partij maakt een gewone uitgaande TLS-verbinding naar de TURN-server (die elke NAT toestaat), en de server stuurt bytes door tussen beide kanten.

TURN kost echt iets. Elk videopakket moet een extra netwerkstap nemen. Bij een regionale TURN-relay komt daar zo'n 30 tot 80 milliseconden rondreislatentie bij. Over regio's heen — zeg een relay in Frankfurt voor een partij in Tokio en een partij in São Paulo — kan het 80 tot 200 milliseconden zijn. De TURN-beheerder betaalt ook voor bandbreedte: elke bit van je stream gaat door zijn leidingen.

Daarom gebruikt een goed ontworpen app TURN alleen wanneer hole punching aantoonbaar is mislukt. ICE regelt die beslissing automatisch.

ICE: alle kandidaten tegelijk proberen

Interactive Connectivity Establishment, RFC 8445, is de choreografie die dit alles samenbindt. ICE kiest niet vooraf een strategie. Het verzamelt elk mogelijk kandidaatadres voor elke partij, wisselt de volledige lijst met de andere kant uit, en laat dan beide stacks elk kandidaatpaar tegelijk testen — een race om het eerste te vinden dat werkt.

Voor elke partij verzamelt ICE doorgaans:

De twee partijen wisselen deze lijsten uit via een signaleringskanaal — bij Remio is dat een kleine WebSocket-verbinding met relay.remio.net die de ICE-kandidaten en de WebRTC-sessiebeschrijving (de SDP) doorgeeft en daarna niets meer te doen heeft zodra de media gaan stromen.

Zodra beide lijsten binnen zijn, begint ICE met connectiviteitscontroles. Elke partij stuurt in volgorde van prioriteit een STUN-binding-request langs elk kandidaatpaar. De prioriteiten zijn zo ontworpen dat het pad met de laagste latentie de voorkeur krijgt:

  1. Host naar host — beide partijen op hetzelfde lokale netwerk. Dit is het droomgeval: een paar honderd microseconden latentie, geen router in het spel.
  2. Host naar server-reflexive, of server-reflexive naar server-reflexive — partijen op verschillende netwerken, via hole punching door hun eigen NAT's heen. Dit is in de praktijk meestal wat "P2P via internet" betekent.
  3. Alles met een relay — laatste redmiddel, alleen gebruikt als alle paden met hogere prioriteit hun connectiviteitscontroles niet doorstaan.

Het eerste kandidaatpaar waarbij beide richtingen slagen, wordt als winnaar benoemd en de media gaan over dat pad stromen. Het hele proces is doorgaans ruim binnen een seconde klaar.

ICE verzamelt kandidaten ook continu. Verschijnt er midden in een sessie een beter pad — bijvoorbeeld doordat je telefoon van mobiel internet op wifi overstapt — dan kan ICE naar het nieuwe pad overschakelen zonder het gesprek te verbreken.

Waarom Remio zo sterk de voorkeur geeft aan P2P

Remio is een app voor extern bureaublad, geen videogesprek. Het latentiebudget is moordend. Wil een sessie aanvoelen alsof je aan de hostmachine zit, dan moet de hele pijplijn — vastleggen, coderen, netwerk, decoderen, weergeven — piepklein zijn: op een lokaal netwerk kost het zo'n 8 ms, en de rest is de eigen verversingsfrequentie van 60 Hz van je scherm (ongeveer 16,7 ms per frame). Elke extra stap is een zonde.

Bij een directe P2P-verbinding op een lokaal netwerk is het netwerkdeel van dat budget zo'n 1 tot 5 milliseconden heen en terug. Er is geen relay; de bytes gaan rechtstreeks van het ene apparaat naar het andere. Met de pijplijn van Remio komt dat op zo'n 8 ms verwerking op een lokaal netwerk (intern gemeten; de rest is de eigen verversingsfrequentie van 60 Hz van je scherm) — je invoer landt vóór het volgende frame wordt getekend. De externe machine voelt niet te onderscheiden van een lokale.

Bij een verbinding via een TURN-relay — zelfs een regionale — springt het netwerkdeel naar 30 tot 80 milliseconden. De totale door de gebruiker ervaren latentie is dan 40 tot 100 ms. Nog steeds bruikbaar voor de meeste taken, maar je voelt het bij een snelle sleepbeweging of een snelle reeks klikken. Het trackpad voelt niet meer helemaal als van jou.

Dat verschil is waarom we zoveel moeite doen om sessies op P2P te houden. De WebRTC-stack van Remio verzamelt zowel IPv4- als IPv6-kandidaten, spreekt meerdere STUN-servers tegelijk aan en geeft bij de selectie van kandidaatparen door ICE sterk de voorkeur aan directe paden. Intern gebruiken we zelfs de gemeten rondreistijd van de verbinding om het netwerk te classificeren — onder 15 ms weten we dat het een lokaal netwerk is, zodat de encoder hoog begint en veel meer bandbreedte mag gebruiken. Alles wat trager is, wordt als WAN behandeld en voorzichtiger afgesteld.

En — dit is het deel dat concurrenten vaak stilzwijgend weglaten — de verbinding is end-to-end versleuteld, ongeacht het pad. Je scherm raakt onze servers nooit aan, en zelfs een TURN-relay ziet alleen cijfertekst: sleutels worden rechtstreeks tussen de twee partijen afgesproken tijdens de handshake, voordat er ook maar één pixel beweegt. Of de bytes nu via P2P of via TURN stromen, noch de signaleringsserver van Remio noch de TURN-beheerder kan ze lezen. P2P betekent alleen dat er helemaal geen derde partij op het datapad zit.

Wanneer een relay onvermijdelijk is (en dat is prima)

Soms zeggen de netwerkgoden nee. Symmetrische NAT aan beide kanten, dubbele CGNAT bij een mobiele provider met een strenge isp, een bedrijfsfirewall die alleen uitgaand TLS naar bekende cloudproviders toestaat — dit zijn echte, gangbare configuraties. In die gevallen moet de sessie via een relay lopen of het lukt helemaal niet.

De TURN-backend van Remio is Cloudflare Calls, dat ons een wereldwijd netwerk van relays dicht bij de meeste gebruikers geeft. Kiest ICE een relaypad, dan gaat de ervaring van "voelt lokaal" naar "voelt als Splashtop" — nog steeds goed bruikbaar, maar je merkt het. De extra latentie komt uit op 30 tot 80 ms bij een regionale relay; over regio's heen kan het 200 ms worden.

Het belangrijkste: de data blijft end-to-end versleuteld. Cloudflare ziet versleutelde UDP-pakketten de ene kant op en versleutelde UDP-pakketten de andere kant op. Het kan bytes tellen voor facturering. Het kan je scherm, je toetsaanslagen of enige sessie-inhoud niet zien. Ook aan de kant van Remio is er geen punt waar ontsleuteld wordt, want er zit geen Remio-cloud in de pijplijn — we beheren de TURN-dienst via Cloudflare en raken de payloads nooit aan.

Dit is de architectuur die ons beveiligingswhitepaper in meer detail beschrijft. Kort gezegd: P2P of relay, het dreigingsmodel is hetzelfde.

De IPv6-nooduitgang

IPv6 heeft 340 sextiljoen adressen (3,4 × 1038) — genoeg om elk zandkorrel op aarde een eigen openbaar IP te geven, met een paar biljoen over. In een wereld met alleen IPv6 is NAT grotendeels overbodig. Twee apparaten met IPv6 kunnen elkaar gewoon pakketten sturen, en het enige obstakel is de hostfirewall aan beide kanten.

Heb je IPv6 thuis en bij je mobiele provider, dan is je misschien opgevallen dat sommige apps sneller verbinden wanneer beide kanten IPv6 hebben — omdat de hele dans van "kandidaten verzamelen, paren testen" dan minder obstakels kent. Er is geen NAT-vertaling te ontdekken, geen STUN-rondje nodig, alleen directe adressen.

Maar dit is het addertje: in 2026 is de wereldwijde uitrol nog niet af. Veel thuisrouters ondersteunen IPv6 slecht of helemaal niet. Veel bedrijfsnetwerken blokkeren inkomend IPv6 standaard. Sommige providers bieden IPv6 aan de radiozijde aan maar bruggen elders naar IPv4. Pure IPv6-naar-IPv6-paden bestaan, maar je kunt er niet op vertrouwen als enig mechanisme.

Dus verzamelt Remio — net als elke serieuze P2P-stack — zowel IPv4- als IPv6-kandidaten en laat ICE ze tegen elkaar racen. Bestaat er een direct IPv6-pad en werkt het, dan wint het meestal op latentie. Zo niet, dan neemt IPv4 met hole punching het over. Mislukken beide, dan relay. De gebruiker ziet hier niets van; de verbinding komt gewoon tot stand.

Zo weet je welk pad je sessie gebruikt

Benieuwd op welk pad je sessie terecht is gekomen? De verbindingsindicator van Remio toont het type in gewone taal — "Direct" voor P2P, "Relay" voor TURN. Het statistiekenpaneel voor ontwikkelaars toont de volledige WebRTC-status, inclusief de kandidaattypen van het gekozen paar (host, srflx, relay) en de gemeten RTT.

Een paar snelle interpretaties:

Val je betrouwbaar terug op een relay, zelfs thuis, dan zijn de gebruikelijke verdachten een isp-modem die symmetrische NAT doet, IPv4-CGNAT op je thuisverbinding (vaker dan je denkt bij wederverkopers van glasvezel), of een overijverige firewall die inkomend UDP blokkeert. Onze gids om vertraging op extern bureaublad te verminderen loopt de gangbare boosdoeners langs, en de pagina over directe verbinding op het lokale netwerk is de snelle route als beide apparaten op jouw netwerk zitten.

Prestatiecijfers uit de praktijk

Alles bij elkaar zijn dit de latentiecijfers die we in productie meten over de verschillende paden die een Remio-sessie kan nemen:

Dit komt overeen met de cijfers in de benchmarks van Remio en verklaart waarom we de grens tussen lokaal netwerk en WAN op 15 ms RTT leggen — die scheidt directe paden netjes van elke relay (minimaal 30 ms) of mobiel pad (minimaal 40 ms), met zeer weinig valse positieven.

NAT traversal is zo'n onderwerp waarbij de protocollen afzonderlijk simpel zijn maar de combinatoriek lastig. De meeste gebruikers hoeven nooit te weten dat ICE, STUN en TURN bestaan — ze merken alleen een app die snel verbindt van overal naar overal. De protocollen doen hun werk als je ze niet opmerkt. Merk je ze wel op — een sessie duurt net te lang, of "Direct" wordt "Relay" — dan heb je nu het mentale model.

Lees voor meer over de native pijplijn van Remio en de keuzes die 1–5 ms netwerklatentie omzetten in zo'n 8 ms verwerking (de rest is de eigen verversingsfrequentie van 60 Hz van je scherm) waarom native ertoe doet. Voor het dreigingsmodel van relaypaden, zie het beveiligingswhitepaper. Of bekijk de functies en download Remio om het te voelen werken.

✦Vragen

Veelgestelde vragen

Wat is NAT traversal?
NAT traversal is het geheel van technieken dat een peer-to-peer-app gebruikt om een directe verbinding op te zetten tussen twee apparaten die elk achter een thuis- of kantoorrouter zitten. Omdat routers veel privé-IP-adressen vertalen naar één openbaar IP (Network Address Translation, of NAT), worden inkomende verbindingen standaard geblokkeerd. NAT traversal — vooral ICE, STUN en TURN — ontdekt het openbare adres van elk apparaat, opent een tijdelijk pad door beide routers en valt alleen terug op een relayserver als directe hole punching mislukt.
Hoe werkt STUN?
STUN (Session Traversal Utilities for NAT) is een klein verzoek-antwoordprotocol. De client stuurt een UDP-pakket naar een openbare STUN-server, en de server antwoordt met het bron-IP en de bronpoort die hij daadwerkelijk op de lijn zag — dat is het door NAT vertaalde adres van de client zoals het openbare internet het ziet. De client geeft dat adres via een signaleringskanaal door aan zijn peer, zodat die weet waarheen hij pakketten moet sturen. STUN zelf voegt tijdens het opzetten van de verbinding zo'n één rondreis latentie toe en daarna geen overhead.
Wat is het verschil tussen STUN en TURN?
STUN vertelt alleen elke partij haar eigen openbare adres, zodat ze een directe verbinding kunnen proberen. TURN stuurt media daadwerkelijk door via een server in de cloud wanneer de directe verbinding niet tot stand kan komen. STUN voegt vrijwel geen latentie of bandbreedtekosten toe; TURN voegt een stap toe, die bij een regionale relay ongeveer 30 tot 80 milliseconden latentie kost en bandbreedte aan serverzijde verbruikt. Een goed ontworpen P2P-app gebruikt eerst STUN en valt alleen terug op TURN als het nodig is.
Waarom valt mijn extern bureaublad terug op een relay?
Directe peer-to-peer hole punching mislukt wanneer een of beide kanten achter symmetrische NAT, carrier-grade NAT (gangbaar op mobiele netwerken) of een strikte bedrijfsfirewall zitten die de benodigde UDP-stroom blokkeert. In die gevallen valt de app terug op een TURN-relay, zodat de verbinding toch werkt. De sessie blijft end-to-end versleuteld — de relay ziet alleen ondoorzichtige versleutelde blobs — maar voegt 30 tot 80 milliseconden latentie toe bij een regionale relay en tot 200 milliseconden tussen regio's.
Wat is ICE in WebRTC?
ICE (Interactive Connectivity Establishment) is het raamwerk dat alle technieken voor adresontdekking combineert en ze tegelijk probeert. Elke partij verzamelt een lijst met kandidaatadressen — lokaal netwerk (host), openbaar via STUN (server-reflexive) en via TURN doorgestuurd — en wisselt de lijst uit met de andere kant. De twee stacks sturen tegelijk testpakketten langs elk kandidaatpaar, en het eerste paar dat slaagt, wint. Kandidaten met hogere prioriteit (host, dan server-reflexive, dan relay) hebben de voorkeur, zodat het pad met de laagste latentie wordt gekozen wanneer het beschikbaar is.
Maakt IPv6 NAT traversal overbodig?
Grotendeels wel — IPv6 geeft elk apparaat een routeerbaar openbaar adres, zodat twee partijen met IPv6 rechtstreeks kunnen verbinden zonder vertaling. Maar in 2026 is een groot deel van de thuis- en mobiele netwerken nog alleen IPv4 of dual-stack, en veel firewalls blokkeren inkomend IPv6 standaard. NAT traversal blijft dus nodig als terugvaloptie, en de meeste productie-apps verzamelen zowel IPv4- als IPv6-kandidaten en laten ICE het pad kiezen dat het snelst verbindt.
App-icoon van Remio

Voel het directe pad.

Remio laat elke kandidaat racen om de route met de laagste latentie naar je machine te vinden — geen port forwarding, geen vpn, end-to-end versleuteld via P2P of relay.

Gratis te gebruikenGeen accountGekoppeld in 30 seconden