Come abbiamo superato il Grande Firewall Cinese (Parte 2)

Hi!

Nikita è di nuovo con te, un ingegnere di sistema dell'azienda SEMrush. E con questo articolo continuo la storia su come abbiamo trovato una soluzione alternativa Firewall cinese per il nostro servizio semrush.com.

В sezione precedente Ho detto:

  • quali problemi sorgono dopo aver preso la decisione “Dobbiamo far funzionare il nostro servizio in Cina”
  • Quali problemi ha Internet cinese?
  • perché hai bisogno di una licenza ICP?
  • come e perché abbiamo deciso di testare i nostri banchi di prova con Catchpoint
  • qual è stato il risultato della nostra prima soluzione basata su Cloudflare China Network
  • Come abbiamo trovato un bug nel DNS di Cloudflare

Questa parte è la più interessante, secondo me, perché si concentra su specifiche implementazioni tecniche della messa in scena. E inizieremo, o meglio continueremo, con Alibaba Cloud.

Alibaba Cloud

Alibaba Cloud è un fornitore di servizi cloud abbastanza grande, che dispone di tutti i servizi che gli consentono di definirsi onestamente un fornitore di servizi cloud. È positivo che abbiano la possibilità di registrarsi per gli utenti stranieri e che la maggior parte del sito sia tradotta in inglese (per la Cina questo è un lusso). In questo cloud puoi lavorare con molte regioni del mondo, con la Cina continentale e con l'Asia oceanica (Hong Kong, Taiwan, ecc.).

IPsec

Abbiamo iniziato con la geografia. Poiché il nostro sito di prova si trovava su Google Cloud, avevamo bisogno di “collegare” Alibaba Cloud con GCP, quindi abbiamo aperto un elenco di località in cui è presente Google. A quel tempo non avevano ancora un proprio data center a Hong Kong.
La regione più vicina si è rivelata essere asia-est1 (Taiwan). Ali si è rivelata la regione della Cina continentale più vicina a Taiwan cn-shenzhen (Shenzhen).

Con Terraform descritto e realizzato l'intera infrastruttura in GCP e Ali. Un tunnel da 100 Mbit/s tra le nuvole è stato realizzato quasi istantaneamente. Da parte di Shenzhen e Taiwan, sono state sollevate macchine virtuali proxy. A Shenzhen il traffico degli utenti viene terminato, inoltrato attraverso un tunnel fino a Taiwan, e da lì va direttamente all'IP esterno del nostro servizio in noi-est (Costa orientale degli Stati Uniti). Ping tra macchine virtuali tramite tunnel 24ms, il che non è poi così male.

Allo stesso tempo, abbiamo allestito un'area di prova Alibaba Cloud DNS. Dopo aver delegato la zona a NS Ali, il tempo di risoluzione è diminuito da 470 ms a ms 50. Prima di questo, la zona era anche su Cloudlfare.

Parallelo al tunnel a asia-est1 ha sollevato un altro tunnel direttamente da Shenzhen noi-est4. Lì hanno creato più macchine virtuali proxy e hanno iniziato a testare entrambe le soluzioni, instradando il traffico di prova utilizzando cookie o DNS. Il banco prova è descritto schematicamente nella figura seguente:

La latenza per i tunnel è risultata essere la seguente:
Ali cn-shenzhen <—> GCP asia-est1 — 24ms
Ali cn-shenzhen <—> GCP us-east4 — 200 ms

I test del browser Catchpoint hanno riportato un eccellente miglioramento.

Confronta i risultati dei test per due soluzioni:

Soluzione
Uptime
Mediano
75 percentile
95 percentile

Cloudflare
86.6
18 secondi
30 secondi
60 secondi

IPsec
99.79
18 secondi
21 secondi
30 secondi

Si tratta di dati provenienti da una soluzione che utilizza un tunnel IPSEC tramite asia-est1. Attraverso us-east4 i risultati sono stati peggiori e c'erano più errori, quindi non fornirò i risultati.

