Hoe we de Grote Chinese Firewall doorbraken (deel 2)

Hey there!

Nikita is weer bij u, een systeemingenieur van het bedrijf SEMrush. En met dit artikel vervolg ik het verhaal over hoe we tot een oplossing kwamen Chinese firewall voor onze service semrush.com.

В vorig deel Ik zei:

  • welke problemen ontstaan ​​nadat de beslissing is genomen “We moeten onze service in China laten werken”
  • Welke problemen heeft het Chinese internet?
  • Waarom heb je een ICP-licentie nodig?
  • hoe en waarom we besloten om onze testbedden met Catchpoint te testen
  • wat was het resultaat van onze eerste oplossing op basis van Cloudflare China Network
  • Hoe we een bug in Cloudflare DNS hebben gevonden

Dit deel is naar mijn mening het meest interessant omdat het zich richt op specifieke technische implementaties van enscenering. En daar gaan we mee beginnen, of beter gezegd, mee doorgaan Alibaba Cloud.

Alibaba Cloud

Alibaba Cloud is een vrij grote cloudprovider, die alle diensten in huis heeft waarmee zij zich met recht een cloudprovider mag noemen. Het is goed dat ze de mogelijkheid hebben om zich te registreren voor buitenlandse gebruikers, en dat het grootste deel van de site in het Engels is vertaald (voor China is dit een luxe). In deze cloud kunt u met veel regio's van de wereld, het vasteland van China en Oceanisch Azië (Hong Kong, Taiwan, enz.) werken.

IPSEC

We zijn begonnen met aardrijkskunde. Omdat onze testsite zich op Google Cloud bevond, moesten we Alibaba Cloud met GCP ‘koppelen’, dus openden we een lijst met locaties waar Google aanwezig is. Op dat moment hadden ze nog geen eigen datacenter in Hong Kong.
De dichtstbijzijnde regio bleek te zijn Azië-Oost1 (Taiwan). Ali bleek de regio van het Chinese vasteland die het dichtst bij Taiwan lag cn-shenzhen (Shenzhen).

Met terraform heeft de gehele infrastructuur in GCP en Ali beschreven en verhoogd. Een tunnel van 100 Mbit/s tussen de wolken ging vrijwel onmiddellijk omhoog. Aan de kant van Shenzhen en Taiwan kwamen proxying-virtuele machines op de markt. In Shenzhen wordt het gebruikersverkeer beëindigd, via een proxy via een tunnel naar Taiwan gestuurd, en van daaruit gaat het rechtstreeks naar het externe IP-adres van onze service in ons-oost (Oostkust van de VS). Ping tussen virtuele machines via tunnel 24ms, wat niet zo erg is.

Tegelijkertijd hebben we een testruimte geplaatst Alibaba Cloud-DNS. Nadat de zone aan NS Ali was gedelegeerd, daalde de oplossingstijd van 470 ms naar 50 ms. Voordien lag de zone ook op Cloudlfare.

Parallel aan de tunnel naar Azië-Oost1 hief een andere tunnel rechtstreeks van Shenzhen op us-oost4. Daar creëerden ze meer proxy-virtuele machines en begonnen ze beide oplossingen te testen, waarbij ze testverkeer routerden met behulp van cookies of DNS. In de volgende figuur wordt de proefbank schematisch beschreven:

De latentie voor tunnels bleek als volgt:
Ali cn-shenzhen <—> GCP Azië-Oost1 — 24 ms
Ali cn-shenzhen <—> GCP us-oost4 — 200 ms

Catchpoint-browsertests rapporteerden een uitstekende verbetering.

Vergelijk testresultaten voor twee oplossingen:

beslissing
Uptime
Mediaan
75 percentiel
95 percentiel

Cloudflare
86.6
18s
30s
60s

IPsec
99.79
18s
21s
30s

Dit zijn gegevens van een oplossing die gebruikmaakt van een IPSEC-tunnel via Azië-Oost1. Via us-east4 waren de resultaten slechter en waren er meer fouten, dus ik zal de resultaten niet geven.

Op basis van de resultaten van deze test van twee tunnels, waarvan er één eindigt in de dichtstbijzijnde regio bij China, en de andere op de eindbestemming, werd duidelijk dat het belangrijk is om zo snel mogelijk onder de Chinese firewall vandaan te ‘komen’. mogelijk, en maak dan gebruik van snelle netwerken (CDN-providers, cloudproviders etc.). U hoeft niet te proberen door de firewall heen te komen en in één klap uw bestemming te bereiken. Dit is niet de snelste manier.

