%

Guide du Routeur OpenBSD

Article publié, le et modifié le
85 minutes de lecture

Cet article contient 17918 mots.
Source brute de l'article :
Commit version : 9c0a93f

Guide du Routeur OpenBSD

Pare-feu segmentant un réseau, avec DHCP, DNS (Unbound), blocage de domaine et bien plus encore.

  • OpenBSD: 6.9 · Publié : 2020-11-05 · Mis-à-jour : 2021-07-21 · Version : 1.9.4

Introduction

Dans ce guide, nous verrons comment nous pouvons utiliser du matériel “bas de gamme” bon marché pour construire un routeur OpenBSD terrible avec des capacités de pare-feu, des réseaux locaux segmentés, du DNS avec blocage de noms de domaines, du DHCP et bien plus.

Nous commencerons par paramétrer les segments réseaux (LAN) par trois réseaux séparés, un pour les adultes à la maison, un pour les enfants et un pour les serveurs face à Internet (comme une DMZ), tel qu’un serveur web ou serveur mail privé. Nous chercherons à voir comment nous pouvons utiliser DNS pour bloquer les publicités, le porno, et d’autres sites sur Internet. Le routeur OpenBSD peut aussi être utilisé dans de petites ou moyennes entreprises.

Conventions typographiques utilisées dans ce guide

  • La police à largeur fixe (mono-espacement) est utilisée pour les commandes en console, les noms de fichiers et leurs chemins, les paramètres de configuration, etc…
  • Les commandes en console qui doivent être tapées en tant qu’utilisateur root sont préfixées du symbole dièse # et la commande apparaît en gras dans le texte.
  • Les commandes en console qui doivent être tapées en tant qu’utilisateur normal sont préfixées du symbole dollar $ et la commande apparaît en gras dans le texte.

Pourquoi un pare-feu ?

Info

Peu importe comment vous vous connectez à Internet depuis votre domicile ou votre bureau, vous avez besoin d’un vrai pare-feu entre vous et le modem ou routeur que vous fourni votre FAI.

Il est très rare que les modems ou routeurs grand public reçoivent des mises à jour du micrologiciel et sont souvent vulnérables aux attaques réseau qui transforment ces appareils en Botnet, tel que le fait le logiciel malveillant Mirai. De nombreux modems et routeurs grand public sont à blâmer à propos de certaines attaques par déni de service de grande envergure (DOS)

Un pare-feu entre vous et le modem ou routeur de votre FAI ne peut pas protéger votre dispositif modem ou routeur contre de telles attaques, mais il peut protéger vos ordinateurs et dispositifs à l’intérieur du réseau, et il peut vous aider à surveiller et contrôler le trafic qui arrive vers votre réseau local et qui en part.

Sans un pare-feu entre votre réseau local et le modem ou routeur du FAI, vous pouvez considérer basiquement que votre porte est grande ouverte, comme laisser grande ouverte la porte de votre maison, ainsi vous ne pouvez pas faire confiance en l’équipement de votre FAI.

C’est toujours réellement une bonne idée de mettre un vrai pare-feu entre votre réseau local et Internet, et avec OpenBSD vous avez une solution très solide.

Le Matériel

Vous n’avez pas besoin d’acheter du matériel cher pour avoir un routeur et un pare-feu efficaces pour votre maison ou votre bureau. Même avec du matériel “bas de gamme” bon marché, vous pouvez avoir une solution très solide.

J’ai créé de multiples solutions avec la carte-mère ASRock Q1900DC-ITX qui est fournie avec un processeur Intel Celeron Quadri-Cœur.

ASRock Q1900DC-ITX
ASRock Q1900DC-ITX

Je l’admet, c’est une carte-mère assez “pourrie”, mais elle fait le boulot et j’ai de nombreuses solutions très solides qui fonctionnent depuis de nombreuses années sur des réseaux Gigabit avec saturation complète et le pare-feu, DNS, faisant des “heures supplémentaires” et où le CPU ne chauffe pas.

La carte-mère ASRock Q1900DC-ITX a pour avantage qu’elle est fournie avec une prise jack DC-In (entrée électrique) qui est compatible avec un adaptateur électrique 9-19V, ce qui la rend très économe en énergie. Malheureusement, la carte-mère ASRock Q1900DC-ITX n’est plus fabriquée, mais comme je l’utilise juste comme exemple ; j’ai utilisé de nombreuses autres carte-mères bon marché tout aussi bien.

Info

J’ai aussi utilisé l’ASRock Q1900-ITX (qui est fournie sans la prise jack DC-In) combinée à un PicoPSU.

PicoPSU
PicoPSU

Vous pouvez trouvez différentes marques et version du PicoPSU, certains sont de meilleurs qualités que d’autres. J’ai deux marques différentes, l’original et une copie moins chère, toutes deux sont très performants et permettent d’économiser par mal d’énergie contrairement à une alimentation normale.

Enfin, j’utilise une carte réseau quadruple port Intel bon marché, trouvé sur Ebay, tel que celle-ci :

Quad NIC Intel
Quad NIC Intel

Je sais, il est préférable d’utiliser du matériel de qualité, spécifiquement sur un réseau dont vous avez à prendre soin, mais ce tutoriel est relatif au fait de comment vous pouvez vous en sortir en utilisant du matériel bon marché tout en ayant un produit extrêmement utile qui continue à bien vous servir pendant de nombreuses années - du moins, telle est mon expérience.

Je vous recommande de chercher une carte mini-ITX dont le matériel est pris en charge par OpenBSD, tel qu’un CPU Intel Celeron ou Intel i3. Ces cartes-mères sont typiquement peu chères, peu gourmandes d’énergie, et ne prennent pas beaucoup de place. Je ne recommande pas l’utilisation d’un CPU Intel Atom si vous avez un réseau Gigabit, car il ne peut pas gérer la quantité de trafic.

Vous pourriez également avoir besoin de quelques commutateurs Gigabit bon marché pour segmenter votre réseau local, au moins si vous avez plus d’un ordinateur connecté sur le même LAN :)

Pourquoi OpenBSD ?

En vérité, vous pouvez avoir le même paramétrage avec une autre saveur BSD ou une des différentes distributions Linux, mais OpenBSD est spécifiquement très bien adapté et conçu pour ce genre de tâche. Non seulement il est livré avec tous les logiciels nécessaires dans l’installation de base, mais il offre également une sécurité nettement supérieure, et des tonnes de mesure d’atténuation améliorées déjà intégrées dans le système d’exploitation. Je recommande chaudement OpenBSD plutôt que tout autre système d’exploitation pour ce genre de tâches.

Ce guide ne vous montre pas comment installer OpenBSD. Si vous ne savez pas faire, je vous recommande de faire fonctionner une machine virtuelle avant ou de voir si vous avez du matériel inutilisé et pris en charge avec lequel vous pourriez tester. OpenBSD est un des systèmes d’exploitations des plus faciles et rapides à installer. N’ayez pas peur de l’approche sans GUI (interface utilisateur) ; une fois que vous l’avez essayé, vous apprécierez vraiment sa simplicité. Dans le doute, utilisez les paramètres par défaut.

Avant de commencer ce voyage, assurez-vous de consulter la documentation d’OpenBSD ! Non seulement, chaque chose est très bien documentée, mais vous trouverez très probablement toutes les réponses dont vous avez besoin. Lisez la FAQ OpenBSD, regardez les différentes pages de manuels à propos des différents logiciels que nous allons utiliser.

Un autre endroit vraiment utile où trouver des informations générales à propos d’OpenBSD sont les archives des listes de diffusions d’OpenBSD. Aussi assurez-vous de rester à jour des informations pertinentes en souscrivant à la liste de diffusion des Annonces et avis de sécurité.

Astuce

Le réseau

Un routeur est basiquement un dispositif qui régule le trafic réseau entre deux ou plusieurs réseaux séparés. Le routeur garantira que le trafic réseau à destination du réseau local ne circule pas sur Internet, et que le trafic sur Internet, qui n’est pas à destination de votre réseau local, reste sur Internet.

Info

Dans ce tutoriel, nous construirons un routeur et nous avons 4 réseaux de même type à faire travailler ensemble. L’un est Internet, et les trois autres sont segmentés intentionnellement en réseaux locaux (LAN). Certaines personnes préfèrent travailler avec des LAN virtuels (VLAN), mais dans ce tutoriel nous utiliserons une interface réseau 4 ports, telle que vue sur l’illustration ci-dessus. Vous pouvez arriver au même résultat en utilisant de multiples cartes réseau à port unique, si vous préférez ; vous devez juste vous assurez d’avoir assez de place et de slot PCI libre sur la carte-mère. Vous pouvez aussi utiliser le port Ethernet de la carte-mère, mais cela dépend du pilote et de la prise en charge du dispositif. Je n’ai pas de problème à utiliser un contrôleur Ethernet Gigabit PCI Realtek qui est fourni avec beaucoup de carte-mères, bien que je recommande plutôt Intel.

Bien sûr, vous n’avez pas à segmenter le réseau en de nombreuses parties si vous n’avez pas besoin de cela, et il serait très facile de changer les paramètres de ce guide, mais j’ai décidé d’utiliser cette approche avant de vous montrer comment vous pouvez protéger vos enfants en segmentant leur réseau dans un LAN séparé qui permet non seulement de bloquer la publicité et la pornographie grâce au blocage des DNS (tous les segments en bénéficient), mais vous pouvez même mettre sur une liste blanche les partie de l’Internet auxquelles vous voulez qu’ils aient accès. La dernière partie à propos des listes blanches est difficile et n’est généralement pas recommandé à moins que vos enfants aient besoin d’un accès très limité, mais c’est faisable avec un peu de travail, et le guide va vous montrer une façon de faire.

Ceci est une illustration du réseau que nous allons paramétrer :

Les adresses IP qui commencent par 10.24.0 sont n’importe quelle adresse IP que le routeur ou modem de votre FAI vous donne ; elles peuvent être très différentes. Les adresses IP commençant par 192.168 sont les adresses IP que nous allons utiliser dans ce guide pour notre réseau local (LAN).

Ce guide ne s’occupe en aucun cas de connectivité Wifi. Les micrologiciels des puces sans fil sont notoirement bogués et exploitables ; je vous recommande de n’utiliser aucun type de connectivité sans fil, si vous pouvez vous en passer. Si vous avez besoin de la connectivité sans fil, je recommande chaudement que vous désactiviez l’accès Wifi du modem ou routeur du FAI (si possible), et ensuite d’acheter le meilleur routeur Wifi que vous pouvez trouver puis de le mettre derrière le pare-feu dans un segment isolé. Ainsi, si jamais votre appareil sans fil est compromis, vous pourrez mieux contrôler le résultat et limiter les dégâts. Vous pouvez en outre configurer le routeur sans fil de telle sorte que tout appareil, qui y est connecté, dispose de ses propres adresses IP qui passent directement par le routeur sans fil, tout en bloquant le trafic provenant du routeur sans fil lui-même. De cette façon, vous pouvez empêcher le routeur sans fil de “téléphoner à la maison”. Vous pouvez aussi avoir un adaptateur Wifi supporté par OpenBSD et que votre routeur OpenBSD agisse en tant que point d’accès, toutefois je préfère de beaucoup segmenter la partie Wifi soit par un routeur sans fil séparé, soit par une autre machine OpenBSD servant de point d’accès Wifi derrière le pare-feu lui-même.

Info

Paramétrer le réseau

La première chose que nous allons paramétrer sont les différentes interfaces réseaux de notre routeur OpenBSD. Sur ma machine, j’ai désactivé l’interface réseau qui est livré avec la carte-mère via le BIOS, et je n’utilise que l’interface réseau 4 ports d’Intel.

Si vous suivez ce tutoriel et que vous souhaitez seulement un pare-feu basique alors vous avez au moins besoin de deux interfaces réseaux séparées.

Avant de commencer, assurez-vous de lire et de comprendre les différentes options de la page de manuel hostname.if. Prenez aussi le temps de lire la section réseau de la FAQ d’OpenBSD.

Puisque j’utilise Intel, le pilote em est celui qu’OpenBSD charge sur chacun des ports de cette interface réseau, qui sont listés comme étant des cartes séparées. Cela signifie que chaque carte est listée en tant qu’emX où X est le numéro actuel du port de la carte.

dmesg liste ma carte réseau avec 4 ports de telle manière :

# dmesg
em0 at pci2 dev 0 function 0 "Intel I350" rev 0x01: msi, address a0:36:9f:a1:66:b8
em1 at pci2 dev 0 function 1 "Intel I350" rev 0x01: msi, address a0:36:9f:a1:66:b9
em2 at pci2 dev 0 function 2 "Intel I350" rev 0x01: msi, address a0:36:9f:a1:66:ba
em3 at pci2 dev 0 function 3 "Intel I350" rev 0x01: msi, address a0:36:9f:a1:66:bb

Ce qui montre que ma carte est reconnu comme étant une Intel I350-T4 PCI Express Quad Port Gigabit NIC.

Il faut ensuite déterminer quel est le port correspondant physiquement au numéro indiqué ci-dessus. Vous pouvez le faire en connectant manuellement un câble Ethernet, connecté sur un commutateur actif, un modem ou un routeur, sur chacun des ports, un à la fois, afin de voir quel port est activé et le noter ensuite quelque part.

Vous pouvez vérifier le statuts d’activité avec la commande ifconfig. Un port sans câble Ethernet sera listé comme ayant le champ status notifié no carrier alors qu’un port avec un câble attaché sera listé en active. Tel que :

