Je me suis inscrit pour vous poser la sempiternelle question : est-ce que mon script netfilter/iptables tient la route ?
J’ai un serveur maison fait avec un mini-PC peu gourmand connecté à un routeur grand public d’une marque bien connue derrière une bonne connexion (1000/100 Mbps).
Les services ouverts sur le web sont Apache (site statique), SSH et Deluge, ce sont les trois seuls ports entrants ouverts sur le routeur (redirection vers la machine locale).
Je voulais un bon pare-feu en plus sur le serveur lui-même (serveur qui est avec mes autres machines sur le LAN du routeur), alors j’ai essayé de faire de mon mieux avec netfilter/iptables et j’ai lentement réussi à obtenir un ensemble de règles :
#!/bin/sh
### BEGIN INIT INFO
# Provides: firewall
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Démarre les règles iptables
# Description: Charge la configuration du pare-feu iptables
### END INIT INFO
#Réinitialise les règles
iptables -t filter -F
iptables -t filter -X
# Stratégie drop par defaut (pas de forwarding non plus)
iptables -t filter -P INPUT DROP
iptables -t filter -P FORWARD DROP
iptables -t filter -P OUTPUT DROP
# Autoriser les connexions déja établies et le loopback (pas les related car vulnérables au packet forging, module state préféré à cstate même si obselete)
iptables -A INPUT -m state --state ESTABLISHED -j ACCEPT
iptables -A OUTPUT -m state --state ESTABLISHED -j ACCEPT
iptables -t filter -A INPUT -i lo -j ACCEPT
iptables -t filter -A OUTPUT -o lo -j ACCEPT
# ICMP
#Autoriser
iptables -t filter -A INPUT -p icmp -j ACCEPT
iptables -t filter -A OUTPUT -p icmp -j ACCEPT
#Drop les requêtes ping non sollicitées et limiter à 1/s (ne joue que sur le ping tout en gardant les infos ICMP d'intégrité utiles pour IPv4)
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -m state ! --state ESTABLISHED -j DROP
# SSH (sur port 443, sert aussi pour SFTP, avec une limite anti-DDOS)
/sbin/iptables -N LOGDROP
/sbin/iptables -A LOGDROP -j LOG
/sbin/iptables -A LOGDROP -j DROP
iptables -t filter -A INPUT -p tcp --dport 443 -j ACCEPT
iptables -I INPUT -p tcp --dport 443 -i eth0 -m state --state NEW -m recent --set
iptables -I INPUT -p tcp --dport 443 -i eth0 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 -j LOGDROP
# DNS (sortant seulement, pas de service DNS sur la machine)
iptables -t filter -A OUTPUT -p tcp --dport 53 -j ACCEPT
iptables -t filter -A OUTPUT -p udp --dport 53 -j ACCEPT
#iptables -t filter -A INPUT -p tcp --dport 53 -j ACCEPT
#iptables -t filter -A INPUT -p udp --dport 53 -j ACCEPT
# HTTP (Apache et navigation web sur la machine)
iptables -t filter -A OUTPUT -p tcp --dport 80 -j ACCEPT
iptables -t filter -A INPUT -p tcp --dport 80 -j ACCEPT
# HTTPS (Pour la navigation https sur la machine. Input inactif car déjà ouvert pour le port SSH actuel)
iptables -t filter -A OUTPUT -p tcp --dport 443 -j ACCEPT
#iptables -t filter -A INPUT -p tcp --dport 443 -j ACCEPT
# Deluge (port d'entrée personnalisé, + large plage aléatoire pour connection au nuage de pairs)
iptables -t filter -A OUTPUT -p tcp --dport 1024:65535 -j ACCEPT
iptables -t filter -A OUTPUT -p udp --dport 1024:65535 -j ACCEPT
iptables -t filter -A INPUT -p tcp --dport 56000 -j ACCEPT
#Module FTP passif (actuellement non utilisé)
#modprobe ip_conntrack_ftp
#modprobe ip_nat_ftp
# FTP (actuellement non utilisé)
#iptables -t filter -A OUTPUT -p tcp --dport 21 -j ACCEPT
#iptables -t filter -A INPUT -p tcp --dport 21 -j ACCEPT
#SMTP SSL (exim en smarthost avec Gmail pour les logs)
iptables -t filter -A OUTPUT -p tcp --dport 587 -j ACCEPT
# NTP (synchro de l'horloge avec les serveurs de temps internet)
iptables -t filter -A OUTPUT -p udp --dport 123 -j ACCEPT
#DHCP (Le routeur local attribue une adresse statique par DHCP, évite l'erreur de renouvellement dans les logs du serveur)
iptables -A OUTPUT -p UDP --dport 67:68 -j ACCEPT
#Eviter les DDOS sur le serveur web (pas de log pour éviter la surcharge, srcmask arbitraire pour éviter la surcharge et l'encombrement des règles)
#Limite 50 connexions par masque IP /28
iptables -I INPUT -p tcp --dport 80 -m connlimit --connlimit-above 50 --connlimit-mask 28 -j DROP
#Limite requêtes syn 30/s par masque IP /28
iptables -N SYN-LIMIT
iptables -A SYN-LIMIT -m hashlimit --hashlimit 30/second --hashlimit-mode srcip --hashlimit-srcmask 28 --hashlimit-name SYN-LIMIT -j RETURN
iptables -A SYN-LIMIT -j DROP
iptables -I INPUT -p tcp --dport 80 --syn -j SYN-LIMIT
#IPs bannies à la main si nécessaire
#iptables -I INPUT -s IP_Bannies -j DROP
#Réinitialise les règles IPv6
ip6tables -t filter -F
ip6tables -t filter -X
#Stratégie IPv6 drop par defaut
ip6tables -t filter -P INPUT DROP
ip6tables -t filter -P OUTPUT DROP
ip6tables -t filter -P FORWARD DROP
#Autoriser loopback IPv6
ip6tables -A INPUT -i lo -j ACCEPT
ip6tables -A OUTPUT -o lo -j ACCEPT
En bon noob qui touche du Debian depuis trois ans à petite dose, j’ai vraiment fait de mon mieux, j’ai lu le MAN et regardé des schémas fonctionnels, tout cela en deux semaines sur quelques mois. J’ai même fait des tests avec (Ze)nmap (bouuh !) et bien regardé le retour d’iptables -L -nv.
D’après les logs il y a des trucs qui marchent, fail2ban fonctionne bien lui aussi.
Mais j’ai encore beaucoup de difficultés, et j’aimerais vraiment avoir des conseils sur mes règles, si elles sont fonctionnelles et sans trou de sécurité majeur, ou si je me suis trompé dans l’ordre d’exécution… Pas facile de travailler seul sans un regard extérieur.
Je suis conscient que le pare-feu ne fait pas tout, et que la limitation des DDOS ne protège que le serveur et non la connexion qui y mène.
Voilà, je vous saurais gré d’éclairer ma lanterne, si tant est que mon niveau soit compatible avec vos explications, car mon but premier est bien que ça marche !
Merci de m’avoir lu !