Howto Unbound
- Documentation : https://www.unbound.net/documentation/
- Rôle Ansible : https://forge.evolix.org/projects/ansible-roles/repository/show/unbound
- Man pages : https://man.openbsd.org/unbound ou https://manpages.debian.org/stretch/unbound/unbound.8.en.html
Unbound est un serveur DNS récursif. Il gère notamment du cache et la validation DNSSEC. Par rapport à Bind il est léger et sécurisé, mais il ne sait pas faire autorité pour un nom de domaine. Il a été écrit et est maintenu par NLnet Labs.
Installation
Debian
# apt install unbound
$ /usr/sbin/unbound -V
Version 1.17.1
Configure line: --build=x86_64-linux-gnu --prefix=/usr --includedir=${prefix}/include --mandir=${prefix}/share/man --infodir=${prefix}/share/info --sysconfdir=/etc --localstatedir=/var --disable-option-checking --disable-silent-rules --libdir=${prefix}/lib/x86_64-linux-gnu --runstatedir=/run --disable-maintainer-mode --disable-dependency-tracking --with-pythonmodule --with-pyunbound --enable-subnet --enable-dnstap --enable-systemd --with-libnghttp2 --with-chroot-dir= --with-dnstap-socket-path=/run/dnstap.sock --disable-rpath --with-pidfile=/run/unbound.pid --with-libevent --enable-tfo-client --with-rootkey-file=/usr/share/dns/root.key --enable-tfo-server
Linked libs: libevent 2.1.12-stable (it uses epoll), OpenSSL 3.0.11 19 Sep 2023
Linked modules: dns64 python subnetcache respip validator iterator
TCP Fastopen feature available
BSD licensed, see LICENSE in source package for details.
Report bugs to unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues
OpenBSD
Unbound est intégré dans la base d’OpenBSD, il est donc déjà présent.
Configuration
https://manpages.debian.org/bookworm/unbound/unbound.conf.5.en.html ou https://man.openbsd.org/unbound.conf
Emplacement de la configuration sous Debian
Fichiers de configuration sous Debian :
/etc/unbound/
├── unbound.conf
├── unbound.conf.d
│ ├── remote-control.conf
│ └── root-auto-trust-anchor-file.conf
Remarque : Dans Debian 11 et précédents, le fichier
/etc/unbound/unbound.conf.d/remote-control.conf
n’est pas
présent. Les opérations de rechargement de la configuration (avec
systemctl reload unbound.service
) ne fonctionnent pas. Mais
on peut manuellement rajouter le fichier suivant pour que ça puisse
fonctionner :
remote-control:
control-enable: yes
# by default the control interface is is 127.0.0.1 and ::1 and port 8953
# it is possible to use a unix socket too
control-interface: /run/unbound.ctl
Emplacement de la configuration sous OpenBSD
Fichiers de configuration sous OpenBSD (Attention, Unbound est dans
un chroot dans /var/unbound/
) :
/var/unbound/etc/
└── unbound.conf
Configuration générale
Par défaut, Unbound écoute uniquement sur localhost, la configuration minimale suivante consiste surtout à le sécuriser :
server:
hide-identity: yes
hide-version: yes
Si l’on veut le faire écouter sur un réseau local, il faut ajuster
les directives interface
et access-control
:
La directive
interface: <Adresse IP ou Nom d'interface réseau [@PORT]>
permet de préciser sur quelles IP ou interfaces réseau Unbound doit se mettre en écoute. On peut préciser le port aussi, avec@PORT
. Exempleinterface: 192.0.2.254
,interface: ens3
ouinterface: 192.0.2.1@5353
La directive
access-control: <Bloc IP> <action>
permet de faire des d’autorisation pour permettre ou non l’utilisation du résolveur. Les valeurs habituelles pour<action>
sont deny (ignore sans répondre), refuse (répond avec un message d’erreur), allow (autorise l’usage du résolveur).
Exemple :
server:
interface: 192.0.2.254
interface: 192.0.2.254@5353
interface: 127.0.0.1
interface: ::1
access-control: 0.0.0.0/0 refuse
access-control: 127.0.0.0/8 allow
access-control: 192.0.2.0/24 allow
access-control: ::0/0 refuse
access-control: ::1 allow
Configuration spécifique sous OpenBSD
Avant d’activer Unbound sous OpenBSD, il faut configurer le nombre maximum de file descriptor qu’il peut ouvrir. En effet, 2 fd sont ouverts pour chaque IP sur laquelle Unbound écoute, puis 1 fd est ouvert pour chaque requête active. Dans le cas d’une instabilité réseau, les fd ouverts peuvent s’accumuler et atteindre la limite, bloquant toute nouvelle requête :
unbound: [12503:0] error: can't create socket: Too many open files
Par défaut, cette limite est configurée à 512 dans
/etc/login.conf
. Nous conseillons de l’augmenter à 2048
:
unbound:\
:openfiles=2048:\
:tc=daemon:
Puis exécuter cap_mkdb /etc/login.conf
.
Si cette modification est faite alors qu’unbound est déjà démarré, il faudra le redémarrer pour que la modification soit prise en compte.
Si nécessaire, augmenter également le nombre de file descriptor pouvant être ouverts globalement au système :
# sysctl kern.maxfiles
kern.maxfiles=7030
# sysctl kern.maxfiles=20480
# echo kern.maxfiles=20480 >> /etc/sysctl.conf
Activation sous OpenBSD
On active Unbound dans rc.conf.local
et on démarre le
daemon :
# rcctl enable unbound
# rcctl start unbound
Monitoring
Munin
Il existe un plugin Munin pour Unbound. Il nécessite un réglage spécifique côté Unbound et Munin pour bien fonctionner.
Côté Unbound dans
/etc/unbound/unbound.conf.d/evolinux.conf
:
server:
# Activation des statistiques
extended-statistics: yes
statistics-cumulative: no
statistics-interval: 0
Remarque : Il est nécessaire d’avoir la directive
control-enable: yes
dans la sectionremote-control
. C’est déjà actif par défaut en Debian 12, ou si vous avez configuré Unbound pour que le rechargement de configuration marche.
Côté Munin, dans /etc/munin/plugins-conf.d/unbound
:
[unbound*]
user root
env.statefile /tmp/munin-unbound-state
env.unbound_conf /etc/unbound/unbound.conf
env.unbound_control /usr/sbin/unbound-control
Puis activer les plugins :
# ln -s /usr/share/munin/plugins/unbound_munin_ /etc/munin/plugins/unbound_munin_hits
# ln -s /usr/share/munin/plugins/unbound_munin_ /etc/munin/plugins/unbound_munin_queue
# ln -s /usr/share/munin/plugins/unbound_munin_ /etc/munin/plugins/unbound_munin_memory
# ln -s /usr/share/munin/plugins/unbound_munin_ /etc/munin/plugins/unbound_munin_by_type
# ln -s /usr/share/munin/plugins/unbound_munin_ /etc/munin/plugins/unbound_munin_by_class
# ln -s /usr/share/munin/plugins/unbound_munin_ /etc/munin/plugins/unbound_munin_by_opcode
# ln -s /usr/share/munin/plugins/unbound_munin_ /etc/munin/plugins/unbound_munin_by_rcode
# ln -s /usr/share/munin/plugins/unbound_munin_ /etc/munin/plugins/unbound_munin_by_flags
# ln -s /usr/share/munin/plugins/unbound_munin_ /etc/munin/plugins/unbound_munin_histogram
Et ne pas oublier de redémarrer munin-node
(systemctl restart munin-node
)
Avoir des statistiques
On peut accéder à des statistiques avec unbound-control(8).
Pour cela, le remote-control
doit être activé :
remote-control:
control-enable: yes
control-interface: /run/unbound.ctl
Sous Debian :
# unbound-control stats
Sous OpenBSD :
$ doas -u _unbound unbound-control stats
Si l’on veut avoir des statistiques plus détaillées, avec notamment le type de requêtes, on peut ajouter à la configuration :
extended-statistics: yes
Enfin, les statistiques peuvent régulièrement être affichées dans les logs avec cette configuration :
statistics-interval: 300
dnstop
Voir HowtoBind#dnstop
Bloquer des domaines indésirables
Unbound peut être utilisé pour renvoyer une réponse
NXDOMAIN
pour des domaines spécifiques.
Le script unbound-adblock
est un script personnalisable, qui se lance périodiquement, et qui
permet de bloquer les publicités et autres domaines indésirables à
partir de sources URL de fichiers hosts
, que le script
parse et rend compatible au format d’unbound.
Installation de unbound-adblock
Sous Debian ou OpenBSD :
- Avoir unbound configuré et fonctionnel en tant que serveur DNS récursif local
- Télécharger le script :
wget https://geoghegan.ca/pub/unbound-adblock/0.4/unbound-adblock.sh
- Créer un utilisateur “_adblock” :
useradd -s /sbin/nologin _adblock
- Installer le script avec les permissions appropriées :
install -m 755 -o root -g bin unbound-adblock.sh /usr/local/bin/unbound-adblock.sh
- Apporter une correction au script pour préciser l’emplacement de la
commande unbound-checkconf :
sed -i "s/^unbound-checkconf/\/usr\/sbin\/unbound-checkconf/" /usr/local/bin/unbound-adblock.sh
- Créer le fichier “/etc/unbound/adblock.conf” :
- Sous Debian :
install -m 640 -o _adblock /dev/null /etc/unbound/adblock.conf
- Sous OpenBSD :
install -m 640 -o _adblock -g wheel /dev/null /var/unbound/etc/adblock.conf
- Sous Debian :
- Donner les permissions nécessaires à l’utilisateur “_adblock” :
- Sous Debian avec
visudo
:_adblock ALL=(root) NOPASSWD: /bin/systemctl restart unbound
- Sous OpenBSD en éditant
/etc/doas.conf
:permit nopass _adblock cmd rcctl args reload unbound
- Sous Debian avec
- Ajouter l’inclusion de la configuration dans “unbound.conf”
(avant la section de forward s’il en existe une) :
include: /etc/unbound/adblock.conf
- Éditer la crontab de l’utilisateur “_adblock” pour lancer
quotidiennement le script, avec
crontab -u _adblock -e
:- Sous Debian :
@midnight /bin/sh /usr/local/bin/unbound-adblock.sh -linux
- Sous OpenBSD :
@midnight /bin/sh /usr/local/bin/unbound-adblock.sh
- Sous Debian :
- Lancer une première fois le script manuellement :
- Sous Debian :
sudo -u _adblock sh /usr/local/bin/unbound-adblock.sh -linux
- Sous OpenBSD :
doas -u _adblock sh /usr/local/bin/unbound-adblock.sh
- Sous Debian :
Configuration supplémentaire optionnelle sous OpenBSD
Google impose l’utilisation de ses propres serveurs DNS dans de nombreuses applications et services. De nombreux appareils utilisent également des DNS Google codés en dur et qui ne peuvent pas être modifiés.
Il est possible de contourner ça avec HowtoOpenBSD/PacketFilter en rajoutant la
règle suivante dans /etc/pf.conf
pour forcer l’utilisation
de notre résolveur DNS :
# Remplacer $adblock_server par l'adresse IP de la machine qui heberge le service unbound
pass in quick to {8.8.8.8, 8.8.4.4} rdr-to $adblock_server
# Ou, de façon plus globale
pass in quick proto {tcp udp} to port 53 rdr-to $adblock_server
Puis recharger la configuration :
# pfctl -f /etc/pf.conf
.
Liste de sources de fichiers hosts
Les listes doivent obligatoirement être dans un format de fichier
hosts
pour fonctionner.
Par défaut, l’URL https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts est fournie comme seule source. Des versions plus complètes provenant du même projet peuvent être trouvées sur le README du github (bloquant par exemple tous les réseaux sociaux, les sites de fake news, …) : https://github.com/StevenBlack/hosts.
L’URL https://raw.githubusercontent.com/jerryn70/GoodbyeAds/master/Hosts/GoodbyeAds.txt peut être rajoutée comme seconde source, plus complète et plus agressive.
Whitelister des domaines bloqués
Si un domaine présent dans une des listes a besoin d’être autorisé, il peut être whitelisté. Pour cela, il faut éditer le script, et ajouter dans la fonction whitelist(), à l’intérieur du grep, le domaine en question :
whitelist() {
grep -E -v 'example\.com|example\.org'
}
Attention : Il ne faut pas ajouter une commande grep mais bien ajouter le domaine à la liste actuelle. Une nouvelle commande grep ne sera pas prise en compte.
Bloquer des domaines personnalisés
Il est tout à fait possible de bloquer n’importe quel domaine souhaité sans forcément utiliser le script ci-dessus, ou même en complément du script.
Pour cela, il suffit d’ajouter un autre fichier de configuration à
inclure à unbound.conf
, et d’y ajouter manuellement les
entrées à bloquer souhaitées, en respectant ce format, avec un domaine
par ligne :
local-zone: "example.com" always_nxdomain
À noter que l’ensemble des sous-domaines (*.example.com ; www.example.com par exemple) seront bloqués.
FAQ
Vider le cache pour un domaine particulier
unbound-control flush_zone foo.local
Vider tout le cache
unbound-control flush_infra all
Si l’on spécifie une IP à la place de “all”, alors l’entrée pour cette adresse est supprimée du cache
Utiliser un serveur DNS particulier pour un nom de domaine
On pourra forwarder certaines requêtes vers un serveur différent en rajoutant les directives ci-dessous :
forward-zone:
name: "foo.local."
forward-addr: 192.0.2.1
forward-first: yes
Dans le cas présent, les requêtes concernent une zone locale, ainsi afin d’éviter une vérification DNSSEC pour ces dernières on ajoutera la directive suivante dans la configuration de unbound :
domain-insecure: "foo.local."
Rajouter / modifier un enregistrement DNS
Parfois on veut pouvoir modifier un enregistrement DNS, par exemple
quand on a un VPN. On peut utiliser /etc/hosts
pour les
champs A mais pas pour les MX. On peut donc utiliser unbound pour mentir
:
local-zone: "example.com." typetransparent
local-data: "example.com. IN MX 10 fakemx.example.com."
local-data: "fakemx.example.com. IN A 192.168.1.3"
Configuration sur un routeur
Il NE faut JAMAIS mettre une configuration de type :
interface: 0.0.0.0
…car Unbound ne va pas forcément répondre avec la bonne interface et on peut avoir des erreurs du type :
$ dig @IP-routeur
;; reply from unexpected source: autre.ip.du.routeur#53, expected ipdurouteur#53
Il faut lister explicitement toutes les interfaces sur lesquelles on souhaite qu’Unbound écoute.
dig +trace ne fonctionne pas
C’est certainement parce que le client a une autorisation
insuffisante pour ce type de requête particulière. Il faut donc
remplacer dans la directive access-control:
le mot-clé
allow
par allow_snoop
.
Mentir sur le TTL
On peut vouloir mettre un TTL minimum pour ne pas respecter le TTL quand il est mis à des valeurs anormalement basses. Pour mettre le TTL minimum à 600 :
cache-min-ttl: 600
Diminuer le cache des réponses négatives
Si on veut diminuer à 30s la durée de mise en cache des résolutions n’ayant pas de réponse :
cache-max-negative-ttl: 30
À noter que c’est géré indépendamment de cache-min-ttl
,
ainsi cache-max-negative-ttl
peut être mis très bas (par
exemple 30 secondes), et cache-min-ttl
très haut (par
exemple 24 heures) ce qui semble astucieux dans le cas spécifique où
l’on interroge des DNSRBL pour diminuer un peu le nombre de
requêtes.