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 IPtables et Firewalld.
J'aurai préféré utiliser nftables qui est le successeur de iptables, mais j'ai eu quelques soucis à l'utilisation. Peut-être est-ce pour ça que la distribution RaspiOS a configuré firewalld avec IPtables...
IPtables est installé par défaut: rien à faire ici.
Si on tape:
pi@raspberrypi:~ $ 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@raspberrypi:~ $
On voit que c'est iptables qui a été chosi par RaspiOS.
D'abord, il faut comprendre comment fonctionne Firewalld. Je me suis basé sur les sites suivants:
La documentation de Fedora est la plus compréhensible.
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 sont:
Une très bonne présentation des zones est ici: it connect
Ils ont situés à 2 endroits:
Dans le répertoire /etc/firewalld, le fichier firewalld.conf permet de configurer la zone par défaut, ainsi que le backtend (iptables, nftables et autre).
La zone par défaut est public: pas de confiance, mais possibilité d'ajuster au cas par cas les règles. Le seul accès auorisé est l'accès ssh et dhcp.
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.
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.
Il est possible de configurer les services 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 acuellement 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:~ $
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.
Après reboot, nous voyons que rien n'a été conservé!
Il va falloir investiguer ...
Bien: voilà la procédure à suivre:
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:~ $ sudo cat /etc/firewalld/zones/public.xml
<?xml version="1.0" encoding="utf-8"?>
<zone>
<short>Public</short>
<description>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.</description>
<interface name="eth0"/>
<service name="ssh"/>
<service name="dhcpv6-client"/>
</zone>
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é.
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:~ $
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:~ $
Nous verrons ensuite comment ajouter des règles suivant les services que nous voudrons déployer.