Inleiding

Moderne bedrijfscontentfilteringsystemen, van gerenommeerde fabrikanten zoals Cisco, BlueCoat en FireEye, hebben veel gemeen met hun krachtigere tegenhangers - DPI-systemen, die grootschalig worden geĆÆmplementeerd op nationaal niveau. De kern van hun werking is om het inkomende en uitgaande internetverkeer te inspecteren en op basis van zwarte/witte lijsten besluiten te nemen over het blokkeren van internetverbindingen. Aangezien beide systemen gebaseerd zijn op vergelijkbare principes, zullen ook de methoden om hen te omzeilen veel overeenkomsten vertonen.
Een van de technologieƫn die effectief kan helpen om zowel DPI- als bedrijfsystemen te omzeilen, is domein-fronting. Het idee is om naar een geblokkeerde bron te gaan, waarbij we ons verbergen achter een andere, openbare domeinnaam met een goede reputatie, die zeker niet door enig systeem geblokkeerd zal worden, bijvoorbeeld google.com.
Er zijn al veel artikelen geschreven over deze technologie en er zijn tal van voorbeelden gegeven. De populaire en recent besproken technologieƫn DNS-over-HTTPS en encrypted-SNI, evenals de nieuwe versie van het TLS 1.3-protocol, bieden de mogelijkheid om een alternatieve vorm van domein-fronting te overwegen.
Laten we de technologie onder de loep nemen
Laten we eerst enkele basisconcepten definiƫren, zodat iedereen begrijpt wie wie is en waarom dit allemaal nodig is. We hebben het mechanismen eSNI genoemd, waarvan de werking verder zal worden besproken. Het eSNI-mechanisme (encrypted Server Name Indication) is een beveiligde variant van SNI, die alleen beschikbaar is voor het TLS 1.3-protocol. Het belangrijkste idee is dat ook de informatie over welk domein het verzoek ontvangt, versleuteld wordt.
Laten we nu eens kijken naar de praktische werking van het eSNI-mechanisme.
Stel, we hebben een internetbron die wordt geblokkeerd door een modern DPI-oplossing (laten we het beroemde torrent-tracker ā rutracker.nl ā nemen als voorbeeld). Bij het proberen om de website van de torrent-tracker te bezoeken, zien we de standaard blokkering van de provider die aangeeft dat de bron geblokkeerd is:

Op de RKN-website staat deze domeinnaam inderdaad op de zwarte lijsten:

Bij het opvragen van whois is te zien dat het domein zelf 'verborgen' is achter de cloudprovider Cloudflare.

Maar in tegenstelling tot de 'specialisten' van de RKN, hebben de technisch beter onderlegde medewerkers van Beeline (of zij die hebben geleerd van de bittere ervaring van onze beroemde regulator) de website niet simpelweg geblokkeerd op IP-adres, maar hebben ze het stoplijst toegepast op het domeinname. Dit is gemakkelijk te verifiƫren door te kijken welke andere domeinen zich achter dezezelfde IP-adres, een van hen te bezoeken en te zien dat de toegang niet geblokkeerd is:

Hoe komt dit? Hoe weet de DPI van de provider op welk domein mijn browser zich richt, aangezien alle communicatie via het https-protocol verloopt, en we hebben tot nu toe geen vervangingen van https-certificaten van Beeline waargenomen? Heeft hij een helderziende gave of wordt er achter mij aan gespiekt?
Laten we deze vraag proberen te beantwoorden door naar het verkeer te kijken via Wireshark.

Op de screenshot is te zien dat de browser eerst het IP-adres van de server via DNS ontvangt, daarna vindt een standaard TCP-handshake met de doelserver plaats, en vervolgens probeert de browser een ssl-verbinding met de server tot stand te brengen. Hiervoor verzendt hij een pakket SSL Client Hello, waarin de naam van het oorspronkelijke domein in open tekst aanwezig is. Dit veld is nodig voor de frontend-server van Cloudflare om de verbinding correct te routeren. Hier vangt de provider DPI ons, door onze verbinding te verbreken. We ontvangen geen melding van de provider, en zien de standaard foutmelding van de browser alsof de website is uitgeschakeld of gewoon niet werkt:

