Como rompemos o Grande Firewall da China (Parte 2)

Oi!

Nikita está com você novamente, engenheira de sistemas da empresa SEMrush. E com este artigo continuo a história sobre como criamos uma solução alternativa Firewall Chinês para nosso serviço semrush.com.

В parte anterior Eu disse:

  • quais problemas surgem após a decisão ser tomada “Precisamos fazer nosso serviço funcionar na China”
  • Que problemas tem a Internet chinesa?
  • por que você precisa de uma licença ICP?
  • como e por que decidimos testar nossos testbeds com 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 em implementações técnicas específicas de staging. E começaremos, ou melhor, continuaremos, com Cloud Alibaba.

Cloud Alibaba

Cloud Alibaba é um provedor de nuvem bastante grande, que possui todos os serviços que lhe permitem se autodenominar honestamente como um provedor de nuvem. É bom que eles tenham a oportunidade de se cadastrar para usuários estrangeiros e que a maior parte do site esteja traduzida para o inglês (para a China isso é um luxo). Nesta nuvem, você pode trabalhar com diversas regiões do mundo, com a China continental, bem como com a Ásia Oceânica (Hong Kong, Taiwan, etc.).

IPSEC

Começamos com geografia. Como nosso local de teste estava localizado no Google Cloud, precisávamos “vincular” o Alibaba Cloud ao GCP, por isso abrimos uma lista de locais em que o Google está presente. Naquele momento eles ainda não tinham data center próprio em Hong Kong.
A região mais próxima acabou sendo ásia-leste1 (Taiwan). Ali acabou por ser a região da China continental mais próxima de Taiwan cn-shenzhen (Shenzhen).

Com terraform descreveu e levantou toda a infraestrutura em GCP e Ali. Um túnel de 100 Mbit/s entre as nuvens subiu quase instantaneamente. Do lado de Shenzhen e Taiwan, foram criadas máquinas virtuais de proxy. Em Shenzhen, o tráfego do usuário é encerrado, encaminhado por proxy através de um túnel para Taiwan e de lá vai diretamente para o IP externo do nosso serviço em nós-leste (Costa Leste dos EUA). Ping entre máquinas virtuais via túnel 24ms, o que não é tão ruim.

Ao mesmo tempo, colocamos uma área de teste em Alibaba Nuvem DNS. Depois de delegar a zona para NS Ali, o tempo de resolução diminuiu de 470 ms para 50 ms. Antes disso, a zona também estava no Cloudlfare.

Paralelo ao túnel para ásia-leste1 levantou outro túnel de Shenzhen diretamente para nós-leste4. Lá eles criaram mais máquinas virtuais proxy e começaram a testar ambas as soluções, roteando o tráfego de teste usando Cookies ou DNS. A bancada de testes é descrita esquematicamente na figura a seguir:

A latência dos túneis acabou sendo a seguinte:
Ali cn-shenzhen <—> GCP ásia-leste1 — 24ms
Ali cn-shenzhen <—> GCP us-east4 — 200ms

Os testes do navegador Catchpoint relataram uma excelente melhoria.

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

Solução
Uptime
Mediana
75 percentil
95 percentil

Cloudflare
86.6
18s
30s
60s

IPsec
99.79
18s
21s
30s

Estes são dados de uma solução que utiliza um túnel IPSEC via ásia-leste1. Através do us-east4 os resultados foram piores e houve mais erros, por isso não vou dar 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 destino final, ficou claro que é importante “emergir” do firewall chinês o mais rápido possível. possível e, em seguida, use redes rápidas (provedores de CDN, provedores de nuvem, etc.). Não há necessidade de tentar passar pelo firewall e chegar ao seu destino de uma só vez. Este não é o caminho mais rápido.

Em geral, os resultados não são ruins, porém, semrush.com tem mediana de 8.8s e 75 percentil 9.4s (no mesmo teste).
E antes de prosseguir, gostaria de fazer uma breve digressão lírica.

Digressão lírica

Depois que o usuário entra no site www.semrushchina.cn, que é resolvido por meio de servidores DNS chineses “rápidos”, a solicitação HTTP passa por nossa solução rápida. A resposta é retornada pelo mesmo caminho, mas o domínio é especificado em todos os scripts JS, páginas HTML e outros elementos da página web semrush. com para recursos adicionais que devem ser carregados quando a página é renderizada. Ou seja, o cliente resolve o registro A “principal” semrushchina.cn e entra no túnel rápido, recebe rapidamente uma resposta - uma página HTML que afirma:

  • baixe tal e tal js em sso.semrush.com,
  • Obtenha os arquivos CSS em cdn.semrush.com,
  • e também tire algumas fotos de dab.semrush.com
  • e assim por diante.

