Limiter les requêtes http/Apache avec IpTables

Hello hello,
Je me retrouve avec plein de requêtes sur mon serveur du type ci-dessous.
Je voulais savoir comment limiter avec IpTables ce genre de demande ?
J’utilises déjà fail2ban mais il les bloque 5 à 10 secondes après, ce qui permet de lancer 20,30 voir 50 demandes…
Merci par avance pour vos réponses.

[Sat Nov 25 19:09:34 2017] [error] [client 85.233.150.58] File does not exist: /var/www/default/events
[Sat Nov 25 19:12:36 2017] [error] [client 85.233.150.58] File does not exist: /var/www/default/media-rss
[Sat Nov 25 19:12:36 2017] [error] [client 85.233.150.58] File does not exist: /var/www/default/data
[Sat Nov 25 19:12:36 2017] [error] [client 85.233.150.58] File does not exist: /var/www/default/events
[Sat Nov 25 19:12:36 2017] [error] [client 85.233.150.58] File does not exist: /var/www/default/events
[Sat Nov 25 19:12:36 2017] [error] [client 85.233.150.58] File does not exist: /var/www/default/news
[Sat Nov 25 19:12:36 2017] [error] [client 85.233.150.58] File does not exist: /var/www/default/news
[Sat Nov 25 19:12:36 2017] [error] [client 85.233.150.58] File does not exist: /var/www/default/data
[Sat Nov 25 19:12:36 2017] [error] [client 85.233.150.58] File does not exist: /var/ww »w/default/rss.xml

Tu as plusieurs extensions (limit, connlimit, hashlimit) qui permettent de limiter différentes choses http://ipset.netfilter.org/iptables-extensions.man.html
Elles s’utilisent en indiquant dans ta règle le module d’extension (ex: -m limit) suivi des arguments liés à l’extension.
Exemples donnés pour connlimit:

# limit the number of parallel HTTP requests to 16 per class C sized source network (24 bit netmask)
iptables -p tcp --syn --dport 80 -m connlimit --connlimit-above 16 --connlimit-mask 24 -j REJECT
# limit the number of parallel HTTP requests to 16 for the link local network
(ipv6) ip6tables -p tcp --syn --dport 80 -s fe80::/64 -m connlimit --connlimit-above 16 --connlimit-mask 64 -j REJECT
# Limit the number of connections to a particular host:
ip6tables -p tcp --syn --dport 49152:65535 -d 2001:db8::1 -m connlimit --connlimit-above 100 -j REJECT

Mais si ton serveur est sensible sur un crawl de bot russe qui fait 5 demandes par secondes, c’est que tu as un problème de performance à régler.

hello mattotop,
merci de t’intéresser à mon pb.
no no j’ai pas de pb de performance , 16Go de RAM avec un proc bien véloce quad-core :slight_smile:
j’ai suivie ce tuto avec ces règles en particulier qui, je pensais, feraient l’affaire -->
iptables -A FORWARD -p tcp --syn -m limit --limit 1/second -j ACCEPT
iptables -A FORWARD -p udp -m limit --limit 1/second -j ACCEPT
iptables -A FORWARD -p icmp --icmp-type echo-request -m limit --limit 1/second -j ACCEPT

ton avis ?

Mon avis, c’est qu’une règle FORWARD, c’est sur ce qui traverse ton noyau, mais pas ce qui rentre, qui passe par la INPUT.
Donc je ne sais pas quel est l’objectif du tuto, c’est une règle standard de protection contre le syn flood, mais je ne sais pas comment ça marche un syn flood, et les règles ne s’appliquent pas pour ce que tu veux faire.

Aprés, faut tester, parceque je ne suis pas le meilleur et il y a peut être mieux, mais “bourrinement”, je dirais juste intuitivement:
iptables -A INPUT -p tcp --dport 80 -m limit --limit 1/second -j ACCEPT
iptables -A INPUT -p udp --dport 80 -m limit --limit 1/second -j ACCEPT

Mais bon, moi référenceur, si un de mes clients m’empêche de crawler son site à moins de 5 urls par seconde, je l’engueule parce que je ne peux pas bosser, ça fait quand même pas beaucoup comme rythme considéré comme légitime.
Pareil, comme surfeur, ça m’arrive d’ouvrir dix pages d’un site en même temps , si c’est limité à un onglet qui se charge, moi ça me gonfle.
Donc pour le fun, voir si tu arrives à limiter OK, mais puisque le bot ne met pas down ta machine, je laisserais juste de fail2ban comme protection.

J’appelle ça de l’auto-DoS. Du sabotage pur et simple de son propre service, en somme.

Pour répondre à la question initiale, iptables ne peut pas limiter ce genre de requête de façon fiable. C’est un filtre de paquets, pas un filtre applicatif.

