Je suis sûr que les administrateurs système Linux connaissent assez bien iptables
, l'interface utilisateur du netfilter
framework de filtrage de paquets.
Maintenant, cette "Question" est censée être un wiki communautaire pour rassembler divers bits-n-pièces de iptables
sagesse. Rien n'est trop commun ou trop obscur. Publiez tout ce que vous savez qui pourrait aider les autres à tirer le meilleur parti de iptables
.
ipset
Si vous écrivez un lot de règles similaires basées sur la simple IP, le port ou les deux, envisagez d'utiliser ipset
pour optimiser les performances de netfilter.
Par exemple:
iptables -s 192.168.1.11 -j ACCEPT
iptables -s 192.168.1.27 -j ACCEPT
iptables -s 192.168.1.44 -j ACCEPT
... hundreds of similar rules ...
iptables -s 192.168.251.177 -j ACCEPT
Cela signifie qu'un paquet dont l'adresse source est 192.168.251.177 doit d'abord traverser des centaines de règles avant de pouvoir obtenir son verdict d'ACCEPTER.
Bien sûr, les administrateurs système expérimentés diviseront les règles par sous-réseau. Mais cela encore signifie des centaines de règles.
ipset
à la rescousse!
Tout d'abord, définissez un ensemble IP de type ipmap
:
ipset -N Allowed_Hosts ipmap --network 192.168.0.0/16
Ensuite, remplissez-le avec les adresses:
for ip in $LIST_OF_ALLOWED_IP; do ipset -A Allowed_Hosts $ip; done
Enfin, remplacez les centaines de règles iptables ci-dessus par une règle:
iptables -m set --match-set Allowed_Hosts src -j ACCEPT
Lorsqu'un paquet arrive, netfilter effectue une recherche de bitmap très rapide pour l'IP source (src) du paquet par rapport au Allowed_Hosts
IP Set. Tous les paquets provenant de 192.168.0.0/16 connaîtront une règle. Et croyez-moi, la recherche d'une image bitmap est au moins deux ordres de grandeur plus rapide que l'exécution de centaines de vérifications de règles iptables.
ipset
n'est pas limité aux adresses IP. Il peut également correspondre en fonction des ports, du tuple de port IP, des adresses de réseau/sous-réseau, du tuple IP-MAC, etc. Et il peut correspondre à ces critères comme source ou destination ou un mélange des deux (dans le cas des tuples).
Et enfin, avec ipset
, vous pouvez automatiquement mettre les adresses IP dans les listes noires/blanches. Ces listes noires/listes blanches peuvent également "vieillir", supprimant ainsi automatiquement l'adresse IP après un laps de temps configurable.
Veuillez vous référer à la page de manuel de ipset
pour plus de détails.
Certaines distributions Linux peuvent ne pas prendre en charge 'out-of-the-box' pour ipset
(par exemple, Ubuntu 10.04 a eu ce problème). Sur ces systèmes, une méthode consiste à installer ipset
à partir du code source.
Au lieu de cela, téléchargez la source de ipset
depuis son site Web: http://ipset.netfilter.org/install.html
Alternativement, si vous utilisez xtables-addons
, l'ipset est inclus dans sa source: http: //xtables-addons.sourceforge .net /
#!/bin/bash
WHITELIST=/whitelist.txt
BLACKLIST=/blacklist.txt
#THIS WILL CLEAR ALL EXISTING RULES!
echo 'Clearing all rules'
iptables -F
#
## Whitelist
#
for x in `grep -v ^# $WHITELIST | awk '{print $1}'`; do
echo "Permitting $x..."
$IPTABLES -A INPUT -t filter -s $x -j ACCEPT
done
#
## Blacklist
#
for x in `grep -v ^# $BLACKLIST | awk '{print $1}'`; do
echo "Denying $x..."
$IPTABLES -A INPUT -t filter -s $x -j DROP
done
#!/bin/bash
ALLOWEDTCP="80 3128 3784"
ALLOWEDUDP="3128 3784"
#
## Permitted Ports
#
for port in $ALLOWEDTCP; do
echo "Accepting port TCP $port..."
$IPTABLES -A INPUT -t filter -p tcp --dport $port -j ACCEPT
done
for port in $ALLOWEDUDP; do
echo "Accepting port UDP $port..."
$IPTABLES -A INPUT -t filter -p udp --dport $port -j ACCEPT
done
# Attempt to block portscans
# Anyone who tried to portscan us is locked out for an entire day.
iptables -A INPUT -m recent --name portscan --rcheck --seconds 86400 -j DROP
iptables -A FORWARD -m recent --name portscan --rcheck --seconds 86400 -j DROP
# Once the day has passed, remove them from the portscan list
iptables -A INPUT -m recent --name portscan --remove
iptables -A FORWARD -m recent --name portscan --remove
# These rules add scanners to the portscan list, and log the attempt.
iptables -A INPUT -p tcp -m tcp --dport 139 -m recent --name portscan --set -j LOG --log-prefix "Portscan:"
iptables -A INPUT -p tcp -m tcp --dport 139 -m recent --name portscan --set -j DROP
iptables -A FORWARD -p tcp -m tcp --dport 139 -m recent --name portscan --set -j LOG --log-prefix "Portscan:"
iptables -A FORWARD -p tcp -m tcp --dport 139 -m recent --name portscan --set -j DROP
# Reject spoofed packets
# These adresses are mostly used for LAN's, so if these would come to a WAN-only server, drop them.
iptables -A INPUT -s 10.0.0.0/8 -j DROP
iptables -A INPUT -s 169.254.0.0/16 -j DROP
iptables -A INPUT -s 172.16.0.0/12 -j DROP
iptables -A INPUT -s 127.0.0.0/8 -j DROP
#Multicast-adresses.
iptables -A INPUT -s 224.0.0.0/4 -j DROP
iptables -A INPUT -d 224.0.0.0/4 -j DROP
iptables -A INPUT -s 240.0.0.0/5 -j DROP
iptables -A INPUT -d 240.0.0.0/5 -j DROP
iptables -A INPUT -s 0.0.0.0/8 -j DROP
iptables -A INPUT -d 0.0.0.0/8 -j DROP
iptables -A INPUT -d 239.255.255.0/24 -j DROP
iptables -A INPUT -d 255.255.255.255 -j DROP
# Drop all invalid packets
iptables -A INPUT -m state --state INVALID -j DROP
iptables -A FORWARD -m state --state INVALID -j DROP
iptables -A OUTPUT -m state --state INVALID -j DROP
# Stop smurf attacks
iptables -A INPUT -p icmp -m icmp --icmp-type address-mask-request -j DROP
iptables -A INPUT -p icmp -m icmp --icmp-type timestamp-request -j DROP
iptables -A INPUT -p icmp -m icmp -j DROP
# Drop excessive RST packets to avoid smurf attacks
iptables -A INPUT -p tcp -m tcp --tcp-flags RST RST -m limit --limit 2/second --limit-burst 2 -j ACCEPT
# Don't allow pings through
iptables -A INPUT -p icmp -m icmp --icmp-type 8 -j DROP
Ajoutez des commentaires à vos règles:
-m comment --comment "Comments help to read output of iptables -nvL"
Ajoutez les règles suivantes, de préférence dans -t raw -A PREROUTING
-p tcp --tcp-flags FIN,SYN FIN,SYN -j DROP
-p tcp --tcp-flags SYN,RST SYN,RST -j DROP
-p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,PSH,URG -j DROP
-p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN -j DROP
-p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP
-p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,PSH,ACK,URG -j DROP
Les attaques bloquées sont respectivement:
(n'hésitez pas à modifier les noms des attaques ci-dessus)
echo 1 > /proc/sys/net/ipv4/ip_forward
/sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
L'étape 1 définit le paramètre du noyau pour permettre le transfert IP, l'étape 2 définit une règle iptables qui active NAT sur l'interface eth0.
Ajoutez les règles suivantes, de préférence dans -t raw -A PREROUTING
-p icmp -m u32 ! --u32 "4&0x3FFF=0" -j DROP
-p icmp -m length --length 1492:65535 -j DROP
La première règle bloque tous les paquets ICMP dont le "drapeau de fragmentation" n'est pas 0. (ICMP ne doit jamais être fragmenté; il doit transporter de petites charges utiles)
La seconde règle bloque les paquets ICMP non fragmentés surdimensionnés.
(à partir de mon fichier iptables_tricks.txt, recompilé à partir de nombreux endroits: P)
Fait attendre iptables 15 secondes entre les nouvelles connexions de la même IP sur le port 22 (SSH):
iptables -A INPUT -p tcp -i eth0 -m state --state NEW --dport 22 -m recent --update --seconds 15 -j DROP
iptables -A INPUT -p tcp -i eth0 -m state --state NEW --dport 22 -m recent --set -j ACCEPT
en utilisant FireHOL - wrapper iptables pratique
Je l'ai trouvé beaucoup plus intuitif que les commandes iptables directes. Surtout pour les personnes ayant une expérience passée avec d'autres pare-feu:
FireHOL est un générateur de pare-feu iptables produisant des pare-feu de filtrage de paquets iptables avec état, sur des hôtes et des routeurs Linux avec un nombre illimité d'interfaces réseau, un nombre illimité de routes, un nombre illimité de services servis, un certain nombre de complexité entre les variations des services (y compris positifs et négatifs expressions).
Il existe déjà une réponse mentionnant les ensembles IP. Cependant, il est plutôt unidimensionnel en ce qu'il se concentre sur les gains de performances par rapport aux règles classiques et sur le fait que les ensembles IP atténuent le problème que l'on a avec beaucoup d'adresses IP individuelles qui ne peuvent pas facilement être exprimées sous la forme d'un sous-réseau en notation CIDR.
Pour ipset
j'utiliserai la notation lue par ipset restore
Et écrite par ipset save
.
De même, pour les règles iptables
(et ip6tables
), J'utiliserai la notation lue par iptables-restore
Et écrite par iptables-save
. Cela rend la notation plus courte et me permet de mettre en évidence les règles IPv4 uniquement (préfixées -4
) Ou IPv6 uniquement (préfixées -6
).
Dans certains exemples, nous détournerons le flux de paquets dans une autre chaîne. La chaîne est supposée exister à ce point, donc les lignes pour créer les chaînes ne sont pas produites (ni le nom de la table mentionné ni les commandes COMMIT
- tées à la fin).
Les ensembles IP peuvent faire beaucoup plus que ce qui était mentionné dans l'autre réponse et vous devriez certainement lire la documentation des ensembles IP ( ipset(8)
) avec - iptables-extensions(8)
en plus de cette brève entrée ici.
Par exemple, je me concentrerai principalement sur trois types d'ensembles: hash:ip
, hash:net
Et list:set
, Mais il y en a plus et ils ont tous des cas d'utilisation valides.
Vous pouvez par exemple également faire correspondre les numéros de port, pas seulement les adresses IP .
iptables-save
Et iptables-restore
Vous pouvez créer des déclarations d'ensemble IP en bloc et les importer en les canalisant dans ipset restore
. Si vous souhaitez rendre votre commande plus résistante aux entrées déjà existantes, utilisez ipset -exist restore
.
Si vos règles sont dans un fichier appelé default.set
, Vous utiliseriez:
ipset -exist restore < default.set
Un fichier comme celui-ci peut contenir des entrées dans les ensembles create
et dans les entrées add
. Mais généralement, la plupart des commandes de la ligne de commande semblent avoir une version correspondante dans les fichiers. Exemple (création d'un ensemble de serveurs DNS):
create dns4 hash:ip family inet
create dns6 hash:ip family inet6
# Google DNS servers
add dns4 8.8.8.8
add dns4 8.8.4.4
add dns6 2001:4860:4860::8888
add dns6 2001:4860:4860::8844
Ici, un ensemble est créé pour IPv4 (dns4
) Et un pour IPv6 (dns6
).
Les délais d'expiration dans les ensembles IP peuvent être définis par défaut par ensemble et également par entrée. Ceci est très utile pour les scénarios où vous souhaitez bloquer temporairement quelqu'un (par exemple pour l'analyse de port ou la tentative de forcer brutalement votre serveur SSH).
Le fonctionnement est le suivant (par défaut lors de la création d'ensembles IP):
create ssh_loggedon4 hash:ip family inet timeout 5400
create ssh_loggedon6 hash:ip family inet6 timeout 5400
create ssh_dynblock4 hash:ip family inet timeout 1800
create ssh_dynblock6 hash:ip family inet6 timeout 1800
Nous reviendrons sur ces ensembles particuliers ci-dessous et sur la raison pour laquelle ils sont définis tels qu'ils sont.
Si vous souhaitez définir votre délai d'expiration pour une adresse IP particulière, vous pouvez simplement dire:
add ssh_dynblock4 1.2.3.4 timeout 7200
Pour bloquer IP 1.2.3.4 pendant deux heures au lieu de la demi-heure par défaut (définie).
Si vous regardiez cela avec ipset save ssh_dynblock4
Après un court instant, vous verriez quelque chose du genre:
create ssh_dynblock4 hash:ip family inet hashsize 1024 maxelem 65536 timeout 1800
add ssh_dynblock4 1.2.3.4 timeout 6954
Kernel error received: Unknown error -1
).Sudo ipset add ssh_dynblock4 1.2.3.4 timeout $((120*60))
À l'intérieur de vos scripts, il peut être utile de voir si une entrée existe déjà. Ceci peut être réalisé avec ipset test
Qui retourne zéro si l'entrée existe et non nul sinon. Ainsi, les contrôles habituels peuvent être appliqués dans un script:
if ipset test dns4 8.8.8.8; then
echo "Google DNS is in the set"
fi
Cependant, dans de nombreux cas, vous souhaiterez plutôt utiliser le commutateur -exist
Sur ipset
afin de lui demander de ne pas se plaindre des entrées existantes.
iptables
À mon avis, c'est l'une des principales caractéristiques des ensembles IP. Non seulement vous pouvez comparer les entrées d'un ensemble IP, mais vous pouvez également ajouter de nouvelles entrées à un ensemble IP existant.
Par exemple, dans cette réponse à cette question, vous avez:
-A INPUT -p tcp -i eth0 -m state --state NEW --dport 22 -m recent --update --seconds 15 -j DROP
-A INPUT -p tcp -i eth0 -m state --state NEW --dport 22 -m recent --set -j ACCEPT
... avec l'intention de limiter les tentatives de connexion à SSH (port TCP 22). Le module utilisé recent
garde une trace des tentatives de connexion récentes. Au lieu du module state
, je préfère cependant le module conntrack
.
# Say on your input chain of the filter table you have
-A INPUT -i eth+ -p tcp --dport ssh -j SSH
# Then inside the SSH chain you can
# 1. create an entry in the recent list on new connections
-A SSH -m conntrack --ctstate NEW -m recent --set --name tarpit
# 2. check whether 3 connection attempts were made within 2 minutes
# and if so add or update an entry in the ssh_dynblock4 IP set
-4 -A SSH -m conntrack --ctstate NEW -m recent --rcheck --seconds 120 --hitcount 3 --name tarpit -j SET --add-set ssh_dynblock4 src --exist
-6 -A SSH -m conntrack --ctstate NEW -m recent --rcheck --seconds 120 --hitcount 3 --name tarpit -j SET --add-set ssh_dynblock6 src --exist
# 3. last but not least reject the packets if the source IP is in our
# IP set
-4 -A SSH -m set --match-set ssh_dynblock4 src -j REJECT
-6 -A SSH -m set --match-set ssh_dynblock6 src -j REJECT
Dans ce cas, je redirige le flux vers la chaîne SSH
de sorte que je n'ai pas à me répéter avec -p tcp --dport ssh
Pour chaque règle.
Recommencer:
-m set
Informe iptables
que nous utilisons des commutateurs du module set
(qui gère les ensembles IP)--match-set ssh_dynblock4 src
Indique à iptables
de faire correspondre l'adresse source (src
) à l'ensemble nommé (ssh_dynblock4
) Sudo ipset test ssh_dynblock4 $IP
(où $IP
contient l'adresse IP source du paquet)-j SET --add-set ssh_dynblock4 src --exist
Ajoute ou met à jour l'adresse source (src
) du paquet dans l'ensemble IP ssh_dynblock4
. Si une entrée existe (--exist
), Elle sera simplement mise à jour. Sudo ipset -exist add ssh_dynblock4 $IP
(où $IP
contient l'adresse IP source du paquet)Si vous vouliez plutôt faire correspondre l'adresse cible/destination, vous utiliseriez dst
au lieu de src
. Consultez le manuel pour plus d'options.
Les ensembles IP peuvent contenir d'autres ensembles. Maintenant, si vous avez suivi l'article jusqu'ici, vous vous demanderez s'il est possible de combiner des ensembles. Et bien sûr que ça l'est. Pour les ensembles IP ci-dessus, nous pouvons créer deux ensembles conjoints ssh_dynblock
Et ssh_loggedon
Respectivement pour contenir les ensembles IPv4 uniquement et IPv6 uniquement:
create ssh_loggedon4 hash:ip family inet timeout 5400
create ssh_loggedon6 hash:ip family inet6 timeout 5400
create ssh_dynblock4 hash:ip family inet timeout 1800
create ssh_dynblock6 hash:ip family inet6 timeout 1800
# Sets of sets
create ssh_loggedon list:set
create ssh_dynblock list:set
# Populate the sets of sets
add ssh_loggedon ssh_loggedon4
add ssh_loggedon ssh_loggedon6
add ssh_dynblock ssh_dynblock4
add ssh_dynblock ssh_dynblock6
Et la question suivante qui devrait vous venir à l'esprit est de savoir si cela nous permet de correspondre et de manipuler les ensembles IP d'une manière indépendante de la version IP.
Et la réponse à cette question est retentissante: OUI! (hélas, cela n'a pas été explicitement documenté la dernière fois que j'ai vérifié)
Par conséquent, les règles de la section précédente peuvent être réécrites pour se lire:
-A INPUT -i eth+ -p tcp --dport ssh -j SSH
-A SSH -m conntrack --ctstate NEW -m recent --set --name tarpit
-A SSH -m conntrack --ctstate NEW -m recent --rcheck --seconds 120 --hitcount 3 --name tarpit -j SET --add-set ssh_dynblock src --exist
-A SSH -m set --match-set ssh_dynblock src -j REJECT
ce qui est beaucoup plus concis. Et oui, cela a été essayé et testé et fonctionne comme un charme.
Sur mes serveurs, j'ai un script exécuté comme un travail cron
qui prend un tas de noms d'hôte et les résout en adresses IP, puis les injecte dans l'ensemble IP pour les "hôtes de confiance". L'idée est que les hôtes de confiance obtiennent plus de tentatives de connexion au serveur et ne sont pas nécessairement bloqués aussi longtemps que quiconque.
À l'inverse, des pays entiers ne peuvent pas se connecter à mon serveur SSH, à l'exception (potentielle) des hôtes de confiance (c'est-à-dire que l'ordre des règles est important).
Cependant, cela reste un exercice pour le lecteur. Ici, je voudrais ajouter une solution soignée qui utilisera les ensembles contenus dans l'ensemble ssh_loggedon
Pour permettre aux tentatives de connexion ultérieures d'être transmises et ne pas être soumises au même examen minutieux que les autres paquets.
Il est important de se rappeler les délais d'expiration par défaut de 90 minutes pour ssh_loggedon
Et de 30 minutes pour ssh_dynblock
Lors de l'examen des règles iptables
suivantes:
-A INPUT -i eth+ -p tcp --dport ssh -j SSH
-A SSH -m set --match-set ssh_loggedon src -j ACCEPT
-A SSH -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A SSH -m conntrack --ctstate NEW -m recent --set --name tarpit
-A SSH -m conntrack --ctstate NEW -m recent --rcheck --seconds 120 --hitcount 3 --name tarpit -j SET --add-set ssh_dynblock src --exist
-A SSH -m set --match-set ssh_dynblock src -j REJECT
Vous devriez maintenant vous demander comment l'adresse IP de connexion se retrouve dans les sous-ensembles ssh_loggedon
. Alors lisez la suite ...
Si vous avez expérimenté avec sshrc
et vos amis, vous aurez appris ses défauts. Mais PAM vient à la rescousse. Un module nommé pam_exec.so
Nous permet d'appeler un script lors de la connexion SSH à un point où nous savons que l'utilisateur est admis.
Dans /etc/pam.d/sshd
Sous les entrées pam_env
Et pam_selinux
, Ajoutez la ligne suivante:
session optional pam_exec.so stdout /path/to/your/script
et assurez-vous que votre version du script (/path/to/your/script
ci-dessus) existe et est exécutable.
PAM utilise des variables d'environnement pour communiquer ce qui se passe, vous pouvez donc utiliser un script simple comme celui-ci:
#!/bin/bash
# When called via pam_exec.so ...
SETNAME=ssh_loggedon
if [[ "$PAM_TYPE" == "open_session" ]] && [[ -n "$PAM_RHOST" ]]; then
[[ "x$PAM_RHOST" != "x${PAM_RHOST//:/}" ]] && SETNAME="${SETNAME}6" || SETNAME="${SETNAME}4"
ipset -exist add $SETNAME "$PAM_RHOST"
fi
Malheureusement, l'utilitaire ipset
ne semble pas avoir l'intelligence intégrée de netfilter. Nous devons donc faire la distinction entre IPv4 et IPv6 IP set lors de l'ajout de notre entrée. Sinon, ipset
supposera que nous voulons ajouter un autre set à l'ensemble des ensembles, au lieu de l'IP. Et bien sûr, il est peu probable qu'il y ait un ensemble nommé d'après une adresse IP :)
Nous vérifions donc :
Dans l'adresse IP et ajoutons 6
Au nom défini dans ce cas et 4
Sinon.
La fin.
Tutoriels vidéo IPTABLES
Épisode 1 http://www.youtube.com/watch?v=ldB8kDEtTZA&feature=player_embedded
Épisode 2 http://www.youtube.com/watch?v=aDaEXxRHeXY&feature=related
Dernier épisode
http://www.youtube.com/watch?v=JojqHKcSxpo&feature=player_embedded
Sera un bon début pour tout débutant.
Une autre interface graphique qui peut être utilisée pour configurer iptables est Firewall Builder . Il permet aux utilisateurs de créer des éléments de règle en tant qu'objets dans une base de données, puis de faire glisser et déposer ces objets dans un éditeur de règles pour créer la stratégie de pare-feu souhaitée. L'application génère ensuite un fichier de script avec toutes les commandes iptables requises pour implémenter les règles.
Contrairement à d'autres solutions GUI iptables où vous ne pouvez gérer qu'une seule configuration iptables à la fois, avec Firewall Builder vous pouvez gérer un grand nombre de configurations iptables à partir d'une seule application. Firewall Builder fonctionne sous Linux, Windows et Mac OS X, existe depuis plus de 10 ans et compte des milliers d'utilisateurs actifs à travers le monde.
Divulgation complète - Je suis le co-fondateur de NetCitadel, qui est la société qui développe Firewall Builder.
Exemple: vous avez eth0
eteth1
et vous souhaitez autoriser tout trafic entre eux?
iptables -A FORWARD -i eth+ -o eth+ -j ACCEPT
Je l'ai utilisé dans le passé afin de faire correspondre le veth<something>
interfaces créées dynamiquement et nommées par LXC. Je peux donc faire correspondre tout à la fois avec veth+
.
J'ai aussi intentionnellement nommé quelques interfaces _<something>
pour faire face à _+
.
Limiter toutes les adresses IP individuelles à un quota de bande passante sortante avec les ensembles IP
Vous pouvez, s'il vous plaît, configurer votre serveur pour n'autoriser que chaque IP individuelle de 15 Go d'utilisation de la bande passante par mois, dans l'espoir de refléter ou d'esquiver une attaque d'utilisation de la bande passante, peut-être pour votre quota de bande passante mesurée chez votre FAI. Cela peut être accompli comme suit:
Créez d'abord les ensembles IP pour IPv4 et IPv6:
ipset create IP_QUOTA_SET_OUT hash:ip timeout 345600 counters
ipset create IP_QUOTA_SET_OUT_INET6 hash:ip timeout 345600 counters family inet6
Ajoutez maintenant vos règles iptables. La première ligne ajoutera l'IP à l'ensemble s'il n'est pas déjà là. La deuxième ligne ne correspondra pas si les octets transférés pour l'IP dans l'ensemble sont supérieurs à la quantité spécifiée. Ensuite, il en va de même pour IPv6.
iptables -I OUTPUT -m set ! --match-set IP_QUOTA_SET_OUT dst -j SET --add-set IP_QUOTA_SET_OUT dst --timeout 345600
iptables -I OUTPUT -m set --match-set IP_QUOTA_SET_OUT dst --bytes-gt 16106127360 -j DROP
ip6tables -I OUTPUT -m set ! --match-set IP_QUOTA_SET_OUT_INET6 src -j SET --add-set IP_QUOTA_SET_OUT_INET6 src --timeout 345600
ip6tables -I OUTPUT -m set --match-set IP_QUOTA_SET_OUT_INET6 src --bytes-gt 16106127360 -j DROP
Cela empêchera les attaques telles qu'un utilisateur demandant un fichier volumineux à votre serveur Web pendant une longue période ou à tout autre service d'ailleurs. La même chose peut être faite pour la chaîne INPUT.
journal connexion sortante avec uid
iptables -A OUTPUT -m state --state NEW -m tcp -p tcp -m limit --limit 5/m -j LOG --log-uid --log-prefix="outgoing connection: "
redirection de port/connexion:
iptables -A PREROUTING -t nat -i eth1 -p tcp --dport 80 -j DNAT --to 10.0.1.7:80
iptables -A INPUT -p tcp -m state --state NEW --dport 80 -i eth1 -j ACCEPT
iptables -t mangle -A PREROUTING -p tcp \
-m conntrack --ctstate NEW -m tcpmss ! --mss 536:65535 -j DROP
Le but de cette cible est de vérifier si l'hôte qui a envoyé le paquet SYN établit la connexion ou ne fait rien après avoir lancé la connexion SYN. S'il ne fait rien, il jette le paquet avec un minimum d'effort.
Définissez les paquets de synchronisation sur la table de suivi des connexions dans la table brute
iptables -t raw -A PREROUTING -p tcp -m tcp --dport 80 --syn -j CT --notrack
Activez le synproxy pour le serveur http:
iptables -A INPUT -p tcp -m tcp --dport 80 -m conntrack --ctstate INVALID,UNTRACKED \
-j SYNPROXY --sack-perm --timestamp --wscale 7 --mss 1460
Ressource: cible SYNPROXY du blog RHEL
Je suis d'accord avec les commentaires sur les ipsets et les drapeaux tcp, mais il manque encore beaucoup:
Utilisez xtables-addons geoip match au lieu des ipsets pour les listes de pays. Mettez à jour les données geoip régulièrement (au moins une fois par mois). Les données sont plus dynamiques qu'une liste d'ipsets à tirer et oublier.
Envisagez le suivi de l'état de la connexion avec les drapeaux TCP. Par exemple, un RST ou un ACK tcp n'a de sens que pour une connexion établie. SYN n'a de sens que pour les connexions nouvelles et connexes. Un SYN pour une connexion établie signifie que votre SYN + ACK a été perdu ou une tentative de piratage et doit être réinitialisé car les deux côtés de la connexion ne s'entendent pas sur l'état.
Bien qu'aucune, SYN + RST et FIN + RST soient des combinaisons illégales, SYN + FIN est maintenant valide sous TCP ouverture rapide (option TCP 34), en particulier pour DNS. Les paquets SYN, même avec fast -open, ne doit pas être fragmenté. Je ne considère pas les règles avec les indicateurs PSH et URG comme utiles. Ne confondez pas l'état de suivi de connexion avec TCP état: une réponse RST à un paquet SYN est établi à des fins de suivi.
SYNPROXY est pour les paquets transférés et n'ajoute rien pour ceux livrés localement au-delà de la prise en charge des syncookies.
Les paquets d'erreur ICMP seront toujours dans l'état associé et de longueur 48: 576 s'ils sont valides. Longueur 84: 1280 pour IPv6. Tous les autres doivent être ignorés. Comme leur taille maximale est également la MTU minimale, ils ne doivent jamais être fragmentés. Les requêtes ICMP (pings, horodatages, etc.) seront toujours nouvelles et les réponses établies. Supprimez les paquets ICMP dans d'autres états.
Comme l'exemple SSH avec une liste récente et n'acceptant que les paquets SYN ultérieurs, la même chose devrait être faite pour SMTP et est similaire à la "liste grise" sur la donnée d'adresse IP seule.
Dans la table de filtrage, la première règle (ou la seconde, si vous acceptez d'abord les paquets d'états établis) dans les chaînes d'entrée et de sortie doit tout accepter sur l'interface de bouclage. Vous devez faire confiance à vos propres paquets internes. Si vous ne pouvez pas, vous avez de plus gros problèmes au-delà d'une solution de pare-feu.
Enfin, ne copiez pas les règles à l'aveugle à moins que vous ne compreniez vraiment ce qu'elles font. De nombreuses listes de règles similaires font cela, et la plupart du temps, le résultat est risible.