Como perfuramos o grande firewall chinês (parte 2)

Oi


Nikita está com você novamente - um engenheiro de sistema da SEMrush . E com este artigo, continuo a história de como criamos uma solução para contornar o firewall chinês para o nosso serviço semrush.com.


Na parte anterior, eu disse:


  • que problemas aparecem depois que uma decisão é tomada "Precisamos fazer nosso serviço funcionar na China"
  • que problemas a Internet chinesa tem
  • por que preciso de uma licença ICP
  • como e por que decidimos testar nossas bancadas de teste usando o ponto de captura
  • qual foi o resultado de nossa primeira solução baseada na Cloudflare China Network
  • como encontramos um bug no DNS Cloudflare


Esta parte é a mais interessante, na minha opinião, porque se concentra em implementações técnicas específicas de preparação. E começaremos, ou melhor, continuaremos com o Alibaba Cloud .


Nuvem Alibaba


O Alibaba Cloud é um provedor de nuvem bastante grande, que possui todos os serviços que lhe permitem honestamente se chamar provedor de nuvem. É bom que eles tenham a oportunidade de se registrar com usuários estrangeiros e que a maior parte do site tenha sido traduzida para o inglês (para a China é um luxo). Nesta nuvem, você pode trabalhar com muitas regiões do mundo, na China continental e no Oceano da Ásia (Hong Kong, Taiwan etc.).


IPSEC


Começou com a geografia. Como nosso site de teste estava localizado no Google Cloud, tivemos que "vincular" o Alibaba Cloud ao GCP, por isso abrimos uma lista de locais onde o Google está presente. Naquele momento, eles ainda não tinham seu próprio data center em Hong Kong.
A região mais próxima era a Ásia-leste1 (Taiwan). Ali tinha cn-shenzhen (Shenzhen) como a região mais próxima da China continental a Taiwan.


Usando terraform, eles descreveram e elevaram toda a infraestrutura no GCP e Ali. O túnel de 100 Mbps entre as nuvens subiu quase instantaneamente. No lado de Shenzhen e Taiwan, eles criaram máquinas virtuais de proxy. Em Shenzhen, o tráfego do usuário é encerrado, transferido por proxy para Taiwan e, a partir daí, é direcionado diretamente para o IP externo de nosso serviço no leste do país (costa leste dos EUA). Faça ping entre os virtuais no túnel de 24ms , o que não é tão ruim.


Ao mesmo tempo, colocamos uma zona de teste no Alibaba Cloud DNS . Após delegar a zona ao NS Ali, o tempo de resolução diminuiu de 470 ms para 50 ms . Antes disso, a zona também estava em Cloudlfare.


Paralelamente ao túnel para o leste asiático1 , outro túnel foi erguido de Shenzhen diretamente para o leste4 . Lá, eles criaram mais máquinas virtuais de proxy e começaram a medir as duas 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 para túneis é a seguinte:
Ali cn-shenzhen <--> GCP asia-east1 - 24ms
Ali cn-shenzhen <--> GCP us-east4 - 200ms


Os testes do navegador Catchpoint relataram excelentes melhorias de desempenho.



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


SoluçãoUpimeMedianaPercentil 75Percentil 95
Cloudflare86,618 anos30sAnos 60
IPsec99,7918 anos21s30s

Estes são os dados da solução usando o túnel IPSEC na Ásia-Leste1 . Através de nós-leste4, os resultados foram piores e houve mais erros, então não vou dar os resultados.


De acordo com os resultados desse teste, dois túneis, um dos quais é terminado 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 e usar redes rápidas (provedores CDN) , provedores de nuvem etc.). Não é necessário tentar um toque para atravessar o firewall e chegar ao destino. Este não é o caminho mais rápido.


Em geral, os resultados não são ruins, no entanto, o semrush.com tem uma mediana de 8,8s e um percentil 75 de 9,4s (no mesmo teste).
E antes de prosseguir, gostaria de fazer uma digressão.


Digressão lírica


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


  • baixe esses e esses js de sso.semrush.com,
  • Pegue arquivos CSS de cdn.semrush.com,
  • e tire mais fotos de dab.semrush.com
  • e assim por diante.

O navegador começa a acessar a Internet "externa" para esses recursos, cada vez que passa por um firewall, devorando o tempo de resposta.


