¡Hola!
De nuevo, soy Nikita, ingeniero de sistemas de la empresa SEMrush. Y con este artículo continúo la historia sobre cómo ideamos una solución para sortear el Gran Cortafuegos de China para nuestro servicio semrush.com.
En Hablé de:
- los problemas que surgen después de que se toma la decisión de 'Necesitamos hacer que nuestro servicio funcione en China'
- los problemas que tiene Internet en China
- por qué se necesita una licencia ICP
- cómo y por qué decidimos probar nuestros entornos con la ayuda de Catchpoint
- qué resultados dio nuestra primera variante de solución, basada en la Cloudflare China Network
- cómo encontramos un bug en el DNS de Cloudflare
Esta parte es la más interesante, en mi opinión, porque se centra en implementaciones técnicas concretas. Y empezaremos, o más bien continuaremos, con Alibaba Cloud.
Alibaba Cloud
Alibaba Cloud un proveedor de nube bastante grande que ofrece todos los servicios que le permiten llamarse correctamente un proveedor de nube. Es bueno que tengan la posibilidad de registrarse para usuarios extranjeros y que gran parte del sitio web esté traducido al inglés (para China esto es un lujo). En esta nube se puede trabajar con muchas regiones del mundo, de China continental, así como de Asia Oceánica (Hong Kong, Taiwán, etc.).
IPSEC
Comenzamos con la geografía. Dado que nuestro sitio de pruebas estaba en Google Cloud, necesitábamos 'conectar' Alibaba Cloud con GCP, así que abrimos la lista de ubicaciones donde Google tiene presencia. En ese momento, aún no tenían su propio centro de datos en Hong Kong.
La región más cercana era asia-east1 (Taiwán). Para Ali, la región continental de China más cercana a Taiwán era cn-shenzhen (Shenzhen).
Con terraform Describimos y levantamos toda la infraestructura en GCP y Ali. El túnel de 100 Mbit/s entre las nubes se estableció prácticamente de inmediato. En Shenzhen y Taiwán levantamos máquinas virtuales proxy. En Shenzhen, el tráfico de los usuarios se termina, se enruta a través del túnel hacia Taiwán y de ahí se va directamente a la IP externa de nuestro servicio en us-east (Costa Este de EE. UU.). El ping entre las máquinas virtuales a través del túnel 24 ms, lo cual no está mal.
Al mismo tiempo, establecimos una zona de prueba en Alibaba Cloud DNS. Después de delegar la zona a NS de Ali, el tiempo de resolución se redujo de 470 ms a 50 ms. Antes de esto, la zona también estaba en Cloudflare.
Paralelamente al túnel hacia asia-east1 levantamos otro túnel desde Shenzhen directamente hacia us-east4. Allí se crearon más máquinas virtuales de proxy y se empezaron a medir ambas soluciones, enrutando el tráfico de prueba mediante Cookies o DNS. El banco de pruebas se describe esquemáticamente en la siguiente ilustración:
La latencia para los túneles fue la siguiente:
Ali cn-shenzhen GCP asia-east1 — 24ms
Ali cn-shenzhen GCP us-east4 — 200ms
Las pruebas de navegador Catchpoint informaron una excelente mejora en los indicadores.
Compare los resultados de las pruebas para las dos soluciones:
Solución
Tiempo de actividad
Mediana
Percentil 75
Percentil 95
Cloudflare
86.6
18s
30s
60s
IPsec
99.79
18s
21s
30s
Estos son los datos de la solución que utiliza un túnel IPSEC a través de asia-east1. A través de us-east4, los resultados fueron peores y hubo más errores, por lo que no presentaré los resultados.
Según los resultados de esta prueba de los dos túneles, uno de los cuales termina en la región más cercana a China y el otro en el destino final, quedó claro que es importante "emergir" lo más rápido posible del firewall chino, y luego utilizar redes rápidas (proveedores de CDN, proveedores en la nube, etc.). No hay que intentar atravesar el firewall de una sola vez y llegar al destino. Ese no es el camino más rápido.
En general, los resultados son buenos, sin embargo, el mediana de semrush.com es 8.8s, y el percentil 75 es 9.4s (en la misma prueba).
Y antes de continuar, me gustaría hacer un pequeño paréntesis lírico.
Un desvío lírico
Después de que un usuario ingresa al sitio web www.semrushchina.cn, que se resuelve a través de servidores DNS "rápidos" chinos, la solicitud HTTP pasa a través de nuestra solución rápida. La respuesta regresa por el mismo camino, pero en todos los scripts JS, páginas HTML y otros elementos de la página web se indica el dominio semrush.com para recursos adicionales que deben cargarse al renderizar la página. Es decir, el cliente resuelve el "registro A" principal www.semrushchina.cn y entra en el túnel rápido, recibiendo rápidamente la respuesta — la página HTML, que indica:
- descarga tal js de sso.semrush.com,
- obtén archivos CSS de cdn.semrush.com,
- y además toma imágenes de dab.semrush.com
- y así sucesivamente.
El navegador comienza a ir a la "internet externa" en busca de estos recursos, pasando cada vez por el firewall que consume tiempo de respuesta.
Pero en la prueba anterior se presentan resultados cuando la página no tiene recursos semrush.com, solo semrushchina.cn, y *.semrushchina.cn se resuelve a la dirección de la máquina virtual en Shenzhen, para luego entrar en el túnel.
Solo de esta manera, enviando todo el tráfico posible a través de nuestra solución de acceso rápido al firewall chino, se pueden lograr velocidades y tasas de disponibilidad aceptables del sitio, así como resultados honestos en las pruebas de solución.
Lo hicimos sin una sola modificación en el código de los productos del equipo.
Subfiltro
La solución surgió prácticamente en cuanto se presentó el problema. Necesitábamos PoC (Demostración de Concepto), que nuestras soluciones de acceso al firewall realmente funcionan bien. Para ello, es necesario redirigir todo el tráfico del sitio a esta solución. Y aplicamos en nginx.
Subfiltro — es un módulo bastante simple en nginx que permite cambiar una cadena en el cuerpo de la respuesta por otra cadena. Así que cambiamos todas las apariciones semrush.com en semrushchina.cn en todas las respuestas.
Y… no funcionó, porque de los backends recibíamos contenido comprimido, por lo tanto el subfiltro no encontraba la cadena deseada. Tuvimos que añadir otro servidor local en nginx, que descomprimía la respuesta y la pasaba al siguiente servidor local, que se encargaba de reemplazar la cadena, comprimirla y entregarla al siguiente proxy en la cadena.
Al final, donde el cliente recibiría .semrush.com, recibía .semrushchina.cn y pasaba por nuestra solución.
Sin embargo, no es suficiente simplemente cambiar el dominio en una dirección, ya que los backends también esperan semrush.com en las solicitudes subsiguientes del cliente. Por lo tanto, en el mismo servidor donde se realiza el cambio en una dirección, usando una expresión regular sencilla, obtenemos el subdominio de la solicitud y luego hacemos proxy_pass con la variable $host, establecida en $subdomain.semrush.com. Puede parecer confuso, pero funciona. Y funciona bien. Para dominios específicos que requieren otra lógica, simplemente se crean sus propios bloques de servidor y se realiza una configuración separada. A continuación se presentan configuraciones de nginx abreviadas para ilustrar y demostrar este esquema.
La siguiente configuración procesa todas las solicitudes desde China en .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;
}
}Esta configuración proxy se dirige a localhost el puerto 83, donde espera la siguiente configuración:
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;
}
}Reitero, estas son configuraciones recortadas.
Más o menos así. Puede parecer complicado, pero es solo en palabras. En la práctica, es mucho más simple 🙂
Fin de la digresión lírica
Durante un tiempo fuimos felices porque el mito sobre los túneles IPSEC caídos no se había confirmado. Pero luego los túneles empezaron a caer. Varias veces al día durante unos minutos. Poco, pero no nos satisfacía. Como ambos túneles estaban terminados en la misma ruta de Ali, decidimos que podría ser un problema regional y que había que levantar una región de respaldo.
Lo levantamos. Los túneles comenzaron a caer en diferentes momentos, pero el failover a nivel de upstream en nginx funcionaba perfectamente. Pero luego los túneles comenzaron a caer casi al mismo tiempo 🙂 Y empezaron a aparecer los errores 502 y 504. El tiempo de actividad comenzó a empeorar, por lo que comenzamos a considerar la opción de Alibaba CEN (Red Empresarial en la Nube).
CEN
CEN — es la conectividad entre dos VPC de diferentes regiones dentro de Alibaba Cloud; es decir, se pueden conectar redes privadas de cualquier región dentro de la nube entre sí. Y lo más importante: esta conexión tiene un SLArequisito bastante estricto. Es muy estable tanto en velocidad como en tiempo de actividad. Pero nunca es tan simple:
- es MUY difícil de obtener si no eres ciudadano o persona jurídica china,
- se debe pagar por cada megabit de capacidad del canal.
Al obtener la posibilidad de conectar Mainland China y Overseas, creamos un CEN entre dos regiones de Ali: cn-shenzhen y us-east-1 (el punto más cercano a us-east4). En Ali us-east-1 levantamos otra máquina virtual, para tener otro hop.
Así quedó:
Los resultados de las pruebas en el navegador son los siguientes:
Solución
Tiempo de actividad
Mediana
Percentil 75
Percentil 95
Cloudflare
86.6
18s
30s
60s
IPsec
99.79
18s
21s
30s
CEN
99.75
16s
21s
27s
Los indicadores son un poco mejores que los de IPSEC. Pero a través de IPSEC se puede descargar a una velocidad de 100 Mbps, mientras que a través de CEN solo a 5 Mbps y es más caro.
Se sugiere un híbrido, ¿verdad? Conectar la velocidad de IPSEC y la estabilidad de CEN.
Así lo hicimos, dirigiendo el tráfico tanto a través de IPSEC como de CEN en caso de caída del túnel IPSEC. El tiempo de actividad mejoró considerablemente, pero la velocidad de carga del sitio aún dejaba mucho que desear. Entonces dibujé todos los esquemas que ya habíamos usado y probado, y decidí intentar añadir un poco de GCP a este esquema, es decir, GLB.
GLB
GLB — es (o Google Cloud Load Balancer). Tiene una ventaja importante para nosotros: en el contexto de CDN tiene IP anycast, lo que permite enrutar el tráfico al centro de datos más cercano al cliente, lo que permite que el tráfico llegue más rápido a la red rápida de Google y menos pase por la “internet normal”.
Sin pensarlo mucho, levantamos HTTP/HTTPS LB en GCP y nuestras virtuales con subfilter como backend.
Hubo varios esquemas:
- Usar Red de Cloudflare China, pero esta vez el origen fue especificado como global IP GLB.
- Terminar clientes en cn-shenzhen, y de allí proseguir el tráfico directamente a GLB.
- Ir directamente de China a GLB.
- Terminar clientes en cn-shenzhen, de allí proseguir a asia-east1 a través de IPSEC (en us-east4 a través de CEN), y de allí ir a GLB (tranquilo, abajo habrá una imagen y explicación)
Probamos todas estas opciones y varias híbridas más:
- Cloudflare + GLB
Este esquema no nos satisfizo en cuanto al tiempo de actividad y errores de DNS. Pero la prueba se realizó antes de la corrección de un bug por parte de CF, tal vez ahora haya mejorado (sin embargo, esto no excluye los timeouts HTTP).
- Ali + GLB
Este esquema tampoco nos satisfizo en cuanto al tiempo de actividad, ya que GLB caía con frecuencia del upstream debido a la imposibilidad de conexión a tiempo o timeout, ya que para el servidor dentro de China la dirección de GLB sigue estando afuera, lo que significa que está detrás de un firewall chino. No hubo magia.
- Solo GLB
Una opción similar a la anterior, solo que no se utilizaron servidores en China: el tráfico iba directamente a GLB (cambiamos los registros DNS). Por lo tanto, los resultados no fueron satisfactorios, ya que los clientes chinos normales, que utilizan servicios de proveedores de Internet comunes, tienen una situación con el firewall mucho peor que en Ali Cloud.
- Shenzhen -> (CEN/IPSEC) -> Proxy -> GLB
Aquí decidimos utilizar lo mejor de todas las soluciones:
- estabilidad y SLA garantizado de CEN
- alta velocidad de IPSEC
- la “red rápida” de Google y su anycast.
El esquema se ve aproximadamente así: el tráfico de los usuarios se termina en una virtual en ch-shenzhen. Se configuraron los upstreams de nginx, algunos de los cuales apuntan a servidores IP privados ubicados al otro lado del túnel IPSEC, y otros upstreams apuntan a direcciones privadas de servidores al otro lado de CEN. IPSEC se configuró para la región asia-east1 en GCP (era la región más cercana a China en el momento de crear la solución. Ahora GCP también tiene presencia en Hong Kong). CEN — para la región us-east1 en Ali Cloud.
Luego, el tráfico de ambos extremos se dirigía a anycast IP GLB, es decir, al punto de presencia más cercano de Google, y se enviaba a través de sus redes a la región us-east4 en GCP, donde estaban las máquinas virtuales de reemplazo (con subfilter en nginx).
Esta solución híbrida, como esperábamos, permitió aprovechar las ventajas de cada tecnología. En general, el tráfico pasa a través de un IPSEC rápido, pero si surgen problemas, rápidamente y por unos minutos, sacamos esos servidores de los upstreams y enviamos el tráfico solo a través de CEN, hasta que el túnel se estabiliza.
Implementando la cuarta solución de la lista anterior, logramos lo que queríamos y lo que el negocio exigía en ese momento.
Resultados de las pruebas de navegador para la nueva solución en comparación con las anteriores:
Solución
Tiempo de actividad
Mediana
Percentil 75
Percentil 95
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
En la solución que implementamos, todo está bien, solo que no hay CDN que pueda acelerar el tráfico a nivel regional e incluso a nivel de ciudades. La idea es que esto debería acelerar el funcionamiento del sitio para los usuarios finales al utilizar canales rápidos de comunicación del proveedor CDN. Y siempre estuvimos pensando en eso. Y ahora, ha llegado el momento de la siguiente iteración del proyecto: buscar y probar proveedores de CDN en China.
Y sobre esto les hablaré en la próxima y última parte 🙂
Fuente: habr.com
