修改宝塔Nginx防火墙(WAF)实现自动拉黑IP
本文介绍了如何通过修改宝塔面板WAF的配置文件waf.lua,实现基于自定义IP列表的自动化封禁功能。核心方法是在网站应用层检测恶意IP并写入文本文件,再由WAF读取比对进行拦截。具体步骤包括:创建IP黑名单文件、备份原始配置文件、插入Lua代码实现IP检查逻辑、重启Nginx服务等。该方案将自定义检测与底层拦截相结合,能有效防御各类恶意访问。文中还提供了详细的代码实现、测试方法和注意事项,特别提

在网站运营过程中,我们经常会遇到各种恶意扫描、爬虫或攻击行为。宝塔面板自带的防火墙(WAF)提供了基础的防护能力,但有时我们需要更灵活、更智能的IP封禁策略,例如基于自定义的访问行为或IP类型进行判断。
本文将介绍一种方法,通过修改宝塔WAF的配置文件 waf.lua,使其能够读取一个自定义的IP列表文件,并对列表中的IP进行自动封禁。结合您已有的IP检测逻辑(如识别假登录访问、高频访问、非蜘蛛的机房IP等),可以构建一个强大的自动化防御体系。
核心思路
- 自定义IP检测与写入: 假设您已经在网站层面实现了IP检测逻辑,能够识别出需要封禁的IP(例如访问特定假入口、访问频率过高、非蜘蛛的机房IP等)。这些被识别出的恶意IP将被写入到一个指定的文本文件,例如
/www/wwwroot/api/banned_ips.txt,每行一个IP。 - 修改宝塔WAF配置: 修改宝塔WAF的核心配置文件
waf.lua。在处理每个HTTP请求时,WAF会读取/www/wwwroot/api/banned_ips.txt文件,检查当前请求的客户端IP是否在该文件中。 - 执行封禁: 如果客户端IP存在于
banned_ips.txt文件中,WAF将立即终止该请求,并返回一个特定的状态码(例如 444),从而实现自动拉黑。
这种方法的优点在于,IP检测逻辑可以完全自定义并在您的网站应用层面实现,而封禁的执行则下放到更底层的WAF层面,效率更高,且能拦截对网站任何资源的访问(包括静态文件)。
操作步骤
重要提示: 修改宝塔面板的核心配置文件存在风险,操作前请务必备份相关文件!如果操作不当可能导致网站无法访问或WAF功能失效。
-
生效方式:确保宝塔WAF以及站点防火墙已开启: 在宝塔面板中,进入“网站”菜单,选择您的网站,点击“设置”,找到“网站防火墙(WAF)”,确保其已开启。在站点设置中,开启状态的站点才会受到保护。如果nginx防火墙或站点没开启防火墙,不受封禁列表影响。
-
创建并维护封禁IP文件:
- 创建您指定的封禁IP文件,例如
/www/wwwroot/api/banned_ips.txt。您可以使用SSH命令创建:touch /www/wwwroot/api/banned_ips.txt - 确保您的网站应用(例如PHP脚本)有权限向此文件写入内容。通常,将文件放在网站根目录下,并确保文件权限正确(例如
644或666,取决于您的需求和安全设置,但需要确保Nginx用户有读取权限,您的写入脚本有写入权限)。 - 您的IP检测脚本需要负责将需要封禁的IP按行写入此文件。例如,使用PHP的
file_put_contents函数以追加模式写入,并在写入前检查IP是否已存在,避免重复。
- 创建您指定的封禁IP文件,例如
-
备份
waf.lua文件:- 通过宝塔面板的文件管理器或SSH进入
/www/server/btwaf/目录。 - 找到
waf.lua文件,将其复制一份作为备份,例如命名为waf.lua.bak。
- 通过宝塔面板的文件管理器或SSH进入
-
修改
waf.lua文件:- 修改waf.lua前需要先关闭Nginx防火墙。修改完再打开防火墙
- 使用宝塔面板的文件编辑器或SSH编辑器打开
/www/server/btwaf/waf.lua文件。 - 找到获取客户端IP的代码行,通常是
local ip = IpInfo.get_client_ip_bylog()。 - 在获取客户端IP的代码之后,获取args参数的代码之前(或者根据您提供的代码片段,直接插入到获取IP和获取cookie信息之间),插入您提供的Lua代码。
找到类似以下结构的代码位置:
-- --获取客户端的IP local ip = IpInfo.get_client_ip_bylog() -- --获取args参数 ngx.ctx.get_uri_args = ngx.req.get_uri_args(100000) -- ... 其他代码 ... --获取cookie的信息 -- ... 获取cookie的代码 ...将代码插入到
ngx.ctx.get_uri_args之前:-- --获取客户端的IP local ip = IpInfo.get_client_ip_bylog() -- --获取args参数 ngx.ctx.get_uri_args = ngx.req.get_uri_args(100000) -- >>>>>>>>>>>>>>>>>>>>>>> 新增代码开始 (包含日志记录) <<<<<<<<<<<<<<<<<<<<<<<<< -- 定义封禁IP列表文件的路径 local banned_ips_file = "/www/wwwroot/api/banned_ips.txt" -- 检查封禁IP文件是否存在 local file = io.open(banned_ips_file, "r") if file then -- 文件存在,逐行读取并检查客户端IP是否在列表中 for line in file:lines() do -- 移除行首尾的空白字符 local banned_ip = string.match(line, "^%s*(.-)%s*$") -- 如果行不为空且与客户端IP匹配 if banned_ip ~= "" and banned_ip == ip then -- 客户端IP在封禁列表中 -- 记录封禁日志信息 Public.logs("Blocked banned IP: " .. ip .. " from file " .. banned_ips_file .. " for URL: " .. ngx.var.request_uri) file:close() -- 在退出前关闭文件 -- 返回444状态码 ngx.exit(444) end end file:close() -- 如果循环结束仍未找到匹配,关闭文件 end -- >>>>>>>>>>>>>>>>>>>>>>> 新增代码结束 <<<<<<<<<<<<<<<<<<<<<<<<< --获取cookie的信息 -- ... 获取cookie的代码 ...代码解释:
local banned_ips_file = "/www/wwwroot/api/banned_ips.txt": 定义了存储封禁IP的文件路径。local file = io.open(banned_ips_file, "r"): 尝试以只读模式打开指定的封禁IP文件。if file then ... end: 检查文件是否成功打开。如果文件不存在或无法读取,则跳过封禁检查。for line in file:lines() do ... end: 如果文件打开成功,则逐行读取文件内容。local banned_ip = string.match(line, "^%s*(.-)%s*$"): 使用Lua的字符串匹配功能,提取当前行的内容,并去除行首尾的空白字符。if banned_ip ~= "" and banned_ip == ip then ... end: 判断提取出的IP是否非空,并且是否与当前请求的客户端IP (ip) 相匹配。Public.logs(...): 如果IP匹配,则调用宝塔WAF的日志函数记录一条封禁日志,方便后续排查。file:close(): 关闭文件句柄。在找到匹配IP并退出前关闭,或者在遍历完整个文件后关闭。ngx.exit(444): 这是OpenResty/Nginx Lua模块提供的函数,用于终止当前请求并返回指定的HTTP状态码。444是一个非标准的Nginx状态码,表示“无响应”,客户端会直接断开连接。
-
保存文件并重启Nginx:
- 保存对
waf.lua文件的修改。 - 在宝塔面板中,进入“软件商店”,找到“Nginx”,点击“设置”,然后点击“重启”。重启Nginx服务会加载新的WAF配置。
- 保存对
测试
- 向
/www/wwwroot/api/banned_ips.txt文件中手动添加您当前的公网IP(确保每行只有一个IP)。 - 尝试访问您的网站。如果配置成功,您的浏览器应该会显示连接被重置或无法访问,并且在Nginx的错误日志或宝塔WAF的日志中应该能看到相关的封禁记录。
- 测试完成后,记得从
banned_ips.txt文件中移除您的IP。
注意事项
- 性能影响: 对于高流量网站,每次请求都需要读取并遍历
banned_ips.txt文件。如果这个文件非常大(包含成千上万个IP),可能会对服务器性能产生一定影响。可以考虑优化文件读取逻辑,或者对于超大型列表,探索使用Lua共享内存或Redis等方式存储封禁IP。 - 文件权限: 确保Nginx运行用户(通常是
www)对/www/wwwroot/api/banned_ips.txt文件有读取权限。您的IP写入脚本用户对该文件有写入权限。 - 误杀: 您的IP检测逻辑是关键。请务必谨慎设计拉黑规则,避免误封正常用户或搜索引擎蜘蛛。
- 宝塔更新: 宝塔面板或WAF插件更新时,可能会覆盖
waf.lua文件。在更新前请再次备份,更新后检查并重新应用您的修改。 - 日志: 代码中包含了日志记录,这对于排查问题和监控封禁情况非常有用。请定期查看相关日志。
通过以上步骤,您就成功地将宝塔WAF与您的自定义IP检测逻辑结合起来,实现了基于文件列表的自动化IP拉黑功能。
更多推荐
所有评论(0)