Mas no teste anterior, os resultados são apresentados quando não há recursos semrush.com na página, apenas semrushchina.cn e * .semrushchina.cn são resolvidos para o endereço da máquina virtual em Shenzhen para entrar no túnel mais tarde.


Somente dessa maneira, jogando o máximo possível de todo o tráfego por sua decisão de passar rapidamente pelo firewall chinês, você poderá obter velocidades e indicadores aceitáveis ​​da disponibilidade do site, além de resultados honestos das soluções de teste.
Fizemos isso sem uma única edição de código ao lado dos produtos da equipe.


Subfiltro


A solução nasceu quase imediatamente depois que esse problema apareceu. Precisávamos de PoC (Prova de conceito) para que nossas soluções de passagem de firewall realmente funcionassem bem. Para fazer isso, você deve maximizar todo o tráfego para o site nesta solução. E nós aplicamos o subfiltro no nginx.


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


E ... isso não funcionou, porque recebemos conteúdo compactado dos back-ends; portanto, o subfiltro não conseguiu encontrar a linha necessária. Eu tive que adicionar outro servidor local ao nginx, que expandiu a resposta e a transmitiu para o próximo servidor local, que já estava envolvido na substituição, compactação e entrega de linha para a próxima cadeia de proxies.



Como resultado, onde o cliente receberia <subdomain> .semrush.com , ele receberia <subdomain> .semrushchina.cn e obedeceria a nossa decisão.


No entanto, não basta alterar o domínio em uma direção, porque os back-end ainda esperam semrush.com em solicitações subsequentes do cliente. Assim, no mesmo servidor em que a substituição é feita em uma direção, usando 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 funciona. E isso funciona bem. Para domínios individuais que exigem lógica diferente, eles simplesmente criam seus blocos de servidores e fazem uma configuração separada. Abaixo estão as configurações reduzidas do nginx para maior clareza e demonstração desse esquema.


A seguinte configuração 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; } } 

Essa configuração está em proxy para o host local na porta 83 e aguarda a seguinte 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; } } 

Novamente, essas são configurações cortadas.


Algo assim. Pode parecer complicado, mas está em palavras. Na verdade, tudo é mais fácil do que nabo cozido no vapor :)


O fim da digressão lírica


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 por vários minutos. Um pouco, mas não nos convinha. Como os dois túneis foram terminados no lado Ali no mesmo roteador, decidimos que talvez esse seja um problema regional e precisamos aumentar a região de backup.


Pegou. Os túneis começaram a cair em momentos diferentes, mas tivemos um failover ajustado no nível upstream no nginx. Mas então os túneis começaram a cair na mesma época :) E, novamente, começaram o 502 e o 504. O tempo de atividade começou a se deteriorar, então começamos a elaborar uma opção com o Alibaba CEN (Cloud Enterprise Network).


Cen


O CEN é a conectividade de duas VPCs de diferentes regiões na Nuvem Alibaba, ou seja, você pode conectar redes privadas de qualquer região na nuvem entre si. E o mais importante: esse canal possui um SLA bastante rigoroso. É muito estável, tanto na velocidade quanto no tempo de atividade. Mas nunca é tão simples:


  • é MUITO difícil conseguir se você não é um cidadão chinês ou uma entidade legal,
  • você precisa pagar por cada megabit de largura de banda.

Tendo a oportunidade de conectar a China continental e o exterior , criamos um CEN entre duas regiões Ali: cn-shenzhen e us-east-1 (o ponto mais próximo de us-east4). Em Ali us-east-1, eles criaram outra máquina virtual para ter outro salto .


Aconteceu assim:



Resultados dos testes do navegador abaixo:



SoluçãoUpimeMedianaPercentil 75Percentil 95
Cloudflare86,618 anos30sAnos 60
IPsec99,7918 anos21s30s
Cen99,7516s21s27s

O desempenho é um pouco melhor que o IPSEC. Mas, com o IPSEC, é possível fazer o download potencialmente a uma velocidade de 100 Mbps e, através do CEN, apenas a uma velocidade de 5 Mbps e mais caro.


O híbrido implora, certo? Combine velocidade IPSEC e estabilidade CEN.


