Criando um servido de DNS-over-HTTPS (DoH)

Neste tutorial vamos aprender como criar um servidor para consultar o DNS através de HTTPS, usando o Google DNS-over-protocolo HTTPS e IETF DNS-over-HTTPS (RFC 8484).

O Google Chrome já a partir da versão 78 irá implantar o DNS-over-HTTPS (DoH), criptografando as solicitações de DNS.

Pressupõe que você tenha um servidor DNS em funcionamento (eu uso o bind9).

Estou utilizando Debian 10 (Instalação limpa) para fazer esta instalação

Também será necessário configurar o seu ambiente Golang, veja aqui como proceder

Com o Golang já preparado vamos instalar alguns pacotes necessários para compilação:

# apt install curl software-properties-common build-essential wget unzip

Vamos usar o projeto m13253/DNS-over-HTTPS.

# cd /tmp
# wget https://github.com/m13253/dns-over-https/archive/master.zip
# unzip master.zip
# cd dns-over-https-master/
# make
# make install

Agora vamos configurar o servidor DoH, seu arquivo de configuração fica em /etc/dns-over-https/doh-server.conf
Supondo que você esteja instalando no mesmo servidor de DNS, vamos apenas alterar o upstream para usar as consultar para localhost (127.0.0.1:53).

# mv /etc/dns-over-https/doh-server.conf /etc/dns-over-https/doh-server.conf.old
# vim /etc/dns-over-https/doh-server.conf
# HTTP listen port
listen = [
    "127.0.0.1:8053",
    "[::1]:8053",

    ## To listen on both 0.0.0.0:8053 and [::]:8053, use the following line
    # ":8053",
]

# Local address and port for upstream DNS
# If left empty, a local address is automatically chosen.
local_addr = ""

# TLS certification file
# If left empty, plain-text HTTP will be used.
# You are recommended to leave empty and to use a server load balancer (e.g.
# Caddy, Nginx) and set up TLS there, because this program does not do OCSP
# Stapling, which is necessary for client bootstrapping in a network
# environment with completely no traditional DNS service.
cert = ""

# TLS private key file
key = ""

# HTTP path for resolve application
path = "/dns-query"

# Upstream DNS resolver
# If multiple servers are specified, a random one will be chosen each time.
# You can use "udp", "tcp" or "tcp-tls" for the type prefix.
# For "udp", UDP will first be used, and switch to TCP when the server asks to
# or the response is too large.
# For "tcp", only TCP will be used.
# For "tcp-tls", DNS-over-TLS (RFC 7858) will be used to secure the upstream connection.
upstream = [
    "udp:127.0.0.1:53",
]

# Upstream timeout
timeout = 10

# Number of tries if upstream DNS fails
tries = 3

# Enable logging
verbose = false

# Enable log IP from HTTPS-reverse proxy header: X-Forwarded-For or X-Real-IP
# Note: http uri/useragent log cannot be controlled by this config
log_guessed_client_ip = false

Vamos ativa-lo na inicialização do sistema e restartar o serviço.

# systemctl enable doh-server 
# systemctl restart doh-server

Verifique se o serviço esta rodando

#  systemctl status doh-server

Perfeito nosso doh-server já está rodando!

Instalação de configuração do Apache2 com um domínio virtual utilizando o Let’s Encrypt para criptografar nossa conexão HTTPs.

# apt install apache2 apache2-utils letsencrypt python-certbot-apache
# a2enmod http2 proxy proxy_http proxy_connect
# systemctl restart apache2

Vou editar a configuração padrão do servidor web, informado meu real ServerName, no exemplo “doh.remontti.com.br“, e ErrorDocument quando um IP não autorizado acessar ser redirecionado.

# vim /etc/apache2/sites-available/000-default.conf

Faça as devidas alterações, não esqueça de alterar em Require ip para os IPs que você vai autorizar as conexões.

<virtualhost *:80>
        Protocols h2 http/1.1
        ServerName doh.remontti.com.br
        ServerAdmin noc@remontti.com.br
        ErrorDocument 403 http://www.remontti.com.br/
 
        DocumentRoot /var/www/html
 
        <Directory /var/www/html/>
                Options FollowSymLinks
                AllowOverride All
                Require ip 127.0.0.1 ::1 192.168.0.0/16 172.16.0.0/12 100.64.0.0/10 10.0.0.0/8 250.0.0.0/22 2000:000::/32
        </Directory>
 
        LogLevel warn 
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
</virtualhost>

Por segurança recomendo remover a assinatura do servidor, para isso edite:

# sed -i 's/ServerTokens OS/ServerTokens Prod/' /etc/apache2/conf-available/security.conf
# sed -i 's/ServerSignature On/ServerSignature Off/' /etc/apache2/conf-available/security.conf

Para que quando alguém (autorizado) acessar seu endereço DoH não veja aquela tela Default do Apache2, vamos remover o /var/www/html/index.html e criar uma index mais legal 😛

# rm /var/www/html/index.html
# wget https://blog.remontti.com.br/wp-content/uploads/2019/10/doh.jpg -O /var/www/html/doh.jpg
# vim /var/www/html/index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
    <title>Dns Over Https - DoH</title>
    <!-- Altere para o endereço que você deseja que ele seja direcionado apos 5seg-->
    <meta http-equiv="refresh" content="5; URL='http://www.remontti.com.br/'"/>
    <style type="text/css">
      body, html {
        background-color: #fff112;
      }
      img {
        width: 95%;
        height: auto;
      }
    </style>
</head>
<body>
  <img src="doh.jpg">