# ifconfig
em1: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        lladdr a0:36:9f:a1:66:b9
        index 2 priority 0 llprio 3
        media: Ethernet autoselect (none)
        status: active
em2: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        lladdr a0:36:9f:a1:66:ba
        index 3 priority 0 llprio 3
        media: Ethernet autoselect (none)
        status: no carrier

Nous allons utiliser le port em0 afin de le connecter au modem ou routeur de votre FAI, vers Internet. Dans mon cas, j’ai une adresse IP publique fournie par mon FAI ; vous en aurez besoin si vous voulez faire fonctionner un serveur web depuis votre maison, mais si ce n’est pas le cas, vous n’en avez pas besoin, ainsi vous pouvez paramétrer la carte par DHCP.

Dans mon cas, j’ai besoin de spécifier une adresse IP fixe pour em0 qui recevra alors le trafic redirigé depuis mon FAI vers mon adresse IP publique. Pour faire cela, je paramètre em0 avec l’information suivante :

# echo 'inet 10.24.0.50 255.255.254.0 NONE' > /etc/hostname.em0

Si vous n’avez pas besoin d’une adresse IP publique et que votre adresse IP est obtenue par votre FAI via DHCP, alors écrivez juste dhcp à la place :

# echo 'dhcp' > /etc/hostname.em0

Ensuite, je paramètre le reste des ports de l’interface réseau avec leurs adresses IP, tel que je l’ai précédemment illustré.

# echo 'inet 192.168.1.1 255.255.254.0 NONE' > /etc/hostname.em1
# echo 'inet 192.168.2.1 255.255.254.0 NONE' > /etc/hostname.em2
# echo 'inet 192.168.3.1 255.255.254.0 NONE' > /etc/hostname.em3

Regardez la page du manuel hostname.if pour avoir plus d’informations.

Ensuite, j’ai besoin de paramétrer l’IP de la passerelle du FAI. Selon le paramétrage de votre FAI, cela peut être une autre adresse IP que celle du modem ou routeur du FAI. Si vous n’ajoutez pas le fichier /etc/mygate alors aucune passerelle par défaut ne sera ajouté à la table de routage. Vous n’avez pas besoin de /etc/mygate si votre IP est fournie par le modem ou routeur de votre FAI via DHCP. Si vous utilisez la directive dhcp dans n’importe quel fichier hostname.ifX alors l’entrée dans le fichier /etc/mygate sera ignorée. Cela est parce que la carte obtient son adresse IP depuis un serveur DHCP qui fournira aussi l’information de routage vers la passerelle.

Enfin, mais pas des moindres, nous avons besoin d’activer la redirection IP. La redirection IP est le processus qui dirige les paquets IP qui voyagent entre les interfaces réseaux du routeur. Par défaut, OpenBSD ne fera pas de redirection des paquets IP entre les différentes interfaces réseaux. En d’autres mots, les fonctions de routage (appelées aussi fonctions de passerelles) sont désactivées.

Nous pouvons activer la redirection d’IP en utilisant les commandes suivantes :

# sysctl net.inet.ip.forwarding=1
# echo 'net.inet.ip.forwarding=1' >> /etc/sysctl.conf

Maintenant OpenBSD sera capable de rediriger les paquets IPv4 depuis une interface réseau vers une autre. Ou, tel dans notre cas avec les 4 ports, d’un port à l’autre. Regardez la page du manuel si vous avez besoin d’IPv6.

DHCP

Maintenant nous sommes prêts à paramétrer le service DHCP que nous exécuterons pour nos différents PC et dispositifs attachés aux différents LAN. Avant, assurons-nous de lire et de comprendre les différentes options de la page du manuel dhcp.conf. Prenons aussi le temps de regarder la page de manuel dhcp-options à propos des options que prend en charge dhcpd.

Nous avons une option pour cacher des adresses IP à de PC ou dispositifs spécifiques qui se connectent sur nos différents ports. Cela est nécessaire si nous voulons rediriger le trafic qui vient d’Internet vers quelque chose comme un serveur web. Nous pouvons cacher une adresse IP spécifique vers un PC spécifique via l’adresse MAC de l’interface réseau de la machine concernée.

Dans ce cas, je réserverais toutes les adresses IP dans un ensemble allant de 10 à 254 pour le DHCP, tandis que je laisserais les autres qui restent pour les éventuelles adresses fixes dont je pourrais avoir besoin.

Éditer le fichier /etc/dhcpd.conf avec votre éditeur de texte favori et adapter le à vos besoins.

subnet 192.168.1.0 netmask 255.255.255.0 {
    option domain-name-servers 192.168.1.1;
    option routers 192.168.1.1;
    range 192.168.1.10 192.168.1.254;
}
subnet 192.168.2.0 netmask 255.255.255.0 {
    option domain-name-servers 192.168.2.1;
    option routers 192.168.2.1;
    range 192.168.2.10 192.168.2.254;
}
subnet 192.168.3.0 netmask 255.255.255.0 {
    option domain-name-servers 192.168.3.1;
    option routers 192.168.3.1;
    range 192.168.3.10 192.168.3.254;
    host web.example.com {
        fixed-address 191.168.3.2;
        hardware ethernet 61:20:42:39:61:AF;
        option host-name "webserver";
    }
}

La ligne option domain-name-servers spécifie le serveur DNS que nous allons faire fonctionner sur notre routeur.

De plus l’ordinateur qui est notre serveur web sur le LAN publique a une adresse IP fixe et un nom d’hôte fixé.

De même, si vous ne voulez pas segmenter le réseau en différentes parties, mais que vous avez seulement besoin d’un LAN alors vous pouvez juste laisser de côté les autres sous-réseaux pour avoir juste cela :

subnet 192.168.1.0 netmask 255.255.255.0 {
    option domain-name-servers 192.168.1.1;
    option routers 192.168.1.1;
    range 192.168.1.10 192.168.1.254;
}

Ensuite, nous avons simplement besoin de nous assurer d’activer et de démarrer le service dhcpd :

# rcctl enable dhcpd
# rcctl start dhcpd
Info

PF - un pare-feu filtrant

Un pare-feu filtrant examine chaque paquet qui croise le pare-feu et décide quel paquet accepter ou refuser, selon l’examen des champs dans l’IP et les entêtes de protocole du paquet, et selon l’ensemble des règles que vous spécifiez.

Le filtrage de paquets fonctionne par inspection des adresses IP et du port source et de destination contenus dans chaque paquet du protocole TCP/IP (Transmission Control Protocol / Internet Protocol). Les ports TCP/IP sont des numéros assignés à des services spécifiques qui identifie pour quel service chaque paquet est destiné.

Une faiblesse commune des pare-feux simples à filtrage de paquets est que le pare-feu examine chaque paquet de manière isolée sans tenir compte des paquets qui ont déjà traversé le pare-feu et de ceux qui pourraient le suivre. Ils sont appelés pare-feu “sans état”. Exploiter un filtrage de paquets sans état est assez facile. PF d’OpenBSD n’est pas un pare-feu sans états, c’est un pare-feu à états.

Un pare-feu à états garde trace des connexions ouvertes et permet seulement le trafic correspondant à une connexion existante ou ouvre une nouvelle connexion permise. Quand l’état est spécifié par une règle correspondante, le pare-feu génère dynamiquement des règles internes pour que chaque paquet anticipé puisse être échangé durant la session. Il a suffisamment de capacité de correspondance pour déterminer si un paquet est valide pour une session. Tout paquet qui ne correspond pas au modèle de session sera automatiquement rejeté.

Un des avantages du filtrage à états est que c’est très rapide. Il vous permet de vous focaliser sur le fait de bloquer ou laisser passer de nouvelles sessions. Si une nouvelle session est passée, tous les paquets conséquents sont automatiquement alloués et tout paquet imposteur sera automatiquement rejeté. Si une nouvelle session est bloquée, aucun des paquets conséquents n’est autorisé. Le filtrage à états fournit aussi des capacités avancées de correspondance capables de se défendre contre le flood de différentes méthodes d’attaques employées par des attaquants.

La Traduction d’Adresse Réseau (NAT) permet à un réseau privé derrière le pare-feu de partager une adresse IP publique unique. La NAT permet à chaque ordinateur du réseau privé d’avoir un accès à Internet, sans avoir besoin de comptes multiples à Internet, ou de multiples adresses IP publiques. La NAT traduira automatiquement l’adresse IP du réseau privé pour les ordinateurs et dispositifs sur le réseau vers l’unique adresse IP publique lorsque les paquets sortent du pare-feu vers Internet. La NAT assume aussi la traduction inverse pour les paquets de retour. Avec la NAT, vous pouvez rediriger un trafic spécifique, couramment déterminé par un numéro de port ou un ensemble de numéros de port, entrant depuis votre adresse IP publique depuis Internet vers le ou les serveurs spécifiques localisés quelque part dans votre réseau local.

PF - Packet Filter est le système de pare-feu d’OpenBSD pour le filtrage du trafic TCP/IP et faisant de la NAT. PF est aussi capable de normaliser ou conditionner le trafic TCP/IP, aussi bien que gérer le contrôle de la bande passante ou la priorisation de paquets.

PF est activement maintenu et développé par l’entière équipe d’OpenBSD.

Paramétrage de PF

Avant que nous commencions, je présume que vous avez lu à la fois et le Guide de l’Utilisateur de PF et la page du manuel pf.conf, spécifiquement la page du manuel qui est très importante. Même si vous ne comprenez pas toutes les différentes options, assurez-vous de lire la documentation ! Lisez la page du manuel pf pour avoir une complète compréhension en profondeur de ce que PF peut faire.

De plus, laissez-moi commencer par vous dire que même si la syntaxe de PF est très lisible, il est très facile de faire des erreurs lors de l’écriture des règles de pare-feu. Même des seniors et des administrateurs systèmes expérimentés font des erreurs lors de l’écriture des règles de pare-feu.

Écrire des règles de pare-feu requiert que vous ayez planifié vos buts avec attention, compris comment implémenter les différentes règles avant d’obtenir le résultat attendu, et en même temps de prendre vos précautions afin de vous éviter de vous tromper et de vous déconnecter accidentellement :) Je pense que nous l’avons tous fait à un moment ou l’autre, que ce soit dans la précipitation, la fatigue ou simplement par erreur. J’ai vécu cela de nombreuses fois.

Info

La partie la plus importante est de ne pas faire de suppositions. Testez toujours vos règles de manière approfondie. Si quelque chose ne fonctionne pas, essayez de supprimer autant de règles que possible pour ne garder que le strict minimum. Puis introduisez une règle à la fois jusqu’à trouver la règle qui pose problème. Enfin, continuez avec le paramétrage étape par étape.

La partie réellement difficile est de se souvenir de comment les paquets arrivent sur une interface, comment ils sont rediriger vers une machine sur une autre interface, et de relier correctement ce “voyage” aux termes pass in, pass out, block in, block out, from et to. Souvent, ces termes ne fonctionnent pas exactement comme nous avons tendance à le penser.

Éclaircissements

Je tiens à démarrer en clarifiant certains des paramètres communs par défaut et des mots clés dans PF.

Quand nous parlons du traffic pass in ou pass out, une bonne manière de se rappeler ce dont il s’agit est de penser en terme de paquets de données. Nous utilisons pass in pour les paquets de données entrants qui viennent d’ordinateurs vers une interface réseau (les ordinateurs étant rattachés à ce périphérique réseau) et pass out pour les paquets de données venant de l’interface réseau vers les ordinateurs.

Le format est soit que nous filtrons les paquets de données sur la destination :

from source IP to destination IP [on]  port

Soit que nous filtrons les paquets de données sur la source :

from source IP [on] port to destination