Certes on peut utiliser la correspondance “string” d’iptables pour repérer une chaîne de caractères dans un paquet, mais elle est incapable de dire si cette chaîne se trouve dans le chemin de l’URL ou dans un autre élément de la communication. Et un attaquant malicieux pourrait scinder cette chaîne entre deux paquets consécutifs pour éviter ce genre de détection simpliste.

Si tu as peur pour ton serveur, il faut mettre un reverse proxy en frontal pour filtrer les requêtes HTTP au niveau applicatif.

Salut PascalHambourg, merci pour ta réponse.
Donc pour toi on se coupe le bras avec ce genre de restriction IpTables ?
Pour te donner plus de matière j’ai mis ça sur mon serveur pour Iptables(ci-dessous).
J’étais persuadé que ça limiterai le flood pour avoir accès à mes répertoires.
Je tiens à te préciser que ce n’est pas critique mais j’aimerai mieux comprendre comment contrer ce genre de flood avec Netfilter/iptables.
Si vous avez des conseils je suis preneur.
Merci encore par avance de partager avec nous vos savoirs.

PS: je suis en train de checker le proxy inversé, c’est complexe pour un newbie comme moi mais je suis preneur pour ma culture et je vais approfondir

### Infos
# 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: Demarrage du script du firewall
# Description:       Regles du firewall
### Fin Infos

#!/bin/sh
case "$1" in
start)

########## Initialisation ##########
# Vidage des tables
iptables -t filter -F
iptables -t filter -X

# Interdire toutes connexions entrantes et sortantes
iptables -t filter -P INPUT DROP
iptables -t filter -P FORWARD DROP
iptables -t filter -P OUTPUT DROP

# Ne pas casser les connexions etablies
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

########## Regles ##########
# Trafic local
iptables -t filter -A INPUT -i lo -j ACCEPT
iptables -t filter -A OUTPUT -o lo -j ACCEPT

# Ping
iptables -t filter -A INPUT -p icmp -j ACCEPT
iptables -t filter -A OUTPUT -p icmp -j ACCEPT

# SSH
iptables -t filter -A INPUT -p tcp --dport PORT_SSH -j ACCEPT
iptables -t filter -A OUTPUT -p tcp --dport PORT_SSH -j ACCEPT

# DNS
iptables -t filter -A INPUT -p tcp --dport 53 -j ACCEPT
iptables -t filter -A OUTPUT -p tcp --dport 53 -j ACCEPT
iptables -t filter -A INPUT -p udp --dport 53 -j ACCEPT
iptables -t filter -A OUTPUT -p udp --dport 53 -j ACCEPT

# NTP
iptables -t filter -A OUTPUT -p udp --dport 123 -j ACCEPT

# FTP
modprobe ip_conntrack
modprobe ip_conntrack_ftp
iptables -t filter -A INPUT -p tcp --dport 20:21 -j ACCEPT
iptables -t filter -A OUTPUT -p tcp --dport 20:21 -j ACCEPT
iptables -t filter -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# FTP  passif
iptables -A OUTPUT -o eth0 -p tcp --dport 1024:65535 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

# HTTP
iptables -t filter -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -t filter -A OUTPUT -p tcp --dport 80 -j ACCEPT

# HTTPS
iptables -t filter -A INPUT -p tcp --dport 443 -j ACCEPT
iptables -t filter -A OUTPUT -p tcp --dport 443 -j ACCEPT
iptables -t filter -A INPUT -p tcp --dport 8443 -j ACCEPT

# MYSQL
iptables -t filter -A INPUT -p tcp --dport PORT_MYSQL -j ACCEPT
iptables -t filter -A OUTPUT -p tcp --dport PORT_MYSQL -j ACCEPT

# SMTP
iptables -t filter -A INPUT -p tcp --dport 25 -j ACCEPT
iptables -t filter -A OUTPUT -p tcp --dport 25 -j ACCEPT

# POP3
iptables -t filter -A INPUT -p tcp --dport 110 -j ACCEPT
iptables -t filter -A OUTPUT -p tcp --dport 110 -j ACCEPT

# IMAP
iptables -t filter -A INPUT -p tcp --dport 143 -j ACCEPT
iptables -t filter -A OUTPUT -p tcp --dport 143 -j ACCEPT

# SMTPS
iptables -t filter -A INPUT -p tcp --dport 587 -j ACCEPT
iptables -t filter -A OUTPUT -p tcp --dport 587 -j ACCEPT

# IMAPS
iptables -t filter -A INPUT -p tcp --dport 993 -j ACCEPT
iptables -t filter -A OUTPUT -p tcp --dport 993 -j ACCEPT

# POP3S
iptables -t filter -A INPUT -p tcp --dport 995 -j ACCEPT
iptables -t filter -A OUTPUT -p tcp --dport 995 -j ACCEPT

# Postgrey
iptables -t filter -A INPUT -p tcp --dport 10023 -j ACCEPT
iptables -t filter -A OUTPUT -p tcp --dport 10023 -j ACCEPT

