Fronting de domínio baseado em TLS 1.3

Introdução

Fronting de domínio baseado em TLS 1.3
Os modernos sistemas de filtragem de conteúdo corporativo de fabricantes renomados como Cisco, BlueCoat, FireEye têm muito em comum com seus equivalentes mais poderosos - sistemas DPI, que estão sendo implementados ativamente em nível nacional. A essência do trabalho de ambos é inspecionar o tráfego de entrada e saída da Internet e, com base em listas negras/brancas, tomar a decisão de proibir a conexão à Internet. E como ambos se baseiam em princípios semelhantes na base do seu trabalho, os métodos para contorná-los também terão muito em comum.

Uma das tecnologias que permite ignorar de forma bastante eficaz os sistemas DPI e corporativos é a tecnologia de front-end de domínio. A sua essência é que vamos para um recurso bloqueado, escondendo-nos atrás de outro, de domínio público e de boa reputação, que obviamente não será bloqueado por nenhum sistema, por exemplo google.com.

Muitos artigos já foram escritos sobre esta tecnologia e muitos exemplos foram dados. No entanto, as populares e recentemente discutidas tecnologias DNS-over-HTTPS e SNI criptografado, bem como a nova versão do protocolo TLS 1.3, tornam possível considerar outra opção para fronting de domínio.

Entendendo a tecnologia

Primeiramente, vamos definir alguns conceitos básicos para que todos entendam quem é quem e por que tudo isso é necessário. Mencionamos o mecanismo eSNI, cujo funcionamento será discutido mais adiante. O mecanismo eSNI (indicação de nome de servidor criptografado) é uma versão segura do SNI, disponível apenas para o protocolo TLS 1.3. A ideia principal é criptografar, entre outras coisas, informações sobre para qual domínio a solicitação é enviada.

Agora vamos ver como o mecanismo eSNI funciona na prática.

Digamos que temos um recurso da Internet que está bloqueado por uma solução moderna de DPI (tomemos, por exemplo, o famoso rastreador de torrent rutracker.nl). Quando tentamos acessar o site de um rastreador de torrent, vemos o stub padrão do provedor indicando que o recurso está bloqueado:

Fronting de domínio baseado em TLS 1.3

No site da RKN, este domínio está listado nas listas de parada:

Fronting de domínio baseado em TLS 1.3

Ao consultar whois, você pode ver que o próprio domínio está “escondido” atrás do provedor de nuvem Cloudflare.

Fronting de domínio baseado em TLS 1.3

Mas, ao contrário dos “especialistas” da RKN, funcionários mais experientes tecnicamente da Beeline (ou ensinados pela amarga experiência de nosso famoso regulador) não baniram estupidamente o site por endereço IP, mas adicionaram o nome de domínio à lista de parada. Você pode verificar isso facilmente se observar quais outros domínios estão ocultos atrás do mesmo endereço IP, visitar um deles e ver se o acesso não está bloqueado:

Fronting de domínio baseado em TLS 1.3

Como isso acontece? Como o DPI do provedor sabe em qual domínio meu navegador está, já que todas as comunicações ocorrem através do protocolo https e ainda não percebemos a substituição dos certificados https do Beeline? Ele é clarividente ou estou sendo seguido?

Vamos tentar responder a essa pergunta observando o tráfego através do wireshark

Fronting de domínio baseado em TLS 1.3

A captura de tela mostra que primeiro o navegador obtém o endereço IP do servidor via DNS, depois ocorre um handshake TCP padrão com o servidor de destino e, em seguida, o navegador tenta estabelecer uma conexão SSL com o servidor. Para fazer isso, ele envia um pacote SSL Client Hello, que contém o nome do domínio de origem em texto não criptografado. Este campo é exigido pelo servidor front-end cloudflare para rotear corretamente a conexão. É aqui que o provedor DPI nos pega, interrompendo nossa conexão. Ao mesmo tempo, não recebemos nenhum stub do provedor e vemos um erro padrão do navegador, como se o site estivesse desabilitado ou simplesmente não funcionasse:

Fronting de domínio baseado em TLS 1.3

Agora vamos habilitar o mecanismo eSNI no navegador, conforme está escrito nas instruções para Firefox :
Para fazer isso, abrimos a página de configuração do Firefox about: config e ative as seguintes configurações:

