來源:http://yfydz.cublog.cn1. 前言 對於多連線協定,netfilter需要對其進行特殊的跟蹤和NAT以提供動態對子串連的支援,詳見“防火牆為什麼要對多連線協定進行特殊處理”一文。netfilter對這些多連線協定的跟蹤和NAT和匹配、目標或IP層協議那樣進行模組化的跟蹤和NAT處理。 以下核心代碼說明都使用Linux-2.4.26版本的核心代碼。 2. 協議串連跟蹤 2.1 ip_conntrack_helper結構 netfilter中對每個要進行跟蹤的多連線協定定義了以下的串連輔助結構,每個多連線協定的串連跟蹤處理就是要填寫這樣一個結構: include/linux/netfilter_ipv4/ip_conntrack_helper.h
struct ip_conntrack_helper
{
struct list_head list; /* Internal use. */ const char *name; /* name of the module */
unsigned char flags; /* Flags (see above) */
struct module *me; /* pointer to self */
unsigned int max_expected; /* Maximum number of concurrent
* expected connections */
unsigned int timeout; /* timeout for expecteds */ /* Mask of things we will help (compared against server response) */
struct ip_conntrack_tuple tuple;
struct ip_conntrack_tuple mask;
/* Function to call when data passes; return verdict, or -1 to
invalidate. */
int (*help)(const struct iphdr *, size_t len,
struct ip_conntrack *ct,
enum ip_conntrack_info conntrackinfo);
}; 結構中包括以下參數: struct list_head list:將該結構掛接到多連線協定跟蹤鏈表helpers中, helpers鏈表在ip_conntrack_core.c檔案中定義:
static LIST_HEAD(helpers);
注意是static的,只在該檔案範圍有效; const char *name:協議名稱,字串常量 unsigned char flags:關於本串連跟蹤模組的一些標誌; struct module *me:指向模組本身,統計模組是否被使用 unsigned int
max_expected:子串連的數量,這隻是表示主串連在每個時刻所擁有的的子串連的數量,而不是主串連的整個生存期內總共產生的子串連的數量,如
FTP,不論傳多少個檔案,建立多少個子串連,每個時刻主串連最多隻有一個子串連,一個子串連結束前按協議是不能再派生出第二個子串連的,所以該值為1; unsigned int timeoout:逾時,指在多少時間範圍內子串連沒有建立的話子串連跟蹤失效 struct ip_conntrack_tuple tuple,
mask:這兩個參數用來描述子串連,判斷一個新來的串連是否是主串連期待的子串連,之所以要有mask參數,是因為子串連的某些參數不能確定,如被動模
式的FTP傳輸,只能得到子串連的目的連接埠而不能確定源連接埠,所以源連接埠部分要用mask來進行泛匹配; 結構中包括以下函數: (*help):串連跟蹤基本函數,解析主串連的通訊內容,提取出關於子串連的資訊,將子串連資訊填充到一個struct
ip_conntrack_expect結構中,然後將此結構通過調用函數ip_conntrack_expect_related()把子串連的資訊添
加到系統的期待子串連鏈表ip_conntrack_expect_list中。傳回值是NF_ACCEPT或NF_DROP,或-1表示協議資料非法。
該函數在ip_conntrack_in()函數中調用。2.2 期待的串連的結構 期待的串連結構用來描述所期待的串連,但該串連目前是不存在的,是一個虛構的串連,只是netfilter根據主串連的資訊解析出來的可能的子
串連的資訊,struct ip_conntrack_helper結構中的(*help)成員函數的目的就是建立一個struct
ip_conntrack_expect結構: struct ip_conntrack_expect
{
/* Internal linked list (global expectation list) */
struct list_head list; /* reference count */
atomic_t use; /* expectation list for this master */
struct list_head expected_list; /* The conntrack of the master connection */
struct ip_conntrack *expectant; /* The conntrack of the sibling connection, set after
* expectation arrived */
struct ip_conntrack *sibling; /* Tuple saved for conntrack */
struct ip_conntrack_tuple ct_tuple; /* Timer function; deletes the expectation. */
struct timer_list timeout; /* Data filled out by the conntrack helpers follow: */ /* We expect this tuple, with the following mask */
struct ip_conntrack_tuple tuple, mask; /* Function to call after setup and insertion */
int (*expectfn)(struct ip_conntrack *new); /* At which sequence number did this expectation occur */
u_int32_t seq;