Como superamos o Grande Firewall da China (parte 2)

Olá!

Olá, sou Nikita novamente — engenheiro de sistemas da empresa SEMrush. E com este artigo, continuo a história sobre como criamos uma solução para contornar o Grande Firewall da China para o nosso serviço semrush.com.

Em parte anterior Eu falei sobre:

  • quais problemas surgem após a decisão de "Precisamos fazer nosso serviço funcionar na China"
  • quais são os problemas da internet chinesa
  • por que precisamos de uma licença ICP
  • como e por que decidimos testar nossos ambientes de teste com o Catchpoint
  • qual foi o resultado da nossa primeira solução, baseada na Cloudflare China Network
  • como encontramos um bug no DNS da Cloudflare

Esta parte é a mais interessante, na minha opinião, porque se concentra nas implementações técnicas específicas dos estágios. E começaremos — ou melhor, continuaremos — com Alibaba Cloud.

Alibaba Cloud

Alibaba Cloud — um provedor de nuvem bastante grande, que possui todos os serviços que lhe permitem chamar a si mesmo de provedor de nuvem. É bom que eles tenham a opção de se registrar para usuários estrangeiros e que a maior parte do site esteja traduzida para o inglês (o que é um luxo na China). Nesta nuvem, é possível trabalhar com várias regiões do mundo, da China continental, assim como da Ásia do Pacífico (Hong Kong, Taiwan, etc.).

IPSEC

Começamos pela geografia. Como o site de teste estava no Google Cloud, precisávamos "conectar" o Alibaba Cloud ao GCP, então abrimos a lista de locais onde o Google está presente. Naquele momento, eles ainda não tinham um data center em Hong Kong.
A região mais próxima era asia-east1 (Taiwan). No Alibaba, a região continental da China mais próxima de Taiwan era cn-shenzhen (Shenzhen).

Com terraform Descrevemos e levantamos toda a infraestrutura no GCP e no Alibaba. O túnel de 100 Mbps entre as nuvens foi montado praticamente instantaneamente. Do lado de Shenzhen e Taiwan, levantamos instâncias virtuais de proxy. Em Shenzhen, o tráfego do usuário é terminado, é proxyado através do túnel para Taiwan, e de lá vai diretamente para o IP externo do nosso serviço em us-east (Costa Leste dos EUA). O ping entre as instâncias virtuais pelo túnel é 24ms, o que não é tão ruim.

Ao mesmo tempo, configuramos a zona de teste em Alibaba Cloud DNS. Após a delegação da zona para o NS da Ali, o tempo de resolução caiu de 470 ms para 50 ms. Antes disso, a zona também estava no Cloudflare.

Paralelamente ao túnel, levantamos mais um túnel de Shenzhen diretamente para asia-east1 us-east4 us-east4. Criaram ainda mais máquinas virtuais de proxy e começaram a medir ambas as soluções, roteando o tráfego de teste com a ajuda de Cookies ou DNS. Esquematicamente, o ambiente de teste é descrito na figura a seguir:

A latência para os túneis foi a seguinte:
Ali cn-shenzhen GCP asia-east1 — 24ms
Ali cn-shenzhen GCP us-east4 — 200ms

Os testes de navegador da Catchpoint relataram uma ótima melhoria nos indicadores.

Compare os resultados dos testes para as duas soluções:

Solução
Uptime
Mediana
Percentil 75
Percentil 95

Cloudflare
86.6
18s
30s
60s

IPsec
99.79
18s
21s
30s

Estes são os dados da solução que utiliza um túnel IPSEC através de asia-east1. Através de us-east4, os resultados foram piores, e houve mais erros, portanto, não vou apresentar os resultados.

Com base nos resultados deste teste de dois túneis, um dos quais termina na região mais próxima da China e o outro no ponto final, ficou claro que é importante "emergir" rapidamente do firewall chinês, e depois utilizar redes rápidas (fornecedores de CDN, provedores de nuvem etc.). Não deve-se tentar passar pelo firewall de uma só vez e chegar ao destino. Este não é o caminho mais rápido.

No geral, os resultados são bons, no entanto, o semrush.com tem uma mediana de 8.8s, e o percentil 75 é 9.4s (no mesmo teste).
E antes de seguir em frente, gostaria de fazer uma pequena digressão.

Um desvio lírico

Após o usuário acessar o site www.semrushchina.cn, que é resolvido através de servidores DNS "rápidos" da China, a solicitação HTTP passa pela nossa solução rápida. A resposta retorna pelo mesmo caminho, mas em todos os scripts JS, páginas HTML e outros elementos da página da web está indicado o domínio semrush.com para recursos adicionais que devem ser carregados ao renderizar a página. Ou seja, o cliente resolve o registro A "principal" www.semrushchina.cn e entra no túnel rápido, obtendo rapidamente a resposta — a página HTML, que indica:

  • baixe um determinado js de sso.semrush.com,
  • os arquivos CSS devem ser retirados de cdn.semrush.com,
  • e ainda pegue as imagens de dab.semrush.com
  • e assim por diante.

