Ограничение скорости отдельных запросов URL

8

У меня есть приложение Flask, которое я разрабатываю и которое в значительной степени зависит от взаимодействия с внешним веб-сайтом и инициируется конечным пользователем. Если я оставлю приложение без какого-либо контроля пропускной способности / ограничения скорости, то это приложение может быть использовано со стороны актеров с гнусными намерениями.

Моя цель - довольно простой двухэтапный подход:

  1. Ограничьте скорость отдельных IP-источников от выполнения более чем xчисла соединений в минуту. Это может быть легко достигнуто с iptables. Вот пример, аналогичный моей цели:

     iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 15 \
       --connlimit-mask 32 -j REJECT --reject-with tcp-reset  
    
  2. Оценить ограничение возможности приложений выполнять больше, чем xколичество просмотров на URL . Пример:

     APP ---- 10 pps --->  stackexchange.com   PERMIT
     APP ---- 25 pps --->  google.com          DENY / 15 SECOND BACKOFF
    

Насколько я могу судить, iptablesнет возможности отслеживать отдельные URL-адреса. Это только в состоянии оценить ограничение этих соединений в целом. Это также не кажется единственным ограничением того, чего я пытаюсь достичь. Если бы был способ настроить iptablesтаким образом, это могло бы вызвать некоторые проблемы с моим веб-приложением, так как эти запросы инициированы пользователем.

Я использую Flask, жизнеспособным вариантом может быть использование before_requestловушки и ручное отслеживание этих мест назначения с помощью хранилища данных, такого как Redis. Тем не менее, это довольно высоко в стеке, чтобы иметь дело с соединениями таким образом. Что мне действительно нужно (или я думаю, что я делаю), это интеллектуальное приложение брандмауэра, которое может анализировать запросы нестандартным способом и закрывать соединения, когда достигнуты определенные точки останова.

Есть ли способ добиться того, что я пытаюсь сделать?

Если да, то как?

Райан Фоли
источник

Ответы:

3

iptables имеет дело с уровнями Internet и Transport (в модели Internet) или, альтернативно, с уровнями 3 и 4 в модели OSI, с несколькими исключениями (фильтрация по MAC-адресам, помощники протокола NAT).

URI являются частью прикладного уровня. iptablesне имеет с ними дело.

Вы можете использовать iptables для направления всего вашего исходящего трафика TCP-порта 80 через веб-прокси, что может ограничить вашу скорость (например, возможно , пулы задержек Squid могут это сделать. Или Apache, вероятно, может это сделать mod_proxy.) Это сделать с HTTPS сложнее ( хотя, может быть, вы можете просто настроить свое приложение на использование веб-прокси, что в любом случае будет лучше, чем прозрачный прокси).

Но вы действительно должны перенести оба ограничения скорости в ваше приложение. Причина, по которой вы устанавливаете UX, ужасна ; «Отказ в соединении» вообще не объясняет, что происходит. Для ваших пользователей было бы гораздо лучше, если бы вы вместо этого предоставили страницу с ошибкой, объясняющую, что они слишком быстро отправляют запросы, к кому обратиться за поддержкой, возможно, предложите решить проблему CAPTCHA, чтобы продолжить, и т. Д.

Разумно иметь ограничение скорости соединения для входящих соединений, но это должно быть для защиты приложения от перепадов из-за DoS-атаки - так много запросов, что ваше приложение не может даже обработать страницу ошибки превышения скорости для пользователя. Он должен быть чуть выше, чем при запуске страницы с ошибкой (и, возможно, должен быть глобальным пределом, а не пределом для IP-адреса источника). Обратите внимание, что если ваше приложение работает через веб-сервер и / или обратный прокси-сервер, вы, вероятно, можете настроить ограничения входящей скорости там (а не через iptables) - и делать очень дешевые отклонения, отправляя страницу статической ошибки, и даже не передавая запрос в ваше приложение.

derobert
источник