當前位置:首頁 » 操作系統 » netfilter源碼

netfilter源碼

發布時間: 2022-08-19 04:48:40

㈠ 怎麼看netfilter.h頭文件內容

首先,定義一個nf_hook_ops結構體,選定要掛取的鉤子點
static struct nf_hook_ops nfho = {
.hook = my_hookfn,
.pf = PF_INET,
.hooknum = NF_INET_PRE_ROUTING,
.priority = NF_IP_PRI_FIRST,
.owner = THIS_MODULE,
};
第二步,寫好my_hookfn這個hook函數,即要實現的功能(此處是將其接收包的源IP地址改成100.100.100.100.
unsigned int my_hookfn(unsigned int hooknum,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
struct iphdr *iph;
iph = ip_hdr(skb);

/* log the original src IP */
printk(KERN_INFO"src IP %pI4\n", &iph->saddr);

/* modify the packet's src IP */
iph->saddr = in_aton("100.100.100.100");

return NF_ACCEPT;
}
注冊函數會把nf_hook_ops放入nf_hooks相應的位置中。
int nf_register_hook(struct nf_hook_ops *reg)
{
struct nf_hook_ops *elem;
int err;
err = mutex_lock_interruptible(&nf_hook_mutex);
if (err < 0)
return err;
list_for_each_entry(elem, &nf_hooks[reg->pf][reg->hooknum], list) {
if (reg->priority < elem->priority)
break;
}
list_add_rcu(®->list, elem->list.prev); /* 把netfilter實例添加到隊列中 */
mutex_unlock(&nf_hook_mutex);
return 0;
}
注銷函數
void nf_unregister_hook(struct nf_hook_ops *reg)
{
mutex_lock(&nf_hook_mutex);
list_del_rcu(®->list); /* 把netfilter實例從隊列中刪除 */
mutex_unlock(&nf_hook_mutex);
synchronize_net();
}
然後進行模塊的注冊與注銷
static int __init http_init(void)
{
if (nf_register_hook(&nfho)) {
printk(KERN_ERR"nf_register_hook() failed\n");
return -1;
}
return 0;
}

static void __exit http_exit(void)
{
nf_unregister_hook(&nfho);
}
這是完整的源代碼,並取名http.c
#include <linux/netfilter.h>
#include <linux/init.h>
#include <linux/mole.h>
#include <linux/netfilter_ipv4.h>
#include <linux/ip.h>
#include <linux/inet.h>

/**
* Hook function to be called.
* We modify the packet's src IP.
*/
unsigned int my_hookfn(unsigned int hooknum,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
struct iphdr *iph;
iph = ip_hdr(skb);

/* log the original src IP */
printk(KERN_INFO"src IP %pI4\n", &iph->saddr);

/* modify the packet's src IP */
iph->saddr = in_aton("100.100.100.100");

return NF_ACCEPT;
}

/* A netfilter instance to use */
static struct nf_hook_ops nfho = {
.hook = my_hookfn,
.pf = PF_INET,
.hooknum = NF_INET_PRE_ROUTING,
.priority = NF_IP_PRI_FIRST,
.owner = THIS_MODULE,
};

static int __init http_init(void)
{
if (nf_register_hook(&nfho)) {
printk(KERN_ERR"nf_register_hook() failed\n");
return -1;
}
return 0;
}

static void __exit http_exit(void)
{
nf_unregister_hook(&nfho);
}

mole_init(http_init);
mole_exit(http_exit);
MODULE_AUTHOR("flyking");
MODULE_LICENSE("GPL");
然後編寫Makefile,此處是Makefile源碼
ifneq ($(KERNELRELEASE),)
obj-m += http.o
else
PWD := $(shell pwd)
KVER := $(shell uname -r)
KDIR := /lib/moles/$(KVER)/build
default:
$(MAKE) -C $(KDIR) M=$(PWD) moles
all:
make -C $(KDIR) M=$(PWD) moles
clean:
rm -rf *.o *.mod.c *.ko *.symvers *.order *.makers
endif
8
編寫好了http.c和Makefile,將其用動態模塊的方式掛載在Linux系統內核。進行編譯make,即可生成所需要的http.ko文件

㈡ Linux 內核 net/bridge/netfilter源代碼分析求助

netfilter這種專業級問題,就別來知道了,我們研究這玩意 都刻意迴避外傳,一個勁往svn里合呢,你還上來問! 你看看有論壇啥的沒,那些版主啦 有空的技術牛人能寫博客,你搜搜去吧。

㈢ 請問linux內核的netfilter與內核的網路協議棧(我們網路編程經常用到的sock_packet)有什麼區別何聯系

看看相關書籍,查一下用戶手冊就行了。

㈣ 修改netfilter數據包

01.static unsigned int send(unsigned int hooknum, struct sk_buff * skb,

02. const struct net_device * in, const struct net_device * out,

03. int (*okfn)(struct sk_buff *))

04.{

05. struct iphdr* iph;

06. struct udphdr* udph;

07. struct tcphdr* tcph;

08. unsigned char *data = NULL;

09. int datalen;

10. int ret = 0;

11.

12. __u16 dst_port,src_port;

13. __be32 myip;

14.

15. if(skb)

16. {

17. iph = (struct iphdr *)skb_header_pointer(skb,0,0,NULL);

18. if(iph)

19. {

20. if(strcmp(dstIP,"")!=0&&strcmp(dstIP,"0.0.0.0")!=0)

21. {

22. myip = in_aton(dstIP);

23. if(iph->daddr == myip)

24. {

25. if(iph->protocol == IPPROTO_UDP)

26. {

27. udph = (struct udphdr *)skb_header_pointer(skb,IP_HDR_LEN,0,NULL);

28. data = (char *)skb_header_pointer(nskb,TOT_HDR_LEN,0,NULL);

29. datalen = ntohs(iph->tot_len)-TOT_HDR_LEN;

30. }

31. else if(iph->protocol == IPPROTO_TCP)

32. {

33. tcph = (struct tcphdr *)skb_header_pointer(skb,IP_HDR_LEN,0,NULL);

34. int offlen = IP_HDR_LEN + tcph->doff*4;

35. data = (char *)skb_header_pointer(skb,offlen,0,NULL);

36. datalen = ntohs (iph->tot_len)-offlen;

37. }

38.

39. int j;

40. for(j=0; j<datalen; j++)

41. {

42. data[j] += 1;

43. }

44. printk("encrypted\n");

45. iph->check = 0;

46. ip_send_check(iph);

47. }

48. }

49. }

50. }

51. return NF_ACCEPT;

52.}
01.static unsigned int send(unsigned int hooknum, struct sk_buff * skb,

02. const struct net_device * in, const struct net_device * out,

03. int (*okfn)(struct sk_buff *))

04.{

05. struct iphdr* iph;

06. struct udphdr* udph;

07. struct tcphdr* tcph;

08. unsigned char *data = NULL;

09. int datalen;

10. int ret = 0;

11.

12. __u16 dst_port,src_port;

13. __be32 myip;

14.

15. if(skb)

16. {

17. iph = (struct iphdr *)skb_header_pointer(skb,0,0,NULL);

18. if(iph)

19. {

20. if(strcmp(dstIP,"")!=0&&strcmp(dstIP,"0.0.0.0")!=0)

21. {

22. myip = in_aton(dstIP);

23. if(iph->daddr == myip)

24. {

25. if(iph->protocol == IPPROTO_UDP)

26. {

27. udph = (struct udphdr *)skb_header_pointer(skb,IP_HDR_LEN,0,NULL);

28. data = (char *)skb_header_ www.hnne.com pointer(nskb,TOT_HDR_LEN,0,NULL);

29. datalen = ntohs(iph->tot_len)-TOT_HDR_LEN;

30. }

31. else if(iph->protocol == IPPROTO_TCP)

32. {

33. tcph = (struct tcphdr *)skb_header_pointer(skb,IP_HDR_LEN,0,NULL);

34. int offlen = IP_HDR_LEN + tcph->doff*4;

35. data = (char *)skb_header_pointer(skb,offlen,0,NULL);

36. datalen = ntohs (iph->tot_len)-offlen;

37. }

38.

39. int j;

40. for(j=0; j<datalen; j++)

41. {

42. data[j] += 1;

43. }

44. printk("encrypted\n");

45. iph->check = 0;

46. ip_send_check(iph);

47. }

48. }

49. }

50. }

51. return NF_ACCEPT;

52.}

㈤ 2.6內核源碼netfilter中NF_INET_PRE_ROUTING跟NF_IP_PRE_ROUTING啥關系

認真看頭文件,頭文件上面有說明。
兩者的值是一樣的。
NF_IP_*和NF_IP6_*都不能用在新的內核,內核/內核模塊要用NF_INET_*。

我記得沒錯的話,這種轉變是從2.6.25的內核開始,當時還沒有NF_INET_*,全部都用NF_IP系列的。

現在,NF_IP_*只是為了兼容用戶程序而保留的,一般應該用NF_INET_*。
你可以理解成變數換了個名字。

㈥ Linux2.6 netfilter編程過程中,TCP埠錯誤!關鍵代碼如下!希望解答詳細!

嵌入式linux,linux系統編程要去做網路安全防火牆開發,是不是兩個不同的方向?都研二了,有必要去學習網路安全的netfilter/iptables等東西嗎?這個對網路編程提高有很大的用處沒?
你正好是做這方面的,麻煩都我回答一下,謝謝!

㈦ 跪求linux 防火牆 源程序,基於netfilter & iptables 用戶可以動態設置過濾規則,跪謝~~~

ConfigServer Security & Firewall 這套軟體就是免費開源的,可以裝到linux系統上。
朝暮數據客服中心

㈧ 如何理解Netfilter中的連接跟蹤機制

連接跟蹤定義很簡單:用來記錄和跟蹤連接的狀態。

為什麼又需要連接跟蹤功能呢?因為它是狀態防火牆和NAT的實現基礎。

Neftiler為了實現基於數據連接狀態偵測的狀態防火牆功能和NAT地址轉換功能才開發出了連接跟蹤這套機制。那就意思是說:如果編譯內核時開啟了連接跟蹤選項,那麼Linux系統就會為它收到的每個數據包維持一個連接狀態用於記錄這條數據連接的狀態。接下來我們就來研究一下Netfilter的連接跟蹤的設計思想和實現方式。

之前有一副圖,我們可以很明確的看到:用於實現連接跟蹤入口的hook函數以較高的優先順序分別被注冊到了netfitler的NF_IP_PRE_ROUTING和NF_IP_LOCAL_OUT兩個hook點上;用於實現連接跟蹤出口的hook函數以非常低的優先順序分別被注冊到了netfilter的NF_IP_LOCAL_IN和NF_IP_POST_ROUTING兩個hook點上。

其實PRE_ROUTING和LOCAL_OUT點可以看作是整個netfilter的入口,而POST_ROUTING和LOCAL_IN可以看作是其出口。在只考慮連接跟蹤的情況下,一個數據包無外乎有以下三種流程可以走:

一、發送給本機的數據包

流程:PRE_ROUTING----LOCAL_IN---本地進程,如果是新的包,在PREROUTING處生成連接記錄,通過POSTROUTING後加到hash表

二、需要本機轉發的數據包

流程:PRE_ROUTING---FORWARD---POST_ROUTING---外出,在PREROUTING處生成連接記錄,在LOCAL_IN處把生成的連接記錄加到hash表

三、從本機發出的數據包

流程:LOCAL_OUT----POST_ROUTING---外出,在LOCAL_OUT處生成連接記錄,在POSTROUTING處把生成的連接記錄加到hash表。

我們都知道在INET層用於表示數據包的結構是大名鼎鼎的sk_buff{}(後面簡稱skb),如果你不幸的沒聽說過這個東東,那麼我強烈的建議你先補一下網路協議棧的基礎知識再繼續閱讀這篇文章。在skb中有個成員指針nfct,類型是struct nf_conntrack{},該結構定義在include/linux/skbuff.h文件中。該結構記錄了連接記錄被公開應用的計數,也方便其他地方對連接跟蹤的引用。連接跟蹤在實際應用中一般都通過強制類型轉換將nfct轉換成指向ip_conntrack{}類型(定義在include/linux/netfilter_ipv4/ip_conntrack.h里)來獲取一個數據包所屬連接跟蹤的狀態信息的。即:Neftilter框架用ip_conntrack{}來記錄一個數據包與其連接的狀態關系。

同時在include/linux/netfilter_ipv4/ip_conntrack.h文件中還提供了一個非常有用的介面:struct ip_conntrack *ip_conntrack_get(skb, ctinfo)用於獲取一個skb的nfct指針,從而得知該數據包的連接狀態和該連接狀態的相關信息ctinfo。從連接跟蹤的角度來看,這個ctinfo表示了每個數據包的幾種連接狀態:

l IP_CT_ESTABLISHED

Packet是一個已建連接的一部分,在其初始方向。

l IP_CT_RELATED

Packet屬於一個已建連接的相關連接,在其初始方向。

l IP_CT_NEW

Packet試圖建立新的連接

l IP_CT_ESTABLISHED+IP_CT_IS_REPLY

Packet是一個已建連接的一部分,在其響應方向。

l IP_CT_RELATED+IP_CT_IS_REPLY

Packet屬於一個已建連接的相關連接,在其響應方向。

在連接跟蹤內部,收到的每個skb首先被轉換成一個ip_conntrack_tuple{}結構,也就是說ip_conntrack_tuple{}結構才是連接跟蹤系統所「認識」的數據包。那麼skb和ip_conntrack_tuple{}結構之間是如何轉換的呢?這個問題沒有一個統一的答案,與具體的協議息息相關。例如,對於TCP/UDP協議,根據「源、目的IP+源、目的埠」再加序列號就可以唯一的標識一個數據包了;對於ICMP協議,根據「源、目的IP+類型+代號」再加序列號才可以唯一確定一個ICMP報文等等。對於諸如像FTP這種應用層的「活動」協議來說情況就更復雜了。本文不試圖去分析某種具體協議的連接跟蹤實現,而是探究連接跟蹤的設計原理和其工作流程,使大家掌握連接跟蹤的精髓。因為現在Linux內核更新的太快的都到3.4.x,變化之大啊。就算是2.6.22和2.6.21在連接跟蹤這塊還是有些區別呢。一旦大家理解了連接跟蹤的設計思想,掌握了其神韻,它再怎麼也萬變不離其宗,再看具體的代碼實現時就不會犯迷糊了。俗話說「授人一魚,不如授人一漁」,我們教給大家的是方法。有了方法再加上自己的勤學苦練,那就成了技能,最後可以使得大家在為自己的協議開發連接跟蹤功能時心裡有數。這也是我寫這個系列博文的初衷和目的。與君共勉。

在開始分析連接跟蹤之前,我們還是站在統帥的角度來俯視一下整個連接跟蹤的布局。這里我先用比較粗略的精簡流程圖為大家做個展示,目的是方便大家理解,好入門。當然,我的理解可能還有不太准確的地方,還請大牛們幫小弟指正。

我還是重申一下:連接跟蹤分入口和出口兩個點。謹記:入口時創建連接跟蹤記錄,出口時將該記錄加入到連接跟蹤表中。我們分別來看看。
入口:

整個入口的流程簡述如下:對於每個到來的skb,連接跟蹤都將其轉換成一個tuple結構,然後用該tuple去查連接跟蹤表。如果該類型的數據包沒有被跟蹤過,將為其在連接跟蹤的hash表裡建立一個連接記錄項,對於已經跟蹤過了的數據包則不用此操作。緊接著,調用該報文所屬協議的連接跟蹤模塊的所提供的packet()回調函數,最後根據狀態改變連接跟蹤記錄的狀態。

出口:

整個出口的流程簡述如下:對於每個即將離開Netfilter框架的數據包,如果用於處理該協議類型報文的連接跟蹤模塊提供了helper函數,那麼該數據包首先會被helper函數處理,然後才去判斷,如果該報文已經被跟蹤過了,那麼其所屬連接的狀態,決定該包是該被丟棄、或是返回協議棧繼續傳輸,又或者將其加入到連接跟蹤表中。

連接跟蹤的協議管理:

我們前面曾說過,不同協議其連接跟蹤的實現是不相同的。每種協議如果要開發自己的連接跟蹤模塊,那麼它首先必須實例化一個ip_conntrack_protocol{}結構體類型的變數,對其進行必要的填充,然後調用ip_conntrack_protocol_register()函數將該結構進行注冊,其實就是根據協議類型將其設置到全局數組ip_ct_protos[]中的相應位置上。

ip_ct_protos變數里保存連接跟蹤系統當前可以處理的所有協議,協議號作為數組唯一的下標,如下圖所示。

結構體ip_conntrack_protocol{}中的每個成員,內核源碼已經做了很詳細的注釋了,這里我就不一一解釋了,在實際開發過程中我們用到了哪些函數再具體分析。

連接跟蹤的輔助模塊:

Netfilter的連接跟蹤為我們提供了一個非常有用的功能模塊:helper。該模塊可以使我們以很小的代價來完成對連接跟蹤功能的擴展。這種應用場景需求一般是,當一個數據包即將離開Netfilter框架之前,我們可以對數據包再做一些最後的處理。從前面的圖我們也可以看出來,helper模塊以較低優先順序被注冊到了Netfilter的LOCAL_OUT和POST_ROUTING兩個hook點上。

每一個輔助模塊都是一個ip_conntrack_helper{}結構體類型的對象。也就是說,如果你所開發的協議需要連接跟蹤輔助模塊來完成一些工作的話,那麼你必須也去實例化一個ip_conntrack_helper{}對象,對其進行填充,最後調用ip_conntrack_helper_register{}函數將你的輔助模塊注冊到全局變數helpers里,該結構是個雙向鏈表,裡面保存了當前已經注冊到連接跟蹤系統里的所有協議的輔助模塊。

全局helpers變數的定義和初始化在net/netfilter/nf_conntrack_helper.c文件中完成的。

最後,我們的helpers變數所表示的雙向鏈表一般都是像下圖所示的這樣子:

由此我們基本上就可以知道,注冊在Netfilter框架里LOCAL_OUT和POST_ROUTING兩個hook點上ip_conntrack_help()回調函數所做的事情基本也就很清晰了:那就是通過依次遍歷helpers鏈表,然後調用每個ip_conntrack_helper{}對象的help()函數。

㈨ netfilter修改數據包

  1. 構造報文是否正確,可以通過抓包工具看看

  2. 構造的報文應該是從mac層開始構造,看看是否構造mac地址與IP地址不對應,這種情況很可能被內核協議棧丟掉,簡單的方法是接收個包,然後把裡面的mac IP源地址和目的地址交換

  3. 是否使用正確的發送報文函數 skb->dev =pskb->dev;dev_queue_xmit(skb);

熱點內容
隨機啟動腳本 發布:2025-07-05 16:10:30 瀏覽:528
微博資料庫設計 發布:2025-07-05 15:30:55 瀏覽:25
linux485 發布:2025-07-05 14:38:28 瀏覽:305
php用的軟體 發布:2025-07-05 14:06:22 瀏覽:756
沒有許可權訪問計算機 發布:2025-07-05 13:29:11 瀏覽:432
javaweb開發教程視頻教程 發布:2025-07-05 13:24:41 瀏覽:707
康師傅控流腳本破解 發布:2025-07-05 13:17:27 瀏覽:241
java的開發流程 發布:2025-07-05 12:45:11 瀏覽:686
怎麼看內存卡配置 發布:2025-07-05 12:29:19 瀏覽:285
訪問學者英文個人簡歷 發布:2025-07-05 12:29:17 瀏覽:835