# Le pare-feux Il nous faut installer un pare-feux sur notre raspi pour éviter les intrusions. Nous allons limiter les machines susceptibles de se connecter à celles de notre réseau local, et également limiter les ports accessibles sur notre réseau. Nous allons utiliser NFTables et Firewalld. **Note**: je n'ai jamais utilisé ces programmes. Ce sera l'occasion de les découvrir! ## Installation de nftables pi@piras:~ $ sudo apt install nftables ## Test pi@piras:~ $ sudo nft list ruleset ip table ip filter { chain INPUT { type filter hook input priority 0; policy accept; } chain FORWARD { type filter hook forward priority 0; policy accept; } chain OUTPUT { type filter hook output priority 0; policy accept; } } pi@piras:~ $ ça marche ... ## Installation de Firewalld pi@piras:~ $ sudo apt install firewalld Test du fonctionnement: pi@piras:~ $ sudo systemctl status firewalld ● firewalld.service - firewalld - dynamic firewall daemon Loaded: loaded (/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled) Active: active (running) since Sat 2020-12-12 18:28:00 CET; 19min ago Docs: man:firewalld(1) Main PID: 3552 (firewalld) CGroup: /system.slice/firewalld.service └─3552 /usr/bin/python3 /usr/sbin/firewalld --nofork --nopid déc. 12 18:27:47 piras systemd[1]: Starting firewalld - dynamic firewall daemon... déc. 12 18:28:00 piras systemd[1]: Started firewalld - dynamic firewall daemon. pi@piras:~ $ sudo firewall-cmd --state running pi@piras:~ $ Tout marche. ## Configuration de Firewalld D'abord, il faut comprendre comment fonctionne Firewalld. Je me suis basé sur les sites suivants: * [lw.net](https://lwn.net/Articles/484506/) * [How to get started with Firewalld](https://www.certdepot.net/rhel7-get-started-firewalld/) * [tutorial points](https://www.tutorialspoint.com/network_security/network_security_firewalls.htm) * [la documentation officielle](https://firewalld.org/documentation/zone/predefined-zones.html) * [introduction-to-firewalld](https://linuxconfig.org/introduction-to-firewalld-and-firewall-cmd-command-on-linux) * [La documentation de Fedora](https://doc.fedora-fr.org/wiki/Parefeu_-_firewall_-_FirewallD) * [it connect](https://www.it-connect.fr/centos-7-utilisation-et-configuration-de-firewalld/) La documentation de Fedora est la plus compréhensible. ### La notion de zones Firewalld défnit 9 zones qui sont en fait des règles de pare-feux par défaut. Une zone va par exemple bloquer toute entrée sauf SSH, une autre permettre l'accès en HTTP et HTTPS. Ces zones correspondent à des utilisations types, comme un serveur dans une DMZ, ou un serveur **chez soi**, un serveur public etc. On peut imaginer une zone **émail** qui ne laisserait passer que les ports spécifiques à l'émail et DNS bien sûr. Il est possible de créer des zones personnelles. Un certain nombre de zones sont prédéfinies. Voyons leur contenu. ### Les différentes zones Les différentes zones sont: * trusted: non modifiable * home: modifiable * work: modifiable * internal: modifiable * dmz: modifiable * public: modifiable * external: modifiable * block: non modifiable * drop: non modifiable Une très bonne présentation des zones est ici: [it connect](https://www.it-connect.fr/centos-7-utilisation-et-configuration-de-firewalld/) ### Les fichiers de configuration Ils ont situés à 2 endroits: * /usr/lib/firewalld/ : il ne faut pas toucher au contenu de ce répertoire * /etc/firewalld/: c'est là que nous mettrons notre configuration, en copiant les fichiers de /usr/lib/firewalld si besoin est. Dans le répertoire /etc/firewalld, le fichier firewalld.conf permet de configurer la zone par défaut, ainsi que le backtend à ipfilter. Tout à la fin du fichier de configuration, le FirewallBackend est mis à **iptables**. Comme nous utiliserons nftables, il faudra modifier cette option. Cela est explicite dans le fichier. FirewallBackend=nftables La zone par défaut est **public**: pas de confiance, mais possibilité d'ajuster au cas par cas les règles. ### Quelques commandes * Démarrer Firewalld:**$ sudo systemctl start firewalld** * Stopper Fireawalld:**$ sudo systemctl stop firewalld** * Tester le fonctionnement de Firewalld:**$ sudo firewall-cmd --state** * Connaître les zones prédéfinies: **$ sudo firewall-cmd --get-zones** * Connaître la zone par défaut:**$ sudo firewall-cmd --get-default-zone** * Connaître la zone active:**$ sudo firewall-cmd --get-active-zones** Exemples: pi@piras:~ $ sudo firewall-cmd --state running pi@piras:~ $ Le service tourne. pi@piras:~ $ sudo firewall-cmd --get-default-zone public pi@piras:~ $ La zone par défaut est: public pi@piras:~ $ sudo firewall-cmd --get-zones block dmz drop external home internal public trusted work pi@piras:~ $ Les zones prédéfinies sont: **block dmz drop external home internal public trusted work** Quelle est la zone active: aucune! pi@piras:~ $ sudo firewall-cmd --get-active-zones pi@piras:~ $ Nous pouvons vérifier la zone en fonctionnement et l'interface réseau qui y est attachée: pi@piras:~ $ sudo firewall-cmd --list-all public target: default icmp-block-inversion: no interfaces: sources: services: dhcpv6-client ssh ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: pi@piras:~ $ Aucune interface n'est attachée. Les seuls services autorisé sont: dhcp et ssh. ### Première étape de configuration Nous allons utiliser les commandes en ligne de commande pour configurer Firewalld, mais il existe une GUI pour le faire graphiquement. Référez-vous aux liens que j'ai indiqués au-dessus. * Définition de la zone par défaut: (public) pi@piras:~ $ sudo firewall-cmd --set-default-zone=public Warning: ZONE_ALREADY_SET: public success pi@piras:~ $ * Attribution de l'interface réseau à cette zone: pi@piras:~ $ sudo firewall-cmd --zone=public --change-interface=eth0 success pi@piras:~ $ Attention, ce changement n'est pas permanent! (voir ci-dessous) * Test: pi@piras:~ $ sudo firewall-cmd --list-all public (active) target: default icmp-block-inversion: no interfaces: eth0 sources: services: dhcpv6-client ssh ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: pi@piras:~ $ Nous voyons que l'interface **eth0** a bien été attribuée à la zone **public**. ### Les services Il est possible de configurer les serviecs accessibles (ou pas) attribués à la zone active. Pour connaître les différents services disponibles, tapez la commande suivante: pi@piras:~ $ sudo firewall-cmd --get-services RH-Satellite-6 amanda-client amanda-k5-client amqp amqps apcupsd audit bacula bacula-client bgp bitcoin bitcoin-rpc bitcoin-testnet bitcoin-testnet-rpc ceph ceph-mon cfengine cockpit condor-collector ctdb dhcp dhcpv6 dhcpv6-client distcc dns docker-registry docker-swarm dropbox-lansync elasticsearch etcd-client etcd-server finger freeipa-ldap freeipa-ldaps freeipa-replication freeipa-trust ftp ganglia-client ganglia-master git gre high-availability http https imap imaps ipp ipp-client ipsec irc ircs iscsi-target isns jenkins kadmin kerberos kibana klogin kpasswd kprop kshell ldap ldaps libvirt libvirt-tls lightning-network llmnr managesieve matrix mdns minidlna mongodb mosh mountd mqtt mqtt-tls ms-wbt mssql murmur mysql nfs nfs3 nmea-0183 nrpe ntp nut openvpn ovirt-imageio ovirt-storageconsole ovirt-vmconsole plex pmcd pmproxy pmwebapi pmwebapis pop3 pop3s postgresql privoxy proxy-dhcp ptp pulseaudio puppetmaster quassel radius redis rpc-bind rsh rsyncd rtsp salt-master samba samba-client samba-dc sane sip sips slp smtp smtp-submission smtps snmp snmptrap spideroak-lansync squid ssh steam-streaming svdrp svn syncthing syncthing-gui synergy syslog syslog-tls telnet tftp tftp-client tinc tor-socks transmission-client upnp-client vdsm vnc-server wbem-http wbem-https wsman wsmans xdmcp xmpp-bosh xmpp-client xmpp-local xmpp-server zabbix-agent zabbix-server pi@piras:~ $ Chaque détail des services est détaillé dans un fichier xml dans /usr/lib/firewalld. Voyons quels services sont acuellemnt activés sur notre raspi: pi@piras:~ $ ss -t -u -l -a Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port udp UNCONN 0 0 0.0.0.0:55853 0.0.0.0:* udp UNCONN 0 0 127.0.0.1:domain 0.0.0.0:* udp UNCONN 0 0 0.0.0.0:bootpc 0.0.0.0:* udp UNCONN 0 0 0.0.0.0:mdns 0.0.0.0:* udp UNCONN 0 0 [::1]:domain *:* udp UNCONN 0 0 *:59578 *:* udp UNCONN 0 0 *:mdns *:* tcp LISTEN 0 511 127.0.0.1:domain-s 0.0.0.0:* tcp LISTEN 0 511 127.0.0.1:domain 0.0.0.0:* tcp LISTEN 0 128 0.0.0.0:ssh 0.0.0.0:* tcp ESTAB 0 0 192.168.111.170:ssh 192.168.111.150:59092 tcp LISTEN 0 511 [::1]:domain-s [::]:* tcp LISTEN 0 511 [::1]:domain [::]:* tcp LISTEN 0 128 [::]:ssh [::]:* pi@piras:~ $ Nous voyons notre connexion **ssh** établie entre mon desktop en ip 192.168.111.150 et piras 192.168.111.170. Notre raspi écoute également le port 22 sur toutes les interfaces présentes. Liste des ports en écoute (TCP): pi@piras:~ $ ss -ltn State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 511 127.0.0.1:853 0.0.0.0:* LISTEN 0 511 127.0.0.1:53 0.0.0.0:* LISTEN 0 128 0.0.0.0:22 0.0.0.0:* LISTEN 0 511 [::1]:853 [::]:* LISTEN 0 511 [::1]:53 [::]:* LISTEN 0 128 [::]:22 [::]:* pi@piras:~ $ les ports 22 (ssh) , 53 (dns) , 853 (dns) sont à l'écoute en IPV4 et IPV6. Liste des ports en écoute (UDP): pi@piras:~ $ ss -lun State Recv-Q Send-Q Local Address:Port Peer Address:Port UNCONN 0 0 0.0.0.0:55853 0.0.0.0:* UNCONN 0 0 127.0.0.1:53 0.0.0.0:* UNCONN 0 0 0.0.0.0:68 0.0.0.0:* UNCONN 0 0 0.0.0.0:5353 0.0.0.0:* UNCONN 0 0 [::1]:53 *:* UNCONN 0 0 *:59578 *:* UNCONN 0 0 *:5353 *:* pi@piras:~ $ ### Etat des lieux Vérifions le fonctionnement de Firewalld. Souvenez-vous qu'il était configuré pour fonctionner avec Iptables. Vérifions les règles établies: pi@piras:~ $ sudo iptables -L Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED ACCEPT all -- anywhere anywhere INPUT_direct all -- anywhere anywhere INPUT_ZONES_SOURCE all -- anywhere anywhere INPUT_ZONES all -- anywhere anywhere DROP all -- anywhere anywhere ctstate INVALID REJECT all -- anywhere anywhere reject-with icmp-host-prohibited Chain FORWARD (policy ACCEPT) target prot opt source destination ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED ACCEPT all -- anywhere anywhere FORWARD_direct all -- anywhere anywhere FORWARD_IN_ZONES_SOURCE all -- anywhere anywhere FORWARD_IN_ZONES all -- anywhere anywhere FORWARD_OUT_ZONES_SOURCE all -- anywhere anywhere FORWARD_OUT_ZONES all -- anywhere anywhere DROP all -- anywhere anywhere ctstate INVALID REJECT all -- anywhere anywhere reject-with icmp-host-prohibited Chain OUTPUT (policy ACCEPT) target prot opt source destination OUTPUT_direct all -- anywhere anywhere Chain INPUT_direct (1 references) target prot opt source destination Chain INPUT_ZONES_SOURCE (1 references) target prot opt source destination Chain INPUT_ZONES (1 references) target prot opt source destination IN_public all -- anywhere anywhere [goto] IN_public all -- anywhere anywhere [goto] Chain FORWARD_direct (1 references) target prot opt source destination Chain FORWARD_IN_ZONES_SOURCE (1 references) target prot opt source destination Chain FORWARD_IN_ZONES (1 references) target prot opt source destination FWDI_public all -- anywhere anywhere [goto] FWDI_public all -- anywhere anywhere [goto] Chain FORWARD_OUT_ZONES_SOURCE (1 references) target prot opt source destination Chain FORWARD_OUT_ZONES (1 references) target prot opt source destination FWDO_public all -- anywhere anywhere [goto] FWDO_public all -- anywhere anywhere [goto] Chain OUTPUT_direct (1 references) target prot opt source destination Chain IN_public (2 references) target prot opt source destination IN_public_log all -- anywhere anywhere IN_public_deny all -- anywhere anywhere IN_public_allow all -- anywhere anywhere ACCEPT icmp -- anywhere anywhere Chain IN_public_log (1 references) target prot opt source destination Chain IN_public_deny (1 references) target prot opt source destination Chain IN_public_allow (1 references) target prot opt source destination ACCEPT tcp -- anywhere anywhere tcp dpt:ssh ctstate NEW,UNTRACKED Chain FWDI_public (2 references) target prot opt source destination FWDI_public_log all -- anywhere anywhere FWDI_public_deny all -- anywhere anywhere FWDI_public_allow all -- anywhere anywhere ACCEPT icmp -- anywhere anywhere Chain FWDI_public_log (1 references) target prot opt source destination Chain FWDI_public_deny (1 references) target prot opt source destination Chain FWDI_public_allow (1 references) target prot opt source destination Chain FWDO_public (2 references) target prot opt source destination FWDO_public_log all -- anywhere anywhere FWDO_public_deny all -- anywhere anywhere FWDO_public_allow all -- anywhere anywhere Chain FWDO_public_log (1 references) target prot opt source destination Chain FWDO_public_deny (1 references) target prot opt source destination Chain FWDO_public_allow (1 references) target prot opt source destination pi@piras:~ $ Les règles Iptables ont bien été configurées par Firewalld. Modifions le fichier de configuration pour l'utilisation de nftables (fichier /etc/firewalld/firewalld.conf, tout à la fin) Et rebootons notre raspi. * Test de iptables: les tables doivent être vides maintenant. pi@piras:~ $ sudo iptables -L Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination pi@piras:~ $ * Test de nftables: les tables doivent être configurées. pi@piras:~ $ sudo nft list table filter table ip filter { chain INPUT { type filter hook input priority 0; policy accept; } chain FORWARD { type filter hook forward priority 0; policy accept; } chain OUTPUT { type filter hook output priority 0; policy accept; } } pi@piras:~ $ sudo firewall-cmd --list-all public target: default icmp-block-inversion: no interfaces: sources: services: dhcpv6-client ssh ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: pi@piras:~ $ Nous voyons que rien n'a été conservé, et que les tables nftables sont vides ... ça marchait bien avec iptables ... peut-être est-ce pour ça qu'ils ont configuré le backend à iptables? Il va falloir investiguer ... Bien: voilà la procédure à suivre: 1. sudo firewall-cmd --permanent --zone=public --change-interface=eth0 Permet de changer de façon permanente l'interface associée à la zone **public**. Test: pi@piras:~ $ sudo firewall-cmd --permanent --zone=public --change-interface=eth0 success pi@piras:~ $ ls -l /etc/firewalld/ ls: impossible d'ouvrir le répertoire '/etc/firewalld/': Permission non accordée pi@piras:~ $ sudo ls -l /etc/firewalld/ total 28 -rw-r--r-- 1 root root 2190 déc. 13 12:45 firewalld.conf drwxr-xr-x 2 root root 4096 févr. 1 2019 helpers drwxr-xr-x 2 root root 4096 févr. 1 2019 icmptypes drwxr-xr-x 2 root root 4096 févr. 1 2019 ipsets -rw-r--r-- 1 root root 272 févr. 1 2019 lockdown-whitelist.xml drwxr-xr-x 2 root root 4096 févr. 1 2019 services drwxr-xr-x 2 root root 4096 déc. 13 15:43 zones pi@piras:~ $ sudo ls -l /etc/firewalld/zones total 4 -rw-r--r-- 1 root root 342 déc. 13 15:43 public.xml pi@piras:~ $ sudo cat /etc/firewalld/zones/public.xml Public For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted. pi@piras:~ $ Nous voyons que firewalld a créé des répertoires et un fichier dans le répertoire **zones** dont le contenu correspond à ce que nous avons demandé. Le fichier a été créé, mais si on teste, on voit que l'option n'est pas active. pi@piras:~ $ sudo firewall-cmd --get-active-zones pi@piras:~ $ sudo firewall-cmd --list-all public target: default icmp-block-inversion: no interfaces: sources: services: dhcpv6-client ssh ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: pi@piras:~ $ 2. sudo firewall-cmd --zone=public --change-interface=eth0 Permet de changer l'interface de la zone public d'une façon non-permanente. pi@piras:~ $ sudo firewall-cmd --zone=public --change-interface=eth0 success pi@piras:~ $ sudo firewall-cmd --list-all public (active) target: default icmp-block-inversion: no interfaces: eth0 sources: services: dhcpv6-client ssh ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: pi@piras:~ $ 3. Test après reboot Cette fois-ci, ça marche! (Yes!) pi@piras:~ $ sudo firewall-cmd --list-all public (active) target: default icmp-block-inversion: no interfaces: eth0 sources: services: dhcpv6-client ssh ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: pi@piras:~ $ ### Ajout d'un protocole Nous allons ajouter le service **http** à notre zone. Pour commencer, Ajoutons le serveur web **apache**. Tout d'abord, mise à jour du système, suppression des archives des paquets, installation de apache2 et reboot. sudo apt update && sudo apt upgrade && sudo apt clean && sudo apt install apache2 && sudo systemctl reboot * Nous allons tester à partir du raspi le fonctionnement de apache: pi@piras:~ $ ps aux | grep apache root 424 0.0 2.1 7284 3900 ? Ss 17:18 0:00 /usr/sbin/apache2 -k start www-data 426 0.0 2.0 230832 3712 ? Sl 17:18 0:00 /usr/sbin/apache2 -k start www-data 427 0.0 2.0 230832 3712 ? Sl 17:18 0:00 /usr/sbin/apache2 -k start pi 750 0.0 1.1 7352 2028 pts/0 S+ 17:19 0:00 grep --color=auto apache pi@piras:~ $ Apache tourne. pi@piras:~ $ wget 127.0.0.1:80 --2020-12-13 17:21:01-- http://127.0.0.1/ Connexion à 127.0.0.1:80… connecté. requête HTTP transmise, en attente de la réponse… 200 OK Taille : 10701 (10K) [text/html] Sauvegarde en : « index.html » index.html 100%[====================================================================>] 10,45K --.-KB/s ds 0,001s 2020-12-13 17:21:01 (14,6 MB/s) — « index.html » sauvegardé [10701/10701] pi@piras:~ $ On accède à la page d'accueil. * Puis essayer de se connecter à partir du desktop au raspi (en http): Firefox ne peut établir de connexion avec le serveur à l’adresse piras.yojik.net. Evidemment, on ne peut pas accéder au serveur http du raspi: * Entrons les commandes qui permettent d'ouvrir les ports http et https en IPV4 et IPV6 et de rendre ces règles permanentes: pi@piras:~ $ sudo firewall-cmd --permanent --zone=public --add-service={http,https} success pi@piras:~ $ pi@piras:~ $ sudo firewall-cmd --zone=public --add-service={http,https} success pi@piras:~ $ Vérifions que nos nouvelles règles ont bien été enregistrées. pi@piras:~ $ sudo firewall-cmd --list-all public (active) target: default icmp-block-inversion: no interfaces: eth0 sources: services: dhcpv6-client http https ssh ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: pi@piras:~ $ Elles ont bien été prises en compte. * Testons à nouveau: cette fois-ci nous devrions pouvoir accéder au serveur apache à partir du desktop (machine cliente): La page d'accueil de Débian s'affiche (notez l'adresse du raspi comme on l'a configurée dans une étape précédente!) ![Page d'acceuil de Debian](Images/Capture d’écran de 2020-12-13 17-30-28.png)