Veuillez noter que la partie [on] n’est pas une partie de la syntaxe.

  • quick

    • Si un paquet correspond à une règle pass, block ou match avec le critère quick, le paquet est passé sans inspection des règles de filtrage conséquentes. La règle avec le critère quick devient la dernière règle correspondante.
  • keep state

    • Vous n’avez pas besoin de spécifier le critère keep state pour des règles spécifiques pass ou block. La première fois où un paquet correspond à une règle pass ou block, un état d’entrée est créé par défaut. Seulement si aucune règle ne correspond au paquet, l’action par défaut est de passer le paquet sans créer d’état.
  • on interface/any

    • Cette règle s’applique seulement aux paquets qui sont entrants, ou qui passent au-travers de cette interface en particulier ou d’un groupe d’interface. Le critère on any correspondra à toute interface existante, exceptée celles de bouclage loopback.
  • inet/inet6

    • Les critères inet et inet6 signifie que cette règle s’applique seulement aux paquets entrants, ou passant au-travers ce domaine particulier de routage, soit IPv4, soit IPv6. Vous pouvez appliquer des règles pour des domaines particuliers de routage sans spécifier l’interface réseau. Dans de ce cas, la règle correspondra à tout trafic de toute nature sur toutes les interfaces réseaux. En spécifiant inet, vous adressez explicitement le trafic IPv4 seulement.
  • proto

    • Se limiter à un protocole est faisable en utilisant le critère proto. Une règle s’applique seulement aux paquets de ce protocole, les autres protocoles ne sont pas affectés. Vous pouvez chercher les protocoles dans le fichier /etc/protocols. Les protocoles communs sont ICMP TCP et UDP.
  • in et out

    • C’est l’une des parties les plus faciles où se tromper : la direction du trafic. Un paquet entre ou sort toujours par le port sur l’interface Ethernet. in et out s’applique aux paquets entrants et sortants au-travers du port Ethernet physique auquel est attaché le câble Ethernet. Si rien n’est spécifié, la règle correspondra aux paquets dans les deux directions. in et out ne sont jamais utilisé pour gérer le trafic venant d’ une interface réseau vers une autre, ce qui est fait par la NAT, en utilisant les options nat-to et rdr-to. in et out gèrent seulement le trafic entrant et sortant du port Ethernet physique d’une même carte.
  • from et to

    • Les critères from et to s’appliquent seulement aux paquets avec une adresse et des ports source et destination spécifiés. Des deux, du nom d’hôte ou de l’adresse IP, ou du port, voire les spécifications OS sont optionnels. Quand nous avons affaire avec un routeur ayant de multiples interfaces réseaux, il est facile de penser cela : Je veux passer les paquets entrants depuis l’interface externe (l’interface réseau attachée à Internet) puis qu’ils aillent sur la première interface LAN et de là vers un PC spécifique sur le LAN signifiant que nous suivront le “chemin des données” dans notre esprit, et alors nous écrivons quelque chose comme cela : pass in on $ext_if from $ext_if to $dmz port 80. Mais cela ne fait pas apparaître “par magie” le trafic HTTP sur le port 80 au PC ayant l’adresse IP spécifique sur le LAN. Il nous faudrait aussi une règle pass out spécifique et déterminer exactement sur quelle machine nous voulons que les données arrivent. À moins que vous n’ayez affaire à une exigence très spécifique, vous n’aurez jamais besoin d’une telle règle dans votre jeu de règles ! Les fonctionnalités uRPF (Unicast Reverse Path Forwardint) de PF protégeront votre réseau interne aussi bien avec un paramétrage de base de NAT, avec l’option nat-to et une redirection avec l’option rdr-to, PF gérera les paquets venant de l’intérieur vers l’extérieur et vice-versa. Le paramètre all est équivalent à l’écriture from any to any. Sans une direction explicitement déclarée, la règle par défaut est from any to any. Cette règle : pass in on $p_lan proto udp to port dns se traduit par : pass in on em3 inet proto udp from any to any port = 53. Il n’est pas non plus nécessaire d’utiliser to any port dns, la partie any étant celle par défaut. Vous avez cependant besoin de to port dns.
  • nat-to et rdr-to

    • Les options NAT modifient soit l’adresse et le port source ou destination des paquets associées à une connexion d’états. PF modifie l’adresse spécifié et/ou le port dans le paquet et recalcule les sommes de contrôle IP, TCP et UDP nécessaires. Une option nat-to spécifie que les adresses IP ont été changées car le paquet traverse l’interface donnée. Cette technique permet à une ou plusieurs adresses IP sur l’hôte traduisant (le routeur OpenBSD) de prendre en charge le trafic réseau pour un ensemble plus grand de machines sur le réseau interne, tel qu’un LAN. L’option nat-to est habituellement appliqué à la sortie, signifiant redirigé depuis le réseau interne vers Internet. nat-to vers une adresse IP locale n’est pas pris en charge. L’option rdr-to est appliquée généralement à l’entrée, signifiant redirigé depuis Internet vers le réseau interne.
  • Liste d’éléments et d’ensemble d’adresses et de ports

    • Quand vous avez besoin de spécifier de multiples éléments, e.g. de multiples numéros de ports, vous pouvez les séparer avec une espace ou une virgule. Tel que port { 53 853 } ou port { 53, 853 }. Un ensemble d’adresses est spécifié en utilisant l’opérateur -. e.g. 192.168.1.2 - 192.168.1.10 signifie toutes les adresses IP de 192.168.1.2 à 192.168.1.10, incluant les deux. Un ensemble de ports a de multiples paramètres ; regardez la page du manuel pf.conf et cherchez le texte “Ports and ranges of ports are specified using these operators”.
Attention

Résolution de nom de domaine ou d’hôte

Si vous décidez d’utiliser des noms d’hôtes et/ou des noms de domaines dans votre paramétrage de PF, vous avez besoin de savoir que la résolution de tout nom de domaine ou d’hôte est faite au moment du chargement du jeu de règles. Cela signifie que quand l’adresse IP d’un hôte ou d’un nom de domaine change, le jeu de règles doit être rechargé pour que le changement soit pris en compte par le noyau. Il n’est pas possible qu’à chaque fois qu’une règle s’applique, pour un nom d’hôte ou de domaine listé, que PF fasse une nouvelle requête DNS pour ce nom d’hôte ou de domaine particulier. La requête DNS s’effectue seulement lors du chargement du jeu de règles.

Cela signifie aussi que vous devez vous assurer que le serveur DNS que vous utiliser soit actif et fonctionnel avant que PF ne démarre, autrement PF échouera à charger le jeu de règles car il ne peut résoudre le nom d' hôte ou de domaine.

Sur OpenBSD, PF démarre avant Unbound ou tout autre service DNS installé, ce qui est la bonne manière de faire d’un point de vue de la sécurité.

Je vous conseille d’éviter l’utilisation de noms d’hôtes ou de noms de domaines lorsque vous utilisez les règles PF et de privilégier les adresses IP, si possible. Il est possible d’utiliser les noms d’hôtes et noms de domaines, mais l’adressage d’IP directement est de loin le plus facile et le plus sûr.

Un jeu de règles

C’est une bonne idée de tester votre jeu de règles sur une machine de test. Il y a presque toujours plus d’une manière de faire pour arriver au même résultat. Selon mon humble avis, la meilleure manière est celle qui vous permet d’être le plus clair (i.e. facile à comprendre).

Attention

Essayez de trouver comment vous pouvez faire en sorte que vos règles soient aussi claires et simples que possible, en utilisant les valeurs par défaut, quand c’est possible. N’ayez pas peur de spécifier des critères qui rendent les règles plus claires à comprendre, quand bien même ils sont identiques aux valeurs par défaut. Une valeur par défaut peut être any to any, et vous pouvez laisser cela de côté, mais il serait plus facile de comprendre une règle particulière quand il est écrit any to any textuellement dans le fichier de configuration.

Vous pouvez toujours analyser le jeu de règles et vérifier les erreurs sans qu’il soit déployé avec la commande pfctl -nf /etc/pf.conf. Une fois que vous avez chargé le jeu de règles avec la commande pfctl -f /etc/pf.conf, vous pouvez voir comment le jeu de règles a été traduit par PF avec la commande pfctl -s rules, que je vous conseille d’utiliser régulièrement.

Je préfère organiser mon jeu de règles par section et commentaires, je ferais ainsi dans cet exemple.

Utilisez votre éditeur de texte favori et ouvrez le fichier /etc/pf.conf.

En premier, nous paramétrons quelques macros pour mieux se souvenir quelles interfaces réseaux nous utilisons. Utiliser des macros pour les interfaces réseaux rend aussi plus facile le changement du nom du pilote de la carte si vous achetez une nouvelle carte, ou de multiples nouvelles cartes.

#---------------------------------#
# Macros
#---------------------------------#

ext_if="em0" # Interface externe connectée au modem du FAI (Internet).
g_lan="em1"  # LAN PC Adultes
c_lan="em2"  # LAN PC Enfants
p_lan="em3"  # LAN Publique.

Ensuite, nous paramétrons une table pour les adresses IP non routable. Nous faisons cela, car une mauvaise configuration réseau courante est celle qui permet du trafic avec des adresses non routable vers Internet. Nous utiliserons la table dans notre jeu de règles afin de bloquer tout essai d’initier un contact avec les adresses non routable au-travers de l’interface externe du routeur.

#---------------------------------#
# Tables
#---------------------------------#

# Ceci est une table d'adresses IP privées non routables.
table <martians> { 0.0.0.0/8 10.0.0.0/8 127.0.0.0/8 169.254.0.0/16     \
                   172.16.0.0/12 192.0.0.0/24 192.0.2.0/24 224.0.0.0/3 \
                   192.168.0.0/16 198.18.0.0/15 198.51.100.0/24        \
                   203.0.113.0/24 }
Attention

Alors, commençons avec une politique de blocage par défaut et activons une série de fonctionnalités de protection.

#---------------------------------#
# Protect and block by default
#---------------------------------#
set skip on lo0

# Protection vs l'usurpation d'adresses sur toutes les interfaces réseaux.
block in from no-route
block in quick from urpf-failed

# Bloquage des adresses privées non routable.
# Utilisation du paramétre "quick" pour que cette règle soit la dernière traversée. 
block in quick on $ext_if from <martians> to any
block return out quick on $ext_if from any to <martians>

# Bloquage par défaut de tout trafic sur toutes les interfaces réseaux. 
block return in on { $g_lan $c_lan $dmz }

# Bloquage par défaut de tout trafic sur l'interface reliée à Internet 
# avec journalisation
block drop in log on $ext_if

# Autoriser ICMP.
match in on $ext_if inet proto icmp icmp-type {echoreq } tag ICMP_IN
block drop in on $ext_if proto icmp
pass in proto icmp tagged ICMP_IN max-pkt-rate 100/10

# Autoriser le routeur à accéder à Internet, au-travers de son interface réseau dédiée
pass out inet from $ext_if

Les adresses IP contenues dans la macro martians constituent les adresses référencées dans la RFC1918 qui ne doivent pas être utilisées sur Internet. Le trafic venant ou allant vers de telles adresses doit être abandonné sur l’interface externe du routeur.

Dans les précédentes versions de ce guide (avant la version 1.5.0), j’avais l’habitude d’utiliser l’instruction scrub dans le paramétrage ci-dessus, toutefois après avoir consulté l’équipe OpenBSD avec Henning Brauer (Merci à Henning !) et fais de plus amples recherches, j’ai décidé de la supprimer car elle ne traite que des cas très spécifiques (veuillez lire la documentation). Vous aurez besoin de la règle scrub seulement si un hôte sur votre réseau génére des paquets fragmentés avec le drapeau “dont-fragment”. Le comportement par défaut de PF sans la règle scrub est mieux adapté à un usage général.

La FAQ d’OpenBSD contient un exemple de paramétrage pour un routeur très basique, avec certaines valeurs spécifiques pour scrub, mais ma recommandation est d’utiliser seulement scrub là où vous savez en avoir besoin. Si vous n’en avez pas besoin, insérez-la dans la configuration après la règle set skip pour l’interface de bouclage locale, tel que :

set skip on lo0
match in all scrub

Et ensuite ajoutez les paramètres à la règle scrub dont vous avez besoin.

J’utilisais aussi la règle antispoof suivante dans la section de protection contre l’usurpation :

antispoof quick for { $g_lan $c_lan $dmz }

J’ai depuis supprimé la règle antispoof puisque la fonctionnalité uRPF (Unicast Reverse Path Forwarding) que PF fournit a la même fonctionnalité, et en tant que tel nous n’en avons plus besoin, à la place nous utilisons juste la règle block in quick from urpf-failed.

L’information suivante à-propos du critère antispoof est gardée à des fins d’éducation.

L’usurpation est lorsque quelqu’un fabrique une adresse IP. Le critère antispoof s’étend à un ensemble de règles de filtrage qui empêcheront tout trafic avec une adresse IP source du réseau (directement connecté à l’interface spécifiée) entrant sur le système par une autre interface. Cela est parfois appelé “bleeding over” ou “bleeding through”.

La directive antispoof est traduite par PF par ce qui suit :

block drop in quick on ! em1 inet from 192.168.1.0/24 to any
block drop in quick inet from 192.168.1.1 to any
block drop in quick on ! em2 inet from 192.168.2.0/24 to any
block drop in quick inet from 192.168.2.1 to any
block drop in quick on ! em3 inet from 192.168.3.0/24 to any
block drop in quick inet from 192.168.3.1 to any

Si nous prenons, e.g., la règle block drop in quick on ! em1 inet from 192.168.1.0/24 to any de l’interface réseau em1 qui signifie alors : bloque tout trafic venant du réseau ayant une adresse IP comprise entre 192.168.1.1 et 192.168.1.255, qui n’est pas originaire depuis l’interface em1 elle-même, et qui va ailleurs. Puisque l’interface em1 est l’interface réseau en charge de toutes les adresses IP dans cet ensemble spécifique, alors aucun trafic avec de telles adresses IP ne pourra être originaire de toute autre interface réseau.

Attention

Ainsi que je l’ai mentionnée, j’ai supprimé la règle antispoof et nous utiliserons à la place la vérification stricte d’uRPF. Lorsqu’un paquet passe dans la vérification d’uRPF, l’adresse IP source du paquet est recherchée dans la table de routage. Si l’interface de sortie est trouvée dans la table de routage et que l’entrée est la même que l’interface du paquet qui vient juste d’entrer, alors la vérification d’uRPF autorise. Autrement, il est possible que le paquet ait son adresse IP source usurpée ainsi il sera bloqué.

Nous allons permettre ICMP dans notre paramétrage, quand bien même des administrateurs réseaux bloquent complètement ICMP. La plupart des personnes bloquent complètement ICMP à cause d’actions injustifiées telles que les attaques par découverte de réseaux, les canaux de communication, le ping sweep, le ping flood, le tunnel d’ICMP, et la redirection d’ICMP. Toutefois, ICMP est bien plus que répondre à des ping. Si nous bloquons complètement ICMP, les diagnostics, la fiabilité, et la performance réseau peuvent être défectueuses puisque des mécanismes importants sont désactivés lorsque le protocole ICMP est restreint.

