Contexte

Iptables est utilisé sur une grande partie des serveurs Linux afin d’administrer les règles de filtrage réseau (netfilter) du noyau Linux.

Malgré de nombreuses qualités (possibilité de réaliser un filtrage avancé), iptables possède quelques défauts qui peuvent complexifier sa gestion au quotidien.

Un de ses principaux défauts est de ne pas avoir par défaut de configuration persistante et de chargement automatique des règles au démarrage.

Bien que ce comportement puisse dans certains cas être salvateur (exemple d’un filtrage loupé qui aurait rendu le serveur injoignable) la plupart du temps ce comportement pose problème et impose à l’administrateur système de créer des scripts lancés au démarrage pour recharger cette configuration.

Certaines distributions Linux ont tenté de corriger en déployant des paquets iptables-save et iptables-restore mais leur comportement n’est pas optimal et peut être source d’oubli.

Jaguar a donc développé un service appelé netfilter-rules pour pallier aux manques du système par défaut.

Netfilter-rules

Ces services (netfilter-rules et netfilter6-rules pour la partie ipv6) lancés au démarrage sont un script (/opt/admin/bin/netfilter-rules) exécuté une seule fois lorsqu’il est appelé par les commandes service/systemctl.

Lorsque l’action start est lancée il lit sa configuration et installe les règles iptables nécéssaires.

A l’inverse lors d’un arrêt il va vider la configuration iptables (policy accept sur les tables INPUT / OUTPUT et FORWARD).

/!\ à noter : lors d’un arrêt ou restart du service, il faut également lancer un restart du service fail2ban.

En effet fail2ban utilise iptables pour effectuer son filtrage. Il faut donc le redémarrer pour qu’il réinsère sa configuration.

La configuration est gérée dans les fichiers de configuration :

/etc/netfilter-rules.conf pour la configuration ipv4

/etc/netfilter6-rules.conf pour la configuration ipv4

Fichier de configuration par défaut :

  • On autorise tout sur lo
all="lo "
  • On autorise le ping sur ces interfaces
ping="eth0"
  • Mais plus spécifiquement par interface, par protocole et par port
tcpint="eth0+22"
udpint=""
  • A l’exception de cette liste blanche
exceptions=""
  • Log t’on les packets droppés ?
logdrop="false"
  • Configuration passerelle
gateway="false"
  • Interface externe
extif=""
  • Interface interne
intif=""
  • Autres règles iptables

Par défaut :

  • Tout le trafic est autorisé sur l’interface de loopback (lo)
  • On autorise le ping sur eth0 ainsi que ssh.
  • Il est possible de spécifier une whitelist d’ip qui sera autorisée à accéder à tous les ports/interfaces sans restriction. Dans le cas d’un serveur infogéré par notre support, nous vous invitons à ne pas supprimer nos autorisations IP.
  • On ne log pas les paquets droppés
  • Les paramètres extif et intif sont de simples paramètres déclaratifs par défaut et n’impliquent pas de règles de filtrage. Ils seront en revanche utilisés si le mode gateway est utilisé pour réaliser du nat (tables FORWARD)

Voici la configuration iptables finale qui sera produite avec ce fichier par défaut :

Chain INPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target  prot opt in   out     source     destination

0  0 ACCEPT  icmp --  eth0   *    0.0.0.0/0   0.0.0.0/0

0  0 ACCEPT  tcp  --  eth0   *    0.0.0.0/0   0.0.0.0/0      tcp dpt:ssh

0  0 ACCEPT  all  --  lo     *    0.0.0.0/0   0.0.0.0/0

0  0 ACCEPT  all  --  *      *    0.0.0.0/0   0.0.0.0/0   state RELATED,ESTABLISHED

0  0 REJECT  tcp  --  *      *    0.0.0.0/0   0.0.0.0/0   reject-with tcp-reset

0  0 REJECT  all  --  *      *    0.0.0.0/0   0.0.0.0/0   reject-with icmp-port-unreachable

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)

pkts bytes target prot opt in  out    source   destination

Personnalisation des règles de filtrage

Ce fichier de configuration permet bien sûr de rajouter vos propres règles iptables personnalisées. Dans le cas d’un serveur web, il est possible d’ouvrir les ports http et https sans restriction d’ip source via le paramètre tcpint :

tcpint="eth0+22+80+443"

Dans le cas où l’autorisation de flux concernerait un flux udp, il faudra utiliser le paramètre udpint à la place. Dans le cas où il faudrait ouvrir le port sur une autre interface (eth1 par exemple) :

tcpint="eth0+22 eth1+80+443"

Pour tout ce qui est filtrage nécessitant une autorisation par IP pour des services sensibles (exemple mysql / ssh dans certains cas / redis …), il faudra passer par des règles de filtrages iptables personnalisées.

Exemple de filtrage pour un serveur web/mysql :

Par exemple dans le cas d’un serveur qui hébergerait un serveur apache + mysql, avec une interface publique eth1 et une interface interne eth0, le service mysql doit être accessible depuis l’ip de deux autres serveur web 10.0.5.3 et 10.0.5.4 et un prestataire externe (ip 176.130.221.17) doit pouvoir accéder au serveur:

  • On autorise tout sur lo all=”lo “
  • On autorise le ping sur ces interfaces
ping="eth0 eth1"
  • Mais plus spécifiquement par interface, par protocole et par port
tcpint="eth0+22+80+443 eth1+80+443"
  • A l’exception de cette liste blanche exceptions=
"176.130.221.17/32"
  • Log t’on les packets droppés ?
logdrop="false"
  • Configuration passerelle
gateway="false"
  • Interface externe
extif="eth1"
  • Interface interne
intif="eth0"
  •   Autres regles iptables
  • mysql
iptables -A INPUT -p tcp --dport 3306 -s 10.0.5.3/32 -i eth0 -j ACCEPT
iptables -A INPUT -p tcp --dport 3306 -s 10.0.5.4/32 -i eth0 -j ACCEPT

Bien sûr une fois modifié, il ne faut pas oublier de redémarrer le service.