O navegador começa a ir para a Internet “externa” em busca desses recursos, cada vez passando por um firewall que consome tempo de resposta.

Mas o teste anterior mostra os resultados quando não há recursos na página semrush. comsomente semrushchina.cn, e *.semrushchina.cn resolve o endereço da máquina virtual em Shenzhen para entrar no túnel.

Somente desta forma, empurrando ao máximo todo o tráfego possível através de sua solução para passar rapidamente pelo firewall chinês, você poderá obter velocidades aceitáveis ​​e indicadores de disponibilidade do site, bem como resultados honestos de testes de solução.
Fizemos isso sem uma única edição de código por parte do produto da equipe.

Subfiltro

A solução nasceu quase imediatamente após o surgimento do problema. Nos precisamos PoC (Prova de Conceito) de que nossas soluções de penetração de firewall realmente funcionam bem. Para fazer isso, você precisa envolver todo o tráfego do site nesta solução, tanto quanto possível. E nós aplicamos subfiltro em nginx.

Subfiltro é um módulo bastante simples no nginx que permite alterar uma linha no corpo da resposta para outra linha. Então mudamos todas as ocorrências semrush. com em semrushchina.cn em todas as respostas.

E... não funcionou porque recebemos conteúdo compactado dos backends, então o subfiltro não encontrou a linha necessária. Tive que adicionar outro servidor local ao nginx, que descompactou a resposta e a passou para o próximo servidor local, que já estava ocupado substituindo a string, compactando-a e enviando-a para o próximo servidor proxy da cadeia.

Como resultado, onde o cliente receberia .semrush.com, ele recebeu .semrushchina.cn e obedientemente seguiu nossa decisão.

No entanto, não basta simplesmente alterar o domínio de uma forma, porque os backends ainda esperam semrush.com nas solicitações subsequentes do cliente. Assim, no mesmo servidor onde é feita a substituição unilateral, usando uma expressão regular simples obtemos o subdomínio da solicitação e então fazemos proxy_pass com variável $ host, exibido em $subdomínio.semrush.com. Pode parecer confuso, mas funciona. E funciona bem. Para domínios individuais que exigem lógica diferente, basta criar seus próprios blocos de servidor e fazer uma configuração separada. Abaixo estão as configurações abreviadas do nginx para maior clareza e demonstração deste esquema.

A configuração a seguir processa 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 faz proxy para localhost para a porta 83, e a seguinte configuração está aguardando lá:

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

Repito, estas são configurações cortadas.

Assim. Pode parecer complicado, mas está em palavras. Na verdade, tudo é mais simples do que nabos cozidos no vapor :)

Fim da digressão

Por um tempo ficamos felizes porque o mito da queda dos túneis IPSEC não foi confirmado. Mas então os túneis começaram a cair. Várias vezes ao dia durante alguns minutos. Um pouco, mas isso não nos convinha. Como ambos os túneis terminavam no lado Ali no mesmo roteador, decidimos que talvez este fosse um problema regional e precisávamos aumentar a região de backup.

Eles pegaram. Os túneis começaram a falhar em momentos diferentes, mas o failover funcionou bem para nós no nível upstream do nginx. Mas então os túneis começaram a cair quase ao mesmo tempo 🙂 E os túneis 502 e 504 começaram novamente. O tempo de atividade começou a piorar, então começamos a trabalhar na opção com Alibaba CEN (Rede Empresarial em Nuvem).

CEN

CEN - esta é a conectividade de duas VPCs de regiões diferentes dentro do Alibaba Cloud, ou seja, você pode conectar redes privadas de qualquer região da nuvem entre si. E o mais importante: este canal tem um sistema bastante rígido SLA. É muito estável em velocidade e tempo de atividade. Mas nunca é tão simples:

  • é MUITO difícil de obter se você não for cidadão chinês ou pessoa jurídica,
  • Você precisa pagar por cada megabit de capacidade do canal.

Ter a oportunidade de se conectar China continental и No exterior, criamos um CEN entre duas regiões de Ali: cn-shenzhen и us-leste-1 (ponto mais próximo de us-east4). Em Ali us-leste-1 levantou outra máquina virtual para que haja mais uma salto.

Aconteceu assim:

Os resultados do teste do navegador estão abaixo:

Solução
Uptime
Mediana
75 percentil
95 percentil

Cloudflare
86.6
18s
30s
60s

IPsec
99.79
18s
21s
30s