O navegador começa a ir para a "internet externa" em busca desses recursos, passando a cada vez pelo firewall que consome tempo de resposta.

Mas no teste anterior estão apresentados os resultados, quando na página não há recursos semrush.com, apenas semrushchina.cn, enquanto *.semrushchina.cn resolve-se no endereço da máquina virtual em Shenzhen, para depois entrar no túnel.

Somente dessa forma, maximizando o tráfego através da nossa solução de passagem rápida pelo firewall chinês, é possível obter velocidades aceitáveis e indicadores de disponibilidade do site, além de resultados de testes confiáveis das soluções.
Fizemos isso sem nenhuma alteração no código do lado dos produtos das equipes.

Subfiltro

A solução surgiu praticamente assim que o problema foi identificado. Precisávamos de PoC (Prova de Conceito) de que nossas soluções de passagem pelo firewall realmente funcionavam bem. Para isso, era necessário canalizar todo o tráfego do site por essa solução. E aplicamos subfiltro no nginx.

Subfiltro — é um módulo bastante simples no nginx, que permite trocar uma linha no corpo da resposta por outra linha. Assim, alteramos todas as ocorrências semrush.com para semrushchina.cn em todas as respostas.

E... isso não funcionou, porque estávamos recebendo conteúdo comprimido dos back-ends, e, consequentemente, o subfiltro não encontrava a linha desejada. Foi necessário adicionar mais um servidor local no nginx, que descomprimia a resposta e a passava para o próximo servidor local, que se encarregava de substituir a linha, comprimir e entregar ao próximo servidor proxy na cadeia.

Assim, onde o cliente receberia <subdomain>.semrush.com, ele recebia <subdomain>.semrushchina.cn e passava pelo nosso sistema.

No entanto, não basta apenas trocar o domínio em uma direção, pois os back-ends ainda esperam semrush.com nas solicitações subsequentes do cliente. Portanto, no mesmo servidor onde a troca é feita em uma direção, utilizando uma expressão regular simples, obtemos o subdomínio da solicitação e, em seguida, fazemos proxy_pass com a variável $host, definida em $subdomain.semrush.com. Pode parecer confuso, mas isso funciona. E funciona bem. Para domínios específicos que exigem outra lógica, basta criar seus próprios blocos de servidor e configurar separadamente. Abaixo estão apresentados trechos abreviados das configurações do nginx para ilustrar e demonstrar esse esquema.

A próxima configuração lida com todas as solicitações da China para .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 configuração proxy é para localhost na porta 83, e lá espera a próxima configuração:

    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 são configurações reduzidas.

Mais ou menos assim. Pode parecer complicado, mas isso é só na teoria. Na prática, tudo é mais simples do que parece 🙂

Fim do desvio lírico

Por um tempo, fomos felizes, porque o mito sobre as quedas de túneis IPSEC não se confirmou. Mas depois os túneis começaram a cair. Algumas vezes por dia, por alguns minutos. Pouco, mas isso não nos agradava. Como ambos os túneis terminavam no lado da Ali em um único roteador, decidimos que, talvez, isso fosse um problema regional e era necessário levantar uma região de backup.

Levantamos. Os túneis começaram a cair em momentos diferentes, mas o failover funcionava perfeitamente no nível upstream no nginx. Mas depois os túneis começaram a cair aproximadamente ao mesmo tempo 🙂 E novamente começaram os erros 502 e 504. O uptime começou a piorar, então começamos a explorar a opção com Alibaba CEN (Cloud Enterprise Network).

CEN

CEN — são conexões entre duas VPC de diferentes regiões dentro da Alibaba Cloud, ou seja, é possível conectar redes privadas de quaisquer regiões dentro da nuvem entre si. E o mais importante: este canal possui critérios bastante rígidos SLA. Ele é muito estável tanto em velocidade quanto em uptime. Mas nunca é tão simples:

  • é MUITO difícil de obter, a menos que você seja um cidadão ou pessoa jurídica chinesa,
  • é necessário pagar por cada megabit de capacidade de banda do canal.

Ao obter a possibilidade de conectar Mainland China e Overseas, criamos um CEN entre duas regiões da Ali: cn-shenzhen e us-east-1 (o ponto mais próximo de us-east4). Na Ali us-east-1 levantamos mais uma máquina virtual para ter mais um hop.

O resultado foi o seguinte:

Os resultados dos testes de navegador estão abaixo:

Solução
Uptime
Mediana
Percentil 75
Percentil 95

Cloudflare
86.6
18s
30s
60s

IPsec
99.79
18s
21s
30s

CEN
99.75
16s
21s
27s