network.trr.mode = 2;
network.trr.uri = https://mozilla.cloudflare-dns.com/dns-query
network.security.esni.enabled = true

Depois disso, verificaremos se as configurações estão funcionando corretamente no site da cloudflare. link e vamos tentar o truque com nosso rastreador de torrent novamente.

Fronting de domínio baseado em TLS 1.3

Voilá. Nosso rastreador favorito foi aberto sem VPN ou servidores proxy. Vamos agora dar uma olhada no despejo de tráfego no wireshark para ver o que aconteceu.

Fronting de domínio baseado em TLS 1.3

Desta vez, o pacote hello do cliente SSL não contém explicitamente o domínio de destino, mas em vez disso, um novo campo apareceu no pacote - nome_do_servidor_criptografado - é aqui que o valor de rutracker.nl está contido, e apenas o servidor front-end cloudflare pode descriptografar este campo. E se for assim, então o provedor DPI não tem escolha a não ser lavar as mãos e permitir esse tráfego. Não há outras opções com criptografia.

Então, vimos como a tecnologia funciona no navegador. Agora vamos tentar aplicá-lo a coisas mais específicas e interessantes. E primeiro, ensinaremos o mesmo curl a usar eSNI para trabalhar com TLS 1.3 e, ao mesmo tempo, veremos como funciona o próprio fronting de domínio baseado em eSNI.

Frontagem de domínio com eSNI

Devido ao fato de curl usar a biblioteca openssl padrão para se conectar através do protocolo https, primeiro precisamos fornecer suporte eSNI lá. Ainda não há suporte para eSNI nas ramificações master do openssl, então precisamos baixar uma ramificação especial do openssl, compilá-la e instalá-la.

Clonamos o repositório do GitHub e compilamos normalmente:

$ git clone https://github.com/sftcd/openssl
$ cd openssl
$ ./config

$ make
$ cd esnistuff
$ make

A seguir, clonamos o repositório com curl e configuramos sua compilação usando nossa biblioteca openssl compilada:

$ cd $HOME/code
$ git clone https://github.com/niallor/curl.git curl-esni
$ cd curl-esni

$ export LD_LIBRARY_PATH=/opt/openssl
$ ./buildconf
$ LDFLAGS="-L/opt/openssl" ./configure --with-ssl=/opt/openssl --enable-esni --enable-debug

Aqui é importante especificar corretamente todos os diretórios onde o openssl está localizado (no nosso caso, é /opt/openssl/) e garantir que o processo de configuração ocorra sem erros.

Se a configuração for bem-sucedida, veremos a linha:

AVISO: esni ESNI habilitado, mas marcado como EXPERIMENTAL. Use com cuidado!

$ make

Depois de construir o pacote com sucesso, usaremos um arquivo bash especial do openssl para configurar e executar o curl. Vamos copiá-lo para o diretório com curl por conveniência:

cp /opt/openssl/esnistuff/curl-esni 

e faça uma solicitação https de teste para o servidor cloudflare, enquanto grava simultaneamente pacotes DNS e TLS no Wireshark.

$ ESNI_COVER="www.hello-rkn.ru" ./curl-esni https://cloudflare.com/

Na resposta do servidor, além de muitas informações de depuração do openssl e curl, receberemos uma resposta HTTP com o código 301 do cloudflare.

HTTP/1.1 301 Moved Permanently
< Date: Sun, 03 Nov 2019 13:12:55 GMT
< Transfer-Encoding: chunked
< Connection: keep-alive
< Cache-Control: max-age=3600
< Expires: Sun, 03 Nov 2019 14:12:55 GMT
< Location: https://www.cloudflare.com/

o que indica que nossa solicitação foi entregue com sucesso ao servidor de destino, ouvida e processada.

Agora vamos dar uma olhada no despejo de tráfego no wireshark, ou seja, o que o provedor DPI viu neste caso.

Fronting de domínio baseado em TLS 1.3

