Transportes seguros para DNS

As consultas e respostas DNS tradicionais são enviadas por UDP ou TCP sem criptografia, o que as torna sujeitas a vigilância, spoofing e filtragem de Internet baseada em DNS. As respostas a clientes de resolvedores públicos, como o DNS público do Google, são especialmente vulneráveis a isso, já que as mensagens podem passar por muitas redes, enquanto as mensagens entre resolvedores recursivos e servidores de nomes autoritativos costumam incorporar outras proteções.

Para resolver esses problemas, em 2016 lançamos o DNS via HTTPS (agora chamado de DoH), oferecendo resolução criptografada de DNSSEC para validação por HTTPS e QUIC. Em 2019, adicionamos suporte ao padrão DNS sobre TLS (DoT) usado pelo recurso DNS particular do Android.

O DoH e o DoT melhoram a privacidade e a segurança entre clientes e resolvedores, complementando a validação do DNS público do Google da DNSSEC para fornecer DNS autenticado de ponta a ponta para domínios assinados por DNSSEC. Com o DNS público do Google, temos o compromisso de oferecer resolução de DNS rápida, particular e segura para clientes DoH e DoT.

Versões de TLS e pacotes de criptografia compatíveis

O DNS público do Google é compatível com TLS 1.2 e TLS 1.3 para DoH e DoT. Nenhuma versão anterior de TLS ou SSL é compatível. Há suporte apenas para pacotes de criptografia com segurança direta e Criptografia autenticada com dados adicionais (AEAD, na sigla em inglês). Qualys SSL Labs mostra o conjunto atual de pacotes de criptografia compatíveis.

Endpoints

O DNS público do Google usa os seguintes endpoints para DoH e DoT:

DoT (porta 853) dns.google

Modelos de URI DoH (porta 443)

  • RFC 8484 – https://dns.google/dns-query{?dns}

    • Para POST, o URL é apenas https://dns.google/dns-query e o corpo da solicitação HTTP é o payload de DNS UDP binário com o tipo de conteúdo application/dns-message.
    • Para GET, é https://dns.google/dns-query?dns=BASE64URL_OF_QUERY.
  • API JSON: https://dns.google/resolve{?name}{&type,cd,do,…}

    • Mais parâmetros GET são descritos na página da API JSON. Apenas o parâmetro name é obrigatório.

Clientes

Há vários aplicativos clientes que usam DoT ou DoH

  • Recurso de “Navegação privada” do Android 9 (Pie) – Ponto
  • Intra (app Android): DoH

O site dnsprivacy.org lista vários outros clientes para DoT e DoH, mas eles geralmente exigem configuração moderadamente técnica.

Exemplos de linha de comando

Os exemplos de linha de comando a seguir não se destinam a uso em um cliente real e são apenas ilustrações usando ferramentas de diagnóstico geralmente disponíveis.

DoT

Os comandos a seguir exigem o Knot DNS kdig 2.3.0 ou mais recente. Com 2.7.4 ou mais recente, remova a marca de comentário do +tls‑sni para enviar a SNI, conforme exigido pelo TLS 1.3.

kdig -d +noall +answer @dns.google example.com \
  +tls-ca +tls-hostname=dns.google # +tls-sni=dns.google
;; DEBUG: Querying for owner(example.com.), class(1), type(1), server(dns.google), port(853), protocol(TCP)
;; DEBUG: TLS, imported 312 system certificates
;; DEBUG: TLS, received certificate hierarchy:
;; DEBUG:  #1, C=US,ST=California,L=Mountain View,O=Google LLC,CN=dns.google
;; DEBUG:      SHA-256 PIN: lQXSLnWzUdueQ4+YCezIcLa8L6RPr8Wgeqtxmw1ti+M=
;; DEBUG:  #2, C=US,O=Google Trust Services,CN=Google Internet Authority G3
;; DEBUG:      SHA-256 PIN: f8NnEFZxQ4ExFOhSN7EiFWtiudZQVD2oY60uauV/n78=
;; DEBUG: TLS, skipping certificate PIN check
;; DEBUG: TLS, The certificate is trusted.

;; ANSWER SECTION:
example.com.            2046    IN      A       93.184.216.34
kdig -d +noall +answer @dns.google example.com \
  +tls-pin=f8NnEFZxQ4ExFOhSN7EiFWtiudZQVD2oY60uauV/n78= \
  # +tls-sni=dns.google
;; DEBUG: Querying for owner(example.com.), class(1), type(1), server(dns.google), port(853), protocol(TCP)
;; DEBUG: TLS, received certificate hierarchy:
;; DEBUG:  #1, C=US,ST=California,L=Mountain View,O=Google LLC,CN=dns.google
;; DEBUG:      SHA-256 PIN: lQXSLnWzUdueQ4+YCezIcLa8L6RPr8Wgeqtxmw1ti+M=
;; DEBUG:  #2, C=US,O=Google Trust Services,CN=Google Internet Authority G3
;; DEBUG:      SHA-256 PIN: f8NnEFZxQ4ExFOhSN7EiFWtiudZQVD2oY60uauV/n78=, MATCH
;; DEBUG: TLS, skipping certificate verification

;; ANSWER SECTION:
example.com.            5494    IN      A       93.184.216.34

DoH

POSTAGEM RFC 8484

A string Base64Url codificada nesse comando é a mensagem DNS enviada por dig +noedns example.test A com o campo "ID do DNS" definido como zero, conforme recomendado pela seção 4.1 da RFC 8484 (em inglês). O comando shell envia essa consulta DNS como o conteúdo do corpo de dados binários, usando o Content-Type application/dns-message.