Foi o que fizemos ao permitir o tráfego através do IPSEC e do CEN no caso de uma falha no túnel do IPSEC. O tempo de atividade se tornou muito maior, mas a velocidade de carregamento do site é baixa. Então desenhei todos os esquemas que já usamos e testamos e decidi tentar adicionar um pouco mais de GCP a esse esquema, ou seja, GLB .


GLB


GLB é o Global Load Balancer (ou Google Cloud Load Balancer). Ela tem uma vantagem importante: no contexto da CDN, ela possui anycast IP , que permite rotear o tráfego para o datacenter mais próximo do cliente, graças ao qual o tráfego chega à rede rápida do Google com mais rapidez e menos via Internet "normal".


Sem pensar duas vezes, aumentamos o HTTP / HTTPS LB para o GCP e colocamos nossas máquinas virtuais no back-end do subfiltro.


Havia vários esquemas:


  • Use o Cloudflare China Network , mas desta vez a Origin especifica o GLB IP global.
  • Encerre os clientes no cn-shenzhen e, a partir daí, o tráfego proxy imediatamente para o GLB .
  • Vá direto da China para o GLB .
  • Encerrar clientes em cn-shenzhen , de lá para proxy para asia-east1 via IPSEC (em us-east4 via CEN), de lá para GLB (calmamente, haverá uma imagem e explicação abaixo)

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


  • Cloudflare + GLB


Esse esquema não nos convém para uptime e erros de DNS. Mas o teste foi realizado antes de corrigir o erro por parte do CF, talvez agora seja melhor (no entanto, isso não exclui o tempo limite do HTTP).


  • Ali + GLB


Esse esquema também não nos convinha para o tempo de atividade, uma vez que o GLB costumava sair do upstream devido à impossibilidade de conexão em um tempo ou tempo aceitável, porque 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.


  • Apenas GLB


Uma variante semelhante à anterior, só que não utilizava servidores na própria China: o tráfego foi imediatamente para GLB (registros DNS alterados). Consequentemente, os resultados não foram satisfatórios, pois os clientes chineses comuns que usam os serviços de provedores comuns de Internet têm uma situação muito pior ao passar pelo firewall do que a 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 da IPSEC
  • Rede "rápida" do Google e seu anycast.

O esquema é mais ou menos assim: o tráfego do usuário é encerrado em uma máquina virtual em ch-shenzhen . As configurações de upstream do Nginx são configuradas lá, algumas das quais se referem a servidores IP privados localizados na outra extremidade do túnel IPSEC e algumas conexões upstream a endereços de servidores privados do outro lado do CEN. O IPSEC foi configurado para a região Ásia-Leste1 no GCP (era a região mais próxima da China no momento em que a solução foi criada. Agora o GCP também está presente em Hong Kong). CEN - para a região leste-leste1 em Ali Cloud.


Além disso, o tráfego de ambas as extremidades foi direcionado para anycast IP GLB , ou seja, para o ponto mais próximo da presença do Google, e passou por suas redes para a região leste-leste4 do GCP, na qual havia máquinas virtuais substitutas (com subfiltro no nginx).


Essa solução híbrida, como esperávamos, nos permitiu tirar proveito de cada tecnologia. Em geral, o tráfego passa pelo IPSEC rápido, mas se os problemas começarem, lançamos esses servidores rapidamente e por alguns minutos e enviamos o tráfego pelo CEN apenas até o túnel se estabilizar.


Tendo implementado a quarta solução da lista acima, alcançamos o que queríamos e o que os negócios exigiam de nós naquele momento.


Resultados de teste do navegador para a nova solução em comparação com os anteriores:


SoluçãoUpimeMedianaPercentil 75Percentil 95
Cloudflare86,618 anos30sAnos 60
IPsec99,7918 anos21s30s
Cen99,7516s21s27s
CEN / IPsec + GLB99,7913s16s25s

Cdn


Tudo está bom na solução que implementamos, mas não há CDN que possa acelerar o tráfego no nível das regiões e até das cidades. Em teoria, isso deve acelerar o site para os usuários finais através do uso de canais de comunicação rápidos do provedor de CDN. E pensamos nisso o tempo todo. E agora chegou a hora da próxima iteração do projeto: pesquisando e testando fornecedores de CDN na China.


E vou falar sobre isso na próxima parte final :)


Todas as peças


Parte 1
Parte 3

Source: https://habr.com/ru/post/pt458840/


All Articles