给wordpress增加Basic Auth密码

目录

最近几天博客一直被无聊的人扫描,尝试后台登陆及找回管理员密码。尽管博客没有什么有价值的东西,被攻破了也没有多大的损失,但这种扫描行为本身让人比较恶心,于是就想着增强下博客的安全性。

大的思路其实就三条,增加阿里云ESA的WAF和回源保护、wordpress的薄弱点加固、及增加额外的验证方式。阿里云ESA就不多说了,因为这个产品用的人可能不多,每家CDN的设置差异较大。下面主要集中在wordpress的薄弱点加固和增加额外的验证方式两方面总结下这次的经验。

 

一、主题中修复简单薄弱点

修复项 严重度 说明
统一登录错误消息 严重 无论用户名是否存在,一律返回“登录信息不正确”,防止攻击者通过错误提示枚举用户名
移除密码找回功能 严重 移除密码找回功能,以防无聊的人不断点击
增加登陆失败锁定 严重 随着登陆失败次数的增加不断增加锁定IP时长
增加登陆验证码 严重 将简单算数验证码改为图片显示的算数验证码,以增加机器识别的难度(需要OCR,会增加成本)
移除 WP 版本号 登录页+前端所有 CSS/JS 的 ver= 参数全部移除
移除 REST API Link 头 HTTP 响应头不再暴露 wp-json 端点
删除 readme.html 和 license.txt 这两个文件会暴露 WordPress 版本号
RSS Feed 隐藏作者名 Feed 中作者显示为“作者”而非真实昵称
移除 body class 主题名 不再暴露 wp-theme-nickel
移除登录页语言切换器 减少攻击面

 

二、增加额外的验证方式

增加额外的验证方式有两个思路,一个是增加2FA,就是类似于增加一个和手机端同步的动态密码,或邮件发送的6位数动态密码,从而形成wordpress的账户密码和动态密码的双重验证。另一个思路是增加一个nginx的Basic Auth密码,原理就是在访问登录页等敏感页面时会弹出一个登陆页面,只有通过了这个登陆页面才能看到真正的登录页。我最终选择了Basic Auth方案,原因有三个,一是2FA较复杂,因此插件普遍较重,我不想让网站加载这么多东西;二是除了登录页外/wp-admin/目录也需要保护,而轻量的2FA没有这个功能;三是Basic Auth完全由nginx处理,系统损耗最轻,即是被爆破小鸡也容易扛住。如果大家比较倾向于2FA方案,那么我推荐wp 2FA插件。

Basic Auth部署完后弹出的验证框如下,下面我贴上完整的部署步骤。

 

1、在nginx的配置文件中增加以下代码

记得要加在include enable-php-83.conf 之前,原因是正则 location 之间,先定义的优先。如果 enable-php-83.conf 中的 location ~ \.php$ 在前面,它就会抢先匹配 /wp-admin/index.php,auth_basic 就被绕过了。所以必须把 location ~ ^/wp-admin/.*\.php 放在它前面。

需要添加的代码如下:

NGINX
============= ★ 新增:Basic Auth 保护 wp-admin 和 wp-login =============

# 1) 登录页加密(精确匹配,优先级最高,不被任何正则覆盖)

location = /wp-login.php {

auth_basic “Restricted”;

auth_basic_user_file /www/server/nginx/htpasswd/wp-auth;

try_files $uri =404;

fastcgi_pass unix:/tmp/php-cgi-83.sock;

include fastcgi_params;

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

}

# 2) wp-admin 下 PHP 文件加密(正则,必须在 enable-php-83 之前定义)

location ~ ^/wp-admin/.*\.php(/|$) {

auth_basic “Restricted”;

auth_basic_user_file /www/server/nginx/htpasswd/wp-auth;

try_files $uri =404;

fastcgi_pass unix:/tmp/php-cgi-83.sock;

include fastcgi_params;

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

}

# 3) 放行 admin-ajax.php(精确匹配,优先级高于上面的正则)

location = /wp-admin/admin-ajax.php {

auth_basic off;

try_files $uri =404;

fastcgi_pass unix:/tmp/php-cgi-83.sock;

include fastcgi_params;

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

}

