1. 前言
在linux2.6中自帶了ipsec的實現,可以不再使用freeswan及其變種了,freeswan通過建立ipsec*的
虛擬網絡卡來將傳送和接收ipsec資料報,通過ipsec*網絡卡看到的資料是明文資料,而2.6中的ipsec實
現是不建立ipsec*虛擬網絡卡的,本文分析一下esp包進入系統協議棧的處理流程。
以下linux核心**版本為2.6.19.2。
2. 流程分析
2.1 esp協議結構
esp協議結構定義,對於每個ipv4上層的協議,如tcp、udp、icmp、igmp、esp、ah等都需要定義這個
結構掛接到ipv4的協議鍊錶中,當接收到ip資料報時,會根據包中定義的ip協議號找到該結構,然後
呼叫其成員handler函式進行處理。
/* net/ipv4/esp4.c */
static struct net_protocol esp4_protocol = ;
esp協議的handler函式是xfrm4_rcv()
2.2 xfrm4_rcv
/* net/ipv4/xfrm4_input.c */
int xfrm4_rcv(struct sk_buff *skb)
實際就是xfrm4_rcv_encap,封裝型別引數設定為0,即沒封裝資料
2.3 xfrm4_rcv_encap
/* net/ipv4/xfrm4_input.c */
int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
// 看內層協議是否還要繼續解包, 不需要解時返回1, 需要解時返回0, 錯誤返回負數
// 協議型別可以多層封裝的,比如用ah封裝esp, 就得先解完ah再解esp
if ((err = xfrm_parse_spi(skb, skb->nh.iph->protocol, &spi, &seq)) < 0)
goto drop;
} while (!err);
/* allocate new secpath or cow existing one. */
// 為skb包建立新的安全路徑(struct sec_path)
if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1)
if (xfrm_nr + skb->sp->len > xfrm_max_depth)
goto drop;
// 將剛才迴圈解包用到的sa拷貝到安全路徑
// 因此檢查乙個資料報是否是普通明文包還是解密後的明文包就看skb->sp引數是否為空
memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec,
xfrm_nr * sizeof(xfrm_vec[0]));
skb->sp->len += xfrm_nr;
nf_reset(skb);
if (decaps)
// 重新進入網絡卡接收函式
netif_rx(skb);
return 0;
} else
drop_unlock:
spin_unlock(&x->lock);
xfrm_state_put(x);
drop:
while (--xfrm_nr >= 0)
xfrm_state_put(xfrm_vec[xfrm_nr]);
kfree_skb(skb);
return 0;
}最後說一下返回負協議值的處理, ip上層協議的handler是在ip_local_deliver_finish()函式中呼叫
的:/* net/ipv4/ip_input.c */
static inline int ip_local_deliver_finish(struct sk_buff *skb)
nf_reset(skb);
}// 呼叫協議handler
ret = ipprot->handler(skb);
if (ret < 0)
ip_inc_stats_bh(ipstats_mib_indelivers);
} else
} else
ip_inc_stats_bh(ipstats_mib_indelivers);
kfree_skb(skb);}}
out:
rcu_read_unlock();
return 0;
}3. 結論
雖然在2.6的native ipsec中沒支援虛擬網絡卡,但在通道模式下也用到了netif_rx函式將解碼後的數
據包重新接收處理的過程,並沒有改變skb包的dev網絡卡引數,因此如果在該網絡卡上抓包,就會同時抓
到最初的加密包和解碼後的明文包;而用freeswan的實現,在普通網絡卡上抓包抓到的是加密包,由於
freeswan在解碼後將skb包的dev引數改為了ipsec*,因此是通過在ipsec*網絡卡上能抓到解密包。對於
傳輸模式,由於沒有呼叫netif_rx函式,因此在實際網絡卡抓包只能抓到加密包,解密包只能在
netfilter架構中看到了。
另外,在此情況下nat規則仍然是有效的,制定nat規則時根據解密後的位址埠等資訊來處理就可以
了。識別乙個明文包是否是解密過的就看skb的sp引數即可,該指標為空表示是普通明文包,非空表示是
解密後的明文包。
Linux2 6 核心的 Initrd 機制解析
1 什麼是 initrd initrd 的英文含義是 boot loader initialized ram disk,就是由 boot loader 初始化的記憶體盤。在 linux核心啟動前,boot loader 會將儲存介質中的 initrd 檔案載入到記憶體,核心啟動時會在訪問真正的根檔案...
Linux2 6 核心的 Initrd 機制解析
initrd 的英文含義是 boot loader initialized ram disk,就是由 boot loader 初始化的記憶體盤。在 linux核心啟動前,boot loader 會將儲存介質中的 initrd 檔案載入到記憶體,核心啟動時會在訪問真正的根檔案系統前先訪問該記憶體中的 ...
Linux2 6下如何配置core檔案
1.可以用ulimit a 檢視一下棧的大小。在核心2.6.20下,stack size 為8192 kbytes 如果這裡沒有限制,就棧的大小就只受記憶體的限制。2g是上限。2.core 檔案 開啟或關閉core檔案的生成 ulimit c 可以檢視是否開啟此選項,若為0則為關閉 ulimit c...