Наш сервер завалили запросами HEAD.
Это привело к всплеску TCP-соединений, из-за которого сервер не смог подключиться к своим базам данных mysql.
Мы широко используем ratelimiting nginx, который безупречно работает в сочетании с fail2ban для любых запросов GET и POST. Однако запросы HEAD, похоже, не принимаются.
Действие fail2ban filter.d, которое мы используем, nginx-limit-req
который, похоже, является стандартной конфигурацией для определения достижения предела зоны nginx.
Поскольку нашему веб-приложению не нужны запросы HEAD, у нас есть два варианта (помимо ручного запрета отдельных IP-адресов)
nginx.conf:
http {
...
limit_req_zone "$http_x_forwarded_for" zone=web_zone:50m rate=2r/s;
...
}
server {
...
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
location / {
limit_req zone=web_zone burst=25;
try_files $uri $uri/ @pretty-urls;
}
...
}
jail.conf:
[nginx-limit-req]
enabled = true
filter = nginx-limit-req
action = custom-iptables-proxy
port = http,https
logpath = /var/log/nginx/*error*.log
findtime = 10
bantime = 3600
maxretry = 3
nginx-limit-req.conf:
[Definition]
ngx_limit_req_zones = [^"]+
failregex = ^\s*\[[a-z]+\] \d+#\d+: \*\d+ limiting requests, excess: [\d\.]+ by zone "(?:%(ngx_limit_req_zones)s)", client: <HOST>,
ignoreregex =
datepattern = {^LN-BEG}
пример из журнала доступа:
netdata во время инцидента, нормализованная после бана злоумышленника:
Чтобы отключить запросы HEAD в конфигурации Nginx, просто добавьте следующее в свой серверный блок:
if ($request_method = HEAD) {
return 444;
}
В 444 код статуса HTTP специфичен для Nginx и отбросит все запросы HEAD, поэтому соединение не будет установлено для клиента, инициирующего запрос HEAD. Эти попытки подключения по-прежнему регистрируются в журналах Nginx, поэтому вы можете заблокировать рассматриваемый IP-адрес в конфигурации вашего брандмауэра.