IPTables
Généralités : les pare-feux Linux
https://cybersecuritynews.com/linux-firewall-iptables/ https://www.digitalocean.com/community/tutorials/a-deep-dive-into-iptables-and-netfilter-architecture
Un pare-feu Linux est un appareil ou un composant quelconque qui inspecte le traffic réseau et décide le laisser passer ou non. Iptables est un outil permettant de gérer les règles de pare-feu sous Linux. La sécurité réseau a évolué avec les différents types de pare-feux qui ont existé à travers les âges : traditionnellement, les fw gèrent les couches 3 et 4, soit les couches routage et transport. Mais des pare-feux plus récents peuvent agir sur les couches plus hautes, par exemple pour analyser le trafic au niveau applicatif.
Iptables, c'est quoi
IPTables est une interface en ligne de commandes qui permet de configurer des règles spécifiques, lesquelles iront forcer le kernel avec sa couche netfilter à faire des actions comme inspecter, modifier ou dropper des paquets. Le fait d'utiliser IPtables permet d'accéder à des fonctions de pare-feu, mais aussi des fonctionnalités de routeur.
Différents modules de kernel et programmes sont utilisés pour différents protocoles : iptables est valide pour ipv4, ip6tables pour ipv6, arptables pour arp, ebtables pour les trames ethernet; etc. Le projet nftables, lui, a été développé pour la performance et la scalabilité et son fonctionnement est différent.
Comment marche le filtrage de paquets
Une policy iptables est construite avec un set ordonné de règles, lesquelles disent au kernel les actions qu'il devrait faire sur certains types de paquets.
Hooks netfilter
Il y a 5 hooks netfilter que les programmes peuvent utiliser. Alors qu'un paquet passe dans la stack, il va déclencher les modules de kernel associés à ces hooks (l'image étant que le paquet passant dans la stack s'accroche à certains crochets, un peu comme un steak sur un tapis roulant je suppose :thinking:). Les hooks déclenchés dépendent de la direction du paquet (in ou out), sa destination, et si il a déjà été droppé ou rejeté dans le passé.
Les hooks suivants représentent des points bien définis de la stack:
- NF_IP_PRE_ROUTING : Sera activé par n'importe quel traffic entrant peu après son arrivée dans la stack. Ce hook est pris en compte avant toute décision de routage.
- NF_IP_LOCAL_IN : Sera activé par un paquet entrant qui a été routé, si celui-ci est destiné au système local.
- NF_IP_FORWARD : Activé après qu'un paquet entrant ait été routé vers un autre host que le système local.
- NF_IP_LOCAL_OUT : Activé par n'importe quel traffic à destination de l'extérieur, qui a été créé sur le système local, dès son entrée dans la stack.
- NF_IP_POST_ROUTING : Activé par n'importe quel traffic forwardé ou sortant après le routage et avant l'envoi sur le câble.
Les modules de kernel qui veulent s'enregistrer auprès de ces hooks (pour pouvoir faire des choses lors du déclenchement des hooks) doivent fournir un numéro de priorité pous savoir dans quels ordre ils seront appellés. Ainsi, on peut connecter plusieurs modules à chacun des hooks, le tout dans un ordre déterminé. Chaque module sera appellé à son tour et rendra une décision au framework netfilter pour indiquer ce qu'il doit advenir du paquet.
Tables et chaînes
Iptables utilise des tables pour stocket ses règles : il s'agit de tables au même sens que dans une BDD. Ces tables sont chacune fonction d'un type de décision, et vont stocker des règles en rapport : par exemple, la table nat stocke tout ce qui a trait au nat. La table filter gère le filtrage des paquets en fonction de leur destination, par exemple.
Pour chaque table, les règles sont organisées dans des chaînes. Tandis que les tables sont définies de façon généraliste, les chaînes représentent quels "hooks" seront associés. En somme, les chaînes déterminent à quelle condition les règles seront évaluées. Les chaînes reprennent les noms des hooks netfilter:
- PREROUTING représente NF_IP_PRE_ROUTING
- INPUT représente NF_IP_LOCAL_IN
- FORWARD représente NF_IP_FORWARD
- OUTPUP représente NF_IP_LOCAL_OUT
- POSTROUTING représente NF_IP_POST_ROUTING.
Chaque table ayant plusieurs chaînes, elle peut intervenir à plusieurs endroits de la stack. Cela dit, toutes les tables n'ont pas toutes les chaînes, cela dépend de ce qui est logique avec leur nature. Il n'y a que 5 hooks, ce qui fait que les chaînes de plusieurs tables sont présentes à chaque hook : par exemple, il existe 3 tables ayant des chaînes PREROUTING. Elles sont donc hiérarchisées entre elles au niveau du hook.
Il existe plusieurs tables:
- filter : la plus utilisée. Prend des décisions pour laisser un paquet continuer vers sa destination ou non. C'est la table de filtrage qui fait le gros de ce qu'on attend d'un fw.
- nat : Sert à implémenter la traduction d'adresses. Les règles de cette table vont déterminer les modifications du paquet en lien avec la source / la dest afin d'avoir du nat.
- mangle : Utilisée pour altérer les en-têtes IP du paquet de plusieurs façons. Elle peut par exemple ajuster le ttl, modifiant ainsi le nombre de sauts valides pour le paquet. Elle peut aussi mettre une marque sur le paquet à destination du kernel, qui ne touche pas au contenu mais permettra divers traitements.
- raw : iptables est statefull, donc les paquets sont gérés en fonction de leur relation à ce qui s'est passé avant. Ainsi, netfilter permet de voir les paquets comme faisant partie d'une connection et pas simplement comme des colis. Cette logique de connection s'applique très tôt après que le paquet soit arrivé sur l'interface réseau. La table raw ne sert qu'à une chose : permettre de marquer les paquets pour s'échapper de cette logique de connection.
- security : Utilisée pour gérer les marques en lien avec le contexte de sécurité interne de SELinux.
Lien entre tables et chaînes
Le tableau qui suit indique quelles chaînes sont dispo pour chaque table, de gauche à droite en fonction de l'ordre des hooks. Lu de haut en bas, il indique l'ordre dans lequel les tables accèdent aux hooks. Il faut noter que la table NAT a été subdivisée : DNAT est pour Destination NAT et SNAT pour Source NAT. On indique aussi des points du routage sont prises et ou la gestion des connections est activées afin de donner une vue généraliste du processus :
Ordre de traversée des chaînes
En supposant qu'on sait comment router le paquet et qu'il a le droit d'être là en fonction des règles de fw, le flux suivant représente le chemin traversé selon la situation:
- Paquets entrant pour le système local : PREROUTING -> INPUT
- Paquets entrants à forwarder : PREROUTING -> FORWARD -> POSTROUTING
- Paquets générés localement : OUTPUT -> POSTROUTING
Ainsi, un paquet entrant pour le système local va passer par PREROUTING et activer les chaînes des tables raw, mangle, nat; puis par INPUT et activer les chaines des tables mangle,filter,security,nat. Dans cet ordre.
Règles IPTables
Les règles se placent à l'intérieur des chaînes. Lorsqu'un paquet déclenche la chaîne, il est comparé aux règles, une par une et dans l'ordre.
Match
La portion 'matching' d'une règle spécifie les critères pour lesquels un paquet pour l'action (ou target) de la règle soit exécutée. Le système de matching est souple et peut être étendu à l'aide des extensions d'IPTables disponibles au niveau du système. Les règles peuvent matcher sur :
- protocole
- adresse source / dst
- port source / dst
- réseau source / dst
- interface entrée / sortie,
- les headers
- l'état de la connection
- et autres, les critères pouvant être combinés.
Targets
Les targets, qui sont les actions déclenchées lors d'un match, peuvent être divisées en 2 catégories:
- Terminating targets : Ce genre de target termine l'évaluation de la chaîne : on ne traite plus de règles après celles-ci et on renvoie le contrôle au hook netfilter. En fonction de la valeur retournée, on peut dropper le paquet ou le laisser continuer sur la chaine.
- Non-terminating targets : Celles-ci ne terminent pas l'évaluation de la chaîne. Elles font une action et laisse l'évaluation de la chaîne continuer. Bien que toute chaîne doive donner une décision finale, un certain nombre de non-terminating targets peuvent avoir lieu entretemps.
La disponibilité de chacune des targets dépend de la table et de la chaîne, cela est fonction du contexte.
Liste des targets
Possiblement non exhaustif, c'est le bordel.
Standard:
- <user-defined-chain> — Replace <user-defined-chain> with the name of a user-defined chain within the table. This target passes the packet to the target chain.
- ACCEPT — Allows the packet to successfully move on to its destination or another chain.
- DROP — Drops the packet without responding to the requester. The system that sent the packet is not notified of the failure.
- QUEUE — The packet is queued for handling by a user-space application.
- RETURN — Stops checking the packet against rules in the current chain. If the packet with a RETURN target matches a rule in a chain called from another chain, the packet is returned to the first chain to resume rule checking where it left off. If the RETURN rule is used on a built-in chain and the packet cannot move up to its previous chain, the default target for the current chain decides what action to take.
- LOG — Logs all packets that match this rule. Since the packets are logged by the kernel, the /etc/syslog.conf file determines where these log entries are written. By default, they are placed in the /var/log/messages file.
<source>
Additional options can be used after the LOG target to specify the way in which logging occurs:
--log-level — Sets the priority level of a logging event. A list of priority levels can be found within the syslog.conf man page.
--log-ip-options — Logs any options set in the header of a IP packet.
--log-prefix — Places a string of up to 29 characters before the log line when it is written. This is useful for writing syslog filters for use in conjunction with packet logging.
--log-tcp-options — Logs any options set in the header of a TCP packet.
--log-tcp-sequence — Writes the TCP sequence number for the packet in the log.
</source>
- REJECT — Sends an error packet back to the remote system and drops the packet. The REJECT target accepts --reject-with <type> (where <type> is the rejection type) allowing more detailed information to be sent back with the error packet. The message port-unreachable is the default <type> error given if no other option is used. Available reject options are icmp-net-unreachable, icmp-host-unreachable, icmp-port-unreachable, icmp-proto-unreachable, icmp-net-prohibited and icmp-host-prohibited.
Jumping et chaînes utilisateur
Bien que les chaînes soit fortement liées aux hooks netfilter, l'utilisateur peut créer ses propres chaînes qui seront prises en compte. Les jump targets sont des actions qui font que l'évaluation passera à une autre chaîne pour prise en compte. Les règles vont dans les chaînes utilisateurs de la même manière que pour les autres chaînes; cependant, elle ne seront atteintes qu'après un jump vers celle-ci. En effet, les chaînes utilisateur n'agissent que comme une extension de la chaîne y menant : lors de l'évaluation dans une chaîne utilisateur, l'évaluation retournera à la chaîne d'origine si on atteint une target RETURN ou le bout de la chaîne utilisateur. L'évaluation peut aussi JUMP vers une autre chaîne.
Suivi de connexions
Le suivi de connexion implémenté par-dessus netfilter a déjà été évoqué avec la table raw. Ce suivi de connexion permet à iptables de voir les paquets dans le contexte d'une connexion et non pas comme un simple paquet tout seul et ainsi d'avoir un pare-feu stateful.
Le suivi de connexion s'applique très tôt après l'arrivée d'un paquet dans la stack, et la seule logique appliquée avant ça est la table raw ainsi que certains contrôles de sanité. Le système vérifie chaque paquet en regard d'un ensemble de connexions existantes, et mets à jour le statut des connexions si besoin. Les paquets marqués avec NOTRACK dans une règle de la table raw échapperont à cette logique de connexion.
Une connexion peut avoir plusieurs états:
- NEW : Si un paquet arrive, qu'il n'est pas associé à une connexion et est valide en tant que premier paquet, une connexion NEW est ajoutée. Cela se produit pour TCP par exemple, mais aussi pour des protocoles sans connexion comme UDP.
- ESTABLISHED : Une connection NEW qui reçoit une réponse valide passe à l'état ESTABLISHED. En TCP, cela signifie un syn/ack, et pour UDP ou ICMP une réponse ou la source et la destination du paquet sont inversées par rapport au premier paquet.
- RELATED : Les paquets ne faisant pas partie d'une connexion mais étant en lien avec l'une de celles-ci sont marqués RELATED. Cela peut signifier une connexion "helper", comme avec le FTP et ses transmissions d'envoi de données ou bien des réponses ICMP à des tentatives de connexion d'autres protocoles.
- INVALID : Les paquets n'étant pas liés à une connexion et ne pouvant pas commencer une connexion sont marqués comme INVALID. Ils peuvent par exemple être impossible à identifier, inroutables, etc.
- UNTRACKED : Les paquets seront marqués UNTRACKED si une règle de la table raw leur fait bypasser le tracking.
- SNAT : État virtuel dans lequel l'adresse source a été altérée par le NAT. Utilisé par le système de tracking pour qu'il soit au courant qu'il doit changer l'adresse lors de la réponse.
- DNAT : Même chose, mais avec l'adresse de destination. Ainsi, le système saura qu'il doit changer l'adresse de réponse lors du routage du paquet.
Aller plus loin
Article sur les stratégies de fw
Commandes
Sauvegarder les règles
Par défaut, les règles iptables ne persistent pas après un reboot.
Système Debian et dérivés
sudo apt install iptables-persistent #Toutes les règles sont sauvegardées à l'install sudo iptables-save > /etc/iptables/rules.v4 #OR sudo ip6tables-save > /etc/iptables/rules.v6
Systèmes RedHat et dérivés
Si firewallD n'est pas utilisé (sinon il se débrouille très bien... FirewallD c'est bon, mangez-en) :
<nowiki>
sudo dnf install iptables-services
- Les règles sont sauvegardées
sudo iptables-save > /etc/sysconfig/iptables
- OR
sudo ip6tables-save > /etc/sysconfig/ip6tables
Changer la stratégie par défaut
Par défaut, toutes les chaînes finissent sur un ACCEPT. On peut modifier cela facilement: <source> iptables --policy INPUT DROP iptables --policy OUTPUT DROP iptables --policy FORWARD DROP </source>
Commandes d'affichage
Montrer toutes les règles actives: <source> sudo iptables -n -L -v --line-numbers </source>
On peut aussi sélectionner les chaînes :
iptables -L INPUT -n -viptables -L OUTPUT -n -v --line-numbers
...Sélectionner juste une chaîne:
iptables -L INPUT
...Avoir les spécifications des règles
iptables -S INPUT
...Et un comptage des paquets
iptables -L INPUT -v
La commande suivante est utile car elle permet de savoir quelles règles nous bloquent en mettant en surbrillance les règles au moment ou elles matchent.
watch -n1 -d "iptables -vnxL | grep -v -e pkts -e Chain | sort -nk1 | tac | column -t"
Commandes de modification / création de règles
Création d'une règle
La syntaxe en somme:
iptables [-t table] [ -4 pour ipv4, -6 pour ipv6] -I [insérer dans telle chaîne, suivi du numéro de ligne ] -A chaîne [-o interface_sortie] [-i interface entrée] [-p protocole ] [--dport portdestination ] [ --sport portsource] -j TARGET
Par exemple:
iptables -I RH-Firewall-1-INPUT 10 -i eth0 -p tcp --dport 6556 -j ACCEPT
- Modification d'une règle
La modification de règle reprend le principe de l'argument -I (insert) cité ci-dessus, mais avec -R:
iptables -R INPUT 1 -p tcp -s 192.168.0.0/24 --dport 80 -j ACCEPT
Suppression d'une règle
La suppression utilise l'argument -D (delete):
iptables -D INPUT 5
Flush
On peut flush une chaîne ou toutes les chaînes, c'est-à-dire la vider de ses règles avec -F:
iptables -F <chain>
Tout un tas de règles utiles
https://www.andreafortuna.org/2019/05/08/iptables-a-simple-cheatsheet/
Allow Loopback Connections
iptables -A INPUT -i lo -j ACCEPTiptables -A OUTPUT -o lo -j ACCEPT
Allow Established and Related Incoming Connections
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
Allow Established Outgoing Connections
iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT
Internal to External
iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT
Drop Invalid Packets
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
Block an IP Address
iptables -A INPUT -s 192.168.1.10 -j DROP
Block and IP Address and Reject
iptables -A INPUT -s 192.168.1.10 -j REJECT
Block Connections to a Network Interface
iptables -A INPUT -i eth0 -s 192.168.1.10 -j DROP
Allow All Incoming SSH
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -p tcp --sport 22 -m conntrack --ctstate ESTABLISHED -j ACCEPT
Allow Incoming SSH from Specific IP address or subnet
iptables -A INPUT -p tcp -s 192.168.1.0/24 --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -p tcp --sport 22 -m conntrack --ctstate ESTABLISHED -j ACCEPT
Allow Outgoing SSH
iptables -A OUTPUT -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT iptables -A INPUT -p tcp --sport 22 -m conntrack --ctstate ESTABLISHED -j ACCEPT
Allow Incoming Rsync from Specific IP Address or Subnet
iptables -A INPUT -p tcp -s 192.168.1.0/24 --dport 873 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -p tcp --sport 873 -m conntrack --ctstate ESTABLISHED -j ACCEPT
Allow Incoming HTTP
iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -p tcp --sport 80 -m conntrack --ctstate ESTABLISHED -j ACCEPT
Allow Incoming HTTPS
iptables -A INPUT -p tcp --dport 443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -p tcp --sport 443 -m conntrack --ctstate ESTABLISHED -j ACCEPT
Allow Incoming HTTP and HTTPS
iptables -A INPUT -p tcp -m multiport --dports 80,443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -p tcp -m multiport --dports 80,443 -m conntrack --ctstate ESTABLISHED -j ACCEPT
Allow MySQL from Specific IP Address or Subnet
iptables -A INPUT -p tcp -s 192.168.1.0/24 --dport 3306 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -p tcp --sport 3306 -m conntrack --ctstate ESTABLISHED -j ACCEPT
Allow MySQL to Specific Network Interface
iptables -A INPUT -i eth1 -p tcp --dport 3306 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -o eth1 -p tcp --sport 3306 -m conntrack --ctstate ESTABLISHED -j ACCEPT
Allow PostgreSQL from Specific IP Address or Subnet
iptables -A INPUT -p tcp -s 192.168.1.0/24 --dport 5432 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -p tcp --sport 5432 -m conntrack --ctstate ESTABLISHED -j ACCEPT
Allow PostgreSQL to Specific Network Interface
iptables -A INPUT -i eth1 -p tcp --dport 5432 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -o eth1 -p tcp --sport 5432 -m conntrack --ctstate ESTABLISHED -j ACCEPT
Block Outgoing SMTP Mail
iptables -A OUTPUT -p tcp --dport 25 -j REJECT
Allow All Incoming SMTP
iptables -A INPUT -p tcp --dport 25 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -p tcp --sport 25 -m conntrack --ctstate ESTABLISHED -j ACCEPT
Allow All Incoming IMAP
iptables -A INPUT -p tcp --dport 143 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -p tcp --sport 143 -m conntrack --ctstate ESTABLISHED -j ACCEPT
Allow All Incoming IMAPS
iptables -A INPUT -p tcp --dport 993 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -p tcp --sport 993 -m conntrack --ctstate ESTABLISHED -j ACCEPT
Allow All Incoming POP3
iptables -A INPUT -p tcp --dport 110 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -p tcp --sport 110 -m conntrack --ctstate ESTABLISHED -j ACCEPT
Allow All Incoming POP3S
iptables -A INPUT -p tcp --dport 995 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -p tcp --sport 995 -m conntrack --ctstate ESTABLISHED -j ACCEPT
Drop Private Network Address On Public Interface
iptables -A INPUT -i eth1 -s 192.168.1.0/24 -j DROP iptables -A INPUT -i eth1 -s 10.0.0.0/8 -j DROP
Get Facebook AS:
whois -h v4.whois.cymru.com " -v $(host facebook.com | grep "has address" | cut -d " " -f4)" | tail -n1 | awk '{print $1}'
Drop:
for i in $(whois -h whois.radb.net -- '-i origin AS1273' | grep "^route:" | cut -d ":" -f2 | sed -e 's/^[ \t]*//' | sort -n -t . -k 1,1 -k 2,2 -k 3,3 -k 4,4 | cut -d ":" -f2 | sed 's/$/;/') ; do iptables -A OUTPUT -s "$i" -j REJECTdone
Log and Drop Packets
iptables -A INPUT -i eth1 -s 10.0.0.0/8 -j LOG --log-prefix "IP_SPOOF A: " iptables -A INPUT -i eth1 -s 10.0.0.0/8 -j DROP
By default everything is logged to /var/log/messages file:
tail -f /var/log/messagesgrep --color 'IP SPOOF' /var/log/messages
Log and Drop Packets with Limited Number of Log Entries
iptables -A INPUT -i eth1 -s 10.0.0.0/8 -m limit --limit 5/m --limit-burst 7 -j LOG --log-prefix "IP_SPOOF A: " iptables -A INPUT -i eth1 -s 10.0.0.0/8 -j DROP
Drop or Accept Traffic From Mac Address
iptables -A INPUT -m mac --mac-source 00:0F:EA:91:04:08 -j DROP iptables -A INPUT -p tcp --destination-port 22 -m mac --mac-source 00:0F:EA:91:04:07 -j ACCEPT
Block or Allow ICMP Ping Request
iptables -A INPUT -p icmp --icmp-type echo-request -j DROP iptables -A INPUT -i eth1 -p icmp --icmp-type echo-request -j DROP
Specifying Multiple Ports with multiport
iptables -A INPUT -i eth0 -p tcp -m state --state NEW -m multiport --dports ssh,smtp,http,https -j ACCEPT
Load Balancing with random* or nth*
_ips=("172.31.250.10" "172.31.250.11" "172.31.250.12" "172.31.250.13")for ip in "${_ips[@]}" ; do iptables -A PREROUTING -i eth0 -p tcp --dport 80 -m state --state NEW -m nth --counter 0 --every 4 --packet 0 \ -j DNAT --to-destination ${ip}:80done ===
or
_ips=("172.31.250.10" "172.31.250.11" "172.31.250.12" "172.31.250.13")for ip in "${_ips[@]}" ; do iptables -A PREROUTING -i eth0 -p tcp --dport 80 -m state --state NEW -m random --average 25 \ -j DNAT --to-destination ${ip}:80done ===
Restricting the Number of Connections with limit and iplimit*
iptables -A FORWARD -m state --state NEW -p tcp -m multiport --dport http,https -o eth0 -i eth1 -m limit --limit 20/hour --limit-burst 5 -j ACCEPT
or
iptables -A INPUT -p tcp -m state --state NEW --dport http -m iplimit --iplimit-above 5 -j DROP
Maintaining a List of recent Connections to Match Against
iptables -A FORWARD -m recent --name portscan --rcheck --seconds 100 -j DROPiptables -A FORWARD -p tcp -i eth0 --dport 443 -m recent --name portscan --set -j DROP
Matching Against a string* in a Packet’s Data Payload
iptables -A FORWARD -m string --string '.com' -j DROP iptables -A FORWARD -m string --string '.exe' -j DROP
Time-based Rules with time*
iptables -A FORWARD -p tcp -m multiport --dport http,https -o eth0 -i eth1 -m time --timestart 21:30 --timestop 22:30 --days Mon,Tue,Wed,Thu,Fri -j ACCEPT
Packet Matching Based on TTL Values
iptables -A INPUT -s 1.2.3.4 -m ttl --ttl-lt 40 -j REJECT
Protection against port scanning
iptables -N port-scanningiptables -A port-scanning -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s --limit-burst 2 -j RETURNiptables -A port-scanning -j DROP
SSH brute-force protection
iptables -A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -m recent --setiptables -A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -m recent --update --seconds 60 --hitcount 10 -j DROP
Syn-flood protection
iptables -N syn_floodiptables -A INPUT -p tcp --syn -j syn_floodiptables -A syn_flood -m limit --limit 1/s --limit-burst 3 -j RETURN iptables -A syn_flood -j DROPiptables -A INPUT -p icmp -m limit --limit 1/s --limit-burst 1 -j ACCEPT iptables -A INPUT -p icmp -m limit --limit 1/s --limit-burst 1 -j LOG --log-prefix PING-DROP: iptables -A INPUT -p icmp -j DROPiptables -A OUTPUT -p icmp -j ACCEPT
Mitigating SYN Floods With SYNPROXY
iptables -t raw -A PREROUTING -p tcp -m tcp --syn -j CT --notrack iptables -A INPUT -p tcp -m tcp -m conntrack --ctstate INVALID,UNTRACKED -j SYNPROXY --sack-perm --timestamp --wscale 7 --mss 1460 iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
Block New Packets That Are Not SYN
iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
or
iptables -t mangle -A PREROUTING -p tcp ! --syn -m conntrack --ctstate NEW -j DROP
Force Fragments packets check
iptables -A INPUT -f -j DROP
XMAS packets
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
Drop all NULL packets
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
Block Uncommon MSS Values
iptables -t mangle -A PREROUTING -p tcp -m conntrack --ctstate NEW -m tcpmss ! --mss 536:65535 -j DROP
Block Packets With Bogus TCP Flags
iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,SYN FIN,SYN -j DROP iptables -t mangle -A PREROUTING -p tcp --tcp-flags SYN,RST SYN,RST -j DROP iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,RST FIN,RST -j DROP iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,ACK FIN -j DROP iptables -t mangle -A PREROUTING -p tcp --tcp-flags ACK,URG URG -j DROP iptables -t mangle -A PREROUTING -p tcp --tcp-flags ACK,FIN FIN -j DROP iptables -t mangle -A PREROUTING -p tcp --tcp-flags ACK,PSH PSH -j DROP iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL ALL -j DROP iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL NONE -j DROP iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL SYN,FIN,PSH,URG -j DROP iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP
Block Packets From Private Subnets (Spoofing)
_subnets=("224.0.0.0/3" "169.254.0.0/16" "172.16.0.0/12" "192.0.2.0/24" "192.168.0.0/16" "10.0.0.0/8" "0.0.0.0/8" "240.0.0.0/5")for _sub in "${_subnets[@]}" ; do iptables -t mangle -A PREROUTING -s "$_sub" -j DROPdoneiptables -t mangle -A PREROUTING -s 127.0.0.0/8 ! -i lo -j DROP
Iptables, firewalld, et docker
Par défaut, Docker fait un peu ce qu'il veut avec les pare-feux. Notamment, si l'on utilise Firewalld, il ignore ce que l'on fait avec nos tables FirewallD : il se fait ses propres chaînes dans IPTables.
C'est dû au fait que par défaut, Docker est lancé avec l'option --iptables (modifiable semble-t'il dans /etc/daemon.json.
Hors, cela ne nous arrange pas forcément. Pour contrôler la façon dont docker accède au réseau, il va falloir modifier dans iptables sa chaîne DOCKER-USER. Par exemple, dans mon cas, je ne veux pas que l'on puisse accéder à mes conteneurs depuis mon interface menant sur le net, eth0. Je vais donc devoir lui dire :
<source> iptables -I DOCKER-USER 1 -i eth0 -j DROP </source>
Ici, je place ma règle à la première place, car autrement elle se retrouve après la règle qui laisse tout passer. En effet, docker se créée plusieurs chaînes dans IPTables : DOCKER (qu'il ne sert à rien de modifier : ça ne tient pas au reboot dans aucun cas.) et DOCKER-USER que l'on peut modifier.
Mais... Ça n'est pas terrible. J'utilise firewalld sur tous mes serveurs, et j'aimerais bien dire à Docker de ne pas faire joujou avec iptables.
Il va donc falloir lui dire ne plus y toucher ! Pour cela, on va changer ses options de lancement.
Je lui créée un répertoire de config Systemd : <source> mkdir -p /etc/systemd/system/docker.service.d </source>
Puis je lui créée une config modifiant ses options de lancement pour ajouter --iptables=false: <source> [Service] ExecStart= ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --iptables=false </source>
Rechargement des fichiers, redémarrage pour voir : <source> systemctl daemon-reload systemctl restart docker systemctl status docker </source> Puis je reboote pour bien faire le ménage dans les chaînes IPTables. Au redémarrage, un iptables -L ne devrait plus montrer de chaînes DOCKER. Il ne reste plus qu'à vérifier que les conteneurs communiquent correctement.