Voici certaines raisons pour lesquelles ICMP ne devrait pas être bloqué :

  • La découverte Path MTU (PMTUD) est utilisée pour déterminer la taille maximale de l’unité de transmission pour les dispositifs réseau qui relient la source et la destination afin d’éviter la fragmentation IP. TCP dépend des paquets ICMP de type 3 code 4 pour “Path MTU Discovery”. ICMP type 3 code 4 et la taille maximale des paquets sont retournés quand un paquet excède la taille MTU d’un dispositif réseau connecté. Quand les messages ICMP sont bloqués, le système de destination requête continuellement des paquets non délivrés et le système source continue à les renvoyer indéfiniment mais en vain. Ce comportement peut avoir pour résultat un trou noir ICMP (des connexions IP congestionnées et des transmissions cassées).
  • Time to live (TTL) définit le temps de vie d’un paquet de données. Un réseau où ICMP est bloqué ne recevra pas le message de type 11, temps écoulé, code 0, temps écoulé dans le transit des messages d’erreur. Cela signifie que l’hôte source ne sera pas notifié pour augmenter le temps de vie des données afin d’atteindre l’hôte de destination, si le datagram échoue à atteindre l’hôte de destination.
  • Une mauvaise performance du fait de bloquer la redirection ICMP. La redirection ICMP est utilisée par un routeur pour informer un hôte d’un chemin direct entre l’hôte source et celui de destination. Cela réduit le nombre de saut que les données ont à faire pour atteindre la destination. Avec ICMP bloqué, l’hôte ne fera jamais attention à la route la plus optimale vers la destination.

Dans le paramétrage ci-dessus, nous permettons ICMP, mais nous mettons une “limite de taux” du nombre de requêtes ping auxquelles le routeur répondra. Avec le critère max-pkt-rate 100/10, le routeur arrêtera de répondre aux ping si nous en avons plus de 100 en 10 secondes.

Info

Maintenant paramétrons le segment LAN pour les adultes de la maison.

#---------------------------------#
# Paramétrage du réseau LAN adulte
#---------------------------------#

# Autoriser tout ordinateur ou dispositif sur le LAN adulte à envoyer des 
# paquets de données entrants dans l'interface réseau. Cela signifie que 
# tout ordinateur attaché à cette interface réseau peut envoyer des données
# partout, i.e. sur Internet ou tout ordinateur attaché au routeur.
pass in on $g_lan

# Toujours bloquer les requêtes DNS non adressées à notre serveur DNS.
block return in quick on $g_lan proto { udp tcp } to ! $g_lan port { 53 853 }

# J'ai une imprimante réseau et je ne veux pas qu'elle "téléphone maison".
# L'imprimange réseau à l'adresse IP  192.168.1.8.
block in quick on $g_lan from 192.168.1.8

# Autoriser les paquets de données venant du routeur à sortir par l'interface
# réseau vers les ordinateurs et dispositifs attachés à l'interface du 
# réseau Adultes.
# Sans cela nous ne pouvons même pas pingués les ordinateurs attachés à 
# l'interface du réseau Adultes depuis le routeur lui-même.
pass out on $g_lan inet keep state

Dans cet exemple, j’ai une imprimante réseau attachée au réseau des adultes et je ne veux pas qu’elle accéde à Internet ou ailleurs (juste en cas où il y aurait une sorte de micrologiciel espion). Nous le faisons en disant : bloque toutes les données entrantes sur em1 venant de l’adresse IP 192.168.1.8 allant vers toute adresse IP.

De plus, nous nous assurons que toutes les requêtes DNS sur les ports 53 (DNS régulier) et 853 (DNS sur TLS) soient toujours bloquées si elles ne viennent pas de notre serveur DNS.

Info
Info

Le réseau LAN pour les enfants est très similaire.

#---------------------------------#
# Paramétrage LAN enfants
#---------------------------------#

# Autoriser tout PC du LAN Enfant à envoyer des données au-travers du port
# de l'interface réseau
pass in on $c_lan

# Toujours bloquer les requêtes DNS qui ne sont pas adressées à notre 
# serveur DNS.
block return in quick on $c_lan proto { udp tcp} to ! $c_lan port { 53 853 }

# Autorise les paquets de données à passer venant du routeur au-travers 
# l'interface réseau vers les ordinateurs ou dispositifs attachés au 
# LAN Enfants. 
# Sans cela, nous ne pourrions même pas pingués les ordinateurs depuis
# le routeur lui-même
pass out on $c_lan inet keep state

Actuellement les deux réseaux Adultes et Enfants ont le même accès à Internet. Un paramétrage plus restrictif est mentionné dans le chapitre “Liste Blanche pour enfants ”.

Occupons nous alors de la DMZ, i.e. de l’interface réseau qui répond publiquement au serveur web. Puisque nous avons un serveur web publique, nous allons définir un certain nombre de restrictions. Si le serveur web est compromis, l’intrus aura du mal à trouver ce qui est localisé dans notre réseau interne.

Nous bloquons tous les accès excepté le DHCP, afin que le serveur web ait une adresse IP depuis notre routeur, et alors d’ouvrir seulement manuellement certaines choses pour quand nous avons besoin de mettre à jour la machine ou quoi que ce soit d’autres. J’ai commenté les options dont nous avons besoins, quand nous avons besoin de telles choses, laissant les parties restreintes actives. Quand vous aurez besoin de mettre à jour le serveur, ouvrez l’accès DNS et l’accès général à Internet.

Info
#---------------------------------#
# Paramétrage DMZ
#---------------------------------#

# Autorise tout ordinateur ou dispositif attaché à l'interface réseau DMZ
# à obtenir une adresse IP venant du DHCP depuis le routeur
pass in on $dmz inet proto udp from any port 67

# Autorise tout ordinateur ou dispositif attaché à l'interface réseau DMZ
# à faire des requêtes DNS. (décommentez si besoin)
#pass in on $dmz inet proto udp from any port 53

# Toujours bloquer les requêtes DNS non adressées à notre serveur DNS.
block return in quick on $dmz proto { udp tcp} to ! $dmz port { 53 853 }

# Pour autoriser tout ordinateur attaché à l'interface réseau DMZ à accéder
# à Internet, décommentez la ligne ci-dessous. 
# (Cela est pertinent pour les màj)
#pass in on $dmz inet

# No matter what, we do not want the DMZ segment to reach any of the other
# network segments so we explicitly use a block last.
#
# We have several options. If we use this:
#
#   block drop in on $dmz to 192.168/16
#
# Then we block for all subnets, but this also means that the computers
# attached to the DMZ NIC cannot do DNS queries when they need to be upgraded.
#
# In my opinion it is much better to be explicit and block the specific
# segments we want blocked.
#
# Bloque les ordinateurs depuis l'interface réseau DMZ essayant d'atteindre
# les autres sur les deux autres segments réseaux
block drop in on $dmz to { $g_lan:network $c_lan:network }

# En dernier, autorisons les paquets à sortir s'ils viennent de l'interface
# réseau DMZ vers les ordinateurs attachés, autrement pas de "discussion".
# Sans cela nous ne pouvons même pas pinguer les ordinateurs attachés à 
# l'interface réseau DMZ depuis le routeur lui-même
pass out on $dmz inet keep state

Maintenant, occupons nous de la NAT. C’est là où le routeur route les paquets venant d’un segment du réseau vers un autre, dans le cas spécifique venant de notre réseau interne vers Internet, et alors toute réponse venant d’Internet, à destination de l’initiateur de la transmission. Je préfère le paramètre :network qui traduit le(s) réseau(x) attaché(s) à l’interface, et je préfère être spécifique avec une règle pour chaque segment concerné.

#---------------------------------#
# NAT
#---------------------------------#

pass out on $ext_if inet from $g_lan:network to any nat-to ($ext_if)
pass out on $ext_if inet from $c_lan:network to any nat-to ($ext_if)
pass out on $ext_if inet from $dmz:network to any nat-to ($ext_if)

PF gardera une trace de tout le trafic, et quand, e.g. un navigateur web sur le LAN Adultes demandera une page web de certains sites sur Internet, la réponse venant du serveur web depuis Internet sera routé au-travers de l’interface externe vers l’interface interne du LAN Adultes, et alors directement vers le PC qui a initié la requête.

Enfin, occupons-nous de la partie relative à la redirection dans notre jeu de règles. C’est là où nous permettons le trafic venant d’Internet vers notre serveur web publique sur l’interface réseau DMZ. Vous devriez, bien sûr, laisser cette partie si vous n’avez pas de serveurs publiques qui nécessitent de redirection. Dans cet exemple, j’ai seulement permis le trafic IPv4.

#---------------------------------#
# Redirects
#---------------------------------#

# Our web server - let the Internet access it.
pass in on $ext_if inet proto tcp to $ext_if port { 80 443 } rdr-to 192.168.3.2
Attention

C’est tout concernant le paramétrage basique de nos règles filtrantes.

Une liste blanche pour les enfants

Si vous voulez bloquer tout Internet pour les enfants, exceptés peut être quelques sites web ou certains serveurs de jeux, vous avez besoin de connaître quelles adresses IP ces services ont et de créer une liste blanche utilisant ces adresses IP.

Si c’est un simple site web avec une adresse IP unique, c’est très facile et vous pouvez le faire avec cette règle placée en dernier dans le bloc pour enfants (vous devez remplacer la partie x.x.x.x avec l’adresse IP pertinente) :

#---------------------------------#
# Childrens LAN Setup
#---------------------------------#

# Allow any computer or device attached to the childrens NIC to get an IP
# address from DHCP on the router.
pass in on $c_lan inet proto udp from any port 67

# Allow any computer or device attached to the childrens NIC to make DNS
# queries.
pass in on $c_lan inet proto udp from any port 53

# Always block DNS queries not addressed to our DNS server.
block return in quick on $c_lan proto { udp tcp} to ! $c_lan port { 53 853 }

# Then allow any computer or device attached on the childrens LAN to reach
# the IP address x.x.x.x only.
pass in on $c_lan to x.x.x.x

Si le site web a de multiples adresses IP, nous devons comprendre lesquelles. Parfois une requête de nom de domaine peut révéler toutes les adresses IP concernées en une fois. D’autres fois, nous avons besoin de répéter de multiples fois les requêtes à différentes intervalles de la journée avant d’obtenir l’ensemble complet des adresses IP. Vous pouvez faire cela en mettant en place un script automatisé.

Parfois, nous aurons besoin de contacter l’entreprise en question et de demander si nous pouvons avec l’ensemble des adresses IP pour notre liste blanche (certaines compagnies publient publiquement l’information, d’autres refusent de livrer l’information par peur d’un usage malicieux). Une fois que vous avez déterminé quel est l’ensemble d’adresses IP, vous pouvez faire une table PF pour l’utiliser.

Dans cet exemple, nous ajoutons une nouvelle table dans la section table des règles et nous changeons les paramètres des règles pour enfants.

#---------------------------------#
# Tables
#---------------------------------#

…

# Whitelist for the children.
table <whitelist> { x.x.x.x y.y.y.y z.z.z.z }

Et ensuite dans la section pour enfants, changez :

pass in on $c_lan to x.x.x.x

en :

pass in on $c_lan to <whitelist>

Il n’est pas toujours possible d’avoir toutes les adresses IP dans une liste blanche en une fois, mais en surveillant le réseau, en utilisant e.g. tcpdump, quand le jeu essaye d’accéder au serveur, vous pouvez établir une liste, bit après bit. J’ai fait cela avec les serveurs de connexion Mojan et Minecraft et de multiples autres serveurs de jeux.

Utilisation d’une table persistante

Une autre approche pour collecter les IP est d’utiliser une table persistante en combinaison avec /etc/rc.local et les requêtes de noms de domaine. /etc/rc.local est seulement exécuté après que PF soit démarré ainsi les problèmes de résolution de DNS n’entraîneront pas des problèmes pour PF.

Si vous souhaitez utiliser la solution des tables persistantes, vous pouvez le faire en ajoutant une table persistante dans la section des tables dans /etc/pf.conf :

table <whitelist> persist

Dans la section pour enfants, nous avons besoin de passer les données qui viennent de la liste blanche ci-dessus :

pass in on $c_lan to <whitelist>

Alors, dans /etc/rc.local, nous pouvons ajouter la commande suivante :

pfctl -t whitelist -T add example.com

example.com est le domaine que PF doit chercher.

Quand vos enfants ne peuvent pas avoir accès parce que l’adresse IP valide pourrait avoir changé, vous pouvez vous connecter au pare-feu et alors mettre à jour manuellement la table avec plus d’adresses IP en exécutant la commande :

pfctl -t whitelist -T add examples.com

Si vous voulez voir ce qui a été ajouté à cette liste, vous pouvez faire ceci :

# pfctl -t whitelist -T show
74.6.143.25
74.6.143.26
74.6.231.20
74.6.231.21
98.137.11.163
98.137.11.164
216.58.208.110
2001:4998:24:120d::1:0
2001:4998:24:120d::1:1
2001:4998:44:3507::8000
2001:4998:44:3507::8001
2001:4998:124:1507::f000
2001:4998:124:1507::f001
2a00:1450:400e:80e::200e

Éventuellement, vous pouvez ajouter toutes les adresses IP que vous collectez (avant qu’elles ne soient purgées) dans un fichier physique afin que l’option persist prenne en entrée ce fichier, tel que :

table <whitelist> persist file "/etc/pf-whitelist.txt"
Info

Chargement des règles

Une fois que vous avez fini de paramétrer votre jeu de règles, vous pouvez le tester avec :

# pfctl -nf /etc/pf.conf

Si tout est bon, chargez votre jeu de règles en supprimant l’option -n :

# pfctl -f /etc/pf.conf

Regardez le résultat traduit avec :

# pfctl -s rules

Journalisation et Monitoring

