370 lines
15 KiB
Markdown
370 lines
15 KiB
Markdown
---
|
|
categories: linux network firewall minifirewall
|
|
title: Howto netfilter
|
|
...
|
|
|
|
* Documentation : <https://netfilter.org/documentation/>
|
|
|
|
[netfilter](https://netfilter.org/) est la couche de firewalling sous Linux, contrôlable via les commandes `iptables` et `ip6tables`, ou plus récemment avec la commande `nft` (que nous n'utilisons pas encore). Sur les serveurs, nous utilisons notre script [minifirewall](https://gitea.evolix.org/evolix/minifirewall/) permettant une gestion simple d'un firewall local.
|
|
|
|
## Installation
|
|
|
|
~~~
|
|
# apt install iptables
|
|
~~~
|
|
|
|
~~~
|
|
# iptables --version
|
|
iptables v1.8.9 (nf_tables)
|
|
|
|
# modinfo iptable_filter
|
|
filename: /lib/modules/6.1.0-18-cloud-amd64/kernel/net/ipv4/netfilter/iptable_filter.ko
|
|
description: iptables filter table
|
|
author: Netfilter Core Team <coreteam@netfilter.org>
|
|
license: GPL
|
|
depends: ip_tables,x_tables
|
|
retpoline: Y
|
|
intree: Y
|
|
name: iptable_filter
|
|
vermagic: 6.1.0-18-cloud-amd64 SMP preempt mod_unload modversions
|
|
sig_id: PKCS#7
|
|
signer: Debian Secure Boot CA
|
|
sig_key: 32:A0:28:7F:84:1A:03:6F:A3:93:C1:E0:65:C4:3A:E6:B2:42:26:43
|
|
sig_hashalgo: sha256
|
|
signature: 71:F7:F9:B6:38:B0:B8:63:41:D6:DA:39:41:2B:AD:EB:E4:5A:05:36:
|
|
AF:9E:55:6F:CF:39:E2:D9:CD:23:7B:49:B0:C6:4D:BE:1F:A5:68:F2:
|
|
6D:EA:88:A1:CD:B5:4F:CE:3B:A2:10:3D:74:E7:DB:29:31:00:AF:81:
|
|
CD:EA:31:BC:6D:68:F2:5B:1B:3B:85:6E:2C:52:B5:B7:14:44:62:C8:
|
|
B9:2F:89:5A:E0:3A:9B:D9:89:48:A0:E1:F3:92:B7:B8:C2:C2:F4:6D:
|
|
34:95:4D:0A:2F:15:E9:F4:1D:3B:07:49:7B:8C:AB:56:58:18:C8:8D:
|
|
67:70:D7:D5:60:07:33:86:39:DA:5A:D0:6C:F3:37:F4:0A:84:A9:AF:
|
|
FE:AC:8F:ED:C9:CA:C6:A6:DA:4B:23:AA:4F:7D:F0:37:90:AF:1C:EC:
|
|
73:F7:71:E2:50:42:48:0D:8A:7D:61:D4:F3:E2:FC:77:CF:96:0F:4D:
|
|
96:7D:85:A2:EC:7D:A9:A6:2E:41:58:DB:B3:72:A2:02:39:6C:B9:6A:
|
|
02:47:F2:DB:9B:AD:77:D9:04:8E:F8:42:D4:BA:40:D1:CE:3D:36:CB:
|
|
4B:18:C6:CC:4A:09:4A:7C:95:AF:4B:8B:04:83:13:3A:6C:DA:A0:BD:
|
|
CB:D9:74:5E:8C:76:CF:03:CB:D2:E5:4B:F4:10:FB:E5
|
|
parm: forward:bool
|
|
~~~
|
|
|
|
|
|
## Utilisation basique
|
|
|
|
Lister les règles dans les 3 tables filter/nat/mangle :
|
|
|
|
~~~
|
|
# iptables -L -nvt filter --line-number
|
|
# iptables -L -nvt nat --line-number
|
|
# iptables -L -nvt mangle --line-number
|
|
# ip6tables -L -nvt filter --line-number
|
|
# ip6tables -L -nvt nat --line-number
|
|
# ip6tables -L -nvt mangle --line-number
|
|
~~~
|
|
|
|
Interdire toutes les connexions venant de l'IP 192.0.2.66 :
|
|
|
|
~~~
|
|
# iptables -I INPUT -s 192.0.2.66 -j DROP
|
|
~~~
|
|
|
|
Renvoyer les connexions extérieures vers un port à un autre port (avec 192.0.2.42 l'IP du serveur local) :
|
|
|
|
~~~
|
|
/sbin/iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to 192.0.2.42:22
|
|
~~~
|
|
|
|
Désactiver toutes les règles et laisser tout passer :
|
|
|
|
~~~
|
|
# iptables -P INPUT ACCEPT
|
|
# iptables -P OUTPUT ACCEPT
|
|
# iptables -P FORWARD ACCEPT
|
|
# iptables -F -t filter
|
|
# iptables -F -t nat
|
|
# iptables -F -t mangle
|
|
~~~
|
|
|
|
Sauvegarder les règles courantes dans un fichier, réinitialiser les règles à partir d'un fichier :
|
|
|
|
~~~
|
|
# iptables-save > /tmp/IPT
|
|
# ip6tables-save > /tmp/IP6T
|
|
# iptables-restore /tmp/IPT
|
|
# ip6tables-restore /tmp/IP6T
|
|
~~~
|
|
|
|
## minifirewall
|
|
|
|
[minifirewall](https://gitea.evolix.org/evolix/minifirewall/) est un script Shell permettant une gestion simple d'un firewall local, idéal pour un serveur dédié (virtualisé ou non).
|
|
|
|
À partir de la version `22.03`, minifirewall dispose d'une configuration principale `/etc/default/minifirewall` uniquement déclarative et d'un système d'inclusion automatique de ce qui est dans `/etc/minifirewall.d/`
|
|
|
|
### Installation minifirewall
|
|
|
|
~~~
|
|
# [ -e /etc/default/minifirewall ] && cp /etc/default/minifirewall /etc/default/minifirewall.old
|
|
# wget https://gitea.evolix.org/evolix/minifirewall/raw/branch/master/minifirewall.conf -O /etc/default/minifirewall
|
|
# wget https://gitea.evolix.org/evolix/minifirewall/raw/branch/master/minifirewall -O /etc/init.d/minifirewall
|
|
# chmod 700 /etc/init.d/minifirewall
|
|
# chmod 600 /etc/default/minifirewall
|
|
# mkdir /etc/minifirewall.d
|
|
# chmod 700 /etc/minifirewall.d
|
|
# insserv /etc/init.d/minifirewall
|
|
~~~
|
|
|
|
### Configuration déclarative
|
|
|
|
On peut gérer la configuration via le fichier `/etc/default/minifirewall`.
|
|
|
|
* Il faut adapter la variable `INT` avec l'interface réseau principale
|
|
|
|
Pour les règles en entrée, tout est coupé et il faut définir :
|
|
|
|
* les variables `SERVICESTCP1` et `SERVICESUDP1` pour les ports publics en IPv4 et IPv6
|
|
* 2 catégories d'adresses IPv4 : les adresses de confiance `TRUSTEDIPS` et les adresses privilégiées `PRIVILEGIEDIPS`
|
|
* pour les ports semi-publics, on utilise `SERVICESTCP2` et `SERVICESUDP2` ouverts aux adresses `PRIVILEGIEDIPS`
|
|
* pour les ports privés, on utilise `SERVICESTCP3` et `SERVICESUDP3` ouverts aux adresses `TRUSTEDIPS`
|
|
* les variables `SERVICESTCP1p` et `SERVICESUDP1p` ne servent pas, sauf si on a créé une chaîne IPTables spécifique `NEEDRESTRICT`
|
|
|
|
Pour les règles en sortie, tout est coupé et on peut autoriser facilement les ports les plus classiques :
|
|
|
|
* `DNSSERVEURS='0.0.0.0/0 ::/0'` pour autoriser toutes les requêtes DNS (en IPv4 et IPv6)
|
|
* `HTTPSITES='0.0.0.0/0 ::/0'` pour autoriser toutes les requêtes en sortie vers le port 80 (en IPv4 et IPv6)
|
|
* …
|
|
|
|
Il est possible de configurer un proxy http sortant (par exemple Squid).
|
|
La variable `PROXY` active ou désactibe le mécanisme depuis le firewall.
|
|
`PROXYPORT` indique le port à utiliser pour le forward des paquets.
|
|
`PROXYBYPASS` indique la liste des IP de destination pour lesquelles on ne passe pas par le proxy.
|
|
|
|
~~~{.bash}
|
|
# Proxy (Squid)
|
|
PROXY='on'
|
|
# (proxy port)
|
|
PROXYPORT='8888'
|
|
# (destinations that bypass the proxy)
|
|
PROXYBYPASS="${INTLAN} 127.0.0.0/8"
|
|
~~~
|
|
|
|
Il est possible de configurer les autorisations pour les serveurs de backup, en ajoutant des couples `IP:PORT` dans la variable `BACKUPSERVERS`.
|
|
|
|
~~~{.bash}
|
|
# Backup servers
|
|
BACKUPSERVERS='192.0.2.123:1234 203.0.113.42:5678'
|
|
~~~
|
|
|
|
Plusieurs autres variables sont disponibles pour affiner la configuration kernel (via `sysctl`) :
|
|
|
|
~~~{.bash}
|
|
# In most cases, the default values set by minifirewall are good.
|
|
# If you really know what you are doing,
|
|
# you can uncomment some lines and customize the value.
|
|
|
|
# Set 1 to ignore broadcast pings (default)
|
|
# SYSCTL_ICMP_ECHO_IGNORE_BROADCASTS='1'
|
|
|
|
# Set 1 to ignore bogus ICMP responses (default)
|
|
# SYSCTL_ICMP_IGNORE_BOGUS_ERROR_RESPONSES='1'
|
|
|
|
# Set 0 to disable source routing (default)
|
|
# SYSCTL_ACCEPT_SOURCE_ROUTE='0'
|
|
|
|
# Set 1 to enable TCP SYN cookies (default)
|
|
# SYSCTL_TCP_SYNCOOKIES='1'
|
|
|
|
# Set 0 to disable ICMP redirects
|
|
# SYSCTL_ACCEPT_REDIRECTS='0'
|
|
# SYSCTL_SEND_REDIRECTS='0'
|
|
|
|
# Set 1 to enable Reverse Path filtering (default)
|
|
# Set 0 if VRRP is used
|
|
# SYSCTL_RP_FILTER='1'
|
|
|
|
# Set 1 to log packets with inconsistent address (default)
|
|
# SYSCTL_LOG_MARTIANS='1'
|
|
~~~
|
|
|
|
Ces variables sont en général à laisser telles-quelles.
|
|
Attention cependant à `SYSCTL_RP_FILTER` qu'il faut mettre à `0` lorsqu'on utilise VRRP.
|
|
|
|
### Configuration par inclusion
|
|
|
|
Tous les fichiers présents dans `/etc/minifirewall.d` sont automatiquement inclus et exécutés au démarrage de minifirewall, par ordre alphanumérique, en excluant les fichiers contenant des points dans leur nom.
|
|
|
|
On peut y mettre des commandes shell arbitraires pour appliquer des règles spécifiques.
|
|
|
|
Quelques fonctions shell sont disponibles :
|
|
|
|
~~~
|
|
# Within included files, you can use those helper functions :
|
|
# * is_ipv6_enabled: returns true if IPv6 is enabled, or false
|
|
# * is_docker_enabled: returns true if Docker mode is eabled, or false
|
|
# * is_proxy_enabled: returns true if Proxy mode is enabled , or false
|
|
~~~
|
|
|
|
* Pour autoriser toutes les requêtes en sortie vers le port 80 en IPv6 : `ip6tables -A INPUT -i $INT -p tcp --sport 80 --match state --state ESTABLISHED,RELATED -j ACCEPT`
|
|
* Pour autoriser en sortie vers le port 636 d'un serveur extérieur : `iptables -A INPUT -p tcp --sport 636 --dport 1024:65535 -s ssl.evolix.net -m state --state ESTABLISHED,RELATED -j ACCEPT`
|
|
|
|
> *Note* : pour autoriser un port en entrée, on n'utilisera pas de règle spécifique mais les variables dédiées dans la configuration principale
|
|
|
|
> *Note* : pour autoriser un port en sortie, la règle à ajouter paraît contre-intuitive car les paquets en sortie sont déjà tous autorisés (sauf en UDP) : on autorise en fait les paquets de retour (`INPUT`) qui correspondent à des paquets déjà émis en sortie (`--state ESTABLISHED,RELATED`)
|
|
|
|
### IPv6
|
|
|
|
Si on souhaite désactiver le support IPv6, ça se fait via la variable `IPv6=off`
|
|
|
|
Dans tous les cas il est conseillé de mettre les IPv4 et IPv6 dans les variables concernées. Les IPv6 seront ignorées si c'est désactivé.
|
|
|
|
En IPv4, l'autorisation globale est `0.0.0.0/0`. l'équivalent en IPv6 est `::/0`.
|
|
|
|
### Docker
|
|
|
|
#### Général
|
|
|
|
La variable générale `DOCKER` permet de définir si minifirewall doit tenir compte de Docker.
|
|
C'est surtout pour éviter de purger les règles injectées par Docker lors de l'arrêt ou du redémarrage de minifirewall.
|
|
|
|
#### Docker → host
|
|
|
|
Si on souhaite autoriser des conteneurs à communiquer via le réseau avec d'autres processus hors Docker sur le serveur, il faut autorise ces communications de manière explicite. _TODO: documenter avec des exemples et explications._
|
|
|
|
#### Docker Swarm
|
|
|
|
Si on utilise Docker Swarm sur plusieurs serveurs, il faut une configuration particulière pour que la communication inter-nœuds se fasse bien.
|
|
|
|
~~~{.bash}
|
|
# interface par laquelle les nœuds communiquent
|
|
SWARM_INT=eno10
|
|
|
|
## Pour chaque autre serveur de la Swarm (192.0.2.11, 192.0.2.12…) :
|
|
NODE_IP=192.0.2.11
|
|
/sbin/iptables -I INPUT -i ${SWARM_INT} -p tcp -s ${NODE_IP} --dport 2377 -m comment --comment "Allow incomming docker swarm (management TCP) from ${NODE_IP}" -j ACCEPT
|
|
/sbin/iptables -I INPUT -i ${SWARM_INT} -p tcp -s ${NODE_IP} --sport 2377 -m state --state ESTABLISHED,RELATED -m comment --comment "Allow outgoing docker swarm (management TCP) to ${NODE_IP}" -j ACCEPT
|
|
|
|
/sbin/iptables -I INPUT -i ${SWARM_INT} -p tcp -s ${NODE_IP} --dport 7946 -m comment --comment "Allow incomming docker swarm (inter-node TCP) from ${NODE_IP}" -j ACCEPT
|
|
/sbin/iptables -I INPUT -i ${SWARM_INT} -p tcp -s ${NODE_IP} --sport 7946 -m state --state ESTABLISHED,RELATED -m comment --comment "Allow outgoing docker swarm (inter-node TCP) to ${NODE_IP}" -j ACCEPT
|
|
|
|
/sbin/iptables -I INPUT -i ${SWARM_INT} -p udp -s ${NODE_IP} --dport 7946 -m comment --comment "Allow incomming docker swarm (inter-node UDP) from ${NODE_IP}" -j ACCEPT
|
|
/sbin/iptables -I INPUT -i ${SWARM_INT} -p udp -s ${NODE_IP} --sport 7946 -m state --state ESTABLISHED,RELATED -m comment --comment "Allow outgoing docker swarm (inter-node UDP) to ${NODE_IP}" -j ACCEPT
|
|
|
|
/sbin/iptables -I INPUT -i ${SWARM_INT} -p udp -s ${NODE_IP} --dport 4789 -m comment --comment "Allow incomming docker swarm (network UDP) from ${NODE_IP}" -j ACCEPT
|
|
/sbin/iptables -I INPUT -i ${SWARM_INT} -p udp -s ${NODE_IP} --sport 4789 -m state --state ESTABLISHED,RELATED -m comment --comment "Allow outgoing docker swarm (network UDP) to ${NODE_IP}" -j ACCEPT
|
|
|
|
## Une seule fois
|
|
/sbin/iptables -I OUTPUT -o ${SWARM_INT} -p udp --dport 4789 -m comment --comment "Allow outgoing docker swarm (network UDP)" -j ACCEPT
|
|
/sbin/iptables -I OUTPUT -o ${SWARM_INT} -p udp --dport 7946 -m comment --comment "Allow outgoing docker swarm (inter-node UDP)" -j ACCEPT
|
|
|
|
~~~
|
|
|
|
### Commandes (start, stop…)
|
|
|
|
~~~
|
|
# /etc/init.d/minifirewall help
|
|
minifirewall Firewall designed for standalone server
|
|
|
|
Usage: minifirewall [COMMAND]
|
|
|
|
Commands
|
|
start Start minifirewall
|
|
safe-start Start minifirewall, with baground safety checks
|
|
stop Stop minifirewall
|
|
restart Stop then start minifirewall
|
|
safe-restart Restart minifirewall, with background safety checks
|
|
status Print minifirewall status
|
|
reset Reset iptables tables
|
|
check-active-config Check if active config is up-to-date with stored config
|
|
version Print version and exit
|
|
help Print this message and exit
|
|
~~~
|
|
|
|
Il est possible de redémarrer le firewall en mode interactif avec une protection contre le blocage :
|
|
|
|
~~~
|
|
# /etc/init.d/minifirewall safe-restart
|
|
sourcing `/etc/default/minifirewall'
|
|
WARNING: current state is different than persisted state, check /var/run/minifirewall_state_diff
|
|
minifirewall stopping
|
|
flushing all rules and accepting everything
|
|
minifirewall stopped
|
|
minifirewall starting
|
|
sourcing `/etc/minifirewall.d/zzz-custom'
|
|
sourcing `/etc/minifirewall.d/zzzz-ban'
|
|
minifirewall started
|
|
INFO: rules have changed since latest start, check /var/run/minifirewall_state_diff
|
|
Minifirewall will be stopped in 30 seconds if you do nothing.
|
|
Remove `/var/run/minifirewall_safety.lock' or type anything to keep minifirewall started:
|
|
~~~
|
|
|
|
Il faut alors aller retirer le fichier de lock (par n'importe quel moyen) ou saisir et valider n'importe quoi au clavier.
|
|
|
|
Si on ne le fait pas dans les 30 secondes, le firewall sera stoppé pour redonner la main à l'utilisateur.
|
|
|
|
|
|
## FAQ
|
|
|
|
### Bannir une adresse IP
|
|
|
|
En cas de besoin de bannir temporairement une adresse IP 192.0.2.66 :
|
|
|
|
~~~
|
|
# iptables -I INPUT -s 192.0.2.66 -j DROP
|
|
~~~
|
|
|
|
### NAT bidirectionnel
|
|
|
|
~~~
|
|
# iptables -t nat -A PREROUTING -i eth0 -d IP_publique -j DNAT --to-destination 192.0.2.1
|
|
# iptables -t nat -A POSTROUTING -o eth0 -s 192.0.2.1 -j SNAT --to-source IP_publique
|
|
~~~
|
|
|
|
### Autoriser toute une interface
|
|
|
|
Lorsqu'un serveur dispose de plusieurs interfaces, dont une pour un réseau local privé, on peut autoriser tout le trafic sur cette interface (ici "eth1") :
|
|
|
|
~~~
|
|
# iptables -A INPUT -i eth1 -j ACCEPT
|
|
~~~
|
|
|
|
### Autoriser la sortie sur un port
|
|
|
|
Exemple si on a un serveur Munin centralisé, il a besoin de joindre les _munin-node_ :
|
|
|
|
~~~
|
|
# iptables -A INPUT -p tcp --sport 4949 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j ACCEPT
|
|
~~~
|
|
|
|
### Redirection du port 80 en sortie vers un proxy local
|
|
|
|
~~~
|
|
# iptables -t nat -A OUTPUT -p tcp --dport 80 -m owner --uid-owner proxy -j ACCEPT
|
|
# iptables -t nat -A OUTPUT -p tcp --dport 80 -d 192.0.2.42 -j ACCEPT
|
|
# iptables -t nat -A OUTPUT -p tcp --dport 80 -d 127.0.0.1 -j ACCEPT
|
|
# iptables -t nat -A OUTPUT -p tcp --dport 80 -j REDIRECT --to-port 3128
|
|
~~~
|
|
|
|
### FTP Passif
|
|
|
|
~~~
|
|
# iptables -A INPUT -p tcp --dport 60000:61000 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
|
|
~~~
|
|
|
|
### Test des ports TCP
|
|
|
|
Pour tester l'ouverture d'un port TCP en sortie, on peut utiliser <http://portquiz.net/> qui écoute sur tous les ports TCP possibles :
|
|
|
|
~~~
|
|
$ telnet portquiz.net 42
|
|
Trying 52.47.209.216...
|
|
Connected to portquiz.net.
|
|
Escape character is '^]'.
|
|
~~~
|
|
|
|
### Tout autoriser en sortie (IPv4)
|
|
|
|
Si l'on veut tout autoriser en sortie (TCP, UDP), voici la règle à ajouter :
|
|
|
|
~~~
|
|
# iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
|
~~~
|
|
|