如何正確給 Docker 配置 firewalld,以及 Docker 強行覆蓋 iptables 的安全隱患

業務上使用 Docker 也算有一年了,但一直以來 Docker 的容器都是跑在 AWS 雲服務上面,不需要自己配置防火牆服務,firewalld 也從來不需要在主機上啟用,這個週末在普通 VPS 上折騰 Docker + firewalld,哪知一腳掉進了泥水坑。

TL;DR,Docker 會在啟動時自動幫你完成綁定端口的操作,但問題出在,它寫的規則是把端口對所有人開放,而無視你在 firewalld 其他 zone 寫的 IP 限制。

感謝以下文章:

无视系统防火墙的docker https://www.binss.me/blog/docker-pass-through-system-firewall/

firewall-cmd –reload on centos 7.4.1708 removes the DOCKER-USER iptables chain https://github.com/moby/moby/issues/35043#issuecomment-356036671

Docker and iptables https://docs.docker.com/network/iptables/

Configuring iptables to let Docker containers access out https://serverfault.com/a/883184

廢話少說,直接切去重點,經過調查,得知:

  1. Docker 寫的規則是直接寫入 iptables CHAIN 的,不受 firewalld zone 設定的影響
  2. Docker 有一個啟動選項 `–iptables=false`,但這樣子的話 Docker 內網的轉發都要自己加上去了,我懶我不幹
  3. Docker 提供另一個選項,CHAIN `DOCKER-USER`,可以覆蓋 Docker 啟動時的 CHAIN 設定,這次就拿它開刀

以下為最終設置腳本:

> 首先我們讓 firewalld 移除掉 DOCKER-USER 並新建一個(這步非常重要,即便 DOCKER-USER 已經存在,你也需要執行刪除,不然不生效,原因我也沒搞懂)

firewall-cmd --permanent --direct --remove-chain ipv4 filter DOCKER-USER
firewall-cmd --permanent --direct --remove-rules ipv4 filter DOCKER-USER
firewall-cmd --permanent --direct --add-chain ipv4 filter DOCKER-USER

> 下一步,加上你想要的規則,注意 REJECT 規則一定要在最後執行,同時注意不建議多個 IP 地址寫在同一條規則,格式上沒有問題,但不知道為什麼通過 iptables -L 確認時,順序會打亂,導致先被 REJECT

firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 0 -i docker0 -j ACCEPT -m comment --comment "allows incoming from docker"
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 0 -i docker0 -o eth0 -j ACCEPT -m comment --comment "allows docker to eth0"
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m comment --comment "allows docker containers to connect to the outside world"
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 0 -j RETURN -s 172.18.0.0/16 -m comment --comment "allow internal docker communication"
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 0 -s 1.1.1.1/32 -j ACCEPT # 你可以直接允許來自特定 IP 的所有流量
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 0 -p tcp -m multiport --dports 1,2:3 -s 2.2.2.2/32 -j ACCEPT # 你也可以指定端口,這裡僅為示例
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 0 -j REJECT --reject-with icmp-host-unreachable -m comment --comment "reject all other traffic"

> 最後,重啟 firewalld 並通過 iptables -L 和其他 IP 地址確認是否正確生效

firewall-cmd --reload

當時白菜價買來的騰訊雲成都 AMD 系列服務器,1核1G1Mbps,買回來之後吃了半年灰,今天正好有個主意拿來做網站在線率監控,於是回去折騰了一下,發現這機子還真是不錯,入網帶寬沒有什麼限制,所以不用擔心 1Mbps 隨便下載點什麼都要爆炸,機子的性能表現也沒有什麼遲緩的感覺,整體而言,如果你想要一台 Linux 學習機,我還是很推薦的,現在 3 年 607 元。

https://cloud.tencent.com/act/mid-year?from=10815#cvm