報文過濾和連接跟蹤可以說是Netfilter
提供的兩大基本功能。前者被大多數人熟知,因爲我們對防火牆的第一印象就是可以阻止有害的報文傷害計算機;而後者就沒這麼有名了,很多人甚至不知道Netfilter
有這項功能。
Why 使用連接跟蹤
顧名思義,連接跟蹤是保存連接狀態的一種機制。爲什麼要保存連接狀態呢? 舉個例子,當你通過瀏覽器訪問一個網站(連接網站的80
端口)時,預期會收到服務器發送的源端口爲80
的報文迴應,防火牆自然應該放行這些迴應報文。那是不是所有源端口爲80
端口的報文都應該放行呢?顯然不是,我們只應該放行源IP爲服務器地址,源端口爲80
的報文,而應該阻止源地址不符的報文,即使它的源端口也是80
。總結一下這種情況就是,我們只應該讓主動發起的連接產生的雙向報文通過。
另一個例子是NAT
。我們可以使用iptables
配置nat
表進行地址或者端口轉換的規則。如果每一個報文都去查詢規則,這樣效率太低了,因爲同一個連接的轉換方式是不變的!連接跟蹤提供了一種緩存解決方案:當一條連接的第一個數據包通過時查詢nat
表時,連接跟蹤將轉換方法保存下來,後續的報文只需要根據連接跟蹤裏保存的轉換方法就可以了。
連接跟蹤發生在哪裏
Connection tracking hooks into high-priorityNF_IP_LOCAL_OUT
andNF_IP_PRE_ROUTING
hooks, in order to see packets before they enter the system.
連接跟蹤需要拿到報文的第一手資料,因此它們的入口是以高優先級存在於LOCAL_OUT
(本機發送)和PRE_ROUTING
(報文接收)這兩個鏈。
既然有入口,自然就有出口。連接跟蹤採用的方案是在入口記錄,在出口確認(confirm
)。以IPv4
爲例:
當連接的第一個skb
通過入口時,連接跟蹤會將連接跟蹤信息保存在skb->nfctinfo
,而在出口處,連接跟蹤會從skb
上取下連接跟蹤信息,保存在自己的hash
表中。當然,如果這個數據包在中途其他HOOK
點被丟棄了,也就不存在最後的confirm
過程了。
連接跟蹤信息是什麼
連接跟蹤信息會在入口處進行計算,保存在skb
上,信息具體包括tuple
信息(地址、端口、協議號等)、擴展信息以及各協議的私有信息。
-
tuple
信息包括髮送和接收兩個方向,對TCP
和UDP
來說,是IP
加Port
;對ICMP
來說是IP
加Type
和Code
,等等; - 擴展信息比較複雜,本文暫時略過;
- 各協議的私有信息,比如對
TCP
就是序號、重傳次數、縮放因子等。
報文的連接跟蹤狀態
途徑Netfilter
框架的每一個報文總是會在入口處(PRE ROUTING
或者LOCAL OUT
)被賦予一個連接跟蹤狀態。這個狀態存儲在skb->nfctinfo
,有以下常見的取值:
-
IP_CT_ESTABLISHED:這是一個屬於已經建立連接的報文,
Netfilter
目擊過兩個方向都互通過報文了 -
IP_CT_RELATED:這個狀態的報文所處的連接與另一個IP_CT_ESTABLISHED狀態的連接是有聯繫的。比如典型的
ftp
,ftp-data
的連接就是ftp-control
派生出來的,它就是RELATED
狀態 -
IP_CT_NEW:這是連接的第一個包,常見的就是
TCP
中的SYN
包,UDP
、ICMP
中第一個包, - IP_CT_ESTABLISHED + IP_CT_IS_REPLY:與IP_CT_ESTABLISHED類似,但是是在回覆方向
- IP_CT_RELATED + IP_CT_IS_REPLY:與IP_CT_RELATED類似,但是是在回覆方向
總結
-
連接跟蹤是
Netfilter
提供的一項基本功能,它可以保存連接的狀態。用戶可以爲不同狀態的連接的報文制定不同的策略; -
連接跟蹤在報文進入
Netfilter
的入口將信息記錄在報文上,在出口進行confirm
.確認後的連接信息可以影響之後的報文; -
連接跟蹤的信息主要包括基本的描述連接的
tuple
以及各協議的私有信息。