Over het algemeen zijn de resultaten niet slecht, maar semrush.com heeft een mediaan van 8.8 seconden en 75 percentiel 9.4 seconden (op dezelfde test).
En voordat ik verder ga, wil ik graag een korte lyrische uitweiding maken.

Lyrische retraite

Nadat de gebruiker de site heeft betreden www.semrushchina.cn, dat wordt opgelost via ‘snelle’ Chinese DNS-servers, gaat het HTTP-verzoek via onze snelle oplossing. Het antwoord wordt langs hetzelfde pad geretourneerd, maar het domein wordt gespecificeerd in alle JS-scripts, HTML-pagina's en andere elementen van de webpagina semrush.com voor extra bronnen die moeten worden geladen wanneer de pagina wordt weergegeven. Dat wil zeggen dat de client het “hoofd” A-record oplost www.semrushchina.cn en gaat de snelle tunnel in, ontvangt snel een antwoord - een HTML-pagina waarop staat:

  • download die en die js van sso.semrush.com,
  • Haal de CSS-bestanden op van cdn.semrush.com,
  • en maak ook enkele foto's van dab.semrush.com
  • enzovoort.

De browser begint voor deze bronnen naar het “externe” internet te gaan, telkens wanneer hij door een firewall gaat die de responstijd opslokt.

Maar de vorige test toont de resultaten als er geen bronnen op de pagina staan semrush.comalleen semrushchina.cn, en *.semrushchina.cn verwijst naar het adres van de virtuele machine in Shenzhen om vervolgens in de tunnel te komen.

Alleen op deze manier, door al het mogelijke verkeer maximaal door uw oplossing te duwen en zo snel de Chinese firewall te passeren, kunt u acceptabele snelheden en indicatoren voor de beschikbaarheid van websites verkrijgen, evenals eerlijke resultaten van oplossingstests.
We hebben dit gedaan zonder een enkele codebewerking aan de productkant van het team.

Subfilter

De oplossing werd vrijwel onmiddellijk geboren nadat dit probleem aan de oppervlakte kwam. Wij hadden nodig PoC (Proof of Concept) dat onze oplossingen voor firewallpenetratie echt goed werken. Om dit te doen, moet u al het siteverkeer zoveel mogelijk in deze oplossing verwerken. En wij hebben gesolliciteerd subfilter in nginx.

Subfilter is een vrij eenvoudige module in nginx waarmee je de ene regel in de antwoordtekst naar een andere regel kunt wijzigen. Daarom hebben we alle gebeurtenissen gewijzigd semrush.com op semrushchina.cn in alle antwoorden.

En... het werkte niet omdat we gecomprimeerde inhoud van de backends ontvingen, dus het subfilter vond de vereiste regel niet. Ik moest een andere lokale server aan nginx toevoegen, die het antwoord decomprimeerde en doorgaf aan de volgende lokale server, die al bezig was de string te vervangen, te comprimeren en naar de volgende proxyserver in de keten te sturen.

Als gevolg hiervan, waar zou de klant ontvangen .semrush.com, hij ontving .semrushchina.cn en liep gehoorzaam door onze beslissing.

Het is echter niet voldoende om het domein eenvoudigweg op één manier te wijzigen, omdat de backends nog steeds semrush.com verwachten bij volgende verzoeken van de klant. Dienovereenkomstig halen we op dezelfde server waar de eenrichtingsvervanging wordt uitgevoerd, met behulp van een eenvoudige reguliere expressie het subdomein uit het verzoek, en dan doen we dat proxy_pass met variabele $ gastheer, tentoongesteld in $subdomein.semrush.com. Het lijkt misschien verwarrend, maar het werkt. En het werkt goed. Voor individuele domeinen die andere logica vereisen, maakt u eenvoudig uw eigen serverblokken aan en maakt u een afzonderlijke configuratie. Hieronder staan ​​verkorte nginx-configuraties voor de duidelijkheid en demonstratie van dit schema.

