如何阻止IP地址范围?

您好,我正在尝试暂时阻止一个滥用性的 /16 子网,该子网正在向 Discourse 论坛发送大量请求。我尝试了…

…但我在 /var/discourse/shared/standalone/log/var-log/nginx/access.log 中仍然看到来自同一范围的大量新请求。

由于这些是在 Discourse 中配置的,我很确定 IP 是由 Discourse 阻止的,而不是 NGINX,因此它们会显示在 NGINX 日志中。是 Discourse 在阻止它们,而不是 nginx。如果你想阻止它们,让它们不显示在 NGINX 日志中,你可以用防火墙阻止它们。

1 个赞

谢谢 Jay,你说得对,如果是在应用程序级别阻止,它仍然会显示在 Nginx 日志中。但是,应用程序级别的阻止也没有达到我预期的效果。我尝试通过 VPN 连接,然后将我自己的 IP 地址添加到“Screened IPs”(已筛选 IP)列表中,但仍然可以浏览论坛。我认为它之所以被称为“Screened IPs”(已筛选 IP)而不是“Blocked IPs”(已阻止 IP),可能是因为它只阻止这些 IP 注册账户?

我需要 Discourse 应用程序拒绝来自这些地址的请求访问请求的页面,特别是不要渲染这些页面,因为所有这些请求都在占用 CPU。

如果从 /admin/users 查看用户记录,Discourse 是否会识别出您来自被禁止的 IP?(如果您使用 Cloudflare 等代理,Discourse 可能会看到您的代理 IP 而不是用户的 IP。)

是的,当我连接到 VPN 然后查看 Discourse 中我的用户帐户的最后一个 IP 地址时,它显示的是 VPN 分配给我的 IP 地址。但是,当我打开一个无痕浏览器窗口并尝试注册一个新帐户时,它不允许这样做:

不允许从您的 IP 地址进行新注册。

因此,看起来“已屏蔽的 IP 地址”仅用于注册,而不是完全禁止访问网站。

更复杂的是,主机服务器上的 ufw 在 Docker 内部似乎无法按预期阻止流量:

1 个赞

我不确定我们在哪里记录了这一点,但最近它已经出现过几次了。

“已屏蔽IP”会阻止匹配的IP进行注册和登录,但不会阻止现有会话。

我不确定我们在哪里(如果)记录了这一点。

3 个赞

感谢您的确认。

那么,拒绝来自某个 IP 或 IP 地址范围的请求的最简单方法是什么?我找到了这个,但它似乎与我需要的功能相反(白名单而不是黑名单),并且在容器内修改 Nginx 配置感觉像是一个糟糕的解决方案:

我认为使用 UFW 或 IPTABLES 来实现。这样可以在 Discourse 介入之前就阻止它们。我总是对弄乱防火墙含糊不清地感到恐惧,因为我怕我会把自己锁在外面,但如果你只针对 443 端口,你就不会有任何危险。

Digital Ocean 有一些提示:https://www.digitalocean.com/community/tutorials/ufw-essentials-common-firewall-rules-and-commands。我只会搜索示例。

这正是我担心的。但我确实在主机上启用了它,但它仍然没有阻止有问题的 IP 地址范围。显然,它需要一套复杂的规则才能将拒绝规则应用于 Docker 容器。

哦。是的。那是完全正确的。我最终阻止了我的基于 Docker 的 Web 服务器访问基于 Docker 的 PostgreSQL 数据库(这可能不是你的问题)。

这是另一个主意:Geo Blocking plugin

谢谢,我当时也在看这个,但它似乎不允许阻止数字 IP 范围,只允许阻止整个国家/地区?

我最近没有安装它,但我很确定它允许。

(强调已添加)

然后我找到了这个:

所以我想这意味着你可以在那里输入任何你想要的 IP 地址。

1 个赞
/var/discourse/launcher enter app
apt install nano
nano /etc/nginx/conf.d/discourse.conf

然后在 server { 块中添加:

## 2025-10-27
deny 12.34.0.0/16;

然后保存并执行:

nginx -t
service nginx reload

我不完全明白为什么我仍然在 Nginx 的 access.log 中看到来自 12.34.x.x 的访问记录,但它似乎确实有效,因为 CPU 使用率现在已恢复正常。 IMHO,这是一个极其复杂的过程,但足以让网站恢复正常运行。

是的,但目前它只能接受 AS 号码,而不能接受像 1.2.3.0/24 这样的 CIDR 表示法。

1 个赞

这奏效了吗?我认为你需要执行

sv restart nginx

但如果你没有收到错误,那说明我错了。

Nginx 仍然能看到这些吗?它显示正在为它们提供服务吗?你在 rails production.log 中看到这些吗?

啊。也许我应该更多地关注那个关于 AS 号码的维基百科页面。

我认为它们都是现在映射到 systemd 命令的旧别名,所以 systemctl restart nginx 将是最恰当的。~~编辑: 看起来 systemctl 在 Docker 中不起作用。这里有一些关于它们之间区别的解释:

是的,在 access.log 中它们仍然显示为:

[28/Oct/2025:00:29:27 +0000] \"myforum.com\" 12.34.56.78 \"GET /permalink/12345 HTTP/1.1\" \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36\" \"-\" 403 691 \"-\" - 0.000 \"-\" \"-\" \"-\" \"-\" \"-\" \"-\" \"-\"

它们现在似乎主要在访问永久链接(从旧论坛平台迁移而来)。永久链接是否存在某种漏洞,使其能够绕过 deny 规则?我还没有检查 production.log

总的来说,我认为 Discourse 缺乏一个用于检查访问日志的图形用户界面,并且没有应用程序级别的 IP 阻止列表,这是一个相当大的限制。我迁移过来的非常旧的论坛平台显示了一个简单的列表,列出了在可调时间窗口内请求次数最多的用户或 IP,甚至可以按占用 CPU 时间最多的用户和/或 IP 进行过滤。这样我就可以快速识别出有问题地址或范围,然后有一个点击即可操作的界面将其添加到阻止列表中,它会拒绝来自这些 IP 的请求并返回 404。

如果你有一个 deny 规则,nginx 仍然会记录这些信息。而且这是正确的,因为那里有一个 403,这意味着客户端被拒绝访问。

这些请求不会被转发到 Discourse。如果你想知道你的阻止是否正常工作,你应该:

  • 查看 Discourse 的 production.log
  • 查看 nginx 日志,但忽略 HTTP 响应代码字段中包含 403 的任何条目。
3 个赞

这个问题现在解决了么?有没有一个帖子@rgj或@pfaffman我可以选作解决方案?看起来你们在这上面合作了!

:handshake:

您好,我认为目前无法通过“常规”方法解决此问题。“Screened IPs”的管理界面并不像大多数用户期望的那样工作,而实际有效的方法需要操作 Discourse 的 docker 容器内部,所以 IMHO,这更像是一个肮脏的技巧,而不是一个解决方案。如果能引起更多关注,那就太好了: