openresty整合modsecurity实现简单的防止DDOS攻击

openresty配置

确保已经正确整合openresty和modsecurity

完整配置如下,增加了白名单和黑名单已经限制请求次数

load_module modules/ngx_http_modsecurity_module.so;
#user  nobody;
worker_processes  4;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;
	underscores_in_headers on;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    gzip on;  # 启用 Gzip 压缩
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
    gzip_vary on;  # 向响应头添加 `Vary: Accept-Encoding`,以确保代理缓存的正确性
    gzip_min_length 1024;  # 设置压缩的最小文件大小,较小的文件可能不压缩
    gzip_proxied any;  # 启用代理后端的压缩响应
    gzip_comp_level 5;  # 设置压缩级别,范围是1-9,数值越大压缩比越高,但CPU消耗也更大


    geo $whitelist {
        default 0;               # 默认不是白名单中的IP
        #10.0.0.0/8 1;            # 白名单IP段
        #192.168.1.100 1;         # 白名单单个IP
    }

    geo $blacklist {
        default 0;               # 默认不是黑名单中的IP
        #192.168.1.0/24 1;        # 黑名单IP段
        #203.0.113.50 1;          # 黑名单单个IP
    }

    # 将白名单和黑名单组合起来判断
    map $whitelist$blacklist $access {
        "10" 0;                  # 在白名单中时,即使在黑名单中,仍然允许访问
        "11" 0;                  # 在白名单中时,即使在黑名单中,仍然允许访问
        "01" 1;                  # 不在白名单中,但在黑名单中,拒绝访问
        "00" 0;                  # 不在白名单或黑名单中,允许访问(默认行为,可以改为1表示拒绝)
    }

	# 调整为50MB的限流区,允许每秒10个请求,突发请求允许20个根据IP地址的数量自行调整限流区
	limit_req_zone $binary_remote_addr zone=req_zone:50m rate=10r/s;
	# 定义一个连接限制区,大小为10MB,最大连接数为10个
    limit_conn_zone $binary_remote_addr zone=conn_zone:50m;
	
	log_format custom '$remote_addr $host  $proxy_add_x_forwarded_for - $remote_user [$time_local] "$request" '
				   '$status $body_bytes_sent "$http_referer" '
				   '"$http_user_agent" "$http_x_forwarded_for"';

	access_log /app/openresty/nginx/logs/access.log custom;

    server {
        listen       8080;
        server_name  0.0.0.0;

        charset utf-8;
		# 在特定位置启用 ModSecurity
		modsecurity on;
		modsecurity_rules_file /app/openresty/nginx/conf/modsecurity.conf;

        #access_log  logs/host.access.log  main;
		if ($access) {
            return 403;          # 如果$access为1,则拒绝访问
        }

        location / {
            # 应用请求限流
            limit_req zone=req_zone burst=20 nodelay;

            # 应用连接限制
            limit_conn conn_zone 10;

			proxy_pass http://127.0.0.1:9080;
			proxy_set_header X-Real-IP $remote_addr;
			proxy_set_header X-Forwarded-Host $host;
			proxy_set_header X-Forwarded-Port $server_port;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
			proxy_set_header X-Forwarded-Proto $scheme;
			# 关键部分:重写后端服务器的重定向URL
			proxy_redirect default;
			
			# 错误处理
            error_page 503 /error503.html;

        }
		location = /error503.html {
            internal;
            default_type text/html;
            return 503 "Service Unavailable";
        }
    }

}

配置modsecurity

修改modsecurity.conf添加规则

# 启用 ModSecurity
SecRuleEngine On

# 启用日志记录
SecAuditLog /app/openresty/nginx/logs/modsec_audit.log
SecAuditLogParts ABCJFHZ
SecAuditLogType Serial