</body>
</html>

Geramos o certificado

# systemctl stop apache2
# letsencrypt

Agora já é possível acessar “doh.remontti.com.br” com HTTPS, faça um teste se seu domínio esta respondendo corretamente. Teste também seu HTTP2 em https://tools.keycdn.com/http2-test

Para evitar que o certificado expire faça um script e colocando ele no cron para que o mesmo renove automaticamente.

# vim  /etc/renovassl.sh

Adicione

#!/bin/bash
/usr/bin/systemctl stop apache2
/usr/bin/certbot -q renew
/usr/bin/systemctl start apache2

De permissão de execução:

# chmod +x /etc//renovassl.sh

Adicione ao cron e restarte o cron

# echo '00 00   * * *   root    /etc/renovassl.sh' >> /etc/crontab
# systemctl restart cron

Altere algumas configuração no 000-default-le-ssl.conf criado pelo Let’s Encrypt para trabalhar como um proxy do nosso DoH

# vim /etc/apache2/sites-enabled/000-default-le-ssl.conf

Adicione as entradas destacadas:

<IfModule mod_ssl.c>

SSLProtocol TLSv1.2
SSLHonorCipherOrder On
SSLCipherSuite ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+3DES:!aNULL:!MD5:!DSS:!eNULL:!EXP:!LOW:!MD5
SSLUseStapling on
SSLStaplingCache shmcb:/var/lib/apache2/stapling_cache(512000)

<VirtualHost *:443>

        Protocols h2 http/1.1
        ServerName doh.remontti.com.br
        ServerAdmin noc@remontti.com.br
        ErrorDocument 403 http://www.remontti.com.br/

        ProxyPreserveHost On
        ProxyPass /dns-query http://[::1]:8053/dns-query
        ProxyPassReverse /dns-query http://[::1]:8053/dns-query

        <Proxy "*">
            Require ip 127.0.0.1 ::1 192.168.0.0/16 172.16.0.0/12 100.64.0.0/10 10.0.0.0/8 250.0.0.0/22 2000:000::/32
        </Proxy>

        DocumentRoot /var/www/html

        <Directory /var/www/html/>
                Options FollowSymLinks
                AllowOverride All
                Require ip 127.0.0.1 ::1 192.168.0.0/16 172.16.0.0/12 100.64.0.0/10 10.0.0.0/8 250.0.0.0/22 2000:000::/32
        </Directory>

  
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

SSLCertificateFile /etc/letsencrypt/live/su-151.speedrs.com.br/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/su-151.speedrs.com.br/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>

Restar o apache

# systemctl restart apache2

Configuramos o apache para encaminhar solicitações para nosso servidor DoH. Agora vamos fazer alguns testes.
O servidor DoH retorna em formato JSON, e para testar apenas abra no seu navegador:
https://doh.remontti.com.br/dns-query?name=remontti.com.br&type=A
Ou já que você está com o terminal aberto digite:

# curl -s "https://doh.remontti.com.br/dns-query?name=google.com.br&type=A" | python -m json.tool

Vai retornar:

{
    "AD": false,
    "Answer": [
        {
            "Expires": "Fri, 04 Oct 2019 16:48:23 UTC",
            "TTL": 300,
            "data": "172.217.29.227",
            "name": "google.com.br.",
            "type": 1
        }
    ],
    "CD": false,
    "Question": [
        {
            "name": "google.com.br.",
            "type": 1
        }
    ],
    "RA": true,
    "RD": true,
    "Status": 0,
    "TC": false,
    "edns_client_subnet": "186.250.168.0/0"
}

Legal, nosso DoH esta funcionando!

Configure seu navegador
Bem, no Firefox, isso é bem fácil, entre no menu Preferências, role até o final e clique em Configurar Conexão… em seguida marque a caixa Ativar DNS sobre HTTPS selecione Personalizado e informe o endereço do seu servidor DoH https://doh.exemplo.com.br/dns-query

No linux a versão que utilizei foi uma beta, pois na estável ainda não aparecia a opção.

Já no Chrome Versão Dev 79.0.3921.0 no linux não consegui testar, pois a opção aparece como: Not available on your platform.

Agora basta navegar! E para ter certeza que ele realmente ta fazendo as consulta em seu DoH Server, verifique os logs do seu apache:

# tail -f /var/log/apache2/access.log


Parabéns você concluiu!

O que você vai acontecer quando o DoH estiver ativado?
Quando o DoH está ativado, você não notará nada. O Firefox e o Chrome implementaram extensos mecanismos de fallback para situações em que o DoH pode cair, como um provedor de DNS que não oferece suporte a DoH.

Quais navegadores suportam o DoH?
Por enquanto, os únicos principais navegadores programados para oferecer suporte ao DoH são o Mozilla Firefox e Chrome 78 ou superior (embora, especialmente, o Chrome para iOS e o Chrome para Linux não suportem esse recurso ainda). Resta saber se o Safari da Apple seguirá o exemplo.

Ambos os navegadores se o DoH não funcionar como planejado simplesmente retornará ao método padrão de pesquisa de DNS.

Se quiser fazer uma doação para o café ficarei muito feliz pelo seu reconhecimento!

Se não puder doar pode deixar seu agradecimento nos comentário também ficarei feliz em saber que ajudei. Se tiver qualquer pergunta deixe-a também. Se preferir entrar em Contato clique aqui.

Abraço!

Rudimar Remontti

Trabalho atualmente como Gerente de Redes em um Provedor de Internet no Rio Grande do Sul.

Você pode gostar...

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *