Iptables

De Banane Atomic
Aller à la navigationAller à la recherche

Règles recommandées

Bash.svg
# par défaut, droper les paquets qui ne sont pas à destination de l'hôte
iptables -P FORWARD DROP

# par défaut, autoriser les paquets sortants
iptables -P OUTPUT ACCEPT

# par défaut, droper les paquets entrants
iptables -P INPUT DROP

# autorise les paquets des connexions déjà établies ou les paquets de nouvelles connexions liées à celles déjà établies
iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

# autorise les packet de l'interface lo (loopback)
iptables -A INPUT -i lo -j ACCEPT

# dropper le trafic dont l'état est INVALID
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP

# autorise les requêtes echo ICMP (ping)
iptables -A INPUT -p icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT
Les règles sont appliquées dans l'ordre dans lesquelles elles sont écrites.
La première correspondance est appliquée.

TCP et UDP

Bash.svg
# créer les chain TCP et UDP
iptables -N TCP
iptables -N UDP

# jumper les nouvelles connexions udp vers la chain UDP
iptables -A INPUT -p udp -m conntrack --ctstate NEW -j UDP

# jumper les nouvelles (mais pas SYN) connexions tcp vers la chain TCP
iptables -A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP

# logger le reste (ce qui va être rejeté)
iptables -I INPUT 7 -m limit --limit 2/min -j LOG --log-prefix "iptables:INPUT:REJECT: " --log-level 4

# rejeter ce qui n'a pas été jumpé vers TCP et UDP
iptables -A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
iptables -A INPUT -p tcp -j REJECT --reject-with tcp-reset

# rejeter les autres protocoles
iptables -A INPUT -j REJECT --reject-with icmp-proto-unreachable

# ouvrir les ports utilisés
# serveur HTTP et HTTPS
iptables -A TCP -p tcp --dport 80 -j ACCEPT
iptables -A TCP -p tcp --dport 443 -j ACCEPT
# serveur SSH
iptables -A TCP -p tcp --dport 22 -j ACCEPT -s 192.168.0.0/24
# serveur Postfix
iptables -A TCP -p tcp --dport 25 -j ACCEPT
# serveur DNS
iptables -A UDP -p udp -s 192.168.0.0/24 --dport 53 -j ACCEPT
# serveur DHCP
iptables -I UDP -i eth0 -p udp -s 192.168.0.0/24 --dport 67:68 --sport 67:68 -j ACCEPT

ipv6

Bash.svg
# par défaut, droper tous les paquets
ip6tables -P FORWARD DROP
ip6tables -P INPUT DROP
# ip6tables -P OUTPUT DROP
# message d'erreur avec dig: net.c:592: sendmsg() failed: Operation not permitted

# sauvegarder la configuration
ip6tables-save > /etc/iptables/ip6tables.rules

# démarrer le service au démarrage
systemctl enable ip6tables
Commenter les lignes référençant les ipv6 dans /etc/hosts

VPN server

Bash.svg
# port UDP
iptables -A UDP -i eth0 -p udp --dport 1194 -j ACCEPT -m comment --comment "VPN"

# FORWARD
iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m comment --comment "VPN"
iptables -A FORWARD -i tun0 -o eth0 -s 10.8.0.0/24 -d 192.168.0.0/24 -m conntrack --ctstate NEW -j ACCEPT -m comment --comment "VPN"
# retirer -d 192.168.0.0/24 pour permettre aux clients l'accès à internet

# NAT
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE -m comment --comment "VPN"
# iptables -t nat -nvL --line-numbers

# DNS
iptables -A UDP -p udp -s 10.8.0.0/24 --dport 53 -j ACCEPT -m comment --comment "DNS pour VPN"

Log

Bash.svg
# tous les éléments entrant ne provenant pas de 192.168.0.x
iptables -I INPUT 1 -j LOG ! -s 192.168.0.x

# créer une nouvelle chain
iptables -N LOGGING

# inscrire dans le log (journalctl) tous les packet passant par LOGGING
iptables -A LOGGING -j LOG --log-prefix "IPTables-LOGGING: " --log-level 5
# log-level: 0 - Emergency, 1 - Alerts, 2 - Critical, 3 - Errors, 4 - Warnings, 5 - Notification, 6 - Information, 7 - Debug

# rediriger tous les packets entrants et sortants vers LOGGING
iptables -A INPUT -j LOGGING
iptables -A OUTPUT -j LOGGING

Loguer seulement les paquets droppés

Bash.svg
iptables -N LOGDROP

# tous les packet passant par LOGDROP sont logués dans la limite de 10 puis de 5 par minute
iptables -A LOGDROP -m limit --limit 5/m --limit-burst 10 -j LOG
# tous les packet passant par LOGDROP sont droppés
iptables -A LOGDROP -j DROP

# jumper les paquets vers LOGDROP les log puis les drop
iptables -A INPUT -s x.x.x.x -j LOGDROP

Commandes

Lister les règles existantes

Bash.svg
# lister toutes les chaînes et toutes les règles
iptables -nvL --line-numbers
# -n afficher les adresses ip plutôt que les noms d'hôte
# -v plus de détails (pkts, bytes, in, out)
# --line-numbers les numéros des règles

# lister les règles d'une chaîne donnée
iptables -nvL [chain] --line-numbers

Chaînes

Bash.svg
# ajouter une chaîne
iptables -N [new-chain]

# supprimer une chaîne vide créée par un utilisateur
iptables -X [chain]

# définir la politique par défaut d'une chaîne
iptables -P [chain] [ACCEPT ou DROP]
# iptables -P INPUT DROP

Règles

Bash.svg
# ajouter une règle à la fin (Append)
iptables -A [chain] [rule]
# iptables -A INPUT -p tcp --dport 80 -j ACCEPT

# insérer une règle au numéro spécifié, 1 par défaut
iptables -I [chain] [rule_number] [rule]
# iptables -I INPUT 1 -p tcp --dport 80 -j ACCEPT

# supprimer une règle par son numéro
iptables -D [chain] [rule_number]
# iptables -D INPUT 1

# supprimer une règle par correspondance
iptables -D [chain] [rule]

# supprimer toutes les règles de la chaîne spécifiée
iptables -F [chain]
# supprimer toutes les règles (Flush)
iptables -F

# modifier une règle
iptables -R [chain] [rule_number] [règle complète modifiée]

# remettre à 0 les compteurs
iptables -LZ [chain [rule_number]]

# tester si une règle existe déjà
iptables -C [chain] [rule]
# if [[ $? -ne 0 ]]; then [la règle n'existe pas];fi

Écriture des règles

Bash.svg
# protocol (tcp, udp, icmp)
iptables -A INPUT -p tcp ...

# port de destination (pour tcp et udp)
iptables -A INPUT -p tcp --dport xxxx

# adresse ip de l'expéditeur
iptables -A INPUT -s x.x.x.x ...
iptables -A INPUT -m iprange --src-range x.x.x.0-x.x.x.255 ...

# adresse ip du destinataire
iptables -A INPUT -d x.x.x.x ...

# interface réseau d'entrée
iptables -A INPUT -i [interface] ...
# interface réseau de sortie
iptables -A OUTPUT -o [interface] ...

# état de la connexion
iptables -A INPUT -m conntrack --ctstate [state]
iptables -A INPUT -m state --state [state]  # (remplacé par conntrack)
# INVALID le paquet n'est associé à aucune connexion
# NEW le paquet démarre une nouvelle connexion
# ESTABLISHED le paquet appartient à une connexion déjà existante
# RELATED le paquet démarre une nouvelle connexion et appartient à une connexion déjà existante

# commentaires
iptables -A INPUT ... -m comment --comment "mon commentaire"

jump

Bash.svg
# autorise les paquets correspondant à la règle
iptables -A INPUT [rule] -j ACCEPT

# bloque les paquets correspondant à la règle
iptables -A INPUT [rule] -j DROP

