Nginx 安装 ModSecurity WAF 以增强网站安全
Nginx 安装 ModSecurity WAF 以增强网站安全
ModSecurity WAF 连接器扩展依赖
1
$> yum install -y libmodsecurity-devel
下载 ModSecurity WAF 连接器
1
$> git clone https://github.com/owasp-modsecurity/ModSecurity-nginx.git
编译安装
1
2
$> cd /data/softsrc/openresty-1.21.4.1
$> ./configure --prefix= /opt/nginxss --add-module= /pathto/ModSecurity-nginx && make && make install
创建配置文件目录
1
$> mkdir /opt/nginxssl/conf/modsec
核心规则配置
1
2
$> cd /opt/nginxssl/conf/modsec && git clone https://github.com/coreruleset/coreruleset.git
$> cd /opt/nginxssl/conf/modsec/coreruleset && cp -v crs-setup.conf.example crs-setup.conf
下载 ModSecurity 配置相关文件
1
2
$> wget -O /opt/nginxssl/conf/modsec/modsecurity.conf https://raw.githubusercontent.com/SpiderLabs/ModSecurity/v3/master/modsecurity.conf-recommended
$> wget -O /opt/nginxssl/conf/modsec/unicode.mapping https://raw.githubusercontent.com/SpiderLabs/ModSecurity/v3/master/unicode.mapping
创建入口文件
1
2
3
4
$> vim /opt/nginxssl/conf/modsec/main.conf
Include /opt/nginxssl/conf/conf/modsec/modsecurity.conf
Include /opt/nginxssl/conf/modsec/coreruleset/crs-setup.conf
Include /opt/nginxssl/conf/modsec/coreruleset/rules/*.conf
修改配置文件 modsecurity.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
$> vim /opt/nginxssl/conf/modsec/modsecurity.conf
## DetectionOnly 只记录,不拦截
## On 拦截并记录
## Off 完全关闭
# SecRuleEngine DetectionOnly
SecRuleEngine On
# 以下为关键配置, 核心关注SecAuditLog 、 SecAuditLogFormat 配置
SecAuditEngine RelevantOnly
SecAuditLog /var/log/modsec_audit.log
SecAuditLogParts ABIJDEFHZ
SecAuditLogType Serial
SecAuditLogFormat JSON # 设置为 JSON 格式,方便查看
修改 nginx 配置文件启用 ModSecurity WAF
1
2
3
4
$> vim /opt/nginxssl/conf/nginx.conf
# http or server or location
modsecurity on;
modsecurity_rules_file /opt/nginxssl/conf/modsec/main.conf;
拦截测试
1
2
3
$> curl "http://127.0.0.1/?param=<script>alert(1)</script>"
# sql 注入
$> curl "http://127.0.0.1/?param=1' AND 1=1 UNION SELECT 1,2,3,4,5,6,7,8,9,10 FROM users WHERE '1'='1"
白名单添加方案
1
2
3
4
$> vim /opt/nginxssl/conf/modsec/modsecurity.conf
# SecRuleEngine 之后配置, 其中id 字段唯一
# 跳过 192.168.1.100 的全部 ModSecurity 检查
SecRule REMOTE_ADDR "@ipMatch 192.168.1.100" "id:10000,phase:1,pass,nolog,ctl:ruleEngine=Off"
其他白名单方案(未测试)
1
2
3
4
5
6
7
8
9
10
11
12
13
# 限制某路径仅特定 IP 可访问
SecRule REQUEST_URI "^/admin" "phase:1,deny,id:20001,msg:'Forbidden access to /admin',chain"
SecRule REMOTE_ADDR "!@ipMatch 192.168.1.100"
# 禁止某路径使用 GET 请求
SecRule REQUEST_URI "^/secure-action" "phase:1,deny,id:20002,msg:'GET not allowed here',chain"
SecRule REQUEST_METHOD "@streq GET"
# 仅允许特定 Referer 或 User-Agent 访问某路径
SecRule REQUEST_URI "^/api/private" "phase:1,deny,id:20003,msg:'Blocked non-authorized client',chain"
SecRule REQUEST_HEADERS:User-Agent "!@streq MyTrustedClient/1.0"
# 还可以在不同的location下单独设置启用不同规则,用以实现多元化
Rsync 同步的软链接出现,同步结果指向目标会多一个 /rsyncd-munged/
1
2
3
4
# /rsyncd-munged/ 是为了防止客户端通过上传的链接跳出模块目录(安全保护)
# rsyncd.conf 添加配置,重启服务
use chroot = yes # 建议开启此项,如果同时关闭 munge ,可能造成额外的安全隐患
munge symlinks = no
emqx 迁移
emqx迁移只需要备份 etc 和 data 目录,保持迁移前后版本一致, 然后在新节点加载这两个目录即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 当前迁移示例为win到linux
# windows 备份
# 先停掉服务 , 然后直接打包 etc 和 data 目录
$> emqx stop
# linux 恢复
## 创建目录
$> mkdir -p data/{etc,data,log}
# 解压备份文件 data 到 data , etc 到 etc
# 调整权限
$> chown -R 1000:1000 data
# 容器方式运行, 创建compose文件 (注意: 物理环境部署迁移到容器环境,可能导致 node 信息不一致,导致迁移失败,如果是此情况,建议重新部署)
$> vim docker-compose.yml
services:
emqx:
image: emqx/emqx:5.3.2
container_name: emqx
restart: always
environment:
- EMQX_NODE_NAME = emqx@localhost
ports:
- "1883:1883" # MQTT
- "8883:8883" # MQTT over TLS
- "8083:8083" # MQTT over WebSocket
- "8084:8084" # MQTT over WSS
- "18083:18083" # Dashboard
volumes:
- ./data/etc:/opt/emqx/etc
- ./data/data:/opt/emqx/data
- ./data/log:/opt/emqx/log
# 启动服务
$> docker-compose up -d
Fedora 系统界面默认字体是 Adwaita sans,Ubuntu 默认是 Ubuntu sans, 看起来还是有些差异的, 感觉还是 Adwaita sans 好看一些
logrotate 日志轮转示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$> vim /etc/logrotate.d/app-logs
/var/log/myapp/*.log {
daily # 每天轮转
rotate 30 # 保留 30 个归档
missingok # 文件不存在不报错
notifempty # 空文件不轮转
compress # 压缩归档(gzip)
delaycompress # 延迟压缩(下次轮转时压缩)
dateext # 使用日期后缀(如 .20251024)
dateformat -%Y%m%d # 日期格式
create 0640 appuser appgroup # 创建新文件权限
sharedscripts # 所有日志轮转完后只执行一次脚本
postrotate # 轮转后执行
systemctl reload nginx > /dev/null 2>& 1 || true
endscript
}
# 测试配置(不实际执行)
$> logrotate -d /etc/logrotate.d/app-logs
# 强制轮转(调试用)
$> logrotate -f /etc/logrotate.d/app-logs
# 查看 logrotate 状态
$> cat /var/lib/logrotate/status