Os índices são um pouco melhores do que os do IPSEC. Mas através do IPSEC é potencialmente possível transferir a uma velocidade de 100 Mbps, enquanto pelo CEN é apenas a 5 Mbps e mais caro.

Está na hora de um híbrido, não? Conectar a velocidade do IPSEC e a estabilidade do CEN.

Assim fizemos, redirecionando o tráfego tanto através do IPSEC quanto pelo CEN em caso de falha do túnel IPSEC. O uptime melhorou consideravelmente, mas a velocidade de carregamento do site ainda deixava a desejar. Então, desenhei todos os esquemas que já utilizamos e testamos e decidi tentar adicionar um pouco do GCP a este esquema, ou seja, GLB.

GLB

GLB seja Global Load Balancer (ou Google Cloud Load Balancer). Ele possui uma vantagem importante para nós: no contexto de CDN, ele anycast IP, o que permite rotear o tráfego para o data center mais próximo do cliente, fazendo com que o tráfego chegue mais rápido à rede rápida do Google e menos passe pela internet “normal”.

Sem pensar muito, levantamos HTTP/HTTPS LB no GCP e configuramos nossas máquinas virtuais com subfilter como backend.

Havia vários esquemas:

  • Usar Rede China da Cloudflare, mas desta vez o Origin foi definido como global IP GLB.
  • Terminar clientes em cn-shenzhen, e a partir daí proxificar o tráfego diretamente em GLB.
  • Vindo diretamente da China para GLB.
  • Terminar clientes em cn-shenzhen, de lá proxificando para asia-east1 via IPSEC (ou us-east4 via CEN), e daí seguir para o GLB (calma, abaixo estará a imagem e a explicação)

Testamos todas essas opções e ainda mais algumas híbridas:

  • Cloudflare + GLB

Este esquema não nos agradou em relação ao uptime e a erros de DNS. Mas o teste foi realizado antes da correção de um bug por parte do CF, talvez agora esteja melhor (no entanto, isso não exclui os timeouts HTTP).

  • Ali + GLB

Esse esquema também não nos convenceu em relação ao uptime, pois o GLB frequentemente saía do upstream devido à impossibilidade de conexão em um tempo aceitável ou timeouts, já que para um servidor dentro da China o endereço GLB continua por fora, ou seja, atrás do firewall chinês. Não houve mágica.

  • GLB only

Uma opção semelhante à anterior, mas sem servidores na China: o tráfego seguia diretamente para o GLB (alteramos os registros DNS). Consequentemente, os resultados não foram satisfatórios, já que os clientes chineses comuns, que utilizam serviços de provedores de internet regulares, enfrentam uma situação de dificuldade de passagem pelo firewall muito pior do que no Ali Cloud.

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

Aqui decidimos usar o melhor de todas as soluções:

  • estabilidade e SLA garantido do CEN
  • alta velocidade do IPSEC
  • a “rede” rápida do Google e seu anycast.

O esquema se parece mais ou menos assim: o tráfego dos usuários termina em uma máquina virtual em ch-shenzhen. Foi configurado upstreams nginx, parte dos quais se refere a IPs privados de servidores localizados do outro lado de um túnel IPSEC, enquanto parte dos upstreams se refere a endereços privados de servidores do outro lado do CEN. O IPSEC foi configurado para a região asia-east1 no GCP (era a região mais próxima da China no momento da criação da solução. Agora, o GCP também tem presença em Hong Kong). O CEN — para a região us-east1 no Ali Cloud.

Em seguida, o tráfego de ambas as extremidades foi direcionado para anycast IP GLB, ou seja, o ponto de presença mais próximo do Google, e seguia por suas redes para a região us-east4 no GCP, onde estavam as máquinas virtuais substitutas (com subfilter no nginx).

Essa solução híbrida, como esperávamos, permitiu aproveitar as vantagens de cada tecnologia. No geral, o tráfego passa rapidamente pelo IPSEC, mas se surgem problemas, rapidamente removemos esses servidores dos upstreams por alguns minutos e direcionamos o tráfego apenas pelo CEN, até que o túnel se estabilize.

Implantando a 4ª solução da lista acima, alcançamos o que queríamos e o que o negócio exigia naquela época.

Resultados dos testes de navegador para a nova solução em comparação com as anteriores:

Solução
Uptime
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

provedor de CDN). Eles monitoram seu

Na solução que implementamos, tudo está bem, exceto que não há CDN que possa acelerar o tráfego em nível regional e até mesmo nas cidades. A ideia é que isso deve acelerar o funcionamento do site para os usuários finais através do uso de canais rápidos do provedor de CDN. E estávamos sempre pensando nisso. E agora, chegou a hora da próxima iteração do projeto: busca e teste de provedores de CDN na China.

E sobre isso, falarei com você na próxima e última parte 🙂

Fonte: habr.com

Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS 🔥 Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS | ProHoster