Sulla base dei risultati di questo test di due tunnel, uno dei quali termina nella regione più vicina alla Cina, e l’altro nella destinazione finale, è apparso chiaro che è importante “emergere” dal firewall cinese il più rapidamente possibile. possibile, e quindi utilizzare reti veloci (fornitori CDN, fornitori cloud, ecc.). Non è necessario provare a superare il firewall e arrivare a destinazione in un colpo solo. Questo non è il modo più veloce.

In generale, i risultati non sono male, tuttavia, semrush.com ha una media di 8.8 e 75 percentile di 9.4 (nello stesso test).
E prima di proseguire vorrei fare una breve digressione lirica.

Digressione lirica

Dopo che l'utente è entrato nel sito www.semrushchina.cn, che si risolve tramite server DNS cinesi “veloci”, la richiesta HTTP passa attraverso la nostra soluzione veloce. La risposta viene restituita lungo lo stesso percorso, ma il dominio è specificato in tutti gli script JS, nelle pagine HTML e in altri elementi della pagina web semrush.com per risorse aggiuntive che devono essere caricate durante il rendering della pagina. Cioè, il client risolve il record A “principale”. www.semrushchina.cn ed entra nel tunnel veloce, riceve rapidamente una risposta - una pagina HTML che afferma:

  • scarica questo e quel js da sso.semrush.com,
  • Ottieni i file CSS da cdn.semrush.com,
  • e scatta anche alcune foto da dab.semrush.com
  • e così via.

Il browser inizia a rivolgersi a Internet "esterno" per queste risorse, passando ogni volta attraverso un firewall che consuma tempo di risposta.

Ma il test precedente mostra i risultati quando non sono presenti risorse sulla pagina semrush.comsolo semrushchina.cn, e *.semrushchina.cn si risolve nell'indirizzo della macchina virtuale a Shenzhen per poi entrare nel tunnel.

Solo in questo modo, spingendo al massimo tutto il traffico possibile attraverso la vostra soluzione per superare rapidamente il firewall cinese, potrete ottenere velocità accettabili e indicatori di disponibilità del sito web accettabili, nonché risultati onesti dei test della soluzione.
Lo abbiamo fatto senza una singola modifica del codice da parte del prodotto del team.

Sottofiltro

La soluzione è nata quasi immediatamente dopo che questo problema è emerso. Avevamo bisogno PoC (Proof of Concept) che le nostre soluzioni di penetrazione dei firewall funzionano davvero bene. Per fare ciò, è necessario concentrare il più possibile tutto il traffico del sito in questa soluzione. E abbiamo fatto domanda sottofiltro in nginx.

Sottofiltro è un modulo abbastanza semplice in nginx che ti consente di modificare una riga nel corpo della risposta in un'altra riga. Quindi abbiamo cambiato tutte le occorrenze semrush.com su semrushchina.cn in tutte le risposte.

E... non ha funzionato perché abbiamo ricevuto contenuto compresso dai backend, quindi il sottofiltro non ha trovato la riga richiesta. Ho dovuto aggiungere un altro server locale a nginx, che ha decompresso la risposta e l'ha passata al server locale successivo, che era già impegnato a sostituire la stringa, comprimerla e inviarla al server proxy successivo nella catena.

Di conseguenza, dove riceverebbe il cliente .semrush.com, ha ricevuto .semrushchina.cn e obbedientemente ha seguito la nostra decisione.

Tuttavia, non è sufficiente cambiare semplicemente il dominio in un modo, perché i backend si aspettano comunque semrush.com nelle richieste successive del client. Di conseguenza, sullo stesso server in cui viene effettuata la sostituzione unidirezionale, utilizzando una semplice espressione regolare otteniamo il sottodominio dalla richiesta, e poi lo facciamo proxy_pass con variabile $ host, esposto in $sottodominio.semrush.com. Può sembrare confuso, ma funziona. E funziona bene. Per i singoli domini che richiedono una logica diversa, crea semplicemente i tuoi blocchi server ed effettua una configurazione separata. Di seguito sono riportate le configurazioni nginx abbreviate per chiarezza e dimostrazione di questo schema.

