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'"
相关推荐
666IDCaaa1 天前
流量牵引技术与传统防火墙的区别
ddos
秋夫人1 天前
DoS、DDoS、DRDoS 攻击
计算机网络·ddos
666IDCaaa2 天前
为什么需要DDos高防服务器呢?
服务器·网络·ddos
网络研究院3 天前
Radware 报告 Web DDoS 攻击活动
ddos·研究·报告·网络攻击·分析·威胁情报·攻击活动
爱编码的钓鱼佬5 天前
浅谈openresty
运维·nginx·openresty
shall_zhao6 天前
安装OpenResty(Linux-Docker)
linux·docker·openresty
shall_zhao8 天前
黑马点评18——多级缓存-OpenResty
redis·缓存·lua·openresty
代码是谁9 天前
centos8构建nginx1.27.1+BoringSSL+http3+lua+openresty
nginx·lua·http3·openresty
中云时代-防御可测试-小余9 天前
对游戏语音软件Oopz遭遇DDoS攻击后的一些建议
服务器·tcp/ip·安全·web安全·udp·负载均衡·ddos