Laten we nu de eSNI-mechanisme in de browser inschakelen, zoals beschreven in de instructies voor Firefox :
Hiervoor openen we de configuratiepagina van Firefox about:config en schakelen we de volgende instellingen in:
network.trr.mode = 2;
network.trr.uri = https://mozilla.cloudflare-dns.com/dns-query
network.security.esni.enabled = true
Daarna controleren we de correctheid van de instellingen op de Cloudflare-website via de link en proberen we de truc met onze torrent tracker nogmaals.

VoilĆ . Onze favoriete tracker is geopend, zonder enige VPN of proxyservers. Laten we nu eens naar de traffic dump in Wireshark kijken, wat er gebeurd is.

Dit keer bevat het SSL-client-hello-pakket niet expliciet het doel-domein, maar in plaats daarvan is er een nieuw veld toegevoegd aan het pakket ā encrypted_server_name ā daar bevindt zich de waarde rutracker.nl, en alleen de frontend-server van Cloudflare kan dit veld decrypten. Aangezien dit zo is, blijft de provider DPI niets anders over dan zich erbij neer te leggen en dit verkeer toe te laten. En er zijn geen andere opties voor encryptie.
Dus, we hebben de technologie in de browser bekeken ā nu laten we het toepassen voor meer specifieke en interessante dingen. Laten we beginnen met het leren van dezelfde curl om eSNI te gebruiken voor TLS 1.3, terwijl we ook bekijken hoe domein-fronting werkt op basis van eSNI.
Domein-fronting met eSNI
Aangezien curl de standaard openssl-bibliotheek gebruikt voor HTTPS-verbindingen, moeten we eerst zorgen dat eSNI daar wordt ondersteund. In de master-tak van openssl is er momenteel geen ondersteuning voor eSNI, dus we moeten een speciale tak van openssl downloaden, compileren en installeren.
Laten we de repository van GitHub klonen en compileren zoals gewoonlijk:
$ git clone https://github.com/sftcd/openssl
$ cd openssl
$ ./config
$ make
$ cd esnistuff
$ make
Vervolgens klonen we de curl-repository en configureren we de compilatie met onze gebouwde openssl-bibliotheek:
$ cd $HOME/code
$ git clone https://github.com/niallor/curl.git curl-esni
$ cd curl-esni
$ export LD_LIBRARY_PATH=/opt/openssl
$ ./buildconf
$ LDFLAGS="-L/opt/openssl" ./configure --with-ssl=/opt/openssl --enable-esni --enable-debug
Het is belangrijk om de juiste mappen op te geven waar openssl zich bevindt (in ons geval is dit /opt/openssl/) en ervoor te zorgen dat het configuratieproces zonder fouten verloopt.
Bij een succesvolle configuratie zien we de regel:
WARNING: esni ESNI ingeschakeld maar gemarkeerd als EXPERIMENTAL. Gebruik met voorzichtigheid!
$ makeNa een succesvolle compilatie van het pakket zullen we een speciaal bash-bestand uit de openssl-structuur gebruiken om curl in te stellen en te starten. Laten we het kopiƫren naar de curl-map voor gemakkelijke toegang:
cp /opt/openssl/esnistuff/curl-esni en we voeren een test https-verzoek uit naar de Cloudflare-server, terwijl we tegelijkertijd DNS- en TLS-pakketten op Wireshark opnemen.
$ ESNI_COVER="www.hello-rkn.ru" ./curl-esni https://cloudflare.com/In de serverreactie, naast veel debug-informatie van openssl en curl, ontvangen we een HTTP-respons met code 301 van Cloudflare.
HTTP/1.1 301 Moved Permanently
< Date: Sun, 03 Nov 2019 13:12:55 GMT
< Transfer-Encoding: chunked
< Connection: keep-alive
< Cache-Control: max-age=3600
< Expires: Sun, 03 Nov 2019 14:12:55 GMT
< Location: https://www.cloudflare.com/
wat aantoont dat ons verzoek succesvol is afgeleverd bij de bestemmingsserver, gehoord en verwerkt.
Laten we nu kijken naar de verkeersdump in Wireshark, d.w.z. wat de provider DPI in dit geval heeft gezien.