De volgende configuratie verwerkt alle verzoeken van China naar .semrushchina.cn:

    listen 80;

    server_name ~^(?<subdomain>[w-]+).semrushchina.cn$;

    sub_filter '.semrush.com' '.semrushchina.cn';
    sub_filter_last_modified on;
    sub_filter_once off;
    sub_filter_types *;

    gzip on;
    gzip_proxied any;
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript;

    location / {
        proxy_pass http://127.0.0.1:8083;
        proxy_set_header Accept-Encoding "";
        proxy_set_header Host $subdomain.semrush.com;
        proxy_set_header X-Accept-Encoding $http_accept_encoding;
    }
}

Deze configuratie proxy's voor localhost naar poort 83, en de volgende configuratie wacht daar:

    listen 127.0.0.1:8083;

    server_name *.semrush.com;

    location / {
        resolver 8.8.8.8 ipv6=off;
        gunzip on;
        proxy_pass https://$host;
        proxy_set_header Accept-Encoding gzip;
    }
}

Ik herhaal, dit zijn bijgesneden configuraties.

Zoals dat. Het lijkt misschien ingewikkeld, maar het zit in woorden. Eigenlijk is alles eenvoudiger dan gestoomde rapen :)

Einde van de uitweiding

Een tijdje waren we blij omdat de mythe over vallende IPSEC-tunnels niet werd bevestigd. Maar toen begonnen de tunnels te vallen. Meerdere keren per dag gedurende een paar minuten. Een beetje, maar dat beviel ons niet. Omdat beide tunnels aan de Ali-kant op dezelfde router waren afgesloten, besloten we dat dit misschien een regionaal probleem was en dat we de back-upregio moesten verhogen.

Ze hebben het opgehaald. De tunnels begonnen op verschillende tijdstippen te falen, maar de failover werkte prima voor ons op upstream-niveau in nginx. Maar toen begonnen de tunnels ongeveer tegelijkertijd te vallen :) En 502 en 504 begonnen opnieuw te vallen. De uptime begon te verslechteren, dus begonnen we aan de optie te werken met Alibaba CEN (Cloud Enterprise-netwerk).

CEN

CEN - dit is de connectiviteit van twee VPC's uit verschillende regio's binnen Alibaba Cloud, dat wil zeggen dat u privénetwerken van alle regio's binnen de cloud met elkaar kunt verbinden. En het allerbelangrijkste: dit kanaal heeft een vrij strikte SLA. Het is zeer stabiel, zowel qua snelheid als uptime. Maar zo eenvoudig is het nooit:

  • het is ZEER moeilijk te verkrijgen als u geen Chinees staatsburger of rechtspersoon bent,
  • U moet betalen voor elke megabit kanaalcapaciteit.

De mogelijkheid hebben om verbinding te maken Vasteland van China и overzeehebben we een CEN gecreëerd tussen twee Ali-regio's: cn-shenzhen и ons-oost-1 (dichtstbijzijnde punt bij ons-oost4). In Ali ons-oost-1 heeft nog een virtuele machine gemaakt, zodat er nog één is hop.

Het bleek zo:

De resultaten van de browsertest staan ​​hieronder:

beslissing
Uptime
Mediaan
75 percentiel
95 percentiel

Cloudflare
86.6
18s
30s
60s

IPsec
99.79
18s
21s
30s

CEN
99.75
16s
21s
27s

De prestaties zijn iets beter dan IPSEC. Maar via IPSEC kun je potentieel downloaden met een snelheid van 100 Mbit/s, en via CEN alleen met een snelheid van 5 Mbit/s en meer.

Klinkt als een hybride, toch? Combineer IPSEC-snelheid en CEN-stabiliteit.

Dit is wat we hebben gedaan, waardoor verkeer door zowel IPSEC als CEN mogelijk is in het geval van een storing in de IPSEC-tunnel. De uptime is veel hoger geworden, maar de laadsnelheid van de site laat nog steeds veel te wensen over. Vervolgens tekende ik alle circuits die we al hadden gebruikt en getest, en besloot te proberen wat meer GCP aan dit circuit toe te voegen, namelijk pet.

pet

pet - Is Wereldwijde load-balancer (of Google Cloud Load Balancer). Het heeft voor ons een belangrijk voordeel: in de context van een CDN wel anycast-IP, waarmee u verkeer kunt routeren naar het datacenter dat zich het dichtst bij de klant bevindt, zodat verkeer snel in het snelle netwerk van Google terechtkomt en minder via het ‘gewone’ internet.

Zonder er twee keer over na te denken, verhoogden we HTTP/HTTPSLB We hebben onze virtuele machines met subfilter in GCP en als backend geïnstalleerd.

