Fail2Ban iptables 条目拒绝 HTTPS 不会停止对 Amazon Linux 2 上的 Docker 容器的请求

Gra*_*Lea 2 https iptables fail2ban docker amazon-linux-2

我已经在 Amazon Linux 2 上设置了 Fail2Ban,使用nginx-http-auth以下覆盖配置启用内置监狱:

[nginx-http-auth]
enabled = true
action = iptables[name=HTTPS, port=https, protocol=tcp]
logpath = <snip>/logs/*error*.log
findtime = 15m
bantime = 15m
maxretry = 5
Run Code Online (Sandbox Code Playgroud)

该操作正在触发,我收到以下条目iptables -S

-A f2b-HTTPS -s 120.<snip>.122/32 -j REJECT --reject-with icmp-port-unreachable
Run Code Online (Sandbox Code Playgroud)

但是,我可以继续从被禁止的 IP 发出新的 HTTPS 请求,这些请求正在接收来自 Nginx 的 401 响应。我从两个 IP 地址进行复制 - 我的手机和另一个 EC2 主机。

以下是完整输出iptables -L:(注意:Nginx 在 Docker 内部运行,另外两个与本地网络隔离的容器也是如此)

Chain INPUT (policy ACCEPT)
target     prot opt source               destination
f2b-HTTPS  tcp  --  anywhere             anywhere             tcp dpt:https

Chain FORWARD (policy DROP)
target     prot opt source               destination
DOCKER-USER  all  --  anywhere             anywhere
DOCKER-ISOLATION-STAGE-1  all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
DOCKER     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
DOCKER     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain DOCKER (2 references)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             ip-192-168-208-2.ap-southeast-2.compute.internal  tcp dpt:webcache

Chain DOCKER-ISOLATION-STAGE-1 (1 references)
target     prot opt source               destination
DOCKER-ISOLATION-STAGE-2  all  --  anywhere             anywhere
DROP       all  -- !ip-192-168-192-0.ap-southeast-2.compute.internal/20  anywhere
DROP       all  --  anywhere            !ip-192-168-192-0.ap-southeast-2.compute.internal/20
DROP       all  -- !ip-192-168-176-0.ap-southeast-2.compute.internal/20  anywhere
DROP       all  --  anywhere            !ip-192-168-176-0.ap-southeast-2.compute.internal/20
DOCKER-ISOLATION-STAGE-2  all  --  anywhere             anywhere
RETURN     all  --  anywhere             anywhere

Chain DOCKER-ISOLATION-STAGE-2 (2 references)
target     prot opt source               destination
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
RETURN     all  --  anywhere             anywhere

Chain DOCKER-USER (1 references)
target     prot opt source               destination
RETURN     all  --  anywhere             anywhere

Chain f2b-HTTPS (1 references)
target     prot opt source               destination
REJECT     all  --  120.<snip>.122       anywhere             reject-with icmp-port-unreachable
RETURN     all  --  anywhere             anywhere
Run Code Online (Sandbox Code Playgroud)

为什么 iptable 规则不停止 HTTPS 请求?

我是否需要以某种方式更改我的fail2ban 配置才能使其正常工作?

Gra*_*Lea 8

正如@tater 在上面的评论中指出的,fail2ban 默认情况下会将自身插入到 INPUT 链中,但到 Docker 容器的流量是使用 FORWARD 链进行路由的,该路由不会触及 INPUT 链。你可以在这里看到:

$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
f2b-HTTPS  tcp  --  anywhere             anywhere             tcp dpt:https
...
Run Code Online (Sandbox Code Playgroud)

我们可以通过将类似的fail2ban规则插入到FORWARD链中来测试fail2ban是否与Docker一起使用,如下所示(注意:这不是长期解决方案):

$ sudo iptables -I FORWARD 1 -p tcp -j f2b-HTTPS
Run Code Online (Sandbox Code Playgroud)

在英语中,此命令表示“对于 TCP 协议上的所有流量,在位置 1(即第一条规则)处插入对该f2b-HTTPS链的引用”,其效果是包含该链的所有规则。位置。

完成此操作后,FORWARD 链应在顶部包含新规则:

$ sudo iptables -L
...
Chain FORWARD (policy DROP)
target     prot opt source               destination
f2b-HTTPS  tcp  --  anywhere             anywhere
DOCKER-USER  all  --  anywhere             anywhere
...
Run Code Online (Sandbox Code Playgroud)

然后,fail2ban 在 f2b-HTTPS 链下自动管理的规则用于拒绝发往 Docker 的流量。

然而,我们希望fail2ban 自动为我们执行此操作,而不是必须创建我们自己的 iptables 规则。那么,解决方案是在以下文件中的监狱配置中添加第二个操作jail.d/

action = iptables[actname=iptables-input,   name=HTTPS,                       port=https, protocol=tcp]
         iptables[actname=iptables-forward, name=HTTPS-DOCKER, chain=FORWARD, port=8080, protocol=tcp]
Run Code Online (Sandbox Code Playgroud)

只需添加到我原来的规则中可能就足够了chain=FORWARD,但我决定也保留 INPUT 规则。

注意:规则中的端口iptables-forward是 8080,因为这是我的 Docker 容器正在侦听的位置,并且它是 FORWARD 规则上的 iptables 匹配的目标转发端口(看起来),而不是入站端口。

在解决这个问题时我发现了另外两件事:

  1. fail2ban 在安装时默认不启用。要启用它,请运行:
sudo systemctl enable fail2ban
Run Code Online (Sandbox Code Playgroud)
  1. 如果您的系统在禁令处于活动状态时重新启动,则fail2ban将在Docker将其规则插入FORWARD链的顶部之前将其规则插入FORWARD链的顶部。这意味着 Docker 规则将覆盖fail2ban 规则,并且禁令将不起作用。(您可以通过执行来模拟这一点sudo service docker restart。)为了克服这个问题,您需要在 Docker 建立其网络后启动fail2ban。我通过更改 '/etc/lib/systemd/system/fail2ban.service' 来做到这一点:
  • 将“docker.service”添加到“之后:”列表中
  • 删除 PartOf=firewalld.service 行
  • [Service]在等待端口 443 打开的部分中添加此内容:ExecStartPre=/bin/bash -c '(while ! nc -z -v -w1 localhost 443 > /dev/null; do echo "Waiting for port 443 to open..."; sleep 2; done); sleep 2'
  • (注:您还需要nc安装)