天天看點

cache老化時間的思考--以nat為例

區域網路越來越大,于是有人提出了vlan,vlan越來越依賴多而快的端口,于是有人做出了三層交換機,實際上三層交換機僅僅對直接下挂的主機性能有較大的提升,對遠端的主機效果要麼不大,要麼根本沒有,說白了三層交換機就是在學以太網交換機的樣子,本質上就是加了一個cahce功能,使得ip位址直接與端口保持映射,這樣就不必再解包,路由,封包了,是以三層交換機是基于流的,并且隻要是基于流的都會有老化機制。在cache的作用下,三層交換機輕松實作快速轉發,就像二層交換機一樣,擁有學習功能,所謂的學習功能其實就是一個cache功能。

     有必要提一下老化機制,該機制豐富了cache,增加了公平性,但是有的時候行為卻不是很嚴格,比如nat實作中,nat在linux中是基于netfilter的conntrack的,conntrack子產品會偵測過來的每一個資料包,如果它已經屬于一個流,那麼就放過,如果不屬于任何流,那麼就建立一個新的流,将之放入一個哈希,這裡就有了兩個問題。

     第一個問題是由于tcp和udp的行為有很大的不同,那麼連接配接管理子產品有必要将之分開管理,那麼就需要在prerouting的時候知道該資料包是tcp的還是udp的,但是我們知道ip會分片的,是以當時到來的資料包可能僅僅是一個ip片段,我們無法從一個片斷看得出該片斷是udp還是tcp的,除非該片斷是第一個,于是conntrack要做的一件事就是重組分片,然後在forward的時候再将之分片。

     第二個問題就是流的老化時間問題,為了使得核心不頻繁的對流cache進行修改和替換,每個連接配接的每個狀态都有個老化時間,這些時間根據協定和協定的狀态有所不同,比如tcp的ESTABLISHED的狀态的流的老化時間就會特别長,而udp的未回答狀态的老化時間會特别短,于是問題出來了,如果我配置錯了一個nat,那麼當我嘗試連接配接的時候肯定是失敗的,因為nat将會把目的位址轉為一個錯誤的位址,此時流已經建立了,雖然可能不通,但是路由存在,通路允許,流建立了,并且在确認路由存在通路允許之後查nat表找到了錯誤的rule,由于對端還沒有回答,是以這個狀态的流的老化時間很短,雖然時間老化很短,可畢竟建立了,然後我随即将nat配置正确,可是在剛才那個已經建立的流為老化之前,我還是無法連接配接,這說明一旦流比對了,在下面經過nat表的時候就會将nat資訊複制進這個流,于是後面的資料包一旦命中這個流,将會一直使用這個nat資訊,直到該流老化或者被擠出哈希表;另外一個反面的例子是如果nat是配置正确的,那麼在改錯了的一會時間内還是可以通信的,原因就是流還沒有老化,并且新的nat資訊沒有被重新整理。

     另外,nat依賴conntrack的設計本身也許很脆弱,在出現大量連接配接的情況下,conntrack的哈希表很快就會滿,接下來的連接配接就無法加入哈希表了,于是nat就會失敗。脆弱的本質就是nat幾乎完全依賴了一個用于效率優先容量有限的哈希表,而不是公平優先絕對精确的容器,我們在受到cache的恩惠的同時也要主要它會引起的問題,正如cpu的cache有cache一緻性一樣,任何用到cache的地方都要注意這個一緻性,除此之外還必須實作公平性。

 本文轉自 dog250 51CTO部落格,原文連結:http://blog.51cto.com/dog250/1271918

繼續閱讀