歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux綜合 >> Linux資訊 >> 更多Linux

LINUX2.2.x狀態檢測的實現

  1. 引言     狀態檢測是目前防火牆系統必備的功能之一。它工作在IP層,檢查由防火牆轉發的包,並創建相應的結構記錄連接的狀態。它的檢查項包括鏈路層、網絡層、傳輸層、應用層的各種信息,並根據規則表或狀態表來決定是否允許轉發包通過。     開源項目SIFI(網址http://www.ifi.unizh.ch/ikm/SINUS/)實現了一個包含狀態檢測功能的防火牆。這個防火牆內核部分的代碼是建立在Linux2.2.x網絡安全框架的之上,是一個很好的分析、學習狀態檢測技術的實例。下面將從數據結構、狀態檢查、序列號檢查、超時、應用協議數據檢查等幾個方面分析它的狀態檢測是如何實現的。     2. 概況     首先看看SIFI中的幾個重要的數據結構。     2.1. sf_fw_ops     SIFI的內核代碼是在LINUX2.2.x網絡安全框架之上實現的,所以它要定義在檢查點上引用的結構,如下:     strUCt firewall_ops sf_fw_ops =  {   NULL,   sf_forward_chk,   sf_input_chk,   sf_output_chk,   PF_INET,   2   }         結構中sf_forward_chk,sf_input_chk,sf_out_chk三個函數分別在檢查點call_fw_firewall,call_in_firewall,call_out_firewall上被調用。這三個函數都調用函數sf_check_packet去完成真正的動作。這個結構的優先級是2,高於LINUX2.2.x內核中定義的ipfw_ops的優先級,所以在檢查點上,先調用這個結構中定義的函數。只有在 它的函數的返回值是FW_SKIP的情況下才會調用ipfw_ops中定義的函數。     2.2. 規則表     規則表是一個單向鏈表,用於匹配需要處理的包,並決定匹配後的動作。如圖2.1所示。     2.3. 連接表     連接表是一個哈希表,相同哈希值的結構被鏈接成一個雙向鏈表。所有的連接結構又被鏈接成一個雙向鏈表,指針conns指向鏈表的頭,lastc指向鏈表的尾。如圖2.1所示。       2.4. 狀態定義     連接表中的每一個結構在某一刻都有一個確定的狀態。在SIFI中,只為TCP協議和UDP協議創建連接結構。其他協議的檢查都通過匹配規則表實現的,沒有創建連接結構。狀態的定義如下:       [表2.1]     表中用灰色標識的狀態在狀態檢查時沒有使用。     SF_TCP_ESTABLISHEDFTP狀態是為FTP協議的控制連接定義的狀態,定義這個狀態的目的是為檢查FTP協議,找出其中的地址和端口,並創建新的連接結構,使FTP的數據連接在沒有相應規則的情況下也可建立起來。其他狀態定義了TCP連接變遷的過程中的合法狀態,其狀態轉換過程將在下面講到。     3. 基本流程     接下來看看SIFI對不同協議包的處理。     對ICMP協議或IGMP協議的包,它檢查包的長度,並在規則表中查找,如果找到匹配的規則,執行規則所規定的動作;如果沒有找到匹配的規則,默認禁止這個包。它沒有記錄ICMP或IGMP協議的狀態。     對UDP協議的包按如下的流程檢查:       [圖3.1]     首先在連接表中查找,如果找到,則說明此方向的UDP通信是規則允許的;如果沒有找到,則在規則表中查找,如果有匹配的規則,執行規則所規定的動作,如果沒有找到匹配的規則,默認禁止這個包。規則檢查時,如果匹配到的規則允許這個包通過,將在連接表中加入一個新的連接結構,其狀態值是SF_UDP_STATE,後續的包將不再進行規則檢查,直到這個結構被刪除。值得注意的是,對UDP的包在檢查連接表時用的是單向的匹配,這於對TCP的處理不同。     對TCP協議的包按如下的流程檢查:       [圖3.2]     首先在連接表中查看是否有相應的連接結構。這裡的查找使用的是雙向匹配(將目的地址、目的端口和源地址、源端口互換),所以一個TCP連接對應一個連接結構。如果找到相應的連接結構,則進行狀態變遷(狀態如何變遷將會在後面介紹);如果沒有找到,則查看這個包是否是syn置位,但ack沒有置位的包(TCP發起連接的包),如果是,用源端口為零計算哈希值,在連接表中查找相應的結構(這個結構是在處理應用協議數據中的動態地址和動態端口時創建的,與地址轉換中的處理類似),如果找到,刪除原來源端口為零的結構,並用這個包的地址和端口重新計算哈希值,創建新的結構;如果不是syn置位而ack沒有置位的包,則禁止包通過。     4. 狀態檢查     4.1. 狀態檢查     狀態檢查定義了TCP連接變遷過程中的合法狀態,以及在某個特定狀態下允許通過的包的類型。狀態檢查同時對允許通過的包做合法性檢查,比如確定其序列號是否符合TCP協議的規定等。     各狀態之間的變遷如圖所示:            [圖4.1]     連接結構的初始狀態是SF_TCP_ACCEPT_SYN,這是在syn置位而ack沒有置位的TCP包在規則檢查的返回值是FW_ACCEPT時創建。結構創建之後,進入創建連接的狀態檢查。步驟如下:     (1) 如果是CLIENT(連接發起方)的syn置位而ack沒有置位的包,連接狀態變遷到SF_TCP_CLIENT_SYN。     (2) 在SF_TCP_CLIENT_SYN狀態下,如果SERVER(連接接受方)回應syn置位或syn/ack置位的包,連接狀態變遷到SF_TCP_SYN_ACK。在這個狀態下同樣允許CLIENT的syn置位或syn/ack置位的包,連接狀態保持不變。     (3) 在SF_TCP_SYN_ACK狀態下,如果CLIENT回應有ack置位或syn/ack置位的包,連接狀態變遷到SF_TCP_ESTABLISHED3。在這個狀態下,同樣允許SERVER的syn/ack置位的包,連接狀態保持不變,但是不允許SERVER的syn置位和CLIENT的syn置位的包通過。     以上是SF_TCP_ACCEPT_SYN、SF_TCP_CLIENT_SYN、SF_TCP_SYN_ACK三個狀態下對syn或ack置位的包的檢查。這個檢查支持TCP連接的同時打開,但前提是規則要允許。     關閉連接的狀態檢查按如下的步驟進行:     (4) 如果是CLIENT的fin置位的包,連接狀態變遷到SF_TCP_CLIENT_FIN。     (5) 如果是SERVER的fin置位的包,連接變遷到SF_TCP_SERVER_FIN。     (6) 以上兩步的變遷如果都已完成,連接的狀態是SF_TCP_TERMINATED或是大於SF_TCP_TERMINATED( 如果是為FTP控制連接創建的結構)。     (7) 在狀態大於等於SF_TCP_TERMINATED時,如果收到syn置位的包,將刪除連接,並檢查規則。     在任何狀態下如果收到rst置位的包,會刪除連接。並且,如果收到syn、fin置位或syn、rst置位或fin、rst置位的包(聖誕樹數據包),將禁止這個包通過。     4.2. 超時     在每個非ESTABLISHED的狀態上都設置了相應的超時值,如下表:           [表4.1]     超時通過內核定時器實現,超時連接將被刪除。SF_TCP_ESTABLISHED3,SF_TCP_ESTABLISHEDFTP兩個狀態上缺省沒有定義超時值,但是可以通過定義SF_TCP_IDLE編譯選項,使這兩個狀態的超時值為8 * 3600* HZ,是8小時。     4.3. 序列號檢查     序列號是TCP協議用於保證數據可靠性的重要手段。TCP連接中傳遞的每一個字節的數據都用一個序列號來標識。連接的初始序列號在建立連接時協商。收到包的一方會發出ack置位的應答包,告訴對方自己接受的下一個序列號是多少,這樣就確認了下一個序列號之前所收到的數據。TCP協議同時使用序列號窗口來限制對方可以發送的數據包的長度,以控制流量。窗口大小是一個16位的正整數,可以通過TCP的scale選項擴展窗口的大小。使用scale選項,在計算窗口大小時會將窗口值左移以增大窗口的值。     TCP協議中協商初始序列號的syn置位的包占用一個序列號,斷開連接的fin置位的包占用一個序列號。SIFI通過檢查轉發包的序列號來確定這個包是否合法。在SIFI的實現中,可以通過配置參數檢查每一個TCP連接的序列號,其步驟如下:     (1) 對沒有syn置位的包(fin或ack置位的包),先確定發送方的最大序列號在對方的窗口之內,然後如果是ack置位的包,其確認序列號應在對方的序列號之後。     (2) 在SF_TCP_CLIENT_SYN狀態時記錄CLIENT的序列號、窗口大小和縮放因子。在SF_TCP_SYN_ACK狀態時記錄SERVER的序列號、窗口大小和縮放因子,並將CLIENT的序列號增加1。     (3) 在SF_TCP_TERMINATED狀態時,如果收到syn置位的包,它的序列號應在本方序列號之後。     (4) 在SF_TCP_SYN_ACK狀態時,SERVER的重復的syn/ack置位的包,其確認序列號應和連接記錄CLIENT的序列號相等。     4.4. 應用協議數據檢查     應用協議數據檢查所做的是檢查控制連接中的應用協議所傳遞的地址和端口,並創建對應的連接結構,使後續的數據連接能夠建立。一般情況下,除非規則允許所有的端口,否則這些協議中傳遞的動態端口在規則中默認是禁止的。如果能夠動態創建連接結構,則避免檢查規則,對用戶透明。當然,這也可以通過創建動態規則去實現,但是規則是一




Copyright © Linux教程網 All Rights Reserved