Try   HackMD

Linux save iptables on Docker Host Environment - 在安裝了 Docker 的環境處理 iptables 的儲存

tags: blog

iptables 是在 Linux 系統上實用的防火牆、NAT、封包管理系統,但如果需要在複雜的環境當中使用 iptables ,並且將 iptables 的規則保存的話,就需要使用一些技巧

Context

以往在 Linux 當中,我們可以透過 iptables 來當作防火牆使用,只要透過 iptables 中預設的 filter tables,即可做到封包的過濾功能。

但 iptables 的資料是於執行時新增規則,如果想要將規則存檔,並於開機時自動載入的話,我們就需要透過 iptables-saveiptables-restore 這兩個指令來完成。

根據 Debian Wiki[1] 中提到的方法,可以使用 iptables > /etc/iptables.up.rules 的方式將 iptables 的 rule 匯出至檔案,再透過 iptables < /etc/iptable.up.rules 指令將規則檔案還原。

文中也提到,可以在 /etc/network/if-pre-up.d/ 路徑中,放置 bash 檔案,這樣就會在網卡啟動前,呼叫 iptables-restore 指令,載入 iptables 的規則。

Problem

問題來了,傳統作法中,所使用的 iptables-save 指令,會將目前所有的規則匯出,但是如果主機環境中有安裝 Docker 的話, Docker 會建立許多橋接器 (Bridge) ,並透過 iptables 的 filter 、 nat 這兩張表,建立 container 的網路與連線關係。

而 Docker 的環境不清楚他會在何時啟動,並更改 iptables 的狀況下,如果冒然執行 iptables-restore 指令,勢必會破壞原先 docker 所建立的規則。

Solution

如果無法透過 iptables-restore 指令直接匯入規則檔的話,還可以透過另一個方式:使用 iptables 指令動態新增規則。

不過這邊要注意的是,要注意目前 iptables 中的規則是否已經存在,免得重複新增規則。

使用 iptables 的 check 指令可以根據回傳值得之規則是否存在

iptables [-t table] -C chain rule-specification'

一樣將 bash 檔案寫在 /etc/network/if-pre-up.d/ 中,
透過 if 判斷欲新增的規則是否已經存在於 iptables 中,
如果沒有找到的話,再使用 iptables 指令動態增加新的規則。

以下是 bash 的範例,透過 function 的方式判斷規則存不存在,不存在則新增規則

#!/bin/sh

# check iptables rule specification is exist,
# if not add it
check_and_add_iptables()
{
    RULE_SPEC=$@
    iptables -C $RULE_SPEC > /dev/null 2>&1
    EXIST=$?
    if [ $EXIST -ne 0 ]; then
        iptables -A $@
    fi
}

check_and_add_iptables INPUT -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT
check_and_add_iptables INPUT -p tcp --dport 22 -j DROP

Conclusion

iptables 是一個很好用的防火牆軟體,不過在一些複雜的環境當中,無法單純使用 restore 指令套用規則,就得使用動態增加的方式,使用動態增加的方式又得顧慮到該指令重複執行會造成的影響,所以還需要透過一些 test 的方式判斷目前的環境 (Context) 是否可以新增規則。

References


  1. https://wiki.debian.org/iptables ↩︎