CEN
99.75
16s
21s
27s

O desempenho é ligeiramente melhor que o IPSEC. Mas através do IPSEC você pode potencialmente fazer download a uma velocidade de 100 Mbit/s, e através do CEN apenas a uma velocidade de 5 Mbit/s ou mais.

Parece um híbrido, certo? Combine velocidade IPSEC e estabilidade CEN.

Foi isso que fizemos, permitindo o tráfego através de IPSEC e CEN no caso de falha do túnel IPSEC. O tempo de atividade aumentou muito, mas a velocidade de carregamento do site ainda deixa muito a desejar. Depois desenhei todos os circuitos que já tínhamos usado e testado, e decidi tentar adicionar um pouco mais de GCP a este circuito, nomeadamente boné.

boné

boné - É Balanceador de carga global (ou Google Cloud Load Balancer). Tem uma vantagem importante para nós: no contexto de uma CDN tem IP Anycast, que permite rotear o tráfego para o data center mais próximo do cliente, para que o tráfego chegue rapidamente à rede rápida do Google e passe menos pela Internet “normal”.

Sem pensar duas vezes, levantamos HTTP/HTTPSLB Instalamos nossas máquinas virtuais com subfiltro no GCP e como backend.

Havia vários esquemas:

  • Usar Rede Cloudflare China, mas desta vez o Origin deve especificar global IPGL.
  • Encerrar clientes em cn-shenzhene, a partir daí, proxy do tráfego diretamente para boné.
  • Vá direto da China para boné.
  • Encerrar clientes em cn-shenzhen, de lá proxy para ásia-leste1 via IPSEC (em nós-leste4 via CEN), de lá vá para o GLB (com calma, abaixo terá foto e explicação)

Testamos todas essas opções e várias outras híbridas:

  • Cloudflare + GLB

Este esquema não nos agradou devido ao tempo de atividade e erros de DNS. Mas o teste foi realizado antes do bug ser corrigido no lado do CF, talvez seja melhor agora (no entanto, isso não exclui tempos limite de HTTP).

  • Ali + GLB

Este esquema também não nos agradou em termos de tempo de atividade, já que o GLB muitas vezes saía do upstream devido à impossibilidade de conexão em um tempo ou timeout aceitável, pois para um servidor dentro da China, o endereço GLB permanece fora e, portanto, atrás do Firewall chinês. A mágica não aconteceu.

  • Somente GLB

Opção semelhante à anterior, só que não utilizava servidores na própria China: o tráfego ia direto para o GLB (os registros DNS foram alterados). Conseqüentemente, os resultados não foram satisfatórios, uma vez que os clientes chineses comuns que utilizam os serviços de provedores de Internet comuns têm uma situação muito pior ao passar pelo firewall do que o Ali Cloud.

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

Aqui decidimos usar a 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 é mais ou menos assim: o tráfego do usuário é encerrado na máquina virtual em ch-shenzhen. Os upstreams Nginx são configurados lá, alguns dos quais apontam para servidores IP privados localizados na outra extremidade do túnel IPSEC, e alguns upstreams apontam para endereços privados de servidores no outro lado do CEN. IPSEC configurado para região ásia-leste1 no GCP (era a região mais próxima da China no momento em que a solução foi criada. O GCP agora também está presente em Hong Kong). CEN - para a região nós-leste1 em Ali Cloud.

Então o tráfego de ambas as extremidades foi direcionado para IP Anycast GLB, ou seja, até o ponto de presença do Google mais próximo, e passou por suas redes até a região nós-leste4 no GCP, em que houve substituição de máquinas virtuais (com subfiltro no nginx).

Esta solução híbrida, como esperávamos, aproveitou os benefícios de cada tecnologia. Em geral, o tráfego passa por IPSEC rápido, mas se os problemas começarem, rapidamente e por alguns minutos expulsamos esses servidores do upstream e enviamos o tráfego apenas através do CEN até que o túnel se estabilize.

Ao implementar a 4ª solução da lista acima, alcançamos o que queríamos e o que o negócio exigia de nós naquele momento.

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

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

Tudo está bem na solução que implementamos, mas não existe um CDN que possa acelerar o tráfego a nível regional e até municipal. Em teoria, isso deveria acelerar o site para os usuários finais, usando os canais de comunicação rápidos do provedor de CDN. E pensávamos nisso o tempo todo. E agora chegou a hora da próxima iteração do projeto: pesquisar e testar fornecedores de CDN na China.

E falarei sobre isso na próxima parte final :)

Fonte: habr.com

Adicionar um comentário