WordPress前端登录保护

查看Nginx日志发现,我这上线还不到半个月的WordPress新网站,每天竟然都有上千次的爬虫恶意登录试探,每次都是一个时间段同一个IP发送多个请求,虽然请求的频率不高,也就每秒2个左右,但是看着这一堆的恶意登录试探让人不舒服,再者加上一直让它们试探也浪费服务器资源。

恶意登录试探日志

先放一些恶意登录试探日志:

WordPress恶意请求wp-login.php及xmlrpc.php日志

可以看出,大多数试探登录都是针对wp-login.php以及xmlrpc.php这两个文件的,请求的User-Agent都设置的差不多,看起来也是想伪装成正常的浏览器的请求。

一开始我是想,根据日志的请求IP,直接手动到Nginx上使用deny指令禁止其访问就行了,但是经过我的实际测试发现,禁用了部分请求过的IP之后,还会有新的IP过来,使用的UA以及请求方式都差不多,而且有些IP恶意请求一次之后可能不会再次请求,所以手动禁止IP的方法效果并不好,要想有效禁止这些IP还是需要别的办法。

wp-login.php以及xmlrpc.php作用分析

上面通过日志可知,恶意请求主要是针对这两个文件的,我重点去了解了下这两个文件。

wp-login.php是WordPress后台的入口文件,我们登录WordPress后台都是通过这个文件,即使直接访问wp-admin目录,没有登录的情况下,还是会默认跳转到wp-login.php要求登录。

至于xmlrcp.php,是用来对接其他系统的,我完全不需要对接其他什么系统,只是在浏览器写写东西,这文件对我来说用不上。

所以,我的想法是,对wp-login.php进行限制访问,xmlrpc.php完全禁用就行,网上有很多方法,要么是修改function.php文件,要么是使用插件,但是考虑到性能以及后续的升级维护,我没有选择这两个办法,而是想通过Nginx去实现。

限制xmlrpc.php访问

限制xmlrpc.php访问很简单,只需要修改Nginx的配置文件,增加如下几行即可:

location ~* ^/xmlrpc.php$ {
     return 403;
}

也就是针对xmlrpc.php直接返回403状态码,不允许对其进行访问,返回404状态码也是一样的。

对wp-login.php添加401认证

每次登录都需要通过wp-login.php文件,自然不能直接屏蔽对这个文件的访问,好在Nginx有个auth_basic_user_file指令,可以增加HTTP基本认证(HTTP Basic Authentication)功能,而且操作也很简单。

生成认证文件

在配置Nginx之前,需要先手动生成HTTP基本认证所需要的用户名和密码对应的文件,我是用的Debian系统,命令如下:

root@cloudbool.com:~# apt install apache2-utils
root@cloudbool.com:~# htpasswd -c /etc/nginx/auth cloudbool
New password:
Re-type new password:
Adding password for user cloudbool

上述两行命令分别是安装apache2-utils包以及使用htpasswd命令生成新的用户名及设置对应的密码,我是选择将生成的认证文件放在/etc/nginx/目录下面。

配置Nginx启用HTTP Basic Authentication

修改对应的Nginx配置文件,增加如下几行:

        location ^~ /wp-login.php {
                auth_basic "Auth Required!";
                auth_basic_user_file /etc/nginx/conf.d/auth; #上述生成的认证文件
                location ~ \.php$ {
                        try_files $uri /index.php =404;
                        fastcgi_split_path_info ^(.+\.php)(/.+)$;
                        fastcgi_pass unix:/run/php-fpm.sock;
                        fastcgi_index index.php;
                        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                        include fastcgi_params;
                }
        }

其中,HTTP基本认证只需要auth开头的两行,如果是静态资源,可以不需要location ~ \.php$ {…}这个区块,但是因为我这里是需要PHP解析器,所以需要添加对应的区块,不然会出现访问wp-login.php浏览器直接下载对应PHP文件的问题。

需要注意的是,location ~ \.php$ {…}这个区块需要替换成实际使用的,不能直接照搬我的

结果

修改并重启Nginx之后,访问xmlrpc.php会直接返回403错误,同时,访问wp-login.php会要求输入用户名密码,注意,这里输入的是上述通过htpasswd命令生成的,而不是WordPress的登录账号密码,如图:

只有提交正确的账号密码才能显示WordPress的登录表单,否则会返回401 Authorization Required

而查看Nginx,那些还在恶意试探登录的爬虫,Nginx日志也是显示401状态码:

[23/Jun/2021:16:13:24 +0800] "POST /wp-login.php HTTP/1.1" 401 172 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"