Ceci est un exemple de sortie venant du journal de PF des essais bloqués accédant à l’interface externe, selon mon paramétrage. J’ai nettoyé la sortie et supprimé quelques données spécifiques, et bien sûr 0.0.0.0 n’est pas mon adresse IP publique, mais vous savez déjà cela ;)

# tcpdump -n -e -ttt -r /var/log/pflog
23:11:12 rule 14/(match) block in on em0: 45.129.33.4.45980 > 0.0.0.0.3422: S 1501043655:1501043655(0) win 1024
23:11:12 rule 14/(match) block in on em0: 45.129.33.4.45980 > 0.0.0.0.3481: S 311078394:311078394(0) win 1024
23:11:31 rule 14/(match) block in on em0: 176.214.44.229.25197 > 0.0.0.0.23: S 2084440900:2084440900(0) win 33620
23:11:33 rule 14/(match) block in on em0: 45.129.33.4.45980 > 0.0.0.0.3431: S 2774981044:2774981044(0) win 1024
23:11:43 rule 14/(match) block in on em0: 81.68.114.52.17191 > 0.0.0.0.23: S 1346864438:1346864438(0) win 26375
23:12:08 rule 14/(match) block in on em0: 193.27.229.26.53865 > 0.0.0.0.443: S 1057596009:1057596009(0) win 1024
23:12:31 rule 14/(match) block in on em0: 45.129.33.4.45980 > 0.0.0.0.4186: S 1233742605:1233742605(0) win 1024
23:12:44 rule 14/(match) block in on em0: 74.120.14.70.65509 > 0.0.0.0.9125: S 1836577847:1836577847(0) win 1024 <mss 1460> [tos 0x20]
23:12:44 rule 14/(match) block in on em0: 45.129.33.4.45980 > 0.0.0.0.4128: S 2112968453:2112968453(0) win 1024
23:13:15 rule 14/(match) block in on em0: 45.129.33.4.45980 > 0.0.0.0.3669: S 3627248539:3627248539(0) win 1024
23:13:19 rule 14/(match) block in on em0: 45.129.33.4.45980 > 0.0.0.0.3654: S 3889665614:3889665614(0) win 1024
23:13:29 rule 14/(match) block in on em0: 45.129.33.129.42239 > 0.0.0.0.4997: S 2249816896:2249816896(0) win 1024
23:13:37 rule 14/(match) block in on em0: 45.129.33.4.45980 > 0.0.0.0.3612: S 3797528151:3797528151(0) win 1024
23:14:03 rule 14/(match) block in on em0: 190.207.89.17.64372 > 0.0.0.0.445: S 1097568353:1097568353(0) win 8192 <mss 1460,nop,wscale 2,nop,nop,sackOK> (DF)
23:14:15 rule 14/(match) block in on em0: 45.129.33.4.45980 > 0.0.0.0.4219: S 2834775769:2834775769(0) win 1024
23:14:39 rule 14/(match) block in on em0: 45.129.33.4.45980 > 0.0.0.0.3702: S 1855726637:1855726637(0) win 1024
23:14:39 rule 14/(match) block in on em0: 45.129.33.4.45980 > 0.0.0.0.4210: S 3052103070:3052103070(0) win 1024

Comme vous pouvez le voir, il est un peu occupé, d’autant que je n’ai rien en cours d’exécution qui soit publiquement sur Internet dans ce paramétrage.

Vous pouvez aussi monitorer PF en temps réel avec :

# tcpdump -n -e -ttt -i pflog0

DNS

DNS (Domain Name Service) est utilisé pour traduire un nom de domaine dans une adresse IP ou vice-versa. Par exemple, quand vous écrivez wikipedia.org dans la barre d’adresse de votre navigateur web, un serveur DNS faisant autorité traduit le nom de domaine “wikipedia.org” en une adresse IPv4, telle que 91.198.174.192, et/ou une adresse IPv6, telle que 2620:0:862:ed1a::1.

DNS est aussi utilisé, en plus d’autres choses, pour stocker des informations sur les serveurs de messagerie appartenant à un nom de domaine particulier, le cas échéant.

Si vous utilisez un système d’exploitation de type UNIX, vous pouvez démarrer un terminal et essayer de faire une recherche manuelle de nom de domaine avec host :

$ host wikipedia.org
wikipedia.org has address 91.198.174.192
wikipedia.org has IPv6 address 2620:0:862:ed1a::1
wikipedia.org mail is handled by 10 mx1001.wikimedia.org.
wikipedia.org mail is handled by 50 mx2001.wikimedia.org.
Info

La liste qui suit décrit certains des termes associés à DNS :

  • Forward DNS

    • Correspondance des noms d’hôtes ou de domaines avec les adresses IP.
  • Reverse DNS

    • Correspondance des adresses IP avec les noms d’hôtes ou de domaines.
  • Resolver

    • Un système par lequel une machine requiert un serveur de nom pour la zone d’information, i.e. un autre nom pour “Serveur DNS”.
  • Root zone

    • Le début de la hiérarchie des zones Internet. Toutes les zones sont sous la zone racine, similaire à ce que sont tous les fichiers dans un système de fichier sous la hiérarchie racine /.

Ceci est un exemple de zone :

  • . (un point) est la manière dont la zone racine est habituellement référée dans la documentation.
  • org. est le TLD (Top-Level Domain) sous la zone root.
  • wikipedia.org. est la zone sous le TLD org..
  • 1.168.192.in-addr.arpa est la zone référençant toutes les adresses IP qui sont dans l’espace d’adresse IP 192.168.1.*.

Quand un ordinateur sur Internet a besoin de résoudre un nom de domaine, le résolveur découpe le nom dans ses labels de la droite vers la gauche. Le premier composant, le TLD, est demandé en utilisant un serveur racine pour obtenir le serveur faisant autorité responsable. Les requêtes pour chaque label retournent des serveurs de noms plus spécifiques jusqu’à ce qu’un serveur de noms renvoie la réponse à la requête originale.

Même si un serveur DNS local peut implémenter ses propres serveurs de noms racines privés, le terme “serveur racine de noms” est utilisé pour décrire les 13 serveur racines de noms bien connus qui mettent en œuvre le domaine de l’espace racine des noms pour la mise en œuvre mondiale officielle du système de noms de domaine d’Internet. Les résolveurs utilisent un petit fichier nommé root.hints de 3 Ko, publié par Internic pour amorcer cette liste initiale d’adresses des serveurs racines. Pour beaucoup de logiciels, incluant Unbound, cette liste est intégrée à l’intérieur du logiciel.

Sur la base de données de la zone racine, vous pouvez chercher les détails de délégation des domaines TLD, incluant des TLD tels que .com, .org, et des TLD ayant des codes de pays, tels que .uk, .de.

Info

Il y a deux types de configuration de serveur DNS :

  • Autorité

    • [Les serveurs de noms faisant autorité] publie les adresses pour les domaines sous leur contrôle. Ces serveurs sont listés au début de la chaîne d’autorité pour leurs domaines respectifs, et sont capables de fournir une réponse définitive. Les serveurs de noms faisant autorité peuvent être les serveurs de noms primaires, connus aussi en tant que serveurs maîtres, i.e. ils contiennent le jeu original des données, ou être des serveurs de noms secondaires ou esclaves, contenant des copies des données habituellement obtenues par synchronisation directe avec le serveur primaire. Un serveur de nom faisant autorité est un serveur de nom qui donne seulement des réponses aux requêtes DNS venant de données qui ont été configurées par une source originale, par exemple, l’administrateur de domaine. Chaque zone DNS doit être assignée à un ensemble de serveurs de noms faisant autorité. Cet ensemble de serveurs est enregistré dans la zone de domaine parente des enregistrements du serveur de noms (NS). Un serveur faisant autorité indique son statut de fournisseur de réponses définitives, considérées comme faisant autorité, en posant un drapeau de protocole, appelé bit “Authoritative Answer” (AA), dans ses réponses. Vous pouvez utiliser un outil réseau, tel que dig ou drill pour interroger un nom de domaine ; l’outil répondra avec un drapeau faisant autorité qui révèle si le serveur DNS vous avez interrogé est celui qui fait autorité.
  • Récursif

    • Les serveurs récursifs parfois appelés “DNS caches” ou “serveurs de noms de cache seulement” fournissent la résolution de noms DNS pour les applications, en relayant les requêtes de l’application cliente vers la chaîne des serveurs de noms faisant autorité afin de résoudre pleinement un nom de domaine. (Typiquement) ils mettent en cache le résultat pour répondre a de futures requêtes potentielles dans une certaine période de temps avant expiration. La plupart des utilisateurs d’Internet accèdent à un serveur DNS récursif publique fournit par leur FAI ou un fournisseur de service DNS publique. En théorie, les serveurs de noms faisant autorité sont suffisant pour opérer sur Internet. Toutefois, avec seulement les serveurs de noms faisant autorité opérant, chaque requête DNS doit démarrer avec des requêtes successives à la zone racine du système de nom de domaine et chaque utilisateur système devrait avoir à implémenter un logiciel résolveur capable d’opérations de résolution. Pour améliorer l’efficacité, réduire le trafic DNS sur Internet, et augmenter la performance des applications utilisateurs, le système de noms de domaine prend en charge les résolveurs récursifs. Une requête d’un DNS récursif est celle pour laquelle un serveur DNS répond complètement à la requête en interrogeant d’autres serveurs de noms, selon ses besoins.

Un serveur de noms peut être à la fois faisant autorité et récursif, mais il n’est pas recommandé de combiner la configuration des deux types. Pour être en mesure d’effectuer leur travail, les serveurs faisant autorité doivent être disponibles à tous les clients, tout le temps. D’un autre côté, étant donné que la requête récursive prend plus de temps qu’une réponse faisant autorité, les serveurs récursifs devraient être restreints à un nombre de clients seulement, car ils sont enclins à des attaques par déni de service distribué (DDoS).

Info

Je vous présente Unbound

Unbound est un résolveur DNS Open Source récursif, cache et validant avec les fonctionnalités suivantes :

  • Cache avec possibilité de récupèrer des éléments populaires avant qu’ils expirent.
  • Serveur et Redirection DoT (DNS over TLS), avec validation de domaine
  • DoH (DNS over HTTPS)
  • Minimisation du nom de la requête
  • Utilisation aggressive du cache validé par DNSSEC.
  • Zones faisant autorité, pour une copie locale de la zone racine.
  • DNS64
  • DNSCrypt
  • Validation DNSSEC
  • Client de sous-réseau EDNS

Unbound est conçu pour être rapide et sécurisé et incorpore des fonctionnalités modernes basées sur des normes ouvertes. Fin 2019, Unbound a été rigoureusement audité.

Astuce
Attention

Dans notre paramétrage avec Unbound, une requête pour un domaine tel que “wikipedia.org” ressemblera à ceci :

  1. Votre navigateur envoie une requête au système d’exploitation, avec la question “Quelle est l’adresse IP de wikipedia.org ?”
  2. Le système d’exploitation, plus spécifiquement les routines du résolveur dans la bibliothèque C, qui fournit l’accès au Système de Noms de Domaines sur Internet, redirigera la requête DNS vers le(s) serveur(s) de noms de domaine listé dans /etc/resolv.conf (sur des systèmes d’exploitation de type UNIX)
  3. Unbound reçoit la requête et en premier cherche “wikipedia.org” dans son cache et s’il ne le trouve pas, interroge un des serveurs racines listés dans son fichier Root Hints pour le domaine TLD “.org”.
  4. Le serveur racine répond par une référence aux serveurs concernés du domaine TLD “.org”.
  5. Unbound envoie alors une requête à l’un des serveurs concernés demandant quels sont les serveurs DNS faisant autorité pour “wikipedia.org”.
  6. Le serveur répond avec une référence aux serveurs de noms faisant autorité enregistrés pour “wikipedia.org”.
  7. Unbound envoie alors une requête à l’un des serveurs de noms faisant autorité et demande l’adresse IP pour “wikipedia.org”.
  8. Le serveur de noms faisant autorité répond par l’envoi de l’adresse IP listée dans les enregistrements “A” et/ou “AAAA” pour le domaine “wikipedia.org”.
  9. Unbound reçoit l’adresse IP du serveur de noms faisant autorité et retourne la réponse au client.
  10. Si cela est activé, Unbound met en cache alors l’information pour une longueur de temps prédéterminée pour de futures requêtes pour le même nom de domaine.

Vous pouvez essayer de faire une trace DNS par vous-mêmes pour voir le propos ci-dessus. J’utilise drill dans cet exemple avec l’option trace activée.

# drill -T wikipedia.org
.       518400  IN      NS      l.root-servers.net.
.       518400  IN      NS      k.root-servers.net.
.       518400  IN      NS      e.root-servers.net.
.       518400  IN      NS      a.root-servers.net.
.       518400  IN      NS      m.root-servers.net.
.       518400  IN      NS      h.root-servers.net.
.       518400  IN      NS      i.root-servers.net.
.       518400  IN      NS      f.root-servers.net.
.       518400  IN      NS      c.root-servers.net.
.       518400  IN      NS      b.root-servers.net.
.       518400  IN      NS      g.root-servers.net.
.       518400  IN      NS      d.root-servers.net.
.       518400  IN      NS      j.root-servers.net.
org.    172800  IN      NS      a0.org.afilias-nst.info.
org.    172800  IN      NS      a2.org.afilias-nst.info.
org.    172800  IN      NS      b0.org.afilias-nst.org.
org.    172800  IN      NS      b2.org.afilias-nst.org.
org.    172800  IN      NS      c0.org.afilias-nst.info.
org.    172800  IN      NS      d0.org.afilias-nst.org.
wikipedia.org.  86400   IN      NS      ns0.wikimedia.org.
wikipedia.org.  86400   IN      NS      ns1.wikimedia.org.
wikipedia.org.  86400   IN      NS      ns2.wikimedia.org.
wikipedia.org.  600     IN      A       91.198.174.192
Info