# Monitoring du serveur
iptables -A INPUT -i eth0 -s 3_PREMIERS_BLOCS_IP_DU_SERVEUR.0/24 -p tcp --dport 161 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -i eth0 -s 3_PREMIERS_BLOCS_IP_DU_SERVEUR.0/24 -p udp --dport 161 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o eth0 -d 3_PREMIERS_BLOCS_IP_DU_SERVEUR.0/24 -p tcp --sport 161 -m state --state ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o eth0 -d 3_PREMIERS_BLOCS_IP_DU_SERVEUR.0/24 -p udp --sport 161 -m state --state ESTABLISHED -j ACCEPT

# Flood
iptables -A FORWARD -p tcp --syn -m limit --limit 1/second -j ACCEPT
iptables -A FORWARD -p udp -m limit --limit 1/second -j ACCEPT
iptables -A FORWARD -p icmp --icmp-type echo-request -m limit --limit 1/second -j ACCEPT

# Scan de ports
iptables -A FORWARD -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j ACCEPT

# Monit
iptables -t filter -A INPUT -p tcp --dport PORT_MONIT -j ACCEPT
iptables -t filter -A OUTPUT -p tcp --dport PORT_MONIT -j ACCEPT

echo Firewall start
;;
status)

echo - Liste des regles :
iptables -L
;;
stop)

# Vidage des tables
iptables -t filter -F
iptables -t filter -X
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT

echo Firewall stop
;;
esac
exit 0

J’ai pris la liberté d’appliquer la mise en forme “texte préformaté” au contenu du script pour une meilleure lisibilité. Jeu de règles plutôt médiocre à mon avis.

Je n’irais pas jusque là, mais on se l’attache dans le dos.

De quoi parles-tu ? De tes règles dans FORWARD ? Comme l’a dit @mattotop, elles ne s’appliquent pas aux paquets reçus à destination du serveur. De la règle “bourrine” qu’il a proposée dans son second message ? Pour limiter, ça va limiter, mais pas seulement le flood mais aussi toutes les requêtes légitimes sans discrimination. C’est bien le problème. Et 1 paquet par seconde, c’est juste du délire, qui va te faire regretter le temps des modems analogiques.

Le pare-feu doit servir à protéger les ressources du serveur, pas à empêcher de les utiliser.

Je comprends mieux vos reco donc je pense que je vais laisser Fail2ban faire son boulot tranquillement et approfondir mes connaissances d’IpTables et essayer de pas tomber dans la paranoïa sécuritaire :wink:
Concernant Fail2ban et IpTables, vous avez des conseils pour les réglages / règles ?
Les choses qui pour vous sont indispensables ?
Je précise que j’ai déjà cherché mais j’ai tellement de piste et d’infos que ça en tue l’info :yum:

Sur ces klk mots, je vous souhaite un bon dimanche ! !

Concernant ton jeu de règles iptables, j’ai déjà dit ce que je pensais de sa qualité, il mériterait d’être sérieusement remanié.

Les règles INPUT sont censées autoriser les connexions entrantes à des services qui tournent sur le serveur et doivent être accessibles de l’extérieur. Y a-t-il vraiement tous ces services sur ton serveur et doivent-ils vraiment être accessibles de l’extérieur ?

De même, les règles OUTPUT sont censées autoriser les connexions sortantes depuis ton serveur à des services qui tournent sur des machines extérieures. Ton serveur a-t-il vraiment besoin d’accéder à tous ces services ?

Les règles censée autoriser le ping autorisent en fait tous les paquets ICMP, alors que certains types ICMP sont aujourd’hui considérés comme indésirables (redirect, source-quench).

Quant aux règles anti-flood et scan de ports, elles sont tout simplement inopérantes.

PS : le port 587 n’est pas pour le protocole SMTPS mais pour le protocole Submission, sous-ensemble de SMTP utilisé par les agents utilisateurs (MUA) alors que SMTP est utilisé entre agents de transfert (MTA). Le port pour SMTPS est le 465.

Alors j’ai quasiment l’ensemble de ses services qui tournent sur ma machine,
c’est vrai qu’il en a certains que je peux retirer du genre FTP , NTP, IMAP, POP3 et ne garder que IMAPS, POP3S. Je vais aussi héberger mon serveur mail dessus donc je pense que le reste me semble important. peut-être le FTP à retirer car je j’utilise FTPS de mon compte sudo
Dans tous les cas je vais approfondir le sujet car je pense que j’ai mal saisie les notions de INPUT / OUTPUT.
Je pensais qu’il fallait obligatoirement un OUTPUT open pour que le serveur renvoie des réponses vers l’extérieur…
Je vais suivre tes conseils et retirer les règles anti-flood, scan de ports et ICMP (que je pensais justement résoudre le pb d’ICMP indésirables) et replonger dans IpTables.
Merci encore pour tes retours.

Ce sont les règles du début avec ESTABLISHED qui s’en occupent.
Tes règles dans OUTPUT pour des ports particuliers autorisent les connexions sortantes, pas les retours de connexions entrantes.