Pode-se ver que o curl primeiro recorreu ao servidor DNS em busca de uma chave eSNI pública para o servidor cloudflare - uma solicitação DNS TXT para _esni.cloudflare.com (pacote nº 13). Em seguida, utilizando a biblioteca openssl, o curl enviou uma solicitação TLS 1.3 ao servidor cloudflare na qual o campo SNI foi criptografado com a chave pública obtida na etapa anterior (pacote #22). Mas, além do campo eSNI, o pacote SSL-hello também incluía um campo com o usual - open SNI, que podemos especificar em qualquer ordem (neste caso - www.hello-rkn.ru).

Este campo SNI aberto não foi levado em consideração de forma alguma quando processado pelos servidores cloudflare e serviu apenas como máscara para o DPI do provedor. O servidor cloudflare recebeu nosso pacote SSL-hello, descriptografou o eSNI, extraiu o SNI original de lá e processou-o como se nada tivesse acontecido (fez tudo exatamente como planejado durante o desenvolvimento do eSNI).

A única coisa que pode ser detectada neste caso do ponto de vista do DPI é a solicitação de DNS primário para _esni.cloudflare.com. Mas abrimos a solicitação de DNS apenas para mostrar como esse mecanismo funciona por dentro.

Para finalmente tirar o tapete do DPI, usamos o já mencionado mecanismo DNS sobre HTTPS. Uma pequena explicação - DOH é um protocolo que permite proteger contra ataques man-in-the-middle enviando uma solicitação DNS por HTTPS.

Vamos executar a solicitação novamente, mas desta vez receberemos chaves eSNI públicas através do protocolo https, não do DNS:

ESNI_COVER="www.hello-rkn.ru" DOH_URL=https://mozilla.cloudflare-dns.com/dns-query ./curl-esni https://cloudflare.com/

O despejo de tráfego de solicitação é mostrado na captura de tela abaixo:

Fronting de domínio baseado em TLS 1.3

Pode-se observar que curl primeiro acessa o servidor mozilla.cloudflare-dns.com através do protocolo DoH (conexão https ao servidor 104.16.249.249) para obter deles os valores das chaves públicas para criptografia SNI e, em seguida, para o destino servidor, escondendo-se atrás do domínio www.hello-rkn.ru.

Além do resolvedor DoH acima mozilla.cloudflare-dns.com, podemos usar outros serviços DoH populares, por exemplo, da famosa corporação do mal.
Vamos executar a seguinte consulta:

ESNI_COVER="www.kremlin.ru" DOH_URL=https://dns.google/dns-query ./curl-esni https://rutracker.nl/

E obtemos a resposta:

< HTTP/1.1 301 Moved Permanently
< Date: Sun, 03 Nov 2019 14:10:22 GMT
< Content-Type: text/html
< Transfer-Encoding: chunked
< Connection: keep-alive
< Set-Cookie: __cfduid=da0144d982437e77b0b37af7d00438b1a1572790222; expires=Mon, 02-Nov-20 14:10:22 GMT; path=/; domain=.rutracker.nl; HttpOnly; Secure
< Location: https://rutracker.nl/forum/index.php
< CF-Cache-Status: DYNAMIC
< Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
< Server: cloudflare
< CF-RAY: 52feee696f42d891-CPH

Fronting de domínio baseado em TLS 1.3

Nesse caso, recorremos ao servidor rutracker.nl bloqueado, usando o resolvedor DoH dns.google (não há erro de digitação aqui, agora a famosa corporação tem seu próprio domínio de primeiro nível) e nos cobrimos com outro domínio, que é estritamente proibido que todos os DPIs bloqueiem sob pena de morte. Com base na resposta recebida, você pode entender que nossa solicitação foi processada com sucesso.

Como verificação adicional de que o DPI do provedor responde ao SNI aberto, que transmitimos como cobertura, podemos fazer uma solicitação ao rutracker.nl sob o disfarce de algum outro recurso proibido, por exemplo, outro rastreador de torrent “bom”:

$ ESNI_COVER="rutor.info" DOH_URL=https://dns.google/dns-query ./curl-esni https://rutracker.nl/

Não receberemos resposta do servidor porque... nossa solicitação será bloqueada pelo sistema DPI.

Uma breve conclusão da primeira parte

Assim, conseguimos demonstrar a funcionalidade do eSNI usando openssl e curl e testar o funcionamento do fronting de domínio baseado em eSNI. Da mesma forma, podemos adaptar nossas ferramentas favoritas que utilizam a biblioteca openssl para funcionar “sob o disfarce” de outros domínios. Mais detalhes sobre isso em nossos próximos artigos.

Fonte: habr.com

Adicionar um comentário