La seguente configurazione elabora tutte le richieste dalla Cina a .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;
    }
}

Questa configurazione proxy a localhost alla porta 83 e lì è in attesa la seguente configurazione:

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

Ripeto, queste sono configurazioni ritagliate.

Come quello. Può sembrare complicato, ma lo è a parole. In effetti, tutto è più semplice delle rape al vapore :)

Fine della digressione

Per un po' siamo stati contenti perché il mito della caduta dei tunnel IPSEC non è stato confermato. Ma poi i tunnel cominciarono a crollare. Più volte al giorno per pochi minuti. Un po', ma non ci andava bene. Dato che entrambi i tunnel terminavano sul lato Ali dello stesso router, abbiamo deciso che forse si trattava di un problema regionale e che dovevamo aumentare la regione di backup.

L'hanno raccolto. I tunnel hanno iniziato a guastarsi in momenti diversi, ma il failover ha funzionato bene per noi a livello upstream in nginx. Ma poi i tunnel hanno iniziato a crollare più o meno nello stesso momento 🙂 E sono ricominciati 502 e 504. I tempi di attività hanno iniziato a peggiorare, quindi abbiamo iniziato a lavorare sull'opzione con AlibabaCEN (Rete aziendale cloud).

CEN

CEN - questa è la connettività di due VPC di diverse regioni all'interno di Alibaba Cloud, ovvero puoi connettere tra loro reti private di qualsiasi regione all'interno del cloud. E, soprattutto: questo canale ha un approccio abbastanza severo SLA. È molto stabile sia in termini di velocità che di uptime. Ma non è mai così semplice:

  • è MOLTO difficile da ottenere se non sei cittadino cinese o persona giuridica,
  • Devi pagare per ogni megabit di larghezza di banda del canale.

Avere l'opportunità di connettersi La Cina continentale и all'estero, abbiamo creato un CEN tra due regioni Ali: cn-shenzhen и us-est-1 (punto più vicino a noi-est4). Ad Alì us-est-1 ha generato un'altra macchina virtuale in modo che ce ne sia un'altra luppolo.

È risultato così:

I risultati del test del browser sono riportati di seguito:

Soluzione
Uptime
Mediano
75 percentile
95 percentile

Cloudflare
86.6
18 secondi
30 secondi
60 secondi

IPsec
99.79
18 secondi
21 secondi
30 secondi

CEN
99.75
16 secondi
21 secondi
27 secondi

Le prestazioni sono leggermente migliori di IPSEC. Ma tramite IPSEC è possibile scaricare potenzialmente ad una velocità di 100 Mbit/s, mentre tramite CEN solo ad una velocità di 5 Mbit/s e oltre.

Sembra un ibrido, vero? Combina velocità IPSEC e stabilità CEN.

Questo è ciò che abbiamo fatto, consentendo il traffico sia attraverso IPSEC che attraverso CEN in caso di guasto del tunnel IPSEC. Il tempo di attività è diventato molto più elevato, ma la velocità di caricamento del sito lascia ancora molto a desiderare. Poi ho disegnato tutti i circuiti che avevamo già utilizzato e testato e ho deciso di provare ad aggiungere un po' più di GCP a questo circuito, vale a dire GLB.

GLB

GLB - E ' Bilanciatore del carico globale (o bilanciatore del carico di Google Cloud). Per noi ha un vantaggio importante: nel contesto di una CDN sì IP anycast, che consente di instradare il traffico al data center più vicino al client, in modo che il traffico entri rapidamente nella rete veloce di Google e meno passi attraverso Internet "normale".

Senza pensarci due volte, abbiamo rilanciato HTTP/HTTPS LB Abbiamo installato le nostre macchine virtuali con sottofiltro in GCP e come backend.

