Ограничьте максимальное количество подключений на IP-адрес и количество новых подключений в секунду с помощью iptables


37

У нас есть сервер Ubuntu 12.04 с httpd на порту 80, и мы хотим ограничить:

  • максимальное количество подключений на IP-адрес к httpd до 10
  • максимальное количество новых подключений в секунду к httpd до 150

Как мы можем сделать это с iptables?

Ответы:


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

Это приведет к отклонению соединений выше 15 от одного источника IP.

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

При этом допускается 160 новых соединений (реально пакетов) до того, как будет применено ограничение в 150 НОВЫХ соединений (пакетов) в секунду.


1
Можно ли настроить вышеперечисленное для работы на всех портах, а не только на порту 80?
EminezArtus

1
Вы уверены, что это по IP?
LatinSuD

2
Чтобы установить это правило для всех портов, просто удалите --dport 80.
Дэн Притц

5
Второе правило НЕ работает на «новых соединениях». Это явно влияет на существующие («УСТАНОВЛЕННЫЕ») соединения. Для создания новых подключений вы бы хотели --state NEW. Вы также можете рассмотреть возможность использования -m conntrack --ctstateвместо -m state --state. Conntrack является новым и улучшенным по сравнению с государством.
Дэн Притц

2
комментарий выше для добавления второго правила к NEWсоединениям - не делайте этого - он фактически превращает вашу INPUTцепочку в дефолт accept!!!
Стюарт Кардалл

8

Вы хотите, чтобы следующие правила в iptables отвечали обоим требованиям вашего вопроса:

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

Поскольку мы используем -I (согласно запросу OP), мы должны выполнять их в обратном порядке, поэтому «читаем» их снизу вверх.

Я также предлагаю рассмотреть возможность изменения значения NN --connlimit-mask с 32 на 24. Это ограничит полную сеть класса C (максимум 256 IP-адресов в одном диапазоне) до 10 соединений. Вы также можете использовать любой другой бесклассовый номер, например 22 или 30, в зависимости от того, как, по вашему мнению, может использоваться ваша услуга.

Также в зависимости от того, как вы хотите, чтобы клиент вел себя, вы можете использовать «-j REJECT --reject-with tcp-reset» вместо «-j DROP» в двух вышеприведенных правилах или даже только в максимальных 150 соединениях. править.

Если вы ОТКЛЮЧИТЕ соединение, браузер или программное обеспечение, использующее порт 80, сразу же покажет состояние «недоступно», но опция DROP заставит клиента подождать и повторить попытку несколько раз, прежде чем сообщить о сайте как о недоступном. Я склонен склоняться к DROP сам, так как он ведет себя скорее как плохое соединение, чем автономный сервер.

Кроме того, если предел соединения снова падает ниже 150 (или 10), пока он все еще повторяется, то он, наконец, дойдет до вашего сервера.

Однако опция REJECT вызовет на ваш сайт меньший трафик, так как DROP заставит его отправлять дополнительные пакеты во время повторных попыток. Наверное, не все это актуально.

Если, с другой стороны, трафик вашего порта 80 является частью кластера, то REJECT сообщит контроллеру кластера, что он не работает, и прекратит посылать ему трафик на время его ожидания.

Правило RELATED, ESTABLISHED подразумевает, что ваше правило по умолчанию - блокировать весь трафик (iptables -t filter -P INPUT DROP). Это только принимает дальнейшие пакеты, принадлежащие принятым соединениям.

Также --syn говорит ему обращать внимание (или считать) пакеты, которые устанавливают TCP-соединение.


Спасибо, что прошли через мелочи этих команд.
txyoji

Могу ли я получить --connlimit-mask, чтобы блокировать только этот конкретный IP-адрес, а не весь диапазон?
Аналог

--Connlimit-mask 32 - это ограничение по одному адресу. То есть это как / 32 маска. Все, что меньше, например 24, похоже на / 24 сетевую маску, игнорируя младшие 8 бит.
Ян Макинтош

5

Вам необходимо использовать connlimitмодули, которые позволяют ограничивать количество параллельных TCP-подключений к серверу на IP-адрес клиента (или адресный блок).

/sbin/iptables -I INPUT -p tcp --syn --dport 80 -m connlimit \
      --connlimit-above 10 -j DROP

Я обновил ваш ответ, надеюсь, он все еще в порядке (зачем нужен "--syn"?). + А как насчет «Максимальное соединение в секунду (порт 80, tcp) до 150»? Спасибо!
Эвахристин

--syn означает, что правило просматривает только TCP-пакеты с флагом syn - что означает новые соединения. Вы можете сделать примерно то же самое с -m state --state NEW, но это, вероятно, быстрее.
Дэн Притц
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.