Hvordan vi brød igennem den store kinesiske firewall (del 2)

Hi!

Nikita er med dig igen, en systemingeniør fra virksomheden SEMrush. Og med denne artikel fortsætter jeg historien om, hvordan vi fandt på en løsning Kinesisk firewall til vores service semrush.com.

В forrige del Jeg sagde:

  • hvilke problemer opstår efter beslutningen er truffet "Vi skal få vores service til at fungere i Kina"
  • Hvilke problemer har det kinesiske internet?
  • hvorfor har du brug for en ICP-licens?
  • hvordan og hvorfor besluttede vi at teste vores testbeds med Catchpoint
  • hvad var resultatet af vores første løsning baseret på Cloudflare China Network
  • Hvordan vi fandt en fejl i Cloudflare DNS

Denne del er efter min mening den mest interessante, fordi den fokuserer på specifikke tekniske implementeringer af iscenesættelse. Og vi vil begynde, eller rettere fortsætte, med Alibaba Cloud.

Alibaba Cloud

Alibaba Cloud er en ret stor cloud-udbyder, som har alle de tjenester, der gør, at den ærligt kan kalde sig en cloud-udbyder. Det er godt, at de har mulighed for at registrere sig for udenlandske brugere, og at det meste af siden er oversat til engelsk (for Kina er dette en luksus). I denne sky kan du arbejde med mange regioner i verden, det kinesiske fastland samt Oceanic Asien (Hong Kong, Taiwan osv.).

IPsec

Vi startede med geografi. Da vores testside var placeret på Google Cloud, var vi nødt til at "linke" Alibaba Cloud med GCP, så vi åbnede en liste over steder, hvor Google er til stede. På det tidspunkt havde de endnu ikke deres eget datacenter i Hong Kong.
Den nærmeste region viste sig at være asien-øst1 (Taiwan). Ali viste sig at være den region på det kinesiske fastland, der er tættest på Taiwan cn-shenzhen (Shenzhen).

Med terra form beskrevet og løftet hele infrastrukturen i GCP og Ali. En 100 Mbit/s tunnel mellem skyerne gik op næsten øjeblikkeligt. På siden af ​​Shenzhen og Taiwan blev proxying virtuelle maskiner rejst. I Shenzhen afsluttes brugertrafikken, proxes gennem en tunnel til Taiwan, og derfra går den direkte til vores tjenestes eksterne IP i os-øst (USAs østkyst). Ping mellem virtuelle maskiner via tunnel 24ms, hvilket ikke er så slemt.

Samtidig placerede vi et testområde i Alibaba Cloud DNS. Efter at have uddelegeret zonen til NS Ali, faldt opløsningstiden fra 470 ms til 50 ms. Før dette var zonen også på Cloudlfare.

Parallelt med tunnelen til asien-øst1 rejst en anden tunnel fra Shenzhen direkte til os-øst4. Der skabte de flere virtuelle proxy-maskiner og begyndte at teste begge løsninger ved at dirigere testtrafik ved hjælp af cookies eller DNS. Testbænken er beskrevet skematisk i følgende figur:

Latency for tunneler viste sig at være som følger:
Ali cn-shenzhen <—> GCP asia-east1 — 24ms
Ali cn-shenzhen <—> GCP us-east4 — 200ms

Catchpoint browsertests rapporterede fremragende forbedringer.

Sammenlign testresultater for to løsninger:

beslutning
Uptime
median
75 Percentil
95 Percentil

CloudFlare
86.6
18s
30s
60s

IPsec
99.79
18s
21s
30s

Dette er data fra en løsning, der bruger en IPSEC-tunnel via asien-øst1. Gennem us-east4 var resultaterne værre, og der var flere fejl, så jeg vil ikke give resultaterne.

Baseret på resultaterne af denne test af to tunneler, hvoraf den ene er afsluttet i den nærmeste region til Kina, og den anden på slutdestinationen, blev det klart, at det er vigtigt at "dukke op" under den kinesiske firewall så hurtigt som muligt, og så brug hurtige netværk (CDN-udbydere, cloud-udbydere osv.). Der er ingen grund til at forsøge at komme igennem firewallen og komme til din destination med ét hug. Dette er ikke den hurtigste måde.

Generelt er resultaterne ikke dårlige, men semrush.com har en median på 8.8 s og 75 Percentile 9.4 s (på samme test).
Og inden jeg går videre, vil jeg gerne lave en kort lyrisk digression.

Lyrisk digression

Efter at brugeren går ind på webstedet www.semrushchina.cn, som løser gennem "hurtige" kinesiske DNS-servere, går HTTP-anmodningen gennem vores hurtige løsning. Svaret returneres ad samme vej, men domænet er angivet i alle JS-scripts, HTML-sider og andre elementer på websiden semrush.com for yderligere ressourcer, der skal indlæses, når siden gengives. Det vil sige, at klienten løser "hoved" A-recorden www.semrushchina.cn og går ind i den hurtige tunnel, modtager hurtigt et svar - en HTML-side, der siger:

  • download sådan og sådan js fra sso.semrush.com,
  • Hent CSS-filerne fra cdn.semrush.com,
  • og tag også nogle billeder fra dab.semrush.com
  • og så videre.

