解决后编辑
这个问题之所以在防火墙层面很难解决,是因为这不是防火墙问题。@tom-yan 在聊天中说了些什么让我重新审视了提取 IP 地址的脚本。它似乎sed
提取了整个access_log
文件(而不是我告诉它的内容 - 就像在测试中那样)。我将其替换为grep
,现在脚本正在导出我期望的内容。
这使得其他检查你的假设的例子。
感谢 Tom Yan 和 @pillsbury-it-doughboy 的努力。我非常感激。
(因为汤姆的答案是唯一幸存的答案,所以我将把他的答案标记为正确答案。)
你好,
我的办公室有一台小型开发服务器,其端口 80 和 443 端口从调制解调器转发。
以问题的形式重述标题:
为什么防火墙不丢弃来自富规则中列出的 IPv4 地址的传入流量。
背景: 正如你所期望的,机器人与坏人™ 正在寻找各种事物,a) 不存在,b) 如果它们存在,进入它们会很糟糕。所以我有一个脚本,可以从 Apache 日志中提取 IP 地址,然后在我整理它们之后将它们放入防火墙中。
但是,防火墙不会丢弃连接。前几天添加的地址会在接下来的几天出现在要添加的新规则和日志中。
细节: 放入丰富规则的命令是这样的:
firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='165.227.87.0/24' reject"
然而有些规则有额外的信息:
rule family="ipv4" source address="162.159.244.38" log prefix="Shodan.io" reject
有些则很简单:
rule family="ipv4" source address="42.224.165.0/24" reject
(最后两个规则是从 的输出中复制而来的firewall-cmd --list-all
)
如下所示,活动区域是public
,规则中没有明确指出,因为我读到如果没有指定,它适用于活动区域。
在研究这个问题时,我意识到我可能处于一种不寻常的情况,即调制解调器端口转发到机器,而不是将其放在 DMZ 中或外部托管。Apache 日志显示了 http/s 客户端计算机面向互联网的 IP 地址,我一直假设这些 IP 是呈现给防火墙的地址。
(netstat -tn
确实显示了与外部 IPv4 地址的当前连接,但我无法确定它是入站还是出站。)
Warning: ALREADY_ENABLED: rule family='ipv4' source address='201.159.155.0/24' reject
直到我将日志记录注释添加到规则中后,才出现了频繁的响应,现在它很高兴地接受同一子网的多个拒绝规则。
自从我第一次在 serverfault.com 上写下这个问题(然后被告知在那里问这个问题是不行)以来,我有时间添加前面提到的日志记录,现在已经建立了这个:
[user@server ~]# firewall-cmd --list-rich-rules | grep 194.195.251.
rule family="ipv4" source address="194.195.251.0/24" log prefix="Sun May 23 21:23:50 UTC 2021" reject
rule family="ipv4" source address="194.195.251.0/24" log prefix="194.195.251.228 - Mon May 24 23:58:51 UTC 2021" reject
rule family="ipv4" source address="194.195.251.0/24" log prefix="194.195.251.228 - Tue May 25 21:25:27 UTC 2021" reject
rule family="ipv4" source address="194.195.251.0/24" log prefix="194.195.251.228 - Wed May 26 21:25:57 UTC 2021" reject
和这个:
[user@server ~]# firewall-cmd --list-rich-rules | grep 192.241.196.
rule family="ipv4" source address="192.241.196.0/24" log prefix="192.241.196.220 - Mon May 24 23:59:25 UTC 2021" reject
rule family="ipv4" source address="192.241.196.0/24" log prefix="192.241.196.220 - Tue May 25 21:26:02 UTC 2021" reject
rule family="ipv4" source address="192.241.196.0/24" log prefix="192.241.196.220 - Wed May 26 21:26:31 UTC 2021" reject
显然,这不会降低流量。(日期/时间是添加到防火墙的日期。)
如果有帮助的话,这里是firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: eno1
sources:
services: cockpit dhcpv6-client http https ssh
ports: [redacted integer]/tcp [redacted integer]/tcp [redacted integer]-[redacted integer]/udp [redacted integer]-[redacted integer]/tcp
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
接下来是丰富的规则。为什么不呢,这是活动区域查询:
[user@server ~]# firewall-cmd --get-active-zone
libvirt
interfaces: virbr0
public
interfaces: eno1
其他注意事项:
- 盒子上只有一个以太网端口。
- 添加新规则后防火墙重新加载(
firewall-cmd --reload
) - 服务器每晚都会重启
- 该服务器是 CentOS Stream,但我将其转换为 CentOS 8
- 防火墙处于活动状态、已启用且可正常运行(
firewall-cmd --state
返回“正在运行”) - 我知道它
firewall-cmd --complete-reload
存在,但它会终止所有连接,而这不是我需要的。 - conf文件中的一些内容:
FirewallBackend=nftables
IPv6_rpfilter=yes
RFC3964_IPv4=yes
有任何想法吗?
(丰富规则列表:https://pastebin.com/qXFMBvqh)
- 编辑 -
在“这太荒谬了”的标语下,我将另一个本地 IP 放入防火墙(没有 --permanent)进行测试,然后从 CLI 运行 curl。添加前的测试工作正常,添加后的测试给了我curl: (7) Failed connect to **[redacted]**:80; Connection refused
。由于这些行为符合预期,我无法弄清楚为什么这些其他事情不是这样。
现已开启官方日志记录(firewall-cmd --set-log-denied=all
)
-- 编辑 2 -- 有关该脚本的更多信息:
- 第一个脚本解析 Apache 日志并建立 IP 地址列表。之后,它将
firewall-cmd
添加命令放入.txt
文件中。(它还会查找地理位置信息,但这超出了本文的范围。) - 第二个脚本读取
.txt
文件,并执行firewall-cmd
添加命令,然后运行防火墙重新加载(--reload
)
这样.txt
,如果我不在,文件就可以在周末积累起来。在运行第二个脚本之前,我会检查 GEO 位置信息,以确保更仔细地检查同一国家/地区中的任何 IP,以确定是否应将其从列表中删除。
-- 编辑 3 -- 日志显示了这一点:
Jun 21 09:47:42 <SERVER_NAME> kernel: STATE_INVALID_DROP: IN=eno1 OUT= MAC=a8:a1:59:3a:03:14:20:b0:01:c0:a5:26:08:00 SRC=183.158.154.128 DST=<SERVER_INTERNAL_IP> LEN=40 TOS=0x00 PREC=0x00 TTL=44 ID=38952 DF PROTO=TCP SPT=54750 DPT=80 WINDOW=0 RES=0x00 RST URGP=0
有四个这样的条目,都是在同一毫秒内。有趣的是,该 IP 地址根本不在防火墙规则中。
答案1
看看以下解决方法是否有任何不同。以 root 身份运行以下命令/使用 sudo(每次重新加载规则后;在添加新规则后不需要执行此操作)--permanent
然后尽管):
(顺便说一句,请务必记住,未添加的规则--permanent
在重新加载后将会消失,就像下面这样。)
nft add chain inet firewalld filter_IN_public_black
nft add rule inet firewalld filter_IN_public_black jump filter_IN_public_log
nft add rule inet firewalld filter_IN_public_black jump filter_IN_public_deny
nft insert rule inet firewalld filter_INPUT jump filter_IN_public_black
(由于典型的表刷新不会删除链,而只会删除添加到表中的规则,因此您可能无法使用create
而不是add
链来filter_IN_public_black
确定是否需要再次应用。因此,nft list ruleset
如有疑问,只需使用例如进行检查。但当然,firewalld 可能会枚举其表中的所有链并在重新加载时逐个删除它们。如果您想知道,请进行一些测试。)
PS 此覆盖将应用于所有接口/“区域”(添加了日志和拒绝规则,在应用覆盖之前或之后,如果没有--permenant
,为public
区域)。如果需要,可以进一步自定义它,使其不那么“激进”(例如,iifname
为 增加一个匹配项,jump
即filter_IN_public_black
插入到filter_INPUT
)。