搭建好WordPress个人网站后,不少人会遇到这样的糟心情况:服务器突然告警CPU资源占用爆表,网站加载卡顿甚至无法访问。排查日志后发现,罪魁祸首竟是黑客针对xmlrpc.php接口的分布式暴力攻击——大量IP低频重复POST请求,耗尽了服务器资源。
今天就给大家分享一套实操方案,用「Nginx+Fail2ban」组合,既能阻止黑客破解,又不影响自身对xmlrpc接口的使用,新手也能跟着做!
先搞懂:为什么xmlrpc.php会成为攻击目标?
xmlrpc.php是WordPress自带的早期API接口,初衷是方便远程发布内容(比如用手机APP发文章)。但黑客盯上了它的漏洞:一次POST请求就能批量尝试上百组账号密码,比攻击wp-login.php登录页效率高得多。
更棘手的是,黑客会用分布式IP低频攻击,避开常规请求限制,还能通过`https://xxx.com/?author=1`获取管理员用户名。每一次攻击请求都会触发WordPress连接数据库、验证信息,动态请求无法被缓存,直接拉满CPU和内存。
完全封堵xmlrpc.php虽简单,但会影响部分功能使用。而「Nginx+Fail2ban」方案能精准识别攻击IP并封禁,兼顾安全与实用性。
手把手操作:5步搞定防护配置
核心逻辑:用UFW防火墙筑牢基础防护,让Nginx记录详细日志,再通过Fail2ban监控日志、自动封禁攻击IP,最后验证效果并优化。
第一步:启用UFW防火墙,守住服务器大门
UFW是Linux系统轻量防火墙,先通过它限制端口访问,减少攻击面。
安装UFW:更新系统包并安装,命令如下apt update && apt install ufw
设置默认规则:拒绝所有入站请求,允许所有出站请求,保障服务器主动访问正常ufw default deny incoming && ufw default allow outgoing
开放必要端口:放行SSH(远程登录)、HTTP(80端口)、HTTPS(443端口),缺一不可ufw allow ssh && ufw allow http && ufw allow https
启用防火墙:确保已放行SSH再执行,避免被锁机ufw enable
检查状态:确认规则生效,显示“active”即为成功ufw status
第二步:修改Nginx配置,记录精准日志
Fail2ban需依赖Nginx日志识别攻击行为,因此要优化日志配置,记录POST请求详情,同时调整Docker网络模式获取真实攻击IP。
复制Nginx配置文件:因站点用Docker运行,先把容器内的nginx.conf复制到宿主机修改cd ~/my_website && mkdir -p ./nginx/main-conf && docker cp wordpress_nginx:/etc/nginx/nginx.conf ./nginx/main-conf/
编辑日志格式:用nano打开配置文件,找到`log_format main`,在末尾添加`$request_body`变量,记录POST请求内容nano ./nginx/main-conf/nginx.conf修改后内容:log_format main '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for" "$request_body"';
创建日志目录并修改docker-compose.yml:挂载自定义配置和日志目录,同时切换Nginx网络模式为host(获取真实IP) ① 创建日志目录:mkdir -p ./nginx/logs② 编辑配置文件:nano docker-compose.yml③ 调整nginx和wordpress服务配置(关键修改已标注):wordpress:
image: wordpress:php8.2-fpm
container_name: wordpress_fpm
restart: always
ports: # 暴露9000端口给宿主机
- "127.0.0.1:9000:9000"
depends_on:
- db
volumes:
- ./wordpress/html:/var/www/html
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: 'wordpress_user'
WORDPRESS_DB_PASSWORD: 'YOUR_STRONG_USER_PASSWORD'
WORDPRESS_DB_NAME: 'wordpress'
networks:
- app-network
nginx:
image: nginx:1.27.0-alpine
container_name: wordpress_nginx
restart: always
network_mode: "host" # 关键:使用宿主机网络
volumes: # 挂载自定义配置、日志和站点文件
- ./nginx/main-conf/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/logs:/var/log/nginx
- ./nginx/conf.d:/etc/nginx/conf.d
- ./nginx/cache:/var/cache/nginx
- ./wordpress/html:/var/www/html:ro
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/www/certbot
修改站点配置:调整PHP-FPM转发地址,适配host网络nano ./nginx/conf.d/app.conf找到`location ~ \.php$ { … }`块,将`fastcgi_pass wordpress:9000;`改为`fastcgi_pass 127.0.0.1:9000;`
重启服务:使配置生效docker compose down && docker compose up -d
第三步:配置Fail2ban,自动识别并封禁攻击IP
Fail2ban是日志监控工具,能根据预设规则匹配攻击行为,自动封禁违规IP,我们针对性配置xmlrpc和登录页的防护规则。
安装Fail2ban:apt install fail2ban -y
创建 jail 配置:自定义防护规则,指定监控日志、封禁时长等nano /etc/fail2ban/jail.d/wordpress-zerotolerance.conf粘贴以下内容(可根据需求调整封禁时长): [wordpress-xmlrpc]
enabled = true
port = http,https
filter = wordpress-xmlrpc
logpath = /root/my_website/nginx/logs/access.log
maxretry = 1 # 一次攻击即封禁
bantime = 30d # 封禁30天
findtime = 1m
[wordpress-login]
enabled = true
port = http,https
filter = wordpress-login
logpath = /root/my_website/nginx/logs/access.log
maxretry = 1 # 一次错误密码即封禁
bantime = 1d # 封禁1天
findtime = 1m
创建过滤器:定义攻击行为匹配规则,让Fail2ban能识别攻击日志 ① 新建xmlrpc过滤器:nano /etc/fail2ban/filter.d/wordpress-xmlrpc.conf粘贴内容:[Definition]
failregex = ^<HOST> - .* "POST /+xmlrpc.php HTTP/.*
ignoreregex =② 新建登录页过滤器:nano /etc/fail2ban/filter.d/wordpress-login.conf粘贴内容:[Definition]
failregex = ^<HOST> - .* "POST /+wp-login.php.*
ignoreregex =
第四步:设置白名单,重启Fail2ban生效
这一步是重中之重!一定要添加自己的IP到白名单,避免误封导致无法访问服务器。
编辑白名单:打开jail.local配置文件,添加自身IP段nano /etc/fail2ban/jail.local找到或添加`ignoreip`字段,格式如下(家用宽带可填前3段+0/24,覆盖动态IP):[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 117.100.100.0/24(替换为自己的IP段)
重启Fail2ban:使所有配置生效systemctl restart fail2ban
检查状态:确认两个防护规则已激活fail2ban-client status若显示“Jail list: wordpress-login, wordpress-xmlrpc”,说明配置成功。
第五步:验证封禁效果,确保防护生效
配置完成后,建议做两次测试,验证登录页和xmlrpc接口的防护是否正常工作。
测试1:wp-login.php登录页防护
用手机流量(避免Wi-Fi与服务器同IP段)访问`https://xxx.com/wp-login.php`,输入一次错误密码。
再次刷新页面,会发现无法访问,说明IP已被封禁。
服务器端验证:执行命令查看封禁列表,能找到手机IPfail2ban-client status wordpress-login
解封测试IP:若需恢复访问,执行解封命令(替换为实际IP)fail2ban-client unban 222.222.222.222
测试2:xmlrpc.php接口防护
打开两个SSH终端:一个用于监控日志,一个用于查看状态。
监控日志:实时等待攻击请求触发tail -f /root/my_website/nginx/logs/access.log
当出现类似`5.101.157.127 … "POST /xmlrpc.php …"`的日志时,等待片刻执行状态命令:fail2ban-client status wordpress-xmlrpc
若看到“Banned IP list”中出现该IP,说明防护生效。
总结
通过「UFW防火墙+Nginx日志优化+Fail2ban自动封禁」的组合,既能精准拦截针对xmlrpc.php和wp-login.php的暴力攻击,解决CPU占用过高问题,又能保留xmlrpc接口的正常使用,适合有远程发布需求的站长。
操作过程中需注意三点:一是Docker网络模式切换后,WordPress和Nginx的连接地址要同步修改;二是白名单必须准确添加,避免自封;三是测试后及时解封测试IP,防止影响正常使用。
如果操作中遇到Docker配置、日志匹配等问题,欢迎留言交流,我会逐一解答~