Wiki CgX

Parce que j'ai un cerveau, mais pas trop.

Outils pour utilisateurs

Outils du site


it:linux-selfhosting:doh

DNS over HTTPS

C'est quoi ?

DNS over HTTPS (DoH) est un protocole permettant d'effectuer une résolution DNS (Domain Name System) à distance via le protocole HTTPS1. L'un des objectifs de la méthode est d'accroître la confidentialité et la sécurité des utilisateurs en empêchant les écoutes clandestines et la manipulation des données DNS par des attaques de type man-in-the-middle.

En plus d'améliorer la sécurité, DNS over HTTPS a également pour objectif d'améliorer les performances: les tests de résolution DNS des fournisseurs de services Internet ont montré que de nombreux temps de réponse étaient souvent très lents. Ce problème est exacerbé par la nécessité de devoir résoudre plusieurs noms d'hôtes lors du chargement d'une seule page Web.

Install express

Tiré en partie de : https://www.yaleax.com/posts/doh/

On récupère le paquet deb :

wget https://github.com/yaleax/yaleax/releases/download/doh-server/doh-server_2.0.1_amd64.deb
sudo dpkg -i doh-server_2.0.1_amd64.deb

On édite /etc/dns-over-https/doh-server.conf :

doh-server.conf
# HTTP listen port
listen = [
    "127.0.0.1:8053",
]
 
# 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 = "/query"
 
# Upstream DNS resolver
# If multiple servers are specified, a random one will be chosen each time.
upstream = [
    "127.0.0.1:53",
]
 
# Upstream timeout
timeout = 60
 
# Number of tries if upstream DNS fails
tries = 10
 
# Only use TCP for DNS query
tcp_only = false
 
# 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

listen : Le serveur doh écoute sur le port 8053

upstream : Le serveur DNS sur lequel se baser. Ici dans mon cas, j'ai un résolveur local, donc 127.0.0.1:53

Mise en place & Démarrage du service

systemd

C'est déjà en place :

systemctl restart doh-server
systemctl status doh-server

initd

On créé /etc/init.d/doh-server :

doh-server
#! /bin/sh
### BEGIN INIT INFO
# Provides:          doh-server
# Required-Start:    $network $remote_fs $syslog
# Required-Stop:     $network $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: DNS-over-HTTPS Server
# Description:       This daemon will start the DNS-over-HTTPS Daemon
### END INIT INFO
 
# Do NOT "set -e"
 
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
DESC="DNS-over-HTTPS Server"
NAME=doh-server
USERNAME=root
DAEMON=/usr/local/bin/$NAME
DAEMON_ARGS="-conf /etc/dns-over-https/doh-server.conf"
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
 
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
 
# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh
 
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
. /lib/lsb/init-functions
 
#
# Function that starts the daemon/service
#
do_start()
{
        # Return
        #   0 if daemon has been started
        #   1 if daemon was already running
        #   2 if daemon could not be started
        start-stop-daemon -b --chuid $USERNAME --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
                || return 1
        start-stop-daemon -b --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
                $DAEMON_ARGS \
                || return 2
}
 
#
# Function that stops the daemon/service
#
do_stop()
{
        # Return
        #   0 if daemon has been stopped
        #   1 if daemon was already stopped
        #   2 if daemon could not be stopped
        #   other if a failure occurred
        start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
        RETVAL="$?"
        [ "$RETVAL" = 2 ] && return 2
        # Wait for children to finish too if this is a daemon that forks
        # and if the daemon is only ever run from this initscript.
        # If the above conditions are not satisfied then add some other code
        # that waits for the process to drop all resources that could be
        # needed by services started subsequently.  A last resort is to
        # sleep for some time.
        start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
        [ "$?" = 2 ] && return 2
        # Many daemons don't delete their pidfiles when they exit.
        rm -f $PIDFILE
        return "$RETVAL"
}
 
case "$1" in
  start)
        [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
        do_start
        case "$?" in
                0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
                2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
        ;;
  stop)
        [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
        do_stop
        case "$?" in
                0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
                2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
        ;;
  status)
        status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
        ;;
  restart)
        log_daemon_msg "Restarting $DESC" "$NAME"
        do_stop
        case "$?" in
          0|1)
                do_start
                case "$?" in
                        0) log_end_msg 0 ;;
                        1) log_end_msg 1 ;; # Old process is still running
                        *) log_end_msg 1 ;; # Failed to start
                esac
                ;;
          *)
                # Failed to stop
                log_end_msg 1
                ;;
        esac
        ;;
  *)
        echo "Usage: $SCRIPTNAME {start|stop|status|restart}" >&2
        exit 3
        ;;
esac
 
:

et puis :

update-rc.d -f doh-server defaults

Proxy pour Apache

D'abord il faut créer la clé SSL : Let's Encrypt / certbot

Ensuite on fait le vhost qui va bien dans /etc/apache2/sites-available :

doh.conf
<VirtualHost *:443>
        ServerName      monserveurdoh.domain.tld
 
        RequestHeader set X-Forwarded-Proto "https"
        Header always set Strict-Transport-Security "max-age=31536000;"
 
        SSLEngine on
        SSLCertificateFile /etc/letsencrypt/live/monserveurdoh.domain.tld/cert.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/monserveurdoh.domain.tld/privkey.pem
        SSLCertificateChainFile /etc/letsencrypt/live/monserveurdoh.domain.tld/chain.pem
 
        SSLProtocol -all +TLSv1.3
        SSLHonorCipherOrder on
        SSLCipherSuite EECDH+AESGCM:AES256+EECDH:AES128+EECDH
        SSLCompression off
        SSLUseStapling on
 
        ProxyPass /query http://127.0.0.1:8053/query
        ProxyPassReverse /query http://127.0.0.1:8053/query
</VirtualHost>

Et puis évidemment :

a2ensite doh.conf && apache2ctl restart

On fait quoi, après ?

Sur le navigateur à configurer, il faudra entrer l'URL : https://monserveurdoh.domain.tld/query

Si vous souhaitez garder le serveur pour votre usage personnel, tout en ayant besoin d'avoir un accès public, pensez à mettre quelque chose de moins évident que “/query” pour la requête ;-)

it/linux-selfhosting/doh.txt · Dernière modification : 01 Mar 2022 :: 10:46 de CgX