Hallo!
Wieder mit Ihnen Nikita – Systemingenieur von der Firma SEMrush. Mit diesem Artikel setze ich die Geschichte fort, wie wir die Umgehungslösung der chinesischen Firewall für unseren Dienst semrush.com erfunden haben.
Im Ich habe erzählt:
- welche Probleme auftreten, nachdem die Entscheidung getroffen wurde: "Wir müssen sicherstellen, dass unser Dienst in China funktioniert".
- welche Probleme das chinesische Internet hat,
- warum eine ICP-Lizenz erforderlich ist,
- wie und warum wir entschieden haben, unsere Testumgebungen mit Catchpoint zu testen,
- welches Ergebnis unser erster Lösungsansatz, der auf dem Cloudflare China Network basiert, gebracht hat,
- wie wir einen Fehler in der DNS Cloudflare gefunden haben.
Dieser Teil ist meiner Meinung nach der interessanteste, da er sich auf spezifische technische Implementierungen von Staging konzentriert. Und wir beginnen, genauer gesagt setzen wir fort mit Alibaba Cloud.
Alibaba Cloud
Alibaba Cloud - einem ziemlich großen Cloud-Anbieter, der alle Dienste anbietet, die es ihm ermöglichen, sich ehrlich als Cloud-Anbieter zu bezeichnen. Es ist gut, dass sie ausländischen Benutzern die Möglichkeit bieten, sich zu registrieren, und dass ein großer Teil der Website ins Englische übersetzt ist (für China ist das ein Luxus). In dieser Cloud kann man mit einer Vielzahl von Regionen der Welt, dem chinesischen Festland sowie dem pazifischen Asien (Hongkong, Taiwan usw.) arbeiten.
IPSEC
Wir begannen mit der Geografie. Da unsere Testwebsite in Google Cloud gehostet wurde, mussten wir Alibaba Cloud mit GCP "verbinden", also öffneten wir die Liste der Standorte, an denen Google präsent ist. Zu diesem Zeitpunkt hatten sie noch kein eigenes Rechenzentrum in Hongkong.
Die nächstgelegene Region war asia-east1 (Taiwan). Am nächstgelegenen Kontinent China von Ali zu Taiwan war cn-shenzhen (Shenzhen).
Mit Hilfe von terraform Wir beschrieben und richteten die gesamte Infrastruktur in GCP und Ali ein. Der Tunnel von 100 Mbit/s zwischen den Clouds wurde praktisch sofort eingerichtet. Auf der Seite von Shenzhen und Taiwan richteten wir die Proxy-VMs ein. In Shenzhen wird der Benutzertraffic terminiert, über den Tunnel nach Taiwan proxiert, und von dort geht er direkt zu unserer externen IP in us-east (Ostküste der USA). Der Ping zwischen den VMs über den Tunnel beträgt 24 ms, was nicht schlecht ist.
Gleichzeitig haben wir eine Testzone in Alibaba Cloud DNSeingrichtet. Nach der Delegierung der Zone an NS Ali reduzierte sich die Auflösungszeit von 470 ms auf 50 ms. Davor war die Zone ebenfalls auf Cloudflare.
Parallel zum Tunnel bis asia-east1 richteten wir einen weiteren Tunnel direkt von Shenzhen nach us-east4. Dort wurden weitere Proxy-VMs erstellt und beide Lösungen wurden getestet, indem Testverkehr mittels Cookies oder DNS umgeleitet wurde. Das Testsetup ist schematisch in folgendem Bild dargestellt:
Die Latenz für die Tunnel ergab Folgendes:
Ali cn-shenzhen GCP asia-east1 — 24ms
Ali cn-shenzhen GCP us-east4 — 200ms
Die Browser-Tests von Catchpoint berichteten von einer signifikanten Verbesserung der Kennzahlen.
Vergleichen Sie die Testergebnisse der beiden Lösungen:
Lösung
Verfügbarkeit
Median
75. Perzentil
95. Perzentil
Cloudflare
86.6
18s
30s
60s
IPsec
99.79
18s
21s
30s
Dies sind die Daten der Lösung, die ein IPSEC-Tunnel über asia-east1verwendet. Die Ergebnisse über us-east4 waren schlechter und die Fehlerquote höher, daher werde ich die Ergebnisse nicht anführen.
Aus den Ergebnissen dieses Tests der beiden Tunnel, von denen einer in der nächsten Region zu China endet und der andere am endgültigen Ziel, wurde klar, dass es wichtig ist, so schnell wie möglich aus der Kontrolle der chinesischen Firewall zu „tauchen“ und dann schnelle Netze (CDN-Anbieter, Cloud-Anbieter usw.) zu nutzen. Man sollte nicht versuchen, die Firewall auf einmal zu überqueren und zum Ziel zu gelangen. Das ist nicht der schnellste Weg.
Insgesamt sind die Ergebnisse nicht schlecht, jedoch liegt die Medianzeit von semrush.com bei 8.8s, und 75. Perzentil bei 9.4s (bei demselben Test).
Und bevor ich weiter mache, möchte ich eine kleine lyrische Abweichung anmerken.
Lyrische Abschweifung
Nachdem der Benutzer die Website www.semrushchina.cn, die über die „schnellen“ chinesischen DNS-Server aufgelöst wird, besucht, geht die HTTP-Anfrage über unsere schnelle Lösung. Die Antwort kommt auf demselben Weg zurück, jedoch wird in allen JS-Skripten, HTML-Seiten und anderen Elementen der Webseite der Domain semrush.com für zusätzliche Ressourcen angegeben, die beim Rendern der Seite geladen werden sollen. Das heißt, der Client löst den „haupt“ A-Eintrag auf www.semrushchina.cn und geht in den schnellen Tunnel, empfängt schnell die Antwort — die HTML-Seite, in der steht:
- Lade diesen JS von sso.semrush.com herunter,
- Hole die CSS-Dateien von cdn.semrush.com,
- und besorge dir die Bilder von dab.semrush.com
- und so weiter.
Der Browser beginnt, ins „externe“ Internet nach diesen Ressourcen zu gehen und passiert dabei jedes Mal die zeitraubende Firewall.
Aber im vorherigen Test sind die Ergebnisse dargestellt, wenn die Seite keine Ressourcen hat semrush.com, nur semrushchina.cn, während *.semrushchina.cn in die Adresse der virtuellen Maschine in Shenzhen aufgelöst wird, um dann in den Tunnel zu gelangen.
Nur wenn man den gesamten möglichen Traffic über seine Lösung zur Umgehung der chinesischen Firewall maximal leitet, kann man akzeptable Geschwindigkeiten und Verfügbarkeit des Webangebots erreichen sowie ehrliche Testergebnisse erzielen.
Wir haben dies ohne eine einzige Codeänderung auf der Produktseite der Teams erreicht.
Subfilter
Die Lösung entstand praktisch sofort, nachdem dieses Problem auftrat. Wir benötigten PoC (Proof of Concept), dass unsere Firewall-Umgehungslösungen tatsächlich gut funktionieren. Dazu muss der gesamte Traffic der Website maximal in diese Lösung geleitet werden. Und wir haben in nginx angewendet.
Subfilter — das ist ein recht einfaches Modul in nginx, das es ermöglicht, eine Zeile im Antwortkörper durch eine andere Zeile zu ersetzen. Also haben wir alle Vorkommen semrush.com auf semrushchina.cn in allen Antworten geändert.
Und… das hat nicht funktioniert, weil wir von den Backends komprimierte Inhalte erhielten, was bedeutet, dass subfilter die gewünschte Zeile nicht fand. Wir mussten einen weiteren lokalen Server in nginx hinzufügen, der die Antwort dekomprimierte und sie an den nächsten lokalen Server weitergab, der dann für den Zeilenaustausch, die Komprimierung und die Übergabe an den nächsten Proxy-Server in der Kette zuständig war.
Am Ende hätte der Kunde .semrush.com, erhalten müssen, und er erhielt .semrushchina.cn und wurde brav durch unsere Lösung geleitet.
Es reicht jedoch nicht aus, nur die Domain in eine Richtung zu ändern, da die Backends nach wie vor semrush.com in den folgenden Anfragen vom Kunden erwarten. Entsprechend extrahieren wir auf demselben Server, auf dem die Ersetzung in eine Richtung erfolgt, mit Hilfe eines einfachen regulären Ausdrucks das Subdomain aus der Anfrage und setzen die Variable proxy_pass $host , die auf$subdomain.semrush.com , gesetzt ist. Das mag kompliziert erscheinen, aber es funktioniert. Und es funktioniert gut. Für bestimmte Domains, die eine andere Logik erfordern, werden einfach eigene Serverblöcke erstellt und eine separate Konfiguration vorgenommen. Unten sind verkürzte nginx-Konfigurationen zur Veranschaulichung und Demonstration dieses Schemas aufgeführt.Die folgende Konfiguration verarbeitet alle Anfragen aus China auf
.semrushchina.cn: .semrushchina.cn:
höre 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;
}
}Diese Konfiguration leitet weiter nach localhost Port 83, und dort wartet die nächste Konfiguration:
höre 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;
}
}Ich wiederhole, das sind gekürzte Konfigurationen.
So ungefähr. Es mag kompliziert erscheinen, aber das sind nur Worte. In der Praxis ist alles einfacher als gekocht 🙂
Ende des lyrischen Abschweifens
Eine Zeit lang waren wir glücklich, weil der Mythos über fallende IPSEC-Tunnel sich nicht bestätigte. Doch dann begannen die Tunnel zu fallen. Mehrmals täglich für einige Minuten. Ein wenig, aber das genügte uns nicht. Da beide Tunnel auf der Seite von Ali an einem Router terminiert wurden, dachten wir, dass dies ein regionales Problem sein könnte und wir das Backup-Gebiet anheben müssen.
Wir haben es angehoben. Die Tunnel begannen zu verschiedenen Zeiten zu fallen, aber das Failover auf der Ebene des Upstreams in nginx funktionierte hervorragend. Doch dann begannen die Tunnel ungefähr gleichzeitig zu fallen 🙂 Und schon wieder tauchten 502 und 504 auf. Die Verfügbarkeit verschlechterte sich, also begannen wir, die Optionen mit Alibaba CEN (Cloud Enterprise Network).
CEN
CEN — das ist die Verbindung zweier VPCs aus verschiedenen Regionen innerhalb von Alibaba Cloud, das heißt, man kann private Netzwerke beliebiger Regionen innerhalb der Cloud miteinander verbinden. Und das Wichtigste: dieser Kanal hat eine ziemlich strenge SLA. Er ist sowohl hinsichtlich der Geschwindigkeit als auch der Verfügbarkeit sehr stabil. Doch es ist nie alles so einfach:
- es ist SEHR schwierig zu bekommen, wenn man kein chinesischer Staatsbürger oder Unternehmen ist,
- man muss für jedes Megabit Bandbreite des Kanals bezahlen.
Nachdem wir die Möglichkeit geschaffen hatten, Festlandchina und Übersee, haben wir CEN zwischen zwei Ali-Regionen erstellt: cn-shenzhen und us-east-1 (der nächstgelegene Punkt zu us-east4). In Ali us-east-1 haben wir eine weitere virtuelle Maschine hinzugefügt, um einen weiteren hop.
Es ergab sich folgendes:
Die Ergebnisse der Browser-Tests sind unten:
Lösung
Verfügbarkeit
Median
75. Perzentil
95. Perzentil
Cloudflare
86.6
18s
30s
60s
IPsec
99.79
18s
21s
30s
CEN
99.75
16s
21s
27s
Die Werte sind etwas besser als bei IPSEC. Aber über IPSEC kann man potenziell mit 100 Mbit/s herunterladen, während über CEN nur mit 5 Mbit/s und teurer.
Ein Hybrid drängt sich auf, oder? Die Geschwindigkeit von IPSEC mit der Stabilität von CEN verbinden.
So haben wir es gemacht, den Traffic sowohl über IPSEC als auch über CEN zu leiten, falls der IPSEC-Tunnel ausfällt. Die Uptime wurde deutlich höher, aber die Ladegeschwindigkeit der Website ließ noch zu wünschen übrig. Dann habe ich alle Diagramme gezeichnet, die wir bereits verwendet und getestet hatten, und beschlossen, in dieses Diagramm noch ein wenig GCP hinzuzufügen, und zwar GLB.
GLB
GLB sind (oder Google Cloud Load Balancer). Er hat einen für uns wichtigen Vorteil: im Kontext des CDN hat er anycast IP, was es ermöglicht, den Traffic in das nächstgelegene Rechenzentrum zum Kunden zu leiten, wodurch der Traffic schneller in das schnelle Netzwerk von Google gelangt und weniger durch das "normale" Internet geht.
Nach kurzem Überlegen haben wir HTTP/HTTPS LB in GCP eingerichtet und unsere virtuellen Maschinen mit dem Subfilter als Backend verwendet.
Es gab mehrere Diagramme:
- Verwenden Cloudflare China Network, aber diesmal sollte die Origin-Angabe global sein IP GLB.
- Die Kunden im cn-shenzhen, und von dort aus den Traffic direkt in GLB.
- Direkt von China nach GLB.
- Die Kunden im cn-shenzhen, von dort aus den Traffic nach asia-east1 über IPSEC (in us-east4 über CEN), von dort aus schon zu GLB (keine Sorge, unten wird ein Bild und eine Erklärung folgen)
Wir haben all diese Optionen und noch einige hybride getestet:
- Cloudflare + GLB
Dieses Diagramm hat uns bezüglich Uptime und DNS-Fehler nicht überzeugt. Der Test wurde jedoch vor der Behebung eines Bugs von CF durchgeführt; möglicherweise ist es jetzt besser (das schließt jedoch nicht die HTTP-Timeouts aus).
- Ali + GLB
Ein solches Diagramm hat uns ebenfalls nicht bezüglich der Uptime überzeugt, da GLB häufig aus dem Upstream gefallen ist wegen der Unmöglichkeit, eine Verbindung innerhalb eines akzeptablen Zeitrahmens herzustellen oder wegen Timeout, da die GLB-Adresse für den Server innerhalb Chinas weiterhin extern bleibt und somit hinter der chinesischen Firewall versteckt ist. Es gab keine Wunder.
- GLB nur
Eine Variante, ähnlich der vorherigen, nur dass keine Server in China selbst verwendet wurden: Der Traffic ging direkt zu GLB (DNS-Einträge wurden geändert). Dementsprechend waren die Ergebnisse unzufriedenstellend, da bei normalen chinesischen Kunden, die Dienste von regulären Internetanbietern nutzen, die Situation beim Umgang mit der Firewall viel schlechter ist als bei Ali Cloud.
- Shenzhen -> (CEN/IPSEC) -> Proxy -> GLB
Hier haben wir beschlossen, das Beste aus allen Lösungen zu kombinieren:
- Stabilität und garantierter SLA von CEN
- hohe Geschwindigkeit von IPSEC
- "schnelles" Google-Netzwerk und sein Anycast.
Das Diagramm sieht ungefähr so aus: Der Traffic der Benutzer wird auf einer virtuellen Maschine in ch-shenzhen. Dort sind Upstreams für nginx konfiguriert, von denen ein Teil auf private IP-Server verweist, die am anderen Ende des IPSEC-Tunnels stehen, während ein Teil der Upstreams auf private Adressen von Servern auf der anderen Seite des CEN verweist. IPSEC wurde vor der Region asia-east1 in GCP (damals war es die nächstgelegene Region zu China bei der Erstellung der Lösung. Jetzt hat GCP auch eine Präsenz in Hongkong). CEN - bis zur Region us-east1 in Ali Cloud.
Der Datenverkehr von beiden Enden wurde dann an anycast IP GLB, also an den nächstgelegenen Standort von Google, weitergeleitet und über dessen Netzwerke in die Region us-east4 in GCP geleitet, in der die Ersatz-VMs (mit subfilter in nginx) standen.
Diese hybride Lösung, wie wir erwartet hatten, erlaubte es, die Vorteile jeder Technologie zu nutzen. Insgesamt läuft der Datenverkehr über viel schnelleren IPSEC, aber wenn Probleme auftreten, entfernen wir diese Server schnell und für einige Minuten aus den Upstreams und leiten den Datenverkehr nur über CEN, bis der Tunnel stabil ist.
Mit der Implementierung der vierten Lösung aus der obigen Liste haben wir das erreicht, was wir wollten, und was das Geschäft zu diesem Zeitpunkt von uns verlangte.
Die Ergebnisse der Browser-Tests für die neue Lösung im Vergleich zu den vorherigen:
Lösung
Verfügbarkeit
Median
75. Perzentil
95. Perzentil
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
In unserer implementierten Lösung läuft alles gut, nur gibt es kein CDN, das den Datenverkehr auf regionaler und sogar städtischer Ebene beschleunigen könnte. Idealerweise sollte dies die Leistung der Website für Endbenutzer durch die Nutzung schneller Verbindungen des CDN-Anbieters verbessern. Und ständig haben wir darüber nachgedacht. Und nun, es ist Zeit für die nächste Iteration des Projekts: die Suche und das Testen von CDN-Anbietern in China.
Und darüber werde ich Ihnen im nächsten, letzten Teil erzählen 🙂
Quelle: habr.com
