在Linux內(nèi)核中數(shù)據(jù)包會有連接跟蹤的功能,Linux內(nèi)核根據(jù)數(shù)據(jù)包的五元組創(chuàng)建連接跟蹤表。但對于有些數(shù)據(jù)包是不建立連接的,本篇文章介紹了ICMP的回應報文reply,就不會在內(nèi)核中創(chuàng)建連接會話。我們知道會話的建立是在NF_IP_PRE_ROUTING的HOOK點創(chuàng)建。
在ipv4_conntrack_in函數(shù)中調(diào)用了nf_conntrack_in函數(shù)對數(shù)據(jù)包進行會話的建立,其中最關鍵的函數(shù)是resolve_normal_ct(),在該函數(shù)中有下面一段代碼:
-
h = nf_conntrack_find_get(net, &tuple);/*這里對會話進行查找,如果沒有查找到,調(diào)用init_conntrack函數(shù)Allocate a new conntrack*/
-
if (!h) {
-
h = init_conntrack(net, &tuple, l3proto, l4proto, skb, dataoff, hooknum);
-
if (!h)
-
return NULL;
-
if (IS_ERR(h))
-
return (void *)h;
-
}
在ICMP的Request請求包經(jīng)過Linux內(nèi)核中會創(chuàng)建一條會話,如果這條會話成功的存在于會話連接表中,就沒有機會調(diào)用init_conntrack函數(shù),我們看一下該函數(shù)中做對數(shù)據(jù)包做了什么處理:該函數(shù)主要是分配一個conntrack,其中有下面的代碼:
-
if (!l4proto->new(ct, skb, dataoff)) {
-
nf_conntrack_free(ct);
-
pr_debug("init conntrack: can't track with proto module\n");
-
/*return NULL; */
-
goto ERR;
-
}
如果是ICMP報文的話,調(diào)用icmp_new函數(shù),當連接是一個新的連接時,會調(diào)用到該函數(shù),對于Request數(shù)據(jù)報文就正常就會返回true,下面是icmp_new函數(shù)代碼:
-
static bool icmp_new(struct nf_conn *ct, const struct sk_buff *skb,
-
unsigned int dataoff)
-
{
-
static const u_int8_t valid_new[] = {
-
[ICMP_ECHO] = 1,
-
[ICMP_TIMESTAMP] = 1,
-
[ICMP_INFO_REQUEST] = 1,
-
[ICMP_ADDRESS] = 1
-
};
-
-
if (ct->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new)
-
|| !valid_new[ct->tuplehash[0].tuple.dst.u.icmp.type]) {
-
/* Can't create a new ICMP `conn' with this. */
-
pr_debug("icmp: can't create new conn with type %u\n",
-
ct->tuplehash[0].tuple.dst.u.icmp.type);
-
nf_ct_dump_tuple_ip(&ct->tuplehash[0].tuple);
-
return false;
-
}
-
return true;
在上面的代碼中我們看到,在if的判斷中有對連接的icmp數(shù)據(jù)包類型的判斷,如果不是valid_new數(shù)組中的報文類型都會返回false,也就是數(shù)據(jù)包會在該HOOK點DROP掉。在valid_new數(shù)組中并沒有ICMP_ECHOREPLY類型的報文,也就是如果是reply報文的話,這里會被直接的DROP掉。所以在REQUEST數(shù)據(jù)包通過該HOOK點是,創(chuàng)建一條連接同時也會創(chuàng)建一條反方向的連接,所以,當REPLY報文被收到時,正常情況下會查找到相應的連接會話,也就是h = nf_conntrack_find_get(net, &tuple);函數(shù)返回的h不為空。因此,對于reply報文是不會重新創(chuàng)建會話的,如果ICMP的REPLY報文走到icmp_new函數(shù)處,說明ICMP的REQUEST會話并沒有被創(chuàng)建,在查找會話時失敗,同時造成了ICMP數(shù)據(jù)包不通的問題。
|