核心udp報文擷取 修改和傳送

2021-07-09 11:33:33 字數 2285 閱讀 3887

近來做乙個產品需要在閘道器上獲取特定udp埠(假設是1000埠)的報文,並將其**給其它裝置的1000埠。雖然此類文章網上已經有很多了,但我還是貼上來,這樣自己也做下記錄,大家也多乙份參考。

下面只給出了**片段,自己慢慢除錯。

我們假設網路拓撲如下所示:

linux 

--------- --------- --------- 

| pc-1 |-------| server | -------| datasrv | 

--------- --------- --------- 

pc-1傳送udp報文到server的1000埠時,我們將報文拷貝乙份並傳送給datasrv的1000埠。

報文的獲取,我們採用netfilter hook. 我們將hook鉤到 nf_ip_local_in,優先級別設定成nf_ip_pri_first。

為什麼hook到nf_ip_local_in 而不是perrouting呢? 這是因為hook到 local_in的話,我們就不用去考慮報文的重組了。如下圖:

ip_rcv ------> ip_local_deliver ----------> netfilter 

|-----------ip_defrag-------^ 

為什麼優先級別設定成最高了,這樣可以防止udp的穿透。

這裡我們不詳細描述netfilter hook如何編寫。下面我們來看獲取到skb(重組好了的)的報文後,我們如何處理。

首先,我們假設datasrv的ip位址為 192.168.1.254/24;server的ip位址為 192.168.1.253/24。

#define test_xmit(skb, rt) \

nf_hook(pf_inet, nf_ip_local_out, (skb), null, \

(rt)->u.dst.dev, dst_output); 

#define ip_parts_native(n) \

(unsigned int)((n)&0xff), \

(unsigned int)((n)>>8)&0xff, \

(unsigned int)((n)>>16)&0xff, \

(unsigned int)((n)>>24)&0xff

#define test_bug() bug()

#define test_err(msg...) printk(kern_err "test: " msg)

#define test_info(msg...) printk(kern_info "test: " msg)

#define test_warning(msg...) printk(kern_warning "test: " msg)

#define test_err_rl(msg...) \

do while (0)

//呼叫test_pop前 需要 拷貝或轉殖 skb,然後再傳入

static inline int test_pop (struct sk_buff * skb)

//修改ip頭

iph = skb->nh.iph;

iph->saddr = in_aton ("192.168.1.253");//sip;

iph->daddr = in_aton ("192.168.1.254");

//ip位址改變,需要重新計算udp校驗和 

udph = (struct udphdr*) (skb->data iph->ihl * 4);

udphoff = iph->ihl * 4;

skb->csum = 0;

skb->csum = skb_checksum (skb, udphoff, skb->len - udphoff, 0);

udph->check = csum_tcpudp_magic (iph->saddr, iph->daddr,

skb->len - udphoff,

ipproto_udp,

skb->csum);

//獲取ip序號

ip_select_ident(iph, &rt->u.dst, null);

//重新計算ip頭校驗和

ip_send_check(iph);

//重新設定路有入口

dst_release(skb->dst);

skb->dst = &rt->u.dst;

//清除netfilter資訊

nf_reset (skb);

//傳送

test_xmit (skb, rt);

return (0);

}

linux核心中如何修改skb報文

核心 中有許多用於計算校驗和的api,下面是linux網路技術內幕相關api的截圖 sk buf中的csum欄位 sk buf中的ip summed欄位 ip summed欄位表示l4層的校驗和狀態。根據報文的不同 輸入報文和輸出報文 ip summed會有不同的取值。當資料報為輸入報文 defin...

UDP報文段和其檢驗和小結

如圖所示 tcp首部行開銷為20位元組而udp則為8位元組,所以udp分組首部開銷更小。文件為 rfc 1071 從上圖的報文段結構我們知道每個首部欄位為16位元。現在假設源埠號 目的埠號和長度字段三個16位元字分別為 源埠號 0110 0110 0110 0000 十進位制 26208 目的埠號 ...

TCP和UDP報文分片的區別

搞了三年網路,今天才知道這個細節,汗,總結下 mtu大家都知道,是鏈路層中的網路對資料幀的乙個限制,依然以乙太網為例,mtu為1500個位元組。乙個ip資料報在乙太網中 傳輸,如果它的長度大於該mtu值,就要進行分片傳輸,使得每片資料報的長度小於mtu。分片傳輸的ip資料報不一定按序到達,但ip首部...