Browseren begynder at gå til det "eksterne" internet for disse ressourcer, hver gang den passerer gennem en firewall, der æder responstiden.

Men den forrige test viser resultaterne, når der ikke er nogen ressourcer på siden semrush.com, kun semrushchina.cn, og *.semrushchina.cn løser til adressen på den virtuelle maskine i Shenzhen for derefter at komme ind i tunnelen.

Kun på denne måde, ved at skubbe al mulig trafik til det maksimale gennem din løsning for hurtigt at passere den kinesiske firewall, kan du opnå acceptable hastigheder og indikatorer for hjemmesidens tilgængelighed samt ærlige resultater af løsningstests.
Vi gjorde dette uden en eneste koderedigering på teamets produktside.

Underfilter

Løsningen blev født næsten umiddelbart efter, at dette problem dukkede op. Vi havde brug for PoC (Proof of Concept), at vores firewallpenetrationsløsninger virkelig fungerer godt. For at gøre dette skal du pakke al webstedstrafik ind i denne løsning så meget som muligt. Og vi søgte underfilter i nginx.

Underfilter er et ret simpelt modul i nginx, der giver dig mulighed for at ændre en linje i responskroppen til en anden linje. Så vi ændrede alle forekomster semrush.comsemrushchina.cn i alle svar.

Og... det virkede ikke, fordi vi modtog komprimeret indhold fra backends, så subfilter fandt ikke den nødvendige linje. Jeg var nødt til at tilføje en anden lokal server til nginx, som dekomprimerede svaret og sendte det videre til den næste lokale server, som allerede havde travlt med at erstatte strengen, komprimere den og sende den til den næste proxyserver i kæden.

Som et resultat, hvor ville kunden modtage semrush.com, han modtog .semrushchina.cn og gik lydigt igennem vores beslutning.

Det er dog ikke nok blot at ændre domænet én vej, fordi backends stadig forventer semrush.com i efterfølgende anmodninger fra klienten. Følgelig, på den samme server, hvor envejserstatningen udføres, får vi ved hjælp af et simpelt regulært udtryk subdomænet fra anmodningen, og så gør vi proxy_pass med variabel $ vært, udstillet i $subdomain.semrush.com. Det kan virke forvirrende, men det virker. Og det fungerer godt. For individuelle domæner, der kræver forskellig logik, skal du blot oprette dine egne serverblokke og lave en separat konfiguration. Nedenfor er forkortede nginx-konfigurationer for klarhed og demonstration af dette skema.

Følgende konfiguration behandler alle anmodninger fra Kina til .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;
    }
}

Denne konfiguration proxyer til localhost til port 83, og følgende konfiguration venter der:

    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;
    }
}

Jeg gentager, disse er beskårne konfigurationer.

Sådan. Det kan se kompliceret ud, men det er i ord. Faktisk er alt enklere end dampede majroer :)

Slut på digression

I et stykke tid var vi glade, fordi myten om faldende IPSEC-tunneler ikke blev bekræftet. Men så begyndte tunnelerne at falde. Flere gange om dagen i et par minutter. Lidt, men det passede os ikke. Da begge tunneler blev afsluttet på Ali-siden på den samme router, besluttede vi, at det måske var et regionalt problem, og vi var nødt til at hæve backup-regionen.

De tog den op. Tunnellerne begyndte at fejle på forskellige tidspunkter, men failoveren fungerede fint for os på opstrømsniveau i nginx. Men så begyndte tunnelerne at falde nogenlunde samtidig 🙂 Og igen startede 502 og 504. Oppetiden begyndte at blive dårligere, så vi begyndte at arbejde på muligheden med Alibaba CEN (Cloud Enterprise Network).

CEN

CEN - dette er forbindelsen mellem to VPC'er fra forskellige regioner i Alibaba Cloud, det vil sige, at du kan forbinde private netværk i alle regioner i skyen med hinanden. Og vigtigst af alt: denne kanal har en ret streng SLA. Den er meget stabil både i hastighed og oppetid. Men det er aldrig så enkelt:

  • det er MEGET svært at opnå, hvis du ikke er kinesisk statsborger eller en juridisk enhed,
  • Du skal betale for hver megabit kanalbåndbredde.

At have mulighed for at forbinde Mainland Kina и Oversøisk, oprettede vi en CEN mellem to Ali-regioner: cn-shenzhen и os-øst-1 (nærmeste punkt til os-øst4). I Ali os-øst-1 rejste en anden virtuel maskine, så der er en mere Hop.

Det blev sådan her:

Browsertestresultaterne er nedenfor:

beslutning
Uptime
median
75 Percentil
95 Percentil

CloudFlare
86.6
18s
30s
60s

IPsec
99.79
18s
21s
30s

CEN
99.75
16s
21s
27s

