Назад | Перейти на главную страницу

HAProxy «tcp-request connection reject» не работает должным образом

Я попытался реализовать систему блокировки IP-адресов, если они действуют злонамеренно. Похоже, что он работает в процессе тестирования, но в моей живой среде результаты получаются неоднозначными.

Я пытался заблокировать соединения, если у них частота ошибок> 10, количество ошибок> 50 или частота запросов> 150.

Во-первых, мой внешний прокси имеет конфигурацию:

stick-table type ip size 100k expire 30s store http_err_rate(10000),http_err_cnt,http_req_rate(10000)
tcp-request connection track-sc0 src
tcp-request connection accept if { src -f /etc/haproxy/whitelist.lst }
tcp-request connection reject if { sc0_http_err_rate gt 10 }
tcp-request connection reject if { sc0_http_err_cnt gt 50 }
tcp-request connection reject if { sc0_http_req_rate gt 150 }

Недавно у меня был ip, выполняющий сканирование, которое не было заблокировано haproxy, перед блокировкой ip-таблицами я проверил статистику на IP, которая показала:

echo "show table clientsecure key x.x.x.x" | socat stdio /var/run/haproxy.stat
# table: clientsecure, type: ip, size:102400, used:23
xx: key=x.x.x.x use=8 exp=0 http_req_rate(10000)=144 http_err_cnt=34235 http_err_rate(10000)=150

Я чувствую, что у меня есть фундаментальное недопонимание конфигурации haproxy.

Правильно ли я использую stick-table со следующими правилами подключения tcp-запроса?

Блокирует ли "tcp-request connection reject" входящие соединения, если соответствует одно правило, или все они должны совпадать?

Редактировать:

При дальнейшем тестировании я выяснил, что правила проверяются только для новых подключений. Таким образом, использование "option httpclose" остановит людей, как только они достигнут предела. Очевидно, не идеально по соображениям скорости, так что поэкспериментируем с тайм-аутами сохранения активности.

Поскольку я отслеживал только соединение на внешнем интерфейсе, любые поддерживаемые соединения по-прежнему могли выполнять запросы. Итак, решение:

Внешний интерфейс:

  • создать липкую таблицу только с помощью gpc
  • отслеживать связь src с использованием sc1
  • создать acl "is-abuser", если gpc> 0
  • отклонить соединение, если "нарушитель"

Бэкенды:

  • начать липкую таблицу с частотой ошибок, количеством ошибок, частотой запросов
  • отслеживать содержание src с использованием sc2
  • создать ACL злоупотреблений для частоты ошибок, количества и количества запросов
  • создать acl для увеличения gpc, отслеживаемого из таблицы стикеров внешнего интерфейса, используя sc1_inc_gpc
  • отклонить контент, если совпадают злоупотребления ACL и запустить, затем запустить увеличить gpc acl

Подобный пример я нашел прямо из руководства (используя sc0 и sc1 вместо sc1, sc2 в объяснении выше):

#Track per-frontend and per-backend counters, block abusers at the frontend when the backend detects abuse(and marks gpc0).
frontend http
    # Use General Purpose Couter 0 in SC0 as a global abuse counter
    # protecting all our sites
    stick-table type ip size 1m expire 5m store gpc0
    tcp-request connection track-sc0 src
    tcp-request connection reject if { sc0_get_gpc0 gt 0 }
    ...
    use_backend http_dynamic if { path_end .php }

backend http_dynamic
    # if a source makes too fast requests to this dynamic site (tracked
    # by SC1), block it globally in the frontend.
    stick-table type ip size 1m expire 5m store http_req_rate(10s)
    acl click_too_fast sc1_http_req_rate gt 10
    acl mark_as_abuser sc0_inc_gpc0(http) gt 0
    tcp-request content track-sc1 src
    tcp-request content reject if click_too_fast mark_as_abuser