Limitez le nombre maximal de connexions par adresse IP et de nouvelles connexions par seconde avec iptables

37

Nous avons un serveur Ubuntu 12.04 avec httpd sur le port 80 et nous voulons limiter:

  • le nombre maximal de connexions par adresse IP entre httpd et 10
  • le maximum de nouvelles connexions par seconde à httpd à 150

Comment pouvons-nous faire cela avec iptables?

evachristine
la source

Réponses:

48
iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 15 --connlimit-mask 32 -j REJECT --reject-with tcp-reset  

Cela rejettera les connexions supérieures à 15 à partir d'une adresse IP source.

iptables -A INPUT -m state --state RELATED,ESTABLISHED -m limit --limit 150/second --limit-burst 160 -j ACCEPT  

Dans cette configuration, 160 nouvelles connexions (paquets réellement) sont autorisées avant que la limite de 150 nouvelles connexions (paquets) par seconde ne soit appliquée.

totti
la source
1
Ce qui précède peut-il être configuré pour fonctionner sur tous les ports, pas seulement le port 80?
EminezArtus
1
Êtes-vous sûr que c'est par IP?
LatinSuD
2
Pour définir cette règle pour tous les ports, supprimez simplement le --dport 80.
Dan Pritts
5
La deuxième règle ne fonctionne pas sur les "nouvelles connexions". Cela affecte explicitement les connexions existantes ("ESTABLISHED"). Pour faire de nouvelles connexions, vous voudriez --state NEW. Vous pouvez également envisager d'utiliser -m conntrack --ctstateà la place de -m state --state. conntrack est nouveau et amélioré par rapport à l'état.
Dan Pritts
2
le commentaire ci-dessus pour l'ajout de la 2ème règle aux NEWconnexions - ne faites pas cela - il transforme effectivement votre INPUTchaîne en défaut accept!!!
Stuart Cardall
8

Vous voulez que les règles suivantes dans votre iptables répondent aux deux exigences de votre question:

iptables -t filter -I INPUT -p tcp --dport 80 -j ACCEPT

iptables -t filter -I INPUT -p tcp --dport 80 -m state \
  --state RELATED,ESTABLISHED -j ACCEPT

# Adjust "--connlimit-above NN" to limit the maximum connections per IP
#   that you need.
iptables -t filter -I INPUT -p tcp --syn --dport 80 -m connlimit \
  --connlimit-above 10 --connlimit-mask 32 -j DROP

# Adjust "--connlimit-above NNN" to the maximum total connections you
#   want your web server to support
iptables -t filter -I INPUT -p tcp --syn --dport 80 -m connlimit \
  --connlimit-above 150 -j DROP

Parce que nous utilisons -I (conformément à la demande OP), nous devons les faire dans l’ordre inverse afin de les «lire» de bas en haut.

Je suggère également d’envisager une modification de --connlimit-mask NN de 32 à 24. Ceci limitera un réseau complet de classe C (maximum 256 adresses IP dans la même plage) à 10 connexions. Vous pouvez également utiliser n'importe quel autre nombre sans classe comme 22 ou 30, selon la manière dont votre service pourrait être utilisé.

En fonction de la manière dont vous souhaitez que le client se comporte, vous pouvez également utiliser "-j REJECT --reject-with tcp-reset" au lieu de "-j DROP" dans les deux règles ci-dessus, ou même dans les 150 connexions max. règle.

Si vous REFUSEZ la connexion, le navigateur ou le logiciel utilisant le port 80 affichera immédiatement le statut "non disponible", mais l'option DROP fera attendre et réessayer le client plusieurs fois avant de signaler le site comme non disponible. J'ai tendance à m'appuyer moi-même sur DROP, qui se comporte davantage comme une mauvaise connexion que comme un serveur hors ligne.

De plus, si la limite de connexion redescend en dessous de 150 (ou 10) alors que la tentative est en cours, le serveur parviendra à son tour.

L'option REJECT entraînera une fraction de moins de trafic sur votre site, car DROP lui enverra des paquets supplémentaires pendant ses tentatives. Probablement pas tout ce qui est pertinent.

Si, en revanche, le trafic du port 80 fait partie d'un cluster, REJECT informe alors le contrôleur de cluster de son arrêt et arrête de lui envoyer du trafic pendant la durée de son délai d'attente avant tentative.

La règle RELATED, ESTABLISHED est présente dans l'hypothèse où votre règle par défaut consiste à bloquer tout le trafic (iptables -t filter -P INPUT DROP). Cela accepte uniquement les paquets appartenant aux connexions acceptées.

De plus, --syn lui dit de faire attention (ou de compter) les paquets qui établissent une connexion TCP.

Ian Macintosh
la source
Merci d'avoir parcouru la minutie de ces commandes.
Txyoji
Puis-je obtenir --connlimit-mask uniquement pour bloquer cette adresse IP spécifique et non une plage entière?
Analogique
--Connlimit-mask 32 est une adresse unique. C'est à dire, c'est comme un masque de réseau / 32. N'importe quoi de moins, comme 24, c'est comme un masque de réseau / 24, en ignorant les 8 bits inférieurs.
Ian Macintosh
5

Vous devez utiliser les connlimitmodules, ce qui vous permet de limiter le nombre de connexions TCP parallèles à un serveur par adresse IP client (ou bloc d'adresse).

/sbin/iptables -I INPUT -p tcp --syn --dport 80 -m connlimit \
      --connlimit-above 10 -j DROP
Raman_Singh
la source
J'ai mis à jour votre réponse, j'espère que c'est toujours correct (pourquoi "--syn" est-il nécessaire?). + Et que dire de "La connexion maximale par seconde (port 80, TCP) à 150"? Merci!
Evachristine
--syn signifie que la règle ne considère que les paquets TCP avec l'indicateur syn - ce qui signifie de nouvelles connexions. Vous pouvez faire à peu près la même chose avec -m state --state NEW, mais c'est probablement plus rapide.
Dan Pritts