歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux綜合 >> Linux資訊 >> 更多Linux

內核防火牆netfilter入門

  目錄: -. 前言 二. 分析 三. 例子代碼 四. 附錄:與2.2在應用方面的區別簡介 五. 後記 -.前言 在Linux2.2內核中的防火牆ipchains已經被用戶廣泛認可,它提供了完整的防火牆功 能(包過濾,地址偽裝,透明代理),又避免了商業防火牆那高的驚人的價格。如果 你用的是某款國產防火牆,那麼十有八九你實際在受到ipchains(有些甚至是2.0系列 中ipfwadm)的保護:-).在未來的2.4內核中,被稱為netfilter(http://netfilter. kernelnotes.org/)的防火牆以更好的結構重新構造,並實現了許多新功能,如完整的 動態NAT(2.2內核實際是多對一的"地址偽裝"),基於MAC及用戶的過濾,真正的基於狀 態的過濾(不再是簡單的查看tcp的標志位等),包速率限制等。 在原有的網絡部分的LKM中,如果對網絡部分進行處理,一般是先生成strUCt packet _type結構,在用dev_add_pack將其插入網絡層(注意此時的packet_type實際相當於一 個的三層的協議,如ip_packet_type,ipx_8023_packet_type等),具體的例子可參見 phrack 55期 和本月小四寫的月刊文章<利用 LLKM處理網絡通信----對抗IDS、Firewall>。 而netfilter本身在IP層內提供了另外的5個插入點(其文檔中稱為HOOK): NF_IP_PRE_ROUTING,NF_IP_LOCAL_IN,NF_IP_FORWARD,NF_IP_LOCAL_OUT,NF_IP_POST _ROUTING,分別對應IP層的五個不同位置,這樣理論上在寫lkm時便可以選擇更適合的切 入點,再輔以netfilter內置的新功能(如connect tracking),應該會幫助寫出功能更 強的lkm。 本來准備寫出一個完整的例子(限制IP連接數),但計劃總趕不上變化:-(,只好先貼 出個簡單的例子來,權且自我安慰成拋磚引玉了。 本文的參考配置是linux2.4.0-test4和iptable-1.1.1,好,開始拋磚,閃人喽! 二.分析 通俗的說,netfilter的架構就是在整個網絡流程的若干位置放置了一些檢測點(HOOK ),而在每個檢測點上上登記了一些處理函數進行處理(如包過濾,NAT等,甚至可以是 用戶自定義的功能)。 IP層的五個HOOK點的位置如下圖所示(copy from ) : --->[1]--->[ROUTE]--->[3]--->[4]---> ^ [ROUTE] v [2] [5] ^ v [local process] [1]:NF_IP_PRE_ROUTING:剛剛進入網絡層的數據包通過此點(剛剛進行完版本號,校驗 和等檢測), 源地址轉換在此點進行; [2]:NF_IP_LOCAL_IN:經路由查找後,送往本機的通過此檢查點,INPUT包過濾在此點進行; [3]:NF_IP_FORWARD:要轉發的包通過此檢測點,FORWord包過濾在此點進行; [4]:NF_IP_POST_ROUTING:所有馬上便要通過網絡設備出去的包通過此檢測點,內置的目 的地址轉換功能(包括地址偽裝)在此點進行; [5]:NF_IP_LOCAL_OUT:本機進程發出的包通過此檢測點,OUTPUT包過濾在此點進行。 在IP層代碼中,有一些帶有NF_HOOK宏的語句,如IP的轉發函數中有: <-ipforward.c ip_forward()-> NF_HOOK(PF_INET, NF_IP_FORWARD, skb, skb->dev, dev2, ip_forward_finish); 其中NF_HOOK宏的定義提煉如下: <-/include/linux/netfilter.h-> #ifdef CONFIG_NETFILTER #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \ (list_empty(&nf_hooks[(pf)][(hook)]) \


? (okfn)(skb) \ : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn))) #else /* !CONFIG_NETFILTER */ #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb) #endif /*CONFIG_NETFILTER*/ 如果在編譯內核時沒有配置netfilter時,就相當於調用最後一個參數,此例中即執行 ip_forward_finish函數;否則進入HOOK點,執行通過nf_register_hook()登記的功能 (這句話表達的可能比較含糊,實際是進入nf_hook_slow()函數,再由它執行登記的 函數)。 NF_HOOK宏的參數分別為: 1.pf:協議族名,netfilter架構同樣可以用於IP層之外,因此這個變量還可以有諸如 PF_INET6,PF_DECnet等名字。 2.hook:HOOK點的名字,對於IP層,就是取上面的五個值; 3.skb:不用多解釋了吧; 4.indev:進來的設備,以struct net_device結構表示; 5.outdev:出去的設備,以struct net_device結構表示; (後面可以看到,以上五個參數將傳到用nf_register_hook登記的處理函數中。) 6.okfn:是個函數指針,當所有的該HOOK點的所有登記函數調用完後,轉而走此流程。 這些點是已經在內核中定義好的,除非你是這部分內核代碼的維護者,否則無權增加 或修改,而在此檢測點進行的處理,則可由用戶指定。像packet filter,NAT,connection track這些功能,也是以這種方式提供的。正如netfilter的當初的設計目標--提供一 個完善靈活的框架,為擴展功能提供方便。 如果我們想加入自己的代碼,便要用nf_register_hook函數,其函數原型為: int nf_register_hook(struct nf_hook_ops *reg) 我們考察一下struct nf_hook_ops結構: struct nf_hook_ops { struct list_head list; /* User fills in from here down. */ nf_hookfn *hook; int pf; int hooknum; /* Hooks are ordered in ascending priority. */ int priority; }; 我們的工作便是生成一個struct nf_hook_ops結構的實例,並用nf_register_hook將 其HOOK上。其中list項我們總要初始化為{NULL,NULL};由於一般在IP層工作,pf總是 PF_INET;hooknum就是我們選擇的HOOK點;一個HOOK點可能掛多個處理函數,誰先誰後 ,便要看優先級,即priority的指定了。netfilter_ipv4.h中用一個枚舉類型指定了內 置的處理函數的優先級: enum nf_ip_hook_priorities { NF_IP_PRI_FIRST = INT_MIN, NF_IP_PRI_CONNTRACK = -200, NF_IP_PRI_MANGLE = -150, NF_IP_PRI_NAT_DST = -100, NF_IP_PRI_FILTER = 0, NF_IP_PRI_NAT_SRC = 100, NF_IP_PRI_LAST = INT_MAX, }; hook是提供的處理函數,也就是我們的主要工作,其原型為: unsigned int nf_hookfn(unsigned int hooknum, struct sk_buff **skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)); 它的五個參數將由NFHOOK宏傳進去。 了解了這些,基本上便可以可以寫一個lkm出來了。 三.例子代碼 這段代碼是一個例子,其功能實現了一個IDS,檢測幾個簡單攻擊(land,winnuke)和特殊 掃描(nmap),當然,不會有人真把它當嚴肅的IDS使用吧:-)。可以利用類似結構干點別 的。。。 <-example.c begin-> /* * netfilter module example: it`s a kernel IDS(be quie,donot laugh, my friend) * [email protected] * Compile:gcc -O -c -Wall sample.c ,under linux2.4 kernel,netfilter is needed. */

#define __KERNEL__ #define MODULE #include #include #include #include #include #include #include #include #define ALERT(fmt,args...) printk("nsfocus: " fmt, ##args) /*message will be print to screen(too many~),and logged to /var/log/message*/ static unsigned int sample(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; struct tcphdr *tcph; struct udphdr *udph; __u32 sip; __u32 dip; __u16 sport; __u16 dport; iph=(*skb)->nh.iph; sip=iph->saddr; dip=iph->daddr; /*play ip packet here (note:checksum has been checked,if connection track is enabled,defrag have been done )*/ if(iph->ihl!=5){ ALERT("IP packet with packet from %d.%d.%d.%d to %d.%d.%d.%d\n",NIPQUAD(sip),NIPQUAD(dip)); } if(iph->protocol==6){ tcph=(struct tcphdr*)((__u32 *)iph+iph->ihl); sport=tcph->source; dport=tcph->dest; /*play tcp packet here*/ if((tcph->syn)&&(sport==dport)&&(sip==dip)){ ALERT("maybe land attack





Copyright © Linux教程網 All Rights Reserved