# bloque les paquets correspondant à la règle et envoie un message d'erreur à l'expéditeur
iptables -A INPUT [rule] -j REJECT
# « --reject-with tcp-reset » permet de demander à l'expéditeur de fermer la connexion tcp
# « --reject-with icmp-port-unreachable »
# « --reject-with icmp-proto-unreachable »
DROP devrait être utilisé pour les expéditeurs qui ne devraient pas connaître l’existence du serveur
et à l'inverse REJECT devrait être utilisé pour les expéditeurs qui connaissent l’existence du serveur.

Fichier de configuration

Bash.svg
# après avoir utiliser la ligne de commandes pour modifier la configuration d'iptables
# il faut enregistrer ces modifications pour quelles puissent être chargée au démarrage du service
iptables-save > /etc/iptables/iptables.rules

# restaurer la configuration du fichier iptables.rules
iptables-restore < /etc/iptables/iptables.rules

# recharger les règles du fichier de configuration au cas ou le fichier aurait été modifié
systemctl reload iptables

Mangle table

Mark packets.

Bash.svg
iptables -t mangle -A OUTPUT -j CONNMARK --restore-mark
# mark packet sent by [user]
iptables -t mangle -A OUTPUT ! --dest [local-ip] -m owner --uid-owner [user] -j MARK --set-mark 1
iptables -t mangle -A OUTPUT -j CONNMARK --save-mark

# flush the mangle table
iptables -F -t mangle

Service

Bash.svg
# lit le fichier de configuration et charge les règles
systemctl start iptables

# lit le fichier de configuration et charge les règles au démarrage
systemctl enable iptables

Ban IPs with ipsum

Bash.svg
# install ipset and ipset-persistent
ai ipset ipset-persistent

# create a set of IPs
sudo ipset create ipsum hash:ip

# add an iptables rule to drop all communications from the IPs in the ipsum set
iptables -I INPUT -m set --match-set ipsum src -j DROP

# list the ipsets
sudo ipset -n list
# list the ipsets with their content
sudo ipset list
# list the content of a specific ipset
sudo ipset list [SETNAME]
Make it work with UFW
/root/scripts/ban-ipsum.sh
# create a cron script to load the list of IPs to ban

# flush all entries of the ipsum set
ipset -q flush ipsum

# add the IPs to the ipsum set
for ip in $(curl --compressed https://raw.githubusercontent.com/stamparm/ipsum/master/ipsum.txt 2>/dev/null \
    | grep -v "#" | grep -v -E "\s[1-2]$" | cut -f 1); do ipset add ipsum $ip; done

# save the banned ips to /etc/iptables/ipsets so they will be ban again on startup thanks to ipset.service
netfilter-persistent save
ipset-persistent package installs:
  • /lib/systemd/system/netfilter-persistent.service
  • /usr/sbin/netfilter-persistent
  • /usr/share/netfilter-persistent/plugins.d

Bad IP

badips.sh
set -u
set -e
set -o pipefail

DATABASE=badips.db
INTERFACE=eth0
CHAIN=BADIPS


cd /tmp
# Get the bad IPs
wget -qO- http://www.badips.com/get/list/any/5 > ${DATABASE} || { echo "$0: Unable to download ip list."; exit 1; }

# Ajout de la chain BADIPS si elle n'existe pas
set +e
$(iptables -S ${CHAIN} >/dev/null 2>&1)
ok=$?
set -e
if [[ ${ok} -ne 0 ]]; then
    iptables -N ${CHAIN}
fi

# Flush the previous rules
iptables -F ${CHAIN}
 
# Append everything to $CHAIN
for IP in $(cat ${DATABASE})
do
    $(iptables -A ${CHAIN} -s ${IP} -j DROP)
done

# ajoute le filtrage des ips si la règle n'existe pas
set +e
$(iptables -C INPUT -i ${INTERFACE} -j ${CHAIN} >/dev/null 2>&1)
ok=$?
set -e
if [[ ${ok} -ne 0 ]]; then
    iptables -I INPUT 5 -i ${INTERFACE} -j ${CHAIN} 
fi

# supprime le fichier
rm -f ${DATABASE}

exit 0