Blocage par DNS

Le blocage par DNS, appelé aussi filtrage ou usurpation DNS, est le processus qui vous permet de fournir une “fausse” réponse au client qui effectue la requête. Nous bloquons une requête pour une adresse IP valide soit en répondant avec un NXDOMAIN, signifiant nom de domaine inexistant, ou soit en redirigeant vers une autre adresse IP que celle prévue par le propriétaire du domaine.

Cela nous oblige à créer une liste, ou des listes multiples, de domaines que nous voulons bloquer et plutôt que de fournir à l’utilisateur l’adresse IP correcte pour un certain domaine, nous renvoyons le message que le domaine est “inexistant”, ce qui bloquera toute communication vers la destination prévue pour l’application.

Normalement, toutes les requêtes DNS sont envoyés vers le port 53 soit sur le protocole UDP, soit TCP, lors de la mise en place du serveur DNS, ce que nous faisons avec Unbound, et en s’assurant que tout le trafic du port 53 atteigne notre serveur DNS ou autrement soit bloqué ; nous pouvons nous assurer que toutes les réponses DNS viennent de notre serveur Unbound interne à notre routeur OpenBSD.

Info

NXDOMAIN vs redirection

Quand nous voulons bloquer un domaine en utilisant DNS, nous pouvons choisir entre différentes méthodes, mais les deux plus populaires sont soit de rediriger la requête DNS vers une adresse IP locale, tel que 127.0.0.1 ou 0.0.0.0, ou de répondre par une définition NXDOMAIN. NXDOMAIN est une norme de réponse pour un “nom de domaine Intranet ou Internet non existant”. Si le nom de domaine est incapable d’être résolu en utilisant DNS, une condition appellée NXDOMAIN est obtenue.

Nous pouvons essayer de résoudre un domaine non existant avec la commande host :

$ host a1b7c3n9m3b0.com
Host a1b7c3n9m3b0.com not found: 3(NXDOMAIN)

Puisque le nom de domaine “a1b7c3n9m3b0.com” n’est enregistré par personne (au moins pas durant le temps où j’écris cela), nous obtenons une réponse “NXDOMAIN”.

Nous pouvons aussi utiliser drill. L’information pertinente depuis la sortie de drill est le champ rcode dans la section “HEADER” :

$ drill a1b7c3n9m3b0.com
;; ->>HEADER<<- opcode: QUERY, rcode: NXDOMAIN, id: 39710
…

Ou si vous préférez dig, alors l’information pertinente est localisée dans le champ status dans la section “HEADER” :

$ dig a1b7c3n9m3b0.com

; <<>> DiG 9.16.8 <<>> +search a1b7c3n9m3b0.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 48858
…

Utiliser une réponse NXDOMAIN n’est pas seulement la manière correcte de bloquer un domaine, en accord avec la RFC8020, mais c’est aussi la meilleure manière de le faire puisque une redirection vers une adresse IP, telle que 127.0.0.1 ou 0.0.0.0 fera simplement que le client qui initie la requête DNS se parlera à lui-même.

Il se peut que le navigateur réponde avec quelque chose comme : Firefox can't establish a connection to the server at 0.0.0.0.. Toutefois, puisque l’adresse IP 0.0.0.0 se traduit simplement par notre machine locale, nous pouvons toujours envoyé un ping à cette adresse, car elle est synonyme d’un ping à 127.0.0.1 :

$ ping 0.0.0.0
PING 0.0.0.0 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.019 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.049 ms

Et puisque je recommande que vous utilisiez une réponse NXDOMAIN, c’est ce que nous allons utiliser dans ce tutoriel.

Astuce

Le problème avec DNS sur HTTPS (DOH)

Avec l’introduction de DoH (DNS over HTTPS), le blocage par DNS est devenu beaucoup plus difficile, et, bien que j’ai un certain respect pour l’idée originale derrière la promotion de DoH du point de vue de la confidentialité, DoH est mal construit d’un point de vue de la sécurité, et c’est une MAUVAISE approche.

Avec le nombre déjà croissant de serveurs DNS publiques capable de servir du DNS sur HTTPs, toute application peut maintenant utiliser DoH et contourner complétement le blocage par DNS au niveau privé et entreprise. Non seulement cela, mais DoH a ouvert une large porte pour les dévelopeurs d’application afin de paramétrer leurs propres serveurs DoH et de les utiliser dans leurs applications au lieu du serveur DNS régulier attaché au réseau interne. C’est spécifiquement un problème pour le logiciel propriétaire dont nous ne pouvons pas voir le code source, mais dont nous ne pouvons pas aussi changer les paramétres DoH.

À cause de DoH, nous ne pouvons plus bloquer simplement des domaines, tels que les publicitaires ou le porno, nous devons aussi commencer à bloquer les serveurs DoH publiques via le pare-feu. Toutefois, bien que garder une liste croissante d’un nombre d’adresses IP de serveurs DoH publique soit assez problèmatique, garder une liste de serveurs DoH publiques inconnus, qui peuvent être utilisé par du logiciel propriétaire, tel que du micro-logiciel dans des dispositifs IoT, est impossible.

DoH est aussi un complet cauchemard pour les entreprises car il rend basiquement possible de surpasser les paramétres DNS imposés centralement. Cela rend impossible de fournir des solutions de filtrage, telle que celle que nous faisons, pour bloquer la publicité et le porno, et rend impossible pour les administrateurs systèmes de surveiller les paramétres DNS du système d’exploitation afin de prévenir les attaques de manipulation DNS. Avoir de multiples applications qui ont leur unique paramétre DoH est un cauchemar.

DoH gène complétement l’analyse réseau et la surveillance du trafic DNS à des fins de sécurité. En 2019, Godlua, un bot Linux DDoS, était le premier logiciel malveillant vu à utiliser DoH pour cacher son trafic DNS.

De plus, et c’est peut-être l’aspect le plus important, DoH n’empêche aucunément le suivi des utilisateurs. Certaines parties de la connection HTTPS ne sont pas chiffrées, tels que les champs SNI (mais on y arrive lentement), les connexions OCSP, et bien sûr les adresses IP de destination, ce qui à mon humble avis est le point le plus crucial de la communication qui a besoin d’être caché !

Les personnes qui ont vraiment besoin de confidentialité, tels que les journalistes dans des pays ayant une politique de confidentialité compromise, ne peuvent faire confiance à DoH ! L’adresse IP du serveur de destination ne peut pas être caché avec DoH, même si tout le trafic est lui-même chiffré. Si quelqu’un a vraiment besoin de chiffrer la communication, il a besoin d’une stratégie complétement différente de DoH.

Cela me fait me demander qui a pensé que DoH était une bonne idée au départ ?! Ne comprennent-ils pas les bases derrière les communications avec HTTPS, ou peut-être est-ce l’agenda poussé par quelques entreprises privées de service DNS, tel que Cloudflare, qui tire profit en collectant davantage de données utilisateurs ?

Certains fournisseurs de service DNS publique status que d’un point de vue de la confidentialité, DoH est meilleur que d’autres alternatives, telle DoT (DNS over TLS), puisque les requêtes DNS sont cachées dans le large flux du trafic HTTPS. Cela donne aux administrateurs réseaux moins de visibilité mais fournit aux utilisateurs plus de confidentialité.

Ce message est problématique. Bien qu’il soit vrai que la recherche initiale d’un nom de domaine soit caché dans le trafic HTTPS, l’adresse IP de destination fournit par le serveur DoH ne l’est pas. Quand l’application cliente visite l’adresse IP de destination, les deux adresses IP, celle de source et celle de destination, sont journalisées au niveau du FAI (et possiblement à de multiples autres niveaux, aussi bien).

Bien qu’il ne soit pas immédiatement possible de déterminer exactement quel nom de domaine l’utilisateur essaye d’atteindre, spécifiquement si le serveur web fait fonctionner de multiples domaines sur la même adresse IP, ce n’est définitivement pas impossible voire n’est même pas difficile.

Info

Paramétrage d’Unbound

Paramétrages de base

Paramètrer Unbound est très facile, car Unbound est fourni avec les meilleurs paramètres par défaut, mais est aussi très bien documenté. Avant que nous commencions, je vous recommande de regarder les pages des manuels OpenBSD pour unbound, unbound-checkconf et unbound.conf.

Du fait qu’Unbound soit chrooté sur OpenBSD, le fichier de configuration unbound.conf ne réside pas dans /etc, là où il devrait être normalement, mais à la place réside dans /var/unbound/etc/.

Copiez le fichier de configuration existant d’Unbound :

# mv /var/unbound/etc/unbound.conf /var/unbound/etc/unbound.conf.backup

Ensuite, utilisez votre éditeur texte favori et créer un nouveau fichier /var/unbound/etc/unbound.conf et remplissez-le avec le contenu suivant :

server:

    # Logging (default is no).
    # Uncomment this section if you want to enable logging.
    # Note enabling logging makes the server (significantly) slower.
    # verbosity: 2
    # log-queries: yes
    # log-replies: yes
    # log-tag-queryreply: yes
    # log-local-actions: yes

    interface: 127.0.0.1
    interface: 192.168.1.1
    interface: 192.168.2.1
    interface: 192.168.3.1

    # In case you need Unbound to listen on an alternative port, this is the
    # syntax:
    # interface: 127.0.0.1@5353

    # Control who has access.
    access-control: 0.0.0.0/0 refuse
    access-control: ::0/0 refuse
    access-control: 127.0.0.0/8 allow
    access-control: ::1 allow
    access-control: 192.168.1.0/24 allow
    access-control: 192.168.2.0/24 allow
    access-control: 192.168.3.0/24 allow

    # "id.server" and "hostname.bind" queries are refused.
    hide-identity: yes

    # "version.server" and "version.bind" queries are refused.
    hide-version: yes

    # Cache elements are prefetched before they expire to keep the cache up to date.
    prefetch: yes

    # Our LAN segments.
    private-address: 192.168.0.0/16

    # We want DNSSEC validation.
    auto-trust-anchor-file: "/var/unbound/db/root.key"

# Enable the usage of the unbound-control command.
remote-control:
    control-enable: yes
    control-interface: /var/run/unbound.sock

J’ai commenté les options ci-dessus, mais si vous avez besoin d’explications plus profondes concernant la configuration, regardez la page du manuel unbound.conf.

La journalisation est faite par défaut vers syslog. Si vous voulez changer cela, vous pouvez créer un fichier log dans le chroot d’Unbound et ainsi avoir le journal d’Unbound :

# mkdir /var/unbound/log
# touch /var/unbound/log/unbound.log
# chown -R root._unbound /var/unbound/log
# chmod -R 774 /var/unbound/log

Et, dans le fichier unbound.conf, ajoutez les options suivantes vers la section de journalisation :

logfile: "/log/unbound.log"
use-syslog: no
log-time-ascii: yes
Info

Puis, redémarrez Unbound :

# rcctl restart unbound

Dans les paramétres ci-dessus, j’ai autorisé Unbound à écouter l’interface loopback (127.0.0.1) en premier afin que les applications réseaux locales soient capables de faire des recherches si besoin. Dans le fichier etc/resolv.conf de notre routeur OpenBSD, j’ai listé notre serveur DNS Unbound, car je ne veux rien sur le routeur qui interroge les serveurs DNS du FAI :

nameserver 127.0.0.1

Si vous utilisez DHCP sur l’interface externe (l’interface connecté au modem ou routeur de votre FAI), vous devez vous assurez que dhclient ne change pas la configuration du fichier /etc/resolv.conf. Éditez le fichier /etc/dhclient.conf et ajoutez :

supersede domain-name-servers 127.0.0.1;

Cela permettra de s’assurer que nous avons notre serveur DNS local listé.

Activez Unbound avec :

# rcctl enable unbound

Lorsque vous changez la configuration d’Unbound, vous pouvez soit juste redémarrer Unbound avec :

# rcctl restart unbound

ou simplement recharger les options de configuration (ce qui purge aussi le cache) :

# unbound-control reload

Vous pouvez lister avec quels paramétres Unbound est démarré par la commande suivante (qui est fourni pour tout service sous OpenBSD) :

# rcctl get unbound

Si vous voulez avec certaines statitiques des données, vous pouvez exécuter :

# unbound-control stats_noreset
thread0.num.queries=2056
thread0.num.queries_ip_ratelimited=0
thread0.num.cachehits=678
thread0.num.cachemiss=1378
thread0.num.prefetch=15
thread0.num.expired=0
…

Vous pouvez aussi avoir un dump du cache :

# unbound-control dump_cache|less

Si vous voulez voir quelles sont les requêtes du serveur de nom Unbound fait pour un domaine spécifique, vous pouvez faire cela avec :

# unbound-control lookup wikipedia.org

Si vous voulez purger le cache pour un domaine spécifique, vous pouvez faire cela avec :

# unbound-control flush example.com

Prenez le temps de regarder la page du manuel d’unbound-control pour les autres options et commandes.

Ignorer les réglages TTL ridiculeusement bas

Une chose qui crée une grande nuisance est le paramétrage de certaines personnes sur des valeurs TTL ridiculeusement basses pour leurs domaines. Pour certaines raisons, il est presque tendance d’avoir une valeur par défaut de 60 secondes.