C'erano diversi schemi:

  • Da usare Rete cinese Cloudflare, ma questa volta Origin dovrebbe specificare global IP GLB.
  • Termina i client a cn-shenzhene da lì proxy il traffico direttamente a GLB.
  • Vai direttamente dalla Cina a GLB.
  • Termina i client a cn-shenzhen, da lì proxy a asia-est1 tramite IPSEC (in noi-est4 via CEN), da lì andare a GLB (con calma, sotto ci sarà foto e spiegazione)

Abbiamo testato tutte queste opzioni e molte altre ibride:

  • Cloudflare+GLB

Questo schema non è adatto a noi a causa dei tempi di attività e degli errori DNS. Ma il test è stato effettuato prima che il bug lato CF fosse corretto, forse è meglio ora (questo però non esclude i timeout HTTP).

  • Ali + GLB

Anche questo schema non era adatto a noi in termini di tempo di attività, poiché GLB spesso cadeva dall'upstream a causa dell'impossibilità di connettersi in un tempo o timeout accettabile, perché per un server all'interno della Cina, l'indirizzo GLB rimane all'esterno, e quindi dietro Firewall cinese. La magia non è avvenuta.

  • Solo GLB

Un'opzione simile alla precedente, solo che non utilizzava server nella stessa Cina: il traffico andava direttamente a GLB (i record DNS sono stati modificati). Di conseguenza, i risultati non sono stati soddisfacenti, poiché i normali clienti cinesi che utilizzano i servizi dei normali provider Internet si trovano in una situazione molto peggiore nel superare il firewall rispetto ad Ali Cloud.

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

Qui abbiamo deciso di utilizzare la migliore di tutte le soluzioni:

  • stabilità e SLA garantito dal CEN
  • alta velocità da IPSEC
  • La rete “veloce” di Google e il suo anycast.

Lo schema è simile al seguente: il traffico utente viene terminato su una macchina virtuale in ch-shenzhen. Qui vengono configurati gli upstream Nginx, alcuni dei quali puntano a server IP privati ​​situati all'altra estremità del tunnel IPSEC, mentre altri upstream puntano a indirizzi privati ​​di server dall'altra parte del CEN. IPSEC configurato per la regione asia-est1 in GCP (era la regione più vicina alla Cina al momento della creazione della soluzione. GCP ora è presente anche a Hong Kong). CEN - alla regione noi-est1 in Ali Nuvola.

Quindi è stato indirizzato il traffico da entrambe le estremità IP GLB anycast, cioè al punto di presenza di Google più vicino, e ha attraversato le sue reti fino alla regione noi-est4 in GCP, in cui erano presenti macchine virtuali sostitutive (con sottofiltro in nginx).

Questa soluzione ibrida, come ci aspettavamo, ha sfruttato i vantaggi di ciascuna tecnologia. In generale, il traffico passa attraverso IPSEC veloce, ma se iniziano i problemi, eliminiamo rapidamente e per alcuni minuti questi server dall'upstream e inviamo il traffico solo attraverso CEN finché il tunnel non si stabilizza.

Implementando la soluzione 4 dall'elenco precedente, abbiamo ottenuto ciò che volevamo e ciò che l'azienda ci richiedeva in quel momento.

Risultati dei test del browser per la nuova soluzione rispetto a quelle precedenti:

Soluzione
Uptime
Mediano
75 percentile
95 percentile

Cloudflare
86.6
18 secondi
30 secondi
60 secondi

IPsec
99.79
18 secondi
21 secondi
30 secondi

CEN
99.75
16 secondi
21 secondi
27 secondi

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

CDN

Tutto va bene nella soluzione che abbiamo implementato, ma non esiste una CDN che possa accelerare il traffico a livello regionale e persino cittadino. In teoria, questo dovrebbe velocizzare il sito per gli utenti finali utilizzando i canali di comunicazione veloci del provider CDN. E ci abbiamo pensato tutto il tempo. E ora è giunto il momento per la prossima iterazione del progetto: cercare e testare i fornitori CDN in Cina.

E di questo vi parlerò nella prossima, ultima parte :)

Fonte: habr.com

Aggiungi un commento