# 防止SQL注入和XSS等通用攻击
Include /usr/local/nginx/conf/owasp-modsecurity-crs/crs-setup.conf
Include /usr/local/nginx/conf/owasp-modsecurity-crs/rules/*.conf

# 设置请求体大小限制,防止大请求DDoS攻击
SecRequestBodyLimit 31457280  # 设置请求体最大大小为30MB
SecRequestBodyNoFilesLimit 31457280  # 非文件请求体限制为30MB

# 1. 从X-Forwarded-For头中获取真实客户端IP,并去掉端口号
SecRule REQUEST_HEADERS:X-Forwarded-For "^\d+\.\d+\.\d+\.\d+(:\d+)?$" \
    "id:100010,phase:1,pass,t:none,setvar:tx.real_client_ip=%{tx.0},capture,msg:'tx.real_client_ip=%{tx.real_client_ip}'"

# 2. 如果没有X-Forwarded-For头,则使用REMOTE_ADDR作为真实客户端IP,并去掉端口号
SecRule TX:real_client_ip "^$" \
    "id:100011,phase:1,pass,t:none,setvar:tx.real_client_ip=%{REMOTE_ADDR},capture"

SecRule TX:real_client_ip "^\d+\.\d+\.\d+\.\d+(:\d+)?$" \
    "id:100012,phase:1,pass,t:none,setvar:tx.real_client_ip=%{tx.0}"

# 3. 增加IP计数器,每次访问增加计数
SecRule TX:real_client_ip "^\d+\.\d+\.\d+\.\d+$" \
    "id:100002,phase:2,t:none,t:lowercase,log,pass,setvar:ip.dos_counter=+1,expirevar:ip.dos_counter=60,msg:'DOS_COUNTER=%{ip.dos_counter}'"

# 4. 检查请求频率,并标记IP(结合链式规则)
SecRule TX:real_client_ip "^\d+\.\d+\.\d+\.\d+$" \
    "id:100001,phase:2,chain,t:lowercase,pass,setvar:tx.dos_detected=1,msg:'Potential DDoS Attack: High Request Rate Detected'"
    SecRule IP:DOS_COUNTER "@gt 1"

# 5. 阻止被标记的IP,触发429错误
SecRule TX:dos_detected "@eq 1" \
    "id:100003,phase:2,deny,status:429,log,msg:'Potential DDoS Attack: Blocked IP due to excessive requests'"

# 6. 增加连接计数器,每次访问增加计数
SecRule TX:real_client_ip "^\d+\.\d+\.\d+\.\d+$" \
    "id:100005,phase:2,t:none,t:lowercase,nolog,pass,setvar:ip.connection_counter=+1,expirevar:ip.connection_counter=60"

# 7. 检查并阻止过多并发连接
SecRule TX:real_client_ip "^\d+\.\d+\.\d+\.\d+$" \
    "id:100004,phase:2,chain,t:lowercase,pass,setvar:tx.conn_detected=1,msg:'Potential DDoS Attack: Too many concurrent connections from this IP'"
    SecRule IP:CONNECTION_COUNTER "@gt 1"

# 8. 阻止被标记的IP,触发429错误(针对连接)
SecRule TX:conn_detected "@eq 1" \
    "id:100009,phase:2,deny,status:429,log,msg:'Potential DDoS Attack: Blocked IP due to excessive connections'"
相关推荐
中云DDoS CC防护蔡蔡40 分钟前
微信小程序被攻击怎么选择高防产品
服务器·网络安全·微信小程序·小程序·ddos
unix2linux19 小时前
YOLO v5 Series - Image & Video Storage ( Openresty + Lua)
yolo·lua·openresty
javaDocker2 天前
防止DDos的技术方案
网络·ddos
kk_1778036196 天前
HTTP/2新型DDoS攻击:技术深度剖析与防御指南
网络·http·ddos
嚯——哈哈6 天前
DDoS高防服务器:保障业务安全和稳定的抗攻击利器
服务器·安全·ddos
群联云防护小杜8 天前
服务器被挂马怎么办?——解决服务器被挂马的方法和步骤
运维·服务器·网络协议·tcp/ip·安全·ddos
编程武士8 天前
nginx openresty lua-resty-http 使用的一些问题记录
nginx·lua·openresty·lua-resty-http