Iptables

Fail2Ban iptables 條目拒絕 HTTPS 不停止對 Amazon Linux 2 上的 Docker 容器的請求

  • December 5, 2020

nginx-http-auth我已經在 Amazon Linux 2 上設置了 Fail2Ban,使用此覆蓋配置啟用內置監獄:

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

動作正在觸發,我得到以下條目iptables -S

-A f2b-HTTPS -s 120.<snip>.122/32 -j REJECT --reject-with icmp-port-unreachable

但是,我可以繼續從被禁止的 IP 發出新的 HTTPS 請求,這些 IP 正在接收來自 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

為什麼 iptable 規則不停止 HTTPS 請求?

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

正如@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
...

我們可以通過在 FORWARD 鏈中插入類似的 fail2ban 規則來測試讓 fail2ban 與 Docker 一起使用,如下所示(注意:這不是長期解決方案):

$ sudo iptables -I FORWARD 1 -p tcp -j f2b-HTTPS

在英語中,這個命令說“插入到 FORWARD 鏈的位置 1(即第一條規則),對於 TCP 協議上的所有流量,對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
...

然後,fail2ban 在 f2b-HTTPS 鏈下自動管理的規則用於拒絕發往 Docker 的流量。

但是,我們希望 fail2ban 自動為我們執行此操作,而不必創建我們自己的 iptables 規則。然後,解決方案是在以下文件中的 jail 配置中添加第二個操作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]

只添加chain=FORWARD到我的原始規則可能就足夠了,但我決定也保留 INPUT 規則。

**注意:**規則中的埠iptables-forward是 8080,因為這是我的 Docker 容器正在偵聽的位置,並且它是 iptables 在 FORWARD 規則(似乎)上匹配的目標轉發埠,而不是入站埠。

我在解決這個問題時發現了另外兩件事:

  1. fail2ban 安裝時預設不啟用。要啟用它,請執行:
sudo systemctl enable fail2ban
  1. 如果您的系統在禁令處於活動狀態時重新啟動,fail2ban 將在Docker 將其規則插入到 FORWARD 鏈的頂部*之前將其規則插入到 FORWARD 鏈的頂部。*這意味著 Docker 規則將覆蓋 fail2ban 規則並且禁令將不起作用。(你可以通過做來模擬這個sudo service docker restart。)為了克服這個問題,你需要在 Docker 建立網路後啟動 fail2ban。我通過以下方式更改“/etc/lib/systemd/system/fail2ban.service”來做到這一點:
  • 將 ‘docker.service’ 添加到 ‘After:’ 列表中
  • 刪除 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安裝)

引用自:https://serverfault.com/questions/1043964