ip_conntrack将無狀态的在高層有聯系的單個IP資料報用狀态聯系了起來,實際上是在更底層破壞了分組交換網的單分組轉發的原則。
ip_conntrack基于五元組來追蹤一個流,在流的開頭或者涉及到狀态切換的時候設定一些狀态和cache,屬于同一流的後續分組就可以共享這些狀态和cache,這些狀态和cache用于更高層的邏輯判斷,比如NAT,或者Netfilter的state這些match。
在純轉發網絡中或者是ACL比較簡單的網絡節點上,我們希望ip_conntrack可以儲存下面的一些資訊:
1.五元組辨別的資料流。這個在标準核心中已經實作,NAT子產品使用的正是這個資訊。
2.高層filter的結果資訊,如果一個流的第一個包被高層drop了,那麼希望ip_conntrack儲存這個結果資訊,後續的包在PREROUTING這個HOOK點直接drop,而不必繼續往上層走了。這個在标準的核心中還沒有實作,可能是因為要涉及高層過濾規則和底層的ip_conntrack儲存的資訊之間的同步,比如一個UDP流,開始由于某種事件被drop了,不久的後來又被accept了。處理這種同步非常複雜,特别是在核心中這麼做。
3.IP層的路由結果資訊。由于IP資料報的單包被路由的,如果多個IP資料報被看作了一個流,那麼流的第一個資料報的路由結果就可以被ip_conntrack儲存下來,後來的資料報直接根據該儲存的結果直接轉發,而不必再經過标準的IP路由或者IP路由緩存。這個在标準的Linux核心中也沒有實作,原因也是資訊同步問題,特别是涉及動态路由協定并且收斂慢的時候。
但是,如果你确定的知道資訊同步問題不會發生,比如配置靜态的filter,配置靜态的路由,那麼上述的2和3還是有必要實作的,幸運的是,這種實作很容易,以路由緩存為例,基于2.6.32版本的核心,隻需要在struct nf_conn中添加一個指針dst_entry,儲存一個流的第一個包的路由結果資訊,這個資訊應該是第一個包的POSTROUTING或者OUTPUT這個HOOK點上被添加進nf_conn結構體,然後在PREROUTING中被檢查,如果檢查存在這個dst_entry,則直接轉發,調用dst_output,這裡沒有和filter關聯,簡單點說,不考慮filter,并且配置靜态路由,路由不會改變的情況下,這種方式十分可行,為什麼呢?因為本來ip_conntrack的加載就使得TCP/IP協定棧核心路徑多了一次流比對,到了IP層還要進行route查找或者cache查找,為何不在僅有的一次查找中完成所有這些呢,當然前提是一切都是靜态的情況下。其實加入這個patch并不會帶來性能的多大提升,但是它能使得ip_conntrack對性能的危害減輕一些。
最後說一下可惡的NAT,NAT實則破壞了網際網路的原則,它使網際網路不再互聯。這就不由想起一些專家們的話,Internet在設計從來就是先天不足的,現在的Internet已經貼滿了更新檔,沒有地方再貼了,可是反對意見有的是,Internet的發展完全是一幅油畫的創作過程,草稿和定版都位于同一張紙上!
本文轉自 dog250 51CTO部落格,原文連結:http://blog.51cto.com/dog250/1270917