Há muita conversa em torno do Sistema de Nomes de Domínio (DNS) no momento, com grandes mudanças sendo propostas para o protocolo de 36 anos . O serviço de nomes da Internet, que tem origem na ARPANET , nunca teve nenhuma falha de compatibilidade com versões anteriores desde seu início. Mas novas propostas para alterar o mecanismo de transporte do DNS podem estar prestes a mudar isso.
Nesta postagem, analiso duas tecnologias emergentes para proteger DNS, DNS sobre TLS (DoT) e DNS sobre HTTPS (DoH), e mostro como implementá-las usando o NGINX Open Source e o NGINX Plus.
[ Editor – Esta postagem é uma das várias que exploram casos de uso para o módulo NGINX JavaScript. Para uma lista completa, consulte Casos de uso para o módulo JavaScript NGINX .
O código nesta postagem foi atualizado para usar a diretiva js_import
, que substitui a diretiva js_include
obsoleta no NGINX Plus R23<.htmla> e posteriores. Para obter mais informações, consulte a documentação de referência do módulo NGINX JavaScript – a seção Configuração de exemplo mostra a sintaxe correta para a configuração do NGINX e os arquivos JavaScript.]
O DNS foi a segunda tentativa de criar um serviço de nomenclatura para a Internet inicial da Agência de Projetos de Pesquisa Avançada (ARPA), sendo a primeira o protocolo do Servidor de Nomes da Internet publicado por John Postel em 1979 como IEN-116. . O DNS foi projetado para ser hierárquico e fornecer uma estrutura para que nomes de host sejam descentralizados em zonas e gerenciados por muitas autoridades separadas. Os primeiros RFCs para DNS foram publicados em 1983 (RFC882 e883 ), e embora tenham tido diversas extensões ao longo dos anos, um cliente escrito de acordo com os padrões definidos naquela época ainda funcionaria hoje.
Então por que mudar o protocolo agora? Ele claramente funciona como pretendido, justificando a confiança de seus autores, que estavam tão certos de que estavam certos que não incluíram um número de versão no pacote DNS. Não consigo pensar em muitos outros protocolos que podem fazer essa afirmação. O DNS foi concebido em uma época mais inocente, quando a maioria dos protocolos eram em texto simples e geralmente ASCII de 7 bits , mas a Internet de hoje é um lugar muito mais assustador do que a ARPANET dos anos 1980. Hoje, a maioria dos protocolos adotou o Transport Layer Security (TLS) para fins de criptografia e verificação. Os críticos do DNS argumentam que já passou da hora de ele receber algumas proteções de segurança adicionais.
Então, da mesma forma que o DNS foi a segunda tentativa de fornecer um protocolo de serviço de nomes para a Internet, o DNS sobre TLS (DoT) e o DNS sobre HTTPS (DoH) estão surgindo como segundas tentativas de proteger o protocolo DNS. A primeira tentativa foi uma extensão conhecida como DNSSEC e, embora a maioria dos domínios de nível superior (TLDs) faça uso do DNSSEC, ele nunca teve a intenção de criptografar os dados transportados nos pacotes DNS; ele apenas fornece a verificação de que os dados não foram adulterados. DoT e DoH são extensões de protocolo que envolvem o DNS dentro de um túnel TLS e, se adotadas, acabarão com 36 anos de compatibilidade com versões anteriores.
O DoT, creio eu, é visto em grande parte como uma extensão sensata. Ele já recebeu seu próprio número de porta (TCP/853) da Internet Assigned Numbers Authority (IANA) e simplesmente encapsula pacotes TCP DNS dentro de um túnel criptografado TLS. Muitos protocolos já fizeram isso antes: HTTPS é HTTP dentro de um túnel TLS, e SMTPS, IMAPS e LDAPS são versões seguras desses protocolos. O DNS sempre usou UDP (ou TCP em certos casos) como protocolo de transporte, então adicionar o wrapper TLS não é uma grande mudança.
DoH, por outro lado, é um pouco mais controverso. O DoH pega um pacote DNS e o encapsula dentro de uma solicitação HTTP GET
ou POST
, que é então enviada usando HTTP/2 ou superior por meio de uma conexão HTTPS. Para todos os efeitos, isso parece ser igual a qualquer outra conexão HTTPS, e é impossível para empresas ou provedores de serviços verem quais solicitações estão sendo feitas. A Mozilla e outros apoiadores dizem que essa prática aumenta a privacidade dos usuários ao manter os sites que eles visitam privados de olhares curiosos.
Mas isso não é exatamente verdade. Os críticos do DoH ressaltam que ele não é exatamente o Tor do DNS porque, quando o navegador finalmente faz a conexão com o host, que ele pesquisou usando o DoH, a solicitação quase certamente usará a extensão TLS Server Name Indication (SNI) – e isso inclui o nome do host e é enviado em texto simples. Além disso, se o navegador tentar validar o certificado do servidor usando o Protocolo de Status de Certificado Online (OSCP), esse processo provavelmente ocorrerá também em texto simples. Portanto, qualquer pessoa com a capacidade de monitorar pesquisas de DNS também tem a capacidade de ler o SNI na conexão ou o nome do certificado na validação do OCSP.
Para muitas pessoas, o maior problema com o DoH é que os fornecedores de navegadores escolhem os servidores DNS para os quais as solicitações de DoH feitas por seus usuários são enviadas por padrão (no caso de usuários do Firefox nos EUA, por exemplo, os servidores DNS pertencem à Cloudflare ). O operador dos servidores DNS pode ver o endereço IP do usuário e os nomes de domínio dos sites aos quais ele faz solicitações. Isso pode não parecer muito, mas pesquisadores da Universidade de Illinois descobriram que é possível deduzir quais sites uma pessoa visitou a partir de nada mais do que os endereços de destino das solicitações de elementos de uma página da web, a chamada Impressão Digital de Carregamento de Página. Essas informações podem então ser usadas para “criar um perfil e direcionar o usuário para publicidade”.
DoT e DoH não são inerentemente malignos, e há casos de uso em que aumentam a privacidade do usuário. No entanto, há um consenso crescente de que um serviço DoH público e centralizado é ruim para a privacidade do usuário, e recomendamos que você evite usá-lo a todo custo.
Em qualquer caso, para seus sites e aplicativos, você provavelmente gerencia suas próprias zonas DNS – algumas públicas, algumas privadas e algumas com um horizonte dividido. Em algum momento, você pode decidir que deseja executar seu próprio serviço DoT ou DoH. É aqui que o NGINX pode ajudar.
Os aprimoramentos de privacidade fornecidos pelo DoT oferecem algumas grandes vantagens para a segurança do DNS, mas e se o seu servidor DNS atual não oferecer suporte ao DoT? O NGINX pode ajudar aqui fornecendo um gateway entre o DoT e o DNS padrão.
Ou talvez você goste do potencial de destruição de firewall do DoH para casos em que a porta DoT pode estar bloqueada. Mais uma vez, o NGINX pode ajudar, fornecendo um gateway DoH-para-DoT/DNS .
O módulo NGINX Stream (TCP/UDP) suporta terminação SSL, então é realmente muito simples configurar um serviço DoT. Você pode criar um gateway DoT simples em apenas algumas linhas de configuração do NGINX.
Você precisa de um bloco upstream
para seus servidores DNS e um bloco de servidor
para terminação TLS:
É claro que também podemos fazer o contrário e encaminhar solicitações de DNS recebidas para um servidor DoT upstream. No entanto, isso é menos útil porque a maior parte do tráfego DNS é UDP e o NGINX pode traduzir apenas entre DoT e outros serviços TCP, como DNS baseado em TCP.
Comparado a um gateway DoT, a configuração de um gateway DoH simples é um pouco mais complexa. Precisamos de um serviço HTTPS e de um serviço Stream, e usamos o código JavaScript e o módulo NGINX JavaScript<.htmla> (njs) para traduzir entre os dois protocolos. A configuração mais simples é:
Esta configuração realiza a quantidade mínima de processamento necessária para enviar o pacote para o serviço DNS. Este caso de uso pressupõe que o servidor DNS upstream executa qualquer outra função de filtragem, registro ou segurança.
O script JavaScript usado nesta configuração ( nginx_stream.js ) inclui vários arquivos de módulo de biblioteca DNS. Dentro do módulo dns.js , a variável dns_decode_level
define quanto processamento é feito nos pacotes DNS. O processamento de pacotes DNS obviamente prejudica o desempenho. Se você estiver usando uma configuração como a acima, defina dns_decode_level
como0
.
Aqui na NGINX somos realmente muito bons em HTTP, então achamos que usar o NGINX apenas como um simples gateway DoH é uma oportunidade desperdiçada.
O código JavaScript usado aqui pode ser configurado para fazer decodificação total ou parcial dos pacotes DNS. Isso nos permite construir um cache de conteúdo HTTP para as consultas DoH com cabeçalhos Expires e Cache-Control
definidos com base nos TTLs mínimos das respostas DNS.
Segue um exemplo mais completo, com otimização de conexão adicional e suporte para cache e registro de conteúdo:
Se você tiver uma assinatura do NGINX Plus, poderá combinar os exemplos acima com alguns dos recursos mais avançados do NGINX Plus, como verificações de integridade ativas e alta disponibilidade, ou até mesmo usar a API de limpeza de cache para gerenciar respostas DoH armazenadas em cache.
Também é possível usar o armazenamento de chave-valor do NGINX Plus para criar um sistema de filtragem de DNS que protege os usuários de domínios maliciosos, retornando uma resposta de DNS que efetivamente impede o acesso a eles. Você gerencia o conteúdo do armazenamento de chave-valor dinamicamente com a API RESTful NGINX Plus .
Definimos duas categorias de domínios maliciosos, “bloqueados” e “buraco negro”. O sistema de filtragem de DNS lida com uma consulta DNS sobre um domínio de forma diferente dependendo de sua categoria:
NXDOMAIN
(indicando que o domínio não existe)A
de 0.0.0.0 em resposta a solicitações de registros A
, ou um único registro AAAA
de :: em resposta a solicitações de registros AAAA
(IPv6); para outros tipos de registro, ele retorna uma resposta contendo zero respostasQuando nosso filtro DNS recebe uma solicitação, ele primeiro verifica se há uma chave que corresponda exatamente ao FQDN consultado. Se encontrar um, ele “limpa” (bloqueia ou coloca buracos negros) a solicitação conforme especificado pelo valor associado. Se não houver uma correspondência exata, ele procura o nome de domínio em duas listas – uma de domínios bloqueados e outra de domínios bloqueados – e limpa a solicitação da maneira apropriada se houver uma correspondência.
Se o domínio consultado não for malicioso, o sistema o encaminhará para um servidor DNS do Google para processamento regular.
Definimos os domínios que consideramos maliciosos em dois tipos de entradas no armazenamento de chave-valor do NGINX Plus:
bloqueado
ou buraco negro
blocked_domains
e blackholed_domains
, cada uma mapeada para uma lista de domínios no formato de valores separados por vírgula (CSV) A configuração a seguir para armazenamento de chave-valor vai para o contexto de fluxo
. A diretiva keyval_zone
aloca um bloco de memória para o armazenamento de chave-valor, chamado dns_config . A primeira diretiva keyval
carrega qualquer par de chave-valor FQDN correspondente que tenha sido definido, enquanto a segunda e a terceira definem as duas listas de domínios:
Podemos então usar a API NGINX Plus para atribuir o valor blocked
ou blackhole
a qualquer chave FQDN que queremos explicitamente limpar, ou modificar a lista formatada em CSV associada à chave blocked_domains
ou blackhole_domains
. Podemos modificar ou remover FQDNs exatos, ou modificar o conjunto de domínios em qualquer lista, a qualquer momento, e o filtro DNS é atualizado instantaneamente com as alterações.
A configuração a seguir carrega a variável $dns_response
, que é preenchida por uma diretiva js_preread
nos blocos de servidor
definidos em Configurando os servidores que escutam consultas DNS abaixo. Quando o código JavaScript invocado determina que a solicitação precisa ser depurada, ele define a variável como bloqueada
ou blackhole,
conforme apropriado.
Usamos uma diretiva de mapa
para atribuir o valor da variável $dns_response
à variável $upstream_pool
, controlando assim qual dos grupos upstream em Definindo os Servidores Upstream abaixo manipula a solicitação. Consultas para domínios não maliciosos são encaminhadas para o servidor DNS padrão do Google, enquanto consultas para domínios bloqueados ou bloqueados são tratadas pelo servidor upstream para essas categorias.
Esta configuração define os grupos de servidores upstream blocked
, blackhole
e google
, que lidam com solicitações de domínios blocked , blackhole e não maliciosos, respectivamente.
Aqui definimos os servidores no contexto de fluxo
que escutam as solicitações de DNS recebidas. A diretiva js_preread
invoca o código Javascript que decodifica o pacote DNS, recupera o nome de domínio do campo NAME
do pacote e procura o domínio no armazenamento de chave-valor. Se o nome de domínio corresponder a uma chave FQDN ou estiver dentro da zona de um dos domínios na lista blocked_domains
ou blackhole_domains
, ele será limpo. Caso contrário, ele acaba sendo enviado ao servidor DNS do Google para resolução.
É quase isso – só precisamos adicionar nosso bloco de servidor
final, que responde às consultas com a resposta blackholed ou blocked.
Observe que os servidores neste bloco são quase idênticos aos servidores DNS reais logo acima deles, a principal diferença é que esses servidores enviam um pacote de resposta ao cliente em vez de encaminhar a solicitação para um grupo upstream de servidores DNS. Nosso código JavaScript detecta quando está sendo executado na porta 9953 ou 9853 e, em vez de definir um sinalizador para indicar que o pacote deve ser bloqueado, ele preenche $dns_response
com o pacote de resposta real. É só isso.
Claro, também poderíamos ter aplicado essa filtragem aos serviços DoT e DoH, mas usamos DNS padrão para manter as coisas simples. A fusão da filtragem de DNS com o gateway DoH é deixada como um exercício para o leitor.
Anteriormente, usamos a API NGINX Plus para adicionar entradas para dois FQDNs e alguns domínios às duas listas de domínios:
$ curl -s http://localhost:8080/api/5/stream/keyvals/dns_config | jq { "www.some.bad.host": "bloqueado", "www.some.other.host": "blackhole", "domínios_bloqueados": "bar.com,baz.com", "domínios_blackhole": "foo.com,nginx.com" }
Então, quando solicitamos a resolução de www.foo.com (um host dentro do domínio blackholed foo.com ), obtemos um registro A
com endereço IP 0.0.0.0:
$ dig @localhost www.foo.com ; <<>> DiG 9.11.3-1ubuntu1.9-Ubuntu <<>> @localhost www.foo.com ; (1 servidor encontrado) ;; opções globais: +mcd ;; Resposta obtida: ;; ->>HEADER,,- opcode: CONSULTA, status: SEM ERRO, id: 58558 ;; sinalizadores: qr aa rd ad; CONSULTA: 1, RESPOSTA: 1, AUTORIDADE: 0, ADICIONAL: 0 ;; AVISO: recursão solicitada, mas não disponível ;; SEÇÃO DE PERGUNTAS: ; www.foo.com. EM UMA SEÇÃO DE RESPOSTAS: www.foo.com. 300 EM A 0.0.0.0 ;; Tempo de consulta: 0 mseg ;; SERVIDOR: 172.0.0.1#53(126.0.0.1) ;; QUANDO: Seg Dez 2 14:31:35 UTC 2019 ;; MSG SIZEW rcvd: 45
Os arquivos para DOH e DOT estão disponíveis no meu repositório GitHub :
Para experimentar o NGINX Plus, comece hoje mesmo seu teste gratuito de 30 dias ou entre em contato conosco para discutir seus casos de uso .
"Esta postagem do blog pode fazer referência a produtos que não estão mais disponíveis e/ou não têm mais suporte. Para obter as informações mais atualizadas sobre os produtos e soluções F5 NGINX disponíveis, explore nossa família de produtos NGINX . O NGINX agora faz parte do F5. Todos os links anteriores do NGINX.com redirecionarão para conteúdo semelhante do NGINX no F5.com."