📜 ⬆️ ⬇️

Fighting DDOS and DOS at the nginx level

FreeBSD, network Intel fxp, port 100 Mbit, polling, http accept-filter
in sysctl:

sysctl kern.maxfiles=90000
sysctl kern.maxfilesperproc=80000
sysctl net.inet.tcp.blackhole=2
sysctl net.inet.udp.blackhole=1
sysctl kern.polling.burst_max=1000
sysctl kern.polling.each_burst=50
sysctl kern.ipc.somaxconn=32768
sysctl net.inet.tcp.msl=3000
sysctl net.inet.tcp.maxtcptw=40960
sysctl net.inet.tcp.nolocaltimewait=1
sysctl net.inet.ip.portrange.first=1024
sysctl net.inet.ip.portrange.last=65535
sysctl net.inet.ip.portrange.randomized=0


In nginx moments:

worker_processes 1;
worker_rlimit_nofile 80000;
events {
worker_connections 50000;
}

server_tokens off;
log_format IP '$remote_addr';
reset_timedout_connection on;

listen xx.xx.xx.xx:80 default rcvbuf=8192 sndbuf=16384 backlog=32000 accept_filter=httpready;


filtering url for example by the POST criterion of index.php? action = login with an empty referrer can be implemented like this
set $add 1;
location /index.php {
limit_except GET POST {
deny all;
}
set $ban “”;
if ($http_referer = “” ) {set $ban $ban$add;}
if ($request_method = POST ) {set $ban $ban$add;}
if ($query_string = “action=login” ){set $ban $ban$add;}
if ($ban = 111 ) {
access_log /var/log/nginx/ban IP;
return 404;
}
proxy_pass 127.0.0.1:8000; #
}

')
Then they cut at the pf level - they loaded into the IP table from which too many hits came. PF with tables works very quickly. Log parser sources are available at www.comsys.com.ua/files .

Well, on the crown, once a minute, add new ip from the log to the ip table:

25 Mbps DDoS, predominantly chopping ip, the remnants go to nginx, which by the criterion teaches ip and proxies the rest to Apache - LA 0, the site works.

Source: https://habr.com/ru/post/20934/


All Articles