Ydeevnen er lidt bedre end IPSEC. Men gennem IPSEC kan du potentielt downloade med en hastighed på 100 Mbit/s, og gennem CEN kun med en hastighed på 5 Mbit/s og mere.

Det lyder som en hybrid, ikke? Kombiner IPSEC-hastighed og CEN-stabilitet.

Dette er, hvad vi gjorde, og tillod trafik gennem både IPSEC og CEN i tilfælde af en fejl i IPSEC-tunnelen. Oppetiden er blevet meget højere, men sidens indlæsningshastighed lader stadig meget tilbage at ønske. Så tegnede jeg alle de kredsløb, som vi allerede havde brugt og testet, og besluttede at prøve at tilføje lidt mere GCP til dette kredsløb, nemlig kasket.

kasket

kasket - Er Global Load Balancer (eller Google Cloud Load Balancer). Det har en vigtig fordel for os: i forbindelse med et CDN har det anycast IP, som giver dig mulighed for at dirigere trafik til det datacenter, der er tættest på klienten, så trafikken hurtigt kommer ind på Googles hurtige netværk og mindre går gennem det "almindelige" internet.

Uden at tænke os om to gange rejste vi HTTP/HTTPS LB Vi installerede vores virtuelle maskiner med subfilter i GCP og som backend.

Der var flere ordninger:

  • Brug Cloudflare Kina netværk, men denne gang skal Origin angive global IP GLB.
  • Afslut kunder kl cn-shenzhen, og derfra proxy trafikken direkte til kasket.
  • Gå direkte fra Kina til kasket.
  • Afslut kunder kl cn-shenzhen, derfra fuldmagt til asien-øst1 via IPSEC (in os-øst4 via CEN), gå derfra til GLB (roligt, der vil være et billede og forklaring nedenfor)

Vi testede alle disse muligheder og flere hybride:

  • Cloudflare + GLB

Denne ordning passede ikke os på grund af oppetid og DNS-fejl. Men testen blev udført før fejlen blev rettet på CF-siden, måske er den bedre nu (dette udelukker dog ikke HTTP-timeouts).

  • Ali + GLB

Denne ordning passede heller ikke os med hensyn til oppetid, da GLB ofte faldt ud af upstream på grund af umuligheden af ​​at oprette forbindelse i en acceptabel tid eller timeout, fordi for en server inde i Kina forbliver GLB-adressen udenfor, og derfor bagved Kinesisk firewall. Magien skete ikke.

  • Kun GLB

En mulighed, der ligner den forrige, men den brugte ikke servere i selve Kina: trafikken gik direkte til GLB (DNS-posterne blev ændret). Følgelig var resultaterne ikke tilfredsstillende, da almindelige kinesiske kunder, der bruger tjenester fra almindelige internetudbydere, har en meget værre situation med at passere firewallen end Ali Cloud.

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

Her besluttede vi at bruge den bedste af alle løsninger:

  • stabilitet og garanteret SLA fra CEN
  • høj hastighed fra IPSEC
  • Googles "hurtige" netværk og dets anycast.

Skemaet ser nogenlunde sådan ud: brugertrafik afsluttes på en virtuel maskine i ch-shenzhen. Nginx upstreams er konfigureret der, hvoraf nogle peger på private IP-servere placeret i den anden ende af IPSEC-tunnelen, og nogle upstreams peger på private adresser på servere på den anden side af CEN. IPSEC konfigureret til region asien-øst1 i GCP (var den region, der var tættest på Kina på det tidspunkt, hvor løsningen blev skabt. GCP har nu også en tilstedeværelse i Hong Kong). CEN - til region os-øst1 i Ali Cloud.

Så blev trafikken fra begge ender dirigeret til anycast IP GLB, det vil sige til det nærmeste tilstedeværelse af Google, og gik gennem sine netværk til regionen os-øst4 i GCP, hvor der var virtuelle udskiftningsmaskiner (med underfilter i nginx).

Denne hybridløsning udnyttede, som vi forventede, fordelene ved hver teknologi. Generelt går trafikken gennem hurtig IPSEC, men hvis problemer starter, sparker vi hurtigt og i et par minutter disse servere ud af opstrøms og sender kun trafik gennem CEN, indtil tunnelen stabiliserer sig.

Ved at implementere den 4. løsning fra listen ovenfor opnåede vi det, vi ønskede, og hvad virksomheden krævede af os på det tidspunkt.

Browsertestresultater for den nye løsning sammenlignet med tidligere:

beslutning
Uptime
median
75 Percentil
95 Percentil

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

Alt er godt i den løsning, vi implementerede, men der er ingen CDN, der kan accelerere trafikken på regionalt og endda byniveau. I teorien skulle dette fremskynde webstedet for slutbrugere ved at bruge CDN-udbyderens hurtige kommunikationskanaler. Og vi tænkte på det hele tiden. Og nu er tiden kommet til den næste iteration af projektet: at søge og teste CDN-udbydere i Kina.

Og det vil jeg fortælle dig om i den næste, sidste del :)

Kilde: www.habr.com

Tilføj en kommentar