# ============= ★ Basic Auth 结束 =============

 

2、创建密码目录

mkdir -p /www/server/nginx/htpasswd

 

3、安装 htpasswd 工具

# CentOS / AlmaLinux / Rocky
yum install -y httpd-tools

# Ubuntu / Debian
apt install -y apache2-utils

 

4、创建密码文件和用户

# -c 表示创建新文件(首次使用)
# 替换 admin 为你想要的用户名
htpasswd -c /www/server/nginx/htpasswd/wp-auth admin

系统会提示输入两次密码:

New password: ********
Re-type new password: ********
Adding password for user admin

 

5、如果要添加第二个用户(可选)

# 注意:不要加 -c,否则会覆盖已有用户
htpasswd /www/server/nginx/htpasswd/wp-auth user2

 

6、验证密码文件

cat /www/server/nginx/htpasswd/wp-auth

应该看到类似输出(用户名:加密密码):

admin:$apr1$Xk7Zb2Qw$LmN3R4h5K6j7P8qRs9TtU0

 

7、设置文件权限

chown www:www /www/server/nginx/htpasswd/wp-auth
chmod 640 /www/server/nginx/htpasswd/wp-auth

 

8、检查 Nginx 语法并重载

nginx -t

看到 syntax is oktest is successful 后:

nginx -s reload

 

三、最强的方案

CDN端WAF+CDN源站保护(只有CDN节点能回源)+CDN端机器人拦截+网站加固+2FA+Basic Auth(作为简单替代,如果有固定IP的话,可以只允许自己的IP访问敏感页面)。但设置的规则越多,对于小站来说越麻烦,平时容易出错,搬迁时耗费的精力更多,所以如果没有被骚扰,那么CDN端WAF是最好的选择。

一直没有用过静态博客,是不是如果用了静态博客就没有了这些烦恼?

 

作为个人博客原本不用这么折腾的,但无奈蛋疼的人太多,总干这种损人不利己的事情,逼迫着不懂一点点技术的我也不得不花时间来学习这些网站维护知识。