Er waren verschillende regelingen:

  • Gebruiken Cloudflare China-netwerk, maar deze keer zou Origin globaal moeten specificeren IP GLB.
  • Beëindig klanten op cn-shenzhen, en van daaruit proxy het verkeer rechtstreeks naar pet.
  • Ga rechtstreeks vanuit China naar pet.
  • Beëindig klanten op cn-shenzhen, van daaruit proxy naar Azië-Oost1 via IPSEC (in us-oost4 via CEN), vandaar naar GLB (rustig, hieronder volgt een foto en uitleg)

We hebben al deze opties en nog een aantal hybride opties getest:

  • Wolkflare + GLB

Dit schema beviel ons niet vanwege uptime en DNS-fouten. Maar de test werd uitgevoerd voordat de bug aan de CF-kant was opgelost, misschien is het nu beter (dit sluit HTTP-time-outs echter niet uit).

  • Ali + GLB

Dit schema beviel ons ook niet qua uptime, aangezien GLB vaak uit de upstream viel vanwege de onmogelijkheid om binnen een acceptabele tijd of time-out verbinding te maken, omdat voor een server in China het GLB-adres buiten blijft, en dus achter de Chinese firewall. De magie gebeurde niet.

  • Alleen GLB

Een optie vergelijkbaar met de vorige, alleen werd er geen gebruik gemaakt van servers in China zelf: het verkeer ging rechtstreeks naar GLB (de DNS-records werden gewijzigd). Dienovereenkomstig waren de resultaten niet bevredigend, aangezien gewone Chinese klanten die de diensten van gewone internetproviders gebruiken, een veel slechtere situatie hebben bij het passeren van de firewall dan Ali Cloud.

  • Shenzhen -> (CEN/IPSEC) -> Proxy -> GLB

Hier hebben we besloten om de beste van alle oplossingen te gebruiken:

  • stabiliteit en gegarandeerde SLA van CEN
  • hoge snelheid van IPSEC
  • Het ‘snelle’ netwerk van Google en zijn anycast.

Het schema ziet er ongeveer zo uit: gebruikersverkeer wordt beëindigd op een virtuele machine in ch-shenzhen. Daar worden Nginx-upstreams geconfigureerd, waarvan sommige verwijzen naar privé-IP-servers aan het andere uiteinde van de IPSEC-tunnel, en sommige upstreams verwijzen naar privé-adressen van servers aan de andere kant van de CEN. IPSEC geconfigureerd voor regio Azië-Oost1 in GCP (was de regio die het dichtst bij China lag op het moment dat de oplossing werd gecreëerd. GCP is nu ook aanwezig in Hong Kong). CEN - naar regio us-oost1 in AliCloud.

Vervolgens werd het verkeer van beide kanten omgeleid anycast IP GLB, dat wil zeggen naar het dichtstbijzijnde aanwezigheidspunt van Google, en ging via zijn netwerken naar de regio us-oost4 in GCP, waarin er vervangende virtuele machines waren (met subfilter in nginx).

Deze hybride oplossing profiteerde, zoals we verwachtten, van de voordelen van elke technologie. Over het algemeen gaat het verkeer via snelle IPSEC, maar als er problemen optreden, schoppen we deze servers snel en voor een paar minuten uit de upstream en sturen we verkeer alleen via CEN totdat de tunnel zich stabiliseert.

Door de vierde oplossing uit de bovenstaande lijst te implementeren, hebben we bereikt wat we wilden en wat het bedrijf op dat moment van ons verlangde.

Browsertestresultaten voor de nieuwe oplossing vergeleken met de vorige:

beslissing
Uptime
Mediaan
75 percentiel
95 percentiel

Cloudflare
86.6
18s
30s
60s

IPsec
99.79
18s
21s
30s

CEN
99.75
16s
21s
27s

CEN/IPsec + GLB
99.79
13s
16s
25s

CDN

Alles is goed in de oplossing die we hebben geïmplementeerd, maar er is geen CDN dat het verkeer op regionaal en zelfs stedelijk niveau zou kunnen versnellen. In theorie zou dit de site voor eindgebruikers moeten versnellen door gebruik te maken van de snelle communicatiekanalen van de CDN-provider. En we dachten er de hele tijd over na. En nu is het tijd voor de volgende versie van het project: het zoeken en testen van CDN-providers in China.

En hierover vertel ik je in het volgende, laatste deel :)

Bron: www.habr.com

Voeg een reactie