We zien dat curl eerst contact heeft opgenomen met de DNS-server voor de publieke eSNI-sleutel voor de Cloudflare-server ā TXT DNS-verzoek op _esni.cloudflare.com (pakket #13). Vervolgens heeft curl, met behulp van de OpenSSL-bibliotheek, een TLS 1.3-verzoek naar de Cloudflare-server gestuurd waarin het SNI-veld was versleuteld met de publieke sleutel die in de vorige stap was verkregen (pakket #22). Maar naast het eSNI-veld was er ook een normaal ā open SNI-veld in het SSL-hello-pakket opgenomen, dat we in willekeurige volgorde kunnen opgeven (in dit geval ā www.hello-rkn.ru).
Dit open SNI-veld werd niet meegerekend bij de verwerking door de Cloudflare-servers en fungeerde alleen als camouflage voor de provider DPI. De Cloudflare-server accepteerde ons ssl-hello-pakket, decoderen eSNI, haalde daar het originele SNI uit en verwerkte dit zoals gepland (precies zoals bedoeld bij de ontwikkeling van eSNI).
Het enige waar we in dit geval iets mee kunnen met betrekking tot DPI, is het primaire DNS-verzoek naar _esni.cloudflare.com. Maar we hebben het DNS-verzoek open gedaan om te tonen hoe dit mechanisme intern werkt.
Om de grond onder de voeten van de DPI definitief weg te halen, maken we gebruik van het eerder genoemde mechanisme voor DNS-over-HTTPS. Een korte uitleg ā DOH ā is een protocol dat helpt beschermen tegen 'man-in-the-middle'-aanvallen door DNS-verzoeken via het HTTPS-protocol te verzenden.
Laten we de aanvraag opnieuw uitvoeren, maar deze keer zullen we de publieke eSNI-sleutels via het https-protocol verkrijgen, niet via DNS:
ESNI_COVER="www.hello-rkn.ru" DOH_URL=https://mozilla.cloudflare-dns.com/dns-query ./curl-esni https://cloudflare.com/De verkeersdump van het verzoek staat op de onderstaande screenshot:

We zien dat curl eerst contact opneemt met de server mozilla.cloudflare-dns.com via het DoH-protocol (https-verbinding met server 104.16.249.249) om de publieke sleutels voor het versleutelen van SNI te verkrijgen, en vervolgens verbinding maakt met de bestemmingsserver, zich verbergend achter het domein www.hello-rkn.ru.
Naast de eerder genoemde DoH-resolver mozilla.cloudflare-dns.com kunnen we ook andere populaire DoH-diensten gebruiken, bijvoorbeeld van de beruchte kwaadaardige corporation.
Laten we zo'n verzoek uitvoeren:
ESNI_COVER="www.kremlin.ru" DOH_URL=https://dns.google/dns-query ./curl-esni https://rutracker.nl/En we krijgen een antwoord:
< HTTP/1.1 301 Permanent Moved
< Date: Sun, 03 Nov 2019 14:10:22 GMT
< Content-Type: text/html
< Transfer-Encoding: chunked
< Connection: keep-alive
< Set-Cookie: __cfduid=da0144d982437e77b0b37af7d00438b1a1572790222; expires=Mon, 02-Nov-20 14:10:22 GMT; path=/; domain=.rutracker.nl; HttpOnly; Secure
< Location: https://rutracker.nl/forum/index.php
< CF-Cache-Status: DYNAMIC
< Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
< Server: cloudflare
< CF-RAY: 52feee696f42d891-CPH

In dit geval hebben we toegang gekregen tot de geblokkeerde server rutracker.nl, waarbij we de DoH-resolver dns.google hebben gebruikt (er is geen typfout, het beroemde bedrijf heeft nu zijn eigen top-level domein) en ons hebben verhuld met een andere domeinnaam, die onder zware straffen verboden is voor alle DPI. Uit het ontvangen antwoord kan worden opgemaakt dat ons verzoek succesvol is verwerkt.
Als extra controle of de provider DPI reageert op de open SNI die we als dekmantel gebruiken, kunnen we een verzoek naar rutracker.nl doen, ons verhullend met een andere verboden bron, bijvoorbeeld een andere 'goede' torrenttracker:
$ ESNI_COVER="rutor.info" DOH_URL=https://dns.google/dns-query ./curl-esni https://rutracker.nl/We zullen geen antwoord van de server ontvangen, omdat ons verzoek door het DPI-systeem zal worden geblokkeerd.
Korte conclusie bij het eerste deel
We hebben laten zien dat eSNI werkt met behulp van openssl en curl, en dat we de werking van domein-framing op basis van eSNI hebben gecontroleerd. Op dezelfde manier kunnen we onze favoriete tools die de openssl-bibliotheek gebruiken, aanpassen voor 'onder dekmantel' van andere domeinen. Meer hierover in onze volgende artikelen.
Bron: habr.com