Le problème avec un TTL très bas est que cela rend complétement inutile le DNS cache. Une requête utilisera seulement la réponse en cache aussi longtemps que le TTL ne soit pas expiré. Même au-travers des RFC qui disent qu’un TTL doit être respecté, de telles valeurs basses rend le DNS extrêmement inefficace. Je recommande toutefois que vous surchargiez le paramétrage TTL par celui d’une heure par défaut. Une autre amélioration dans la vitesse de requête de DNS est de réduire la latence en se servant des enregistrements périmés avant de les mettre à jour d’une autre manière au lieu de faire l’inverse.

cache-min-ttl: 3600
serve-expired: yes

Un problème théorique avec l’augmentation du TTL est que le domaine pourrait obtenir une nouvelle adresse IP qui ne peut pas être résolu puisque l’ancienne entrée est dans le cache. Toutefois, dans la pratique le risque de fonctionner sur un domaine périmé est minime et ça vaut la peine d’améliorer l’utilisation du cache en fixant un TTL d’une heure minimum par défaut.

Bloquons certains domaines !

Maintenant, intéressons-nous à la partie du blocage de domaines.

J’ai créé un simple script shell appelé DNSBlockBuster qui télécharge automatiquement un jeu de fichiers hosts depuis diverses sources en-ligne, les concaténant ensemble en une seule, la nettoyant, et convertissant le résultat en une liste de blocage de domaines pour Unbound et dnsmasq. Elle bloque principalement les publicités, les sites de porno et de pistage.

Avec DNSBlockBuster, vous avez l’option de créer une liste blanche, si pour vous l’un des domaines listés dans les fichiers hosts est un faux positif, et vous pouvez ajouter votre propre liste de blocage dans le cas où vous voulez bloquer manuellement certains domaines qui ne sont pas listés dans les fichiers hosts. Vous pouvez facilement ajouter de nouvelles listes de blocage ou supprimer l’une des listes de blocage fournies.

Bien sûr, vous n’avez pas besoin d’utiliser mon script, mais je l’utiliserais dans ce tutoriel.

Actuellement le script créé une énorme liste de domaines avec plus de deux millions de domaines listés et Unbound prend près de 705 Mo de mémoire au total quand la liste de blocage est chargée en entier.

Afin d’éviter qu’Unbound tombe en panne lors du chargement de la liste, éditez /etc/rc.conf.local et ajoutez ce qui suit :

unbound_timeout=240

Puis redémarrez Unbound :

# rcctl restart unbound

Regardez la section Usage dans la documentation de DNSBlockBuster pour savoir comment l’utiliser. C’est simple et facile.

Une fois que vous avez créé votre liste de blocage pour Unbound, placez la dans /var/unbound/etc/ et éditez le fichier de configuration d’Unbound /var/unbound/etc/unbound.conf pour insérer quelque chose comme :

include: "/var/unbound/etc/unbound-blocked-hosts.conf"

Maintenant rechargez Unbound avec :

# unbound-control reload

Si vous exécutez la commande top dans un autre terminal, vous remarquerez qu’Unbound consomme pas mal de ressources CPU lors du chargement initial de la liste. Remarquez aussi la consommation mémoire.

Vous pouvez maintenant tester notre blocage DNS en faisant une requête vers un domaine bloqué de la liste :

$ drill 3lift.com
;; ->>HEADER<<- opcode: QUERY, rcode: NXDOMAIN, id: 55906
…

Essayez le même avec le serveur DNS de Cloudflare :

$ drill 3lift.com @1.1.1.1
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 48771
…

Comme nous pouvons le voir, notre serveur DNS bloque l’accès au domaine 3lift.com en répondant avec un NXDOMAIN, alors que le serveur DNS de Cloudflare répond avec l’adresse IP correcte.

Sécurité DNS

La sécurité DNS est un vaste sujet. Dans cette section, nous allons discuter de certains des sujets qui nous concernent plus particulièrement à propos de notre propre serveur DNS.

Le protocole DNS n’est pas chiffré et ne tient, par défaut, aucun compte de la confidentialité, de l’intégrité ou de l’authentification. Si vous utilisez un réseau non fiable, ou un FAI malveillant, vos requêtes DNS peuvent être écoutées et les réponses manipulées. En outre, les FAI peuvent procéder à des détournements de DNS.

Détournement de DNS

Le détournement de DNS signifie que les requêtes DNS que vous faites sont redirigées vers un autre serveur DNS. C’est typiquement fait en redirigeant tout le trafic sur le port 53 à destination d’un autre.

Un des manières les plus simples pour déterminer si votre FAI détourne votre trafic DNS est d’interroger directement un serveur DNS faisant autorité.

Nous pouvons utiliser de multiples outils pour cela. Dans cet exemple, nous utiliserons en premier drill. Ces options, dans cet exemple, sont les mêmes pour dig. Nous utiliserons encore le domaine “wikipedia.org”.

En premier, nous avons besoin d’avoir les serveurs faisant autorité. Ils apparaîtront dans la section “ANSWER SECTION” :

$ drill NS wikipedia.org
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 28789
;; flags: qr rd ra ; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;; wikipedia.org.       IN      NS

;; ANSWER SECTION:
wikipedia.org.  85948   IN      NS      ns2.wikimedia.org.
wikipedia.org.  85948   IN      NS      ns0.wikimedia.org.
wikipedia.org.  85948   IN      NS      ns1.wikimedia.org.

;; AUTHORITY SECTION:

;; ADDITIONAL SECTION:

;; Query time: 1 msec
;; SERVER: 127.0.0.1
;; WHEN: Thu Nov  5 07:53:19 2020
;; MSG SIZE  rcvd: 95

Alors nous devons interroger l’un de ses serveurs faisant autorité directement. Le champ important auquel nous devons faire attention est flags dans le champ “HEADER”. Pour que la réponse fasse autorité, le drapeau aa doit être listé.

$ drill @ns1.wikimedia.org wikipedia.org
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 57611
;; flags: qr aa rd ; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;; wikipedia.org.       IN      A

;; ANSWER SECTION:
wikipedia.org.  600     IN      A       91.198.174.192

;; AUTHORITY SECTION:

;; ADDITIONAL SECTION:

;; Query time: 127 msec
;; SERVER: 208.80.153.231
;; WHEN: Thu Nov  5 07:56:10 2020
;; MSG SIZE  rcvd: 47

Cela montre que la réponse que nous avons n’a pas été détournée puisque la réponse fait autorité. Essayons de l’obtenir depuis le serveur DNS publique de Cloudflare avec la même requête :

$ drill @1.1.1.1 wikipedia.org
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 40562
;; flags: qr rd ra ; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;; wikipedia.org.       IN      A

;; ANSWER SECTION:
wikipedia.org.  555     IN      A       91.198.174.192

;; AUTHORITY SECTION:

;; ADDITIONAL SECTION:

;; Query time: 3 msec
;; SERVER: 1.1.1.1
;; WHEN: Thu Nov  5 08:02:58 2020
;; MSG SIZE  rcvd: 47

Notez que le drapeau aa est manquant dans le champ “HEADER”. Cela signifie que la réponse ne fait pas autorité.

Un autre outil simple est nslookup. En premier interrogeons les serveurs de noms faisant autorité :

nslookup -querytype=NS wikipedia.org
Server:         127.0.0.1
Address:        127.0.0.1#53

Non-authoritative answer:
wikipedia.org   nameserver = ns1.wikimedia.org.
wikipedia.org   nameserver = ns2.wikimedia.org.
wikipedia.org   nameserver = ns0.wikimedia.org.

Essayons alors d’interroger notre propre serveur DNS pour le domaine :

$ nslookup wikipedia.org
Server:         127.0.0.1
Address:        127.0.0.1#53

Non-authoritative answer:
Name:   wikipedia.org
Address: 91.198.174.192

Server:         ns2.wikimedia.org
Address:        91.198.174.239#53

Name:   wikipedia.org
Address: 91.198.174.192

Le message Non-authoritative montre clairement que la réponse n’est pas faite depuis un serveur DNS faisant autorité. C’est très bien, puisque nous avons interrogé notre propre serveur DNS. Essayons d’interroger un des serveurs faisant autorité directement :

$ nslookup wikipedia.org ns0.wikimedia.org
Server:         ns0.wikimedia.org
Address:        208.80.154.238#53

Name:   wikipedia.org
Address: 91.198.174.192

Le message Non-authoritative n’est plus là, la réponse que nous avons obtenu faisait autorité, ce qui signifie que notre requête DNS n’a pas été détournée.

J’ai maintenant activé un service VPN que je connais pour intercepter les requêtes DNS afin de protéger les clients contre la fuite DNS puis je fais une requête à nouveau vers les serveurs faisant autorité :

$ nslookup wikipedia.org ns0.wikimedia.org
Server:         ns0.wikimedia.org
Address:        208.80.154.238#53

Non-authoritative answer:
Name:   wikipedia.org
Address: 91.198.174.192
Name:   wikipedia.org
Address: 2620:0:862:ed1a::1

Comme attendu la réponse ne fait pas autorité quand bien même j’ai interrogé directement le serveur faisant autorité. Le trafic DNS a été détourné et la réponse a été redirigé depuis un autre serveur DNS inconnu.

Le détournement DNS, qu’il soit effectué par un FAI ou par quelqu’un d’autre, est hautement problèmatique. Tout d’abord, nous ne pouvons avoir pleinement confiance aux réponses que nous obtenons depuis le serveur DNS. En second, même si la réponse DNS fournit des données non falsifiées, le trafic DNS a été détourné pour une raison inconnue, qui peut être de la collecte et de l’enregistrement de données, ou pour une raison complètement différente.

Info
Prévention contre le détournement de DNS

Si vous avez découvert que votre trafic DNS sur le port 53 est détourné, vous avez basiquement seulement trois options afin de vous protéger :

  1. Si cela vous est possible, changez de FAI ! Votre FAI ne devrait pas détourner votre trafic DNS.
  2. Paramétrez votre propre serveur DNS à distance dans un centre d’hébergement qui ne fait pas de détournement ou ne bloque pas le port 53. Ensuite, que votre serveur DNS à distance écoute vos connexions DNS sur un port non standard et rediriger toutes vos requêtes DNS vers votre serveur DNS à distance.
  3. Utilisez un VPN de confiance qui ne détourne pas le trafic DNS, ou s’il le fait, assurez-vous que vous pouvez faire confiance à leur politique de non journalisation.

Usurpation de DNS

L’usurpation de DNS, aussi appelé empoisonnement du cache DNS, est différent du détournement de DNS. Alors que le trafic est redirigé d’une destination vers une autre dans une attaque de détournement de DNS, c’est la donnée elle-même qui est manipulée dans une attaque d’usurpation DNS. Souvent ces deux stratégies d’attaques sont combinées.

Dans une attaque d’usurpation de DNS, la donnée manipulée est introduite dans le cache du résolveur DNS, résultant que le serveur de nom retourne un résultat incorrect, e.g. une mauvaise adresse IP.

Prévention contre l’usurpation de DNS

Ce type d’attaque peut être atténuée au niveau de la couche transport ou de la couche application en effectuant une validation de bout en bout une fois qu’une connexion est établie. Un exemple courant de cela est l’utilisation de TLS et des signatures digitales.

DNSSEC utilise des signatures digitales cryptographiques avec un certificat de clé publique de confiance pour déterminer l’authenticité des données. DNSSEC peut protéger contre l’usurpation de DNS, toutefois beaucoup d’administrateurs DNS ne l’ont pas encore implémenté.

À partir de 2020, tous les TLD originaux prennent en charge DNSSEC, comme le font les TLD de code de pays, mais de nombreux TLD de code de pays ne le font toujours pas.

Appendices

Inspecter DNS sur HTTPS (DOH)

Je veux illustrer le fait que DoH ne fournit pas réellement une véritable confidentialité autant de l’adresse IP source que celle de destination, qui peuvent être vues clairement dans la communication HTTPS.

En premier, je m’assure que DoH soit désactivé dans Firefox, sur un des ordinateurs du LAN pour adultes, et je surveille le trafic sur l’interface em1 par l’utilisation de tcdump. J’ai aussi activé la journalisation dans Unbound, juste pour éviter de remplir inutilement syslog avec trop de bruits DNS, et j’ai utilisé tail pour surveiller le journal.

J’irais sur “wikipedia.org” dans le navigateur et voir ce que révèle la surveillance sur le routeur.

# tcpdump -n -i em1 src host 192.168.1.5 and not arp
tcpdump: listening on em1, link-type EN10MB
23:30:33.494352 192.168.1.5.55724 > 192.168.1.1.53: 58136+ A? wikipedia.org.(31) (DF)
23:30:33.774439 192.168.1.5.58372 > 192.168.1.1.53: 58448+ A? www.wikipedia.org.(35) (DF)
23:30:34.184287 192.168.1.5.46639 > 192.168.1.1.53: 15167+ A? www.wikipedia.org.(35) (DF)
…
# tail -f /var/unbound/log/unbound.log
Nov 05 23:30:33 unbound[12636:0] query: 192.168.1.5 wikipedia.org. A IN
Nov 05 23:30:33 unbound[12636:0] reply: 192.168.1.5 wikipedia.org. A IN NOERROR 0.097209 0 47
Nov 05 23:30:33 unbound[12636:0] query: 192.168.1.5 www.wikipedia.org. A IN
Nov 05 23:30:33 unbound[12636:0] reply: 192.168.1.5 www.wikipedia.org. A IN NOERROR 0.154989 0 80
Nov 05 23:30:34 unbound[12636:0] query: 192.168.1.5 www.wikipedia.org. A IN
Nov 05 23:30:34 unbound[12636:0] reply: 192.168.1.5 www.wikipedia.org. A IN NOERROR 0.000000 1 80
…