echo AAABAAABAAAAAAAAB2V4YW1wbGUEdGVzdAAAAQAB | base64 --decode |
 curl -is --data-binary @- -H 'content-type: application/dns-message' \
   https://dns.google/dns-query
HTTP/2 200
strict-transport-security: max-age=31536000; includeSubDomains; preload
access-control-allow-origin: *
date: Wed, 29 May 2019 19:37:16 GMT
expires: Wed, 29 May 2019 19:37:16 GMT
cache-control: private, max-age=19174
content-type: application/dns-message
server: HTTP server (unknown)
content-length: 45
x-xss-protection: 0
x-frame-options: SAMEORIGIN
alt-svc: quic=":443"; ma=2592000; v="46,44,43,39"

RFC 8484 GET

A string codificada Base64Url nesse comando é a mensagem DNS enviada por dig +noedns example.com A com o campo "ID do DNS" definido como zero. Nesse caso, ele é transmitido explicitamente no URL.

curl -i https://dns.google/dns-query?dns=AAABAAABAAAAAAAAB2V4YW1wbGUDY29tAAABAAE
HTTP/2 200
strict-transport-security: max-age=31536000; includeSubDomains; preload
access-control-allow-origin: *
date: Wed, 29 May 2019 19:37:16 GMT
expires: Wed, 29 May 2019 19:37:16 GMT
cache-control: private, max-age=19174
content-type: application/dns-message
server: HTTP server (unknown)
content-length: 45
x-xss-protection: 0
x-frame-options: SAMEORIGIN
alt-svc: quic=":443"; ma=2592000; v="46,44,43,39"

JSON GET

Isso usa a API JSON para DoH.

curl -i 'https://dns.google/resolve?name=example.com&type=a&do=1'
HTTP/2 200
strict-transport-security: max-age=31536000; includeSubDomains; preload
access-control-allow-origin: *
date: Thu, 30 May 2019 02:46:46 GMT
expires: Thu, 30 May 2019 02:46:46 GMT
cache-control: private, max-age=10443
content-type: application/x-javascript; charset=UTF-8
server: HTTP server (unknown)
x-xss-protection: 0
x-frame-options: SAMEORIGIN
alt-svc: quic=":443"; ma=2592000; v="46,44,43,39"
accept-ranges: none
vary: Accept-Encoding

{"Status": 0,"TC": false,"RD": true,"RA": true,"AD": true,"CD": false,"Question":[ {"name": "example.com.","type": 1}],"Answer":[ {"name": "example.com.","type": 1,"TTL": 10443,"data": "93.184.216.34"},{"name": "example.com.","type": 46,"TTL": 10443,"data": "a 8 2 86400 1559899303 1558087103 23689 example.com. IfelQcO5NqQIX7ZNKI245KLfdRCKBaj2gKhZkJawtJbo/do+A0aUvoDM5A7EZKcF/j8SdtyfYWj/8g91B2/m/WOo7KyZxIC918R1/jvBRYQGreDL+yutb1ReGc6eUHX+NKJIYqzfal+PY7tGotS1Srn9WhBspXq8/0rNsEnsSoA="}],"Additional":[]}

TLS 1.3 e SNI para URLs de endereço IP

O TLS 1.3 exige que os clientes forneçam a identificação do nome do servidor (SNI, na sigla em inglês).

A extensão SNI especifica que as informações da SNI são um domínio DNS, e não um endereço IP:

"HostName" contém o nome do host DNS totalmente qualificado do servidor, conforme compreendido pelo cliente. O nome do host é representado como uma string de bytes usando codificação ASCII sem um ponto à direita. Isso permite o suporte de nomes de domínio internacionalizados pelo uso de rótulos A definidos na RFC5890 (link em inglês). Os nomes de host DNS não diferenciam maiúsculas de minúsculas. O algoritmo para comparar nomes de host é descrito na RFC5890, seção 2.3.2.4 (link em inglês).

Os endereços IPv4 e IPv6 literais não são permitidos em "HostName".

Pode ser difícil atender a esses requisitos para aplicativos DoH ou DoT que querem aproveitar as melhorias de segurança no TLS 1.3. Atualmente, o DNS público do Google aceita conexões TLS 1.3 que não fornecem SNI, mas talvez seja necessário alterar isso por motivos operacionais ou de segurança no futuro.

Estas são as recomendações para aplicativos DoT ou DoH relacionados ao SNI:

  1. Envia o nome do host dns.google como SNI para todas as conexões com os serviços de DNS público do Google ou DoH.
  2. Se nenhum nome de host estiver disponível (por exemplo, em um aplicativo que está usando ponto oportunista), é melhor enviar o endereço IP na SNI em vez de deixá-lo em branco.
  3. Os endereços IPv6 aparecem entre colchetes [2001:db8:1234::5678] no cabeçalho Host, mas sem colchetes no SNI.

Truncamento de resposta DNS

Embora o DNS público do Google geralmente não trunque respostas a consultas DoT e DoH, isso acontece em duas circunstâncias:

  1. Se o DNS público do Google não puder receber respostas completas e não truncadas de servidores de nomes autoritativos, ele vai definir a sinalização de TC na resposta.

  2. Nos casos em que a resposta DNS (em formato de mensagem DNS binário) excede o limite de 64 KiB para mensagens de DNS TCP, o DNS público do Google pode definir a flag de TC (truncamento) se os padrões de RFC exigirem.

No entanto, nesses casos, não é necessário que os clientes tentem novamente usando TCP simples ou qualquer outro transporte, já que o resultado será o mesmo.