8 条评论

  1. S

    为什么主页已暂停访问,被太多人爆破吗?
    「抱歉!该站点已经被管理员停止运行,请联系管理员了解详情!」

    1. 水拍石

      我自己测试是正常的,如果你那边过一个小时还不能恢复的话,我就检查下是那出了问题。如果能恢复的话就是限流策略太严了,放宽限流策略应该就好了。

      1. S

        跟一个小时应该没关系,已经几星期了。而且是换了好几个位置设备和ip。

        1. 水拍石

          那我排查下,首页没有走CDN,只有W3缓存,而W3缓存首页刷新的很及时。前段时间是停止了网站升级了下服务器环境,但按道理「抱歉!该站点已经被管理员停止运行,请联系管理员了解详情!」应该不会缓存到现在,页面的浏览器缓存我设置了2分钟。

          1. S

            好的。其实倒也没啥关系,反正主页一般人也不怎么去,更新文章在rss都能看。
            就是不能访问有点影响我的强迫症,哈哈哈!

            1. 水拍石

              我慢慢排查,现在就是想不到那里会出问题。

              1. S

                “只有主页显示‘站点已停止’,其他页面都正常”这个现象非常特殊,因为它直接指向了问题的根源——**这并不是一次全局性的服务器故障,而是WordPress的前端“首页”请求被单独拦截或错误配置了。**

                这个现象通常意味着网站的后台管理、数据库连接、主题和大部分插件功能都是正常的,问题大概率出在**WordPress的首页设置、重定向规则或安全插件**上。

                我为你整理了5个最有效的排查步骤,建议按照下面的顺序操作:

                ### 第一步:检查WordPress后台的“首页”设置(最常见原因)

                这是最符合你描述的场景。很有可能,你或某个插件将站点的“主页”设置成了一个**已被删除、设为私密或密码保护的页面**。

                1. **登录WordPress后台**,进入 **设置 → 阅读**。
                2. 查看 **“您的主页显示”** 这一项:
                * 如果选择了 **“一个静态页面”** ,检查“主页”下拉菜单里选中的页面是否存在且状态为“已发布”。如果不存在,或者是一个无法公开访问的页面(如受密码保护),那么前台就会报错。
                * **解决方法**:你可以临时将它改为 **“您的最新文章”** ,然后保存。保存后立刻去访问主页看看是否恢复了正常。如果恢复,再去重新设置一个正确的静态页面即可。

                ### 第二步:检查是否有安全插件拦截了首页请求

                一些WordPress安全插件(如 `All In One WP Security`、`Wordfence`、`WP Cerber` 等)或主机自带的防火墙,可能设置了“阻止恶意访问首页”的规则,但误伤了你。

                * 可以暂时**停用所有插件**(操作方法和之前提到的FTP重命名`plugins`文件夹一样)。
                * 停用后如果主页恢复,再**逐个激活**插件来找出是哪一个在拦截。找到后,进入该插件的“防火墙”或“访问限制”设置里,查看是否有相关规则。

                ### 第三步:检查URL重定向冲突(特别是HTTPS混用)

                重复或错误的强制跳转规则,有时也会导致服务器对首页请求做出混乱反应。这个问题通常来自**`.htaccess`文件**或**重定向插件**。

                * **刷新固定链接**:登录后台,进入 **设置 → 固定链接**,直接点击 **“保存更改”** 按钮。不要修改任何设置,只需点击一次。这会刷新WordPress的URL重写规则。
                * **检查WordPress地址**:进入 **设置 → 常规**,确保 **“WordPress地址(URL)”** 和 **“站点地址(URL)”** 完全一致,并且协议(`http://` 还是 `https://`)正确。
                * **检查.htaccess文件**:如果刷新固定链接没用,需要通过FTP或主机文件管理器,找到网站根目录下的 `.htaccess` 文件,将其**重命名为 `.htaccess_old`**,然后去后台**再次保存一次“固定链接”**。这会生成一个全新的默认规则文件,可以排除旧规则中的冲突。

                ### 第四步:检查父主题文件(如果你在使用子主题)

                这是一个不太常见但值得检查的情况。如果你使用的是**子主题**,且当前激活的是子主题,但父主题的主题文件(`functions.php` 或 `template-loader.php`)里可能通过代码(如 `is_home()` 判断句)指定了有问题的首页加载逻辑。

                * **临时切换主题**:在后台的 **外观 → 主题** 里,临时切换到WordPress默认的`Twenty Twenty-Four`等主题,然后访问主页。
                * 如果默认主题下主页正常,说明问题确实在之前的主题文件里。

                ### 第五步:检查PHP错误日志

                如果以上所有方法都无效,那么问题可能隐藏得更深。WordPress可能因为某个仅在主页调用的函数出错,但错误被服务器吞掉了,只显示了管理员设置的友好报错。

                * **开启WordPress调试模式**:通过FTP找到 `wp-config.php` 文件,在 `define(‘WP_DEBUG’, false);` 这行代码**之前**,添加以下几行代码:
                “`php
                define(‘WP_DEBUG’, true);
                define(‘WP_DEBUG_LOG’, true);
                define(‘WP_DEBUG_DISPLAY’, false);
                “`
                * **查看错误日志**:保存文件后,再次访问主页,然后回到FTP,查看 `wp-content` 文件夹下是否生成了一个 `debug.log` 文件。打开它,里面的信息会直接指向问题根源。

                总的来说,**“设置-阅读”中的静态页面出错**是导致这种特殊现象可能性最高的原因,可以优先检查。排查的核心思路就是利用其他页面正常这一特点,排除全局故障,集中检查只作用于“首页”的特定设置。

                如果以上步骤操作后仍无法解决,可以把排查到的情况(比如后台设置了什么,或者debug.log里有没有内容)告诉我,我再帮你看看~

                1. 水拍石

                  感谢大佬给的教程,我看了一遍,好像这些都不是。我自己浏览首页正常,在线测试工具中首页也能加载出来,所以你加载不出来大概率和IP段有关系,但如果是IP被拦截的话,你应该连文章页都打不开。我继续测试下,看问题到底出在那。