Naturellement nous avons vu la requête autant dans le trafic de l’interface que dans le journal d’Unbound.

J’ai activé alors DoH et désactivé le DNS régulier dans Firefox, en paramétrant la valeur de network.trr.mode à 4. J’ai alors changé les paramétres réseaux et paramétré Cloudflare en tant que fournisseur DoH.

Astuce

Cette fois, je visiterais “freebsd.org”.

# tcpdump -n -i em1 src 192.168.1.5 and not arp
tcpdump: listening on em1, link-type EN10MB
00:21:10.944243 192.168.1.5.32856 > 1.1.1.1.443: P 2223446146:2223446202(56) ack 157857007 win 501 (DF)
00:21:10.948719 192.168.1.5.46584 > 96.47.72.84.80: S 922508523:922508523(0) win 64240 <mss 1460,sackOK,timestamp 1673624773 0,nop,wscale 7> (DF)
00:21:11.133801 192.168.1.5.33298 > 96.47.72.84.443: S 3275123911:3275123911(0) win 64240 <mss 1460,sackOK,timestamp 1673624958 0,nop,wscale 7> (DF)
…
# tail -f /var/unbound/log/unbound.log
Nov 05 23:30:33 unbound[12636:0] query: 192.168.1.5 wikipedia.org. A IN
Nov 05 23:30:33 unbound[12636:0] reply: 192.168.1.5 wikipedia.org. A IN NOERROR 0.097209 0 47
Nov 05 23:30:33 unbound[12636:0] query: 192.168.1.5 www.wikipedia.org. A IN
Nov 05 23:30:33 unbound[12636:0] reply: 192.168.1.5 www.wikipedia.org. A IN NOERROR 0.154989 0 80
Nov 05 23:30:34 unbound[12636:0] query: 192.168.1.5 www.wikipedia.org. A IN
Nov 05 23:30:34 unbound[12636:0] reply: 192.168.1.5 www.wikipedia.org. A IN NOERROR 0.000000 1 80
…

Cela révèle, depuis la surveillance de l’interface réseau, qu’une connexion a été faite vers le serveur DNS de Cloudflare à l’adresse 1.1.1.1 sur le port 443 (HTTPS) et que nous avons visité l’adresse IP de destination 96.47.72.84 juste après. Dans le même temps, rien n’est arrivé dans le journal d’Unbound, tail nous montrant juste toujours la requête précédente.

Si nous faisons une requête au DNS régulier sur le serveur, nous pouvons vérifier que l’adresse IP 96.47.72.84 est bien l’adresse IP de “freebsd.org”.

De plus, dans cet exemple spécifique, nous pouvons même accéder au site web de “freebsd.org” en écrivant juste l’adresse IP de destination 96.47.72.84 dans le champ de la barre d’adresse du navigateur.

Cela démontre que même si DoH bypasse la requête d’un DNS régulier, il n’est pas capable de cacher l’adresse IP de destination qui est toujours présente en clair dans le trafic de la communication.

Bloquer DNS sur HTTPS (DOH)

Auparavant, le script DNSBlockBuster comportait certains noms de domaines DoH dans la liste, que j’avais ajouté aléatoirement, mais j’ai depuis supprimé le blocage DoH du serveur DNS, car il faut vraiment que cela soit géré au niveau du pare-feu.

Bloquer DoH via les noms de domaine n’a pas beaucoup de sens à mon humble opinion car un nom de domaine peut être cherché en premier lieu. La plupart des clients qui utilisent DoH ont l’adresse IP de l’hôte du serveur DoH encodé directement dans leur code source.

J’ai cherché sur de multiples sites sur Internet, mais aucun n’a trouvé une simple manière de mettre à jour la liste des serveurs publiques DoH, ainsi j’ai décidé de faire ma propre liste appelée DoHBlockBuster. Toutefois c’est une tâche énorme, dont je sais que je n’aurais pas le temps de tenir à jour à l’avenir, à moins que d’autres personnnes ne s’y mettent ; alors si vous avez du temps libre, aidez à tenir à jour les listes (en faisant une demande de retrait ou en m’envoyant un courriel). En outre, cette liste n’est en aucun cas exhaustive.

Si vous n’utilisez pas IPv6, vous pouvez bloquer tout le trafic IPv6, et utilisez alors seulement la liste IPv4 de DoHBlockBuster. Changez le paramétre pass out, dans la section “Default protect and block” de /etc/pf.conf en pass out inet. C’est la manière pour permettre seulement le trafic IPv4 sortant, sans avoir à bloquer spécifiquement les adresses IPv6 relatives à DoH.

Téléchargez les listes depuis DoHBlockBuster et éditez les selon vos besoins et enregistrez les quelque part sur le disque.

J’ai fait un sous-répertoire à /etc/pf-block-lists où j’ai placé toutes les listes de blocage dont j’ai besoin pour PF.

Créez alors un fichier persistant pour PF dans la section “Tables” de /etc/pf.conf :

# Public DoH servers.
table <block_doh> persist file "/etc/pf-block-lists/dohblockbuster-ipv4.txt"

Si vous avez besoin d’IPv6, ajoutez alors cela aussi :

table <block_doh> persist file "/etc/pf-block-lists/dohblockbuster-ipv4.txt" file "/etc/pf-block-lists/dohblockbuster-ipv6.txt"

Et, alors ajoutez un block à la section “Protect and block by default” du pare-feu :

# Let's block DoH.
block in quick on { $g_lan $c_lan $dmz } to <block_doh>

Rechargez PF :

# pfctl -f /etc/pf.conf

Vérifiez la liste avec :

# pfctl -vvt block_doh -T show

Si - après quelques temps - vous voulez voir quelles adresses IP sont actuellement bloquées, vous pouvez filtrer la sortie :

# pfctl -vvt block_doh -T show | awk '/\[/ {p+=$4; b+=$6} END {print p, b}'

Comme mentionné précédemment, cette solution ne prend pas en considération les serveurs DoH inconnus. De plus afin que la liste soit efficace, elle a besoin d’être tenue à jour.

Ajouter l’option domain-name à DHCP et utiliser un FQDN

Si nous paramétrons notre réseau de telle manière que tous les ordinateurs et dispositifs aient leurs adresses IP fixes et noms d’hôtes, beaucoup d’outils ne fonctionneront pas nativement avec ces noms d’hôtes sans ajouter un nom de domaine au serveur DNS. Cela est dû à des outils tel que host qui s’attend à ce que la recherche vers un nom d’hôte soit un nom de domaine pleinement qualifié (FQDN).

Disons que j’ai paramétré un ordinateur sur mon LAN ayant pour nom d’hôte “foo” et l’adresse IP fixée à 192.168.1.7. Je ne me souviens peut être pas que “foo” est l’ordinateur avec telle adresse, ou je ne me souviens pas quel hôte a l’adresse IP 192.168.1.7 associée.

Avec un FQDN, nous pouvons faire une recherche telle que :

$ host foo.example.com
foo.example.com has address 192.168.1.7

Alors nous pouvons faire :

# host 192.168.1.7
7.1.168.192.in-addr.arpa domain name pointer foo.example.com

Toutefois, il est ennuyeux de devoir écrire le nom de domaine complet à chaque fois. Si nous ajoutons l’option domain-name à /etc/resolv.conf le nom de domaine sera automatiquement ajouté. Ainsi, nous pouvons faire juste cela :

$ host foo
foo.example.com has address 192.168.1.7

Certaines personnes recommandent d’enregistrer un nom de domaine et de l’utiliser en interne sur votre LAN, et bien que ce soit certainement fonctionnel, ce n’est pas intéressant du tout. Pour l’utilisation à la maison, vous pouvez utilisez les TLD .intranet, .home ou .lan, en accord avec la RFC 6762 sans aucun problème. Toutefois, n’utilisez pas .local.

Démarrons en faisant quelques changements dans la configuration de /etc/dhcpd.conf. Juste pour faire simple, j’utiliserais le serveur web de notre LAN publique en exemple, mais vous pouvez étendre cela à tout segment où vous le désirez, et vous pouvez aussi l’utiliser sur plusieurs segments si besoin.

Dans notre paramétrage actuel, nous avons déjà le domaine example.com attaché à notre serveur web ainsi nous pouvons juste l’utiliser. Mais si vous n’avez pas de serveur publique qui a un réel nom de domaine, changez-le juste par quelque chose comme net.home. J’ai changé le nom de notre serveur web par “lilo” (oui, de Lilo & Stitch, parce que c’est plus cool que “Luke” ou “Yoda” !).

subnet 192.168.1.0 netmask 255.255.255.0 {
    option domain-name-servers 192.168.1.1;
    option domain-name "example.com";
    option routers 192.168.1.1;
    range 192.168.1.10 192.168.1.254;
}
subnet 192.168.2.0 netmask 255.255.255.0 {
    option domain-name-servers 192.168.2.1;
    option domain-name "example.com";
    option routers 192.168.2.1;
    range 192.168.2.10 192.168.2.254;
}
subnet 192.168.3.0 netmask 255.255.255.0 {
    option domain-name-servers 192.168.3.1;
    option domain-name "example.com";
    option routers 192.168.3.1;
    range 192.168.3.10 192.168.3.254;
    host lilo.example.com {
        fixed-address 191.168.3.2;
        hardware ethernet 61:20:42:39:61:AF;
        option host-name "lilo";
    }
}

Si vous préférez utiliser de multiples domaines plutôt qu’un seul, dites-vous que example.com est pour votre développement web professionnel, et que net.home pour votre LAN privé, vous pouvez faire une recherche de domaine avec l’option domain-search dans /etc/dhcpd.conf au lieu de l’option domain-name. La différence entre les deux est qu’avec domain-name, seulement un seul domaine est ajouté, alors qu’avec l’option domain-search, de multiples domaines peuvent être ajoutés et sont alors “cherchés” un par un jusqu’à ce que l’hôte soit trouvé.

L’option domain-search ressemble à ceci :

option domain-search "example.com", "net.home"

Alors nous avons besoin de paramétrer Unbound pour gérer nos adresses IP fixes. Dans cet exemple, nous avons seulement le serveur web, mais nous pouvons utiliser autant d’hôtes que nécessaires. Vous pouvez juste éditer le fichier de configuration principale d’Unbound, mais je préfére mettre cela dans un fichier séparé et l’inclure dans le fichier principal. Créez un nouveau fichier appelé tel que /var/unbound/etc/unbound-local.conf, par exemple, et paramétrez vos hôtes :

local-data: "lilo.example.com IN A 192.168.3.2"
local-data-ptr: "192.168.3.2 lilo.example.com"

Ou, si vous utilisez la version net.home :

local-data: "lilo.net.home IN A 192.168.3.2"
local-data-ptr: "192.168.3.2 lilo.net.home"

Notez comment l’adresse IP dans le champ local-data-ptr est retourné, ce qui n’est pas une erreur.

Ajoutez alors ce qui suit à notre /var/unbound/etc/unbound.conf :

private-address: 192.168.0.0/16
private-domain: example.com # Use net.home instead if you need that.
include: "/var/unbound/etc/unbound-local.conf"

Redémarrez dhcpd et Unbound :

# rcctl restart dhcpd
# rcctl restart unbound

Si vous retirez le câble Ethernet de l’un des ordinateurs connectés à l’un des LAN et le connectez à nouveau, vous serez notifié que /etc/resolv.conf a ajouté l’option domain :

domain example.com
nameserver 192.168.1.1

Vous pouvez étendre cet exemple ci-dessus à de multiples domaines et de multiples dans tous les segments.

Ajouter pf-badhost

Lorsque vous avez paramétré votre routeur OpenBSD, je vous encourage fortement à paramétrer pf-badhost !

pf-badhost est un script de sécurité léger fait par Jordan Geoghegan qui bloque les plus grandes choses irritantes d’Internet. Les désagréments tels les brute-forceurs SSH et SMTP sont largement éliminés par ce script.

pf-badhost ajoute périodiqument des addresses IP depuis des bases de données de spammeurs d’IP bien connus, tel Spamhaus, Firehol, Emerging Threats and Binary Defense, où ces mauvaises adressses IP sont fréquemment journalisées. pf-badhost les ajoute alors aux adresses IP collectées vers le pare-feu PF dans une table qui est bloquée par défaut.

Lectures recommandées

Comment contribuer à ce guide ?

Veuillez considérer de contribuer si vous avez n’importe quel commentaire, correction, ou changement que vous considéré comme approprié.

  • Faites un clone sur Github
  • Soumettez un PR pour examen

Vous pouvez aussi juste envoyer un courriel.

Traductions de ce guide

Veuillez noter que les traductions listées ici sont commitées par d’autres personnes contribuant généreusement à ce guide. De fait, je ne suis pas responsable de garder à jour ces traductions.


Créé et maintenu par

Unix Sheikh

Le Guide du Routeur OpenBSD est sous licence Creative Commons Attribution 4.0 International.

Si vous trouvez ce contenu utile, soutenez-moi sur Patreon.


Contribuer à la version FR

Cette version traduite du Guide du Routeur OpenBSD est faite par mes soins.

Vous pouvez contribuer au-travers de mon dépôt Framagit.org.

Par facilité, cette traduction est placée aussi sous licence Creative Commons Attribution 4.0 International.

Vous pouvez soutenir mon effort de traduction en me payant un bon café à l'italienne comme je les <3 … :D