22
0
Fork 0
wiki/HowtoNetfilter.md

370 lines
15 KiB
Markdown
Raw Permalink Normal View History

2018-05-30 01:25:57 +02:00
---
2024-02-22 09:50:09 +01:00
categories: linux network firewall minifirewall
2018-05-30 01:25:57 +02:00
title: Howto netfilter
...
2016-12-29 11:25:39 +01:00
2018-05-30 01:25:57 +02:00
* Documentation : <https://netfilter.org/documentation/>
2016-12-29 11:25:39 +01:00
2022-04-29 10:03:05 +02:00
[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.
2016-12-29 11:25:39 +01:00
2018-05-30 01:25:57 +02:00
## Installation
~~~
# apt install iptables
~~~
~~~
# iptables --version
2024-02-22 09:50:09 +01:00
iptables v1.8.9 (nf_tables)
2018-05-30 01:25:57 +02:00
# modinfo iptable_filter
2024-02-22 09:50:09 +01:00
filename: /lib/modules/6.1.0-18-cloud-amd64/kernel/net/ipv4/netfilter/iptable_filter.ko
2018-05-30 01:25:57 +02:00
description: iptables filter table
author: Netfilter Core Team <coreteam@netfilter.org>
license: GPL
2024-02-22 09:50:09 +01:00
depends: ip_tables,x_tables
2018-05-30 01:25:57 +02:00
retpoline: Y
intree: Y
2024-02-22 09:50:09 +01:00
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
2018-05-30 01:25:57 +02:00
parm: forward:bool
~~~
2016-12-29 11:25:39 +01:00
2018-05-30 01:25:57 +02:00
## Utilisation basique
2016-12-29 11:25:39 +01:00
2018-05-30 01:25:57 +02:00
Lister les règles dans les 3 tables filter/nat/mangle :
2016-12-29 11:25:39 +01:00
2018-05-30 01:25:57 +02:00
~~~
# 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
~~~
2016-12-29 11:25:39 +01:00
2018-05-30 01:25:57 +02:00
Interdire toutes les connexions venant de l'IP 192.0.2.66 :
2016-12-29 11:25:39 +01:00
~~~
2018-05-30 01:25:57 +02:00
# iptables -I INPUT -s 192.0.2.66 -j DROP
~~~
2018-06-02 00:44:44 +02:00
Renvoyer les connexions extérieures vers un port à un autre port (avec 192.0.2.42 l'IP du serveur local) :
2018-05-30 01:25:57 +02:00
~~~
/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
~~~
2018-06-02 00:44:44 +02:00
Sauvegarder les règles courantes dans un fichier, réinitialiser les règles à partir d'un fichier :
2018-05-30 01:25:57 +02:00
~~~
# iptables-save > /tmp/IPT
# ip6tables-save > /tmp/IP6T
2018-06-02 00:44:44 +02:00
# iptables-restore /tmp/IPT
# ip6tables-restore /tmp/IP6T
2018-05-30 01:25:57 +02:00
~~~
## minifirewall
2022-04-29 10:03:05 +02:00
[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).
2018-05-30 01:25:57 +02:00
À 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/`
2018-05-30 01:25:57 +02:00
### Installation minifirewall
~~~
# [ -e /etc/default/minifirewall ] && cp /etc/default/minifirewall /etc/default/minifirewall.old
2021-09-14 10:01:32 +02:00
# 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
2016-12-29 11:25:39 +01:00
# chmod 700 /etc/init.d/minifirewall
2018-05-30 01:25:57 +02:00
# chmod 600 /etc/default/minifirewall
# mkdir /etc/minifirewall.d
# chmod 700 /etc/minifirewall.d
# insserv /etc/init.d/minifirewall
2016-12-29 11:25:39 +01:00
~~~
### 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.
2024-02-22 10:45:12 +01:00
~~~{.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`.
2024-02-22 10:45:12 +01:00
~~~{.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`) :
2024-02-22 10:45:12 +01:00
~~~{.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.
2024-02-22 10:45:12 +01:00
~~~{.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…)
2016-12-29 11:25:39 +01:00
~~~
# /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
2016-12-29 11:25:39 +01:00
~~~
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.
2018-05-30 01:25:57 +02:00
## FAQ
2016-12-29 11:25:39 +01:00
2018-05-30 01:25:57 +02:00
### Bannir une adresse IP
En cas de besoin de bannir temporairement une adresse IP 192.0.2.66 :
2016-12-29 11:25:39 +01:00
~~~
2018-05-30 01:25:57 +02:00
# iptables -I INPUT -s 192.0.2.66 -j DROP
2016-12-29 11:25:39 +01:00
~~~
2018-05-30 01:25:57 +02:00
### NAT bidirectionnel
2016-12-29 11:25:39 +01:00
~~~
2018-05-30 01:29:57 +02:00
# 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
2016-12-29 11:25:39 +01:00
~~~
2017-03-21 11:38:04 +01:00
### Autoriser toute une interface
2018-05-30 01:25:57 +02:00
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") :
2017-03-21 11:38:04 +01:00
~~~
2018-05-30 01:25:57 +02:00
# iptables -A INPUT -i eth1 -j ACCEPT
2017-12-26 15:24:12 +01:00
~~~
### Autoriser la sortie sur un port
2018-05-30 01:25:57 +02:00
Exemple si on a un serveur Munin centralisé, il a besoin de joindre les _munin-node_ :
2017-12-26 15:24:12 +01:00
~~~
2018-05-30 01:25:57 +02:00
# 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
~~~
2018-05-31 10:58:03 +02:00
### FTP Passif
~~~
# iptables -A INPUT -p tcp --dport 60000:61000 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
~~~
2021-04-07 12:38:11 +02:00
### 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 :
~~~
2023-06-15 15:40:57 +02:00
# iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
~~~