亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊(cè) 查看新帖 |

Chinaunix

  平臺(tái) 論壇 博客 文庫(kù)
最近訪問板塊 發(fā)新帖
查看: 24621583 | 回復(fù): 24621583
打印 上一主題 下一主題

[網(wǎng)絡(luò)子系統(tǒng)] 求助:利用netfilter和libnetfilter_queue子系統(tǒng)進(jìn)行簡(jiǎn)單上傳回傳測(cè)試出現(xiàn)崩潰問題 [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報(bào)告]
發(fā)表于 2014-07-02 10:19 |只看該作者 |倒序?yàn)g覽
各位大神,我想完成一個(gè)HTTP訪問控制的功能。所以想利用netfilter攔截HTTP數(shù)據(jù)包并且返回NF_QUEUE,上層應(yīng)用利用libnetfilter_queue子系統(tǒng)進(jìn)行接收處理并返回接受或丟棄。
目前測(cè)試的功能如下:
1)netfilter內(nèi)核模塊掛載到POST_ROUTING,檢測(cè)到目的端口是80或8080后 return NF_QUEUE,否則 return NF_ACCEPT;
2) libnetfilter_queue上層應(yīng)用接收到拷貝上來(lái)的數(shù)據(jù)包后,對(duì)包進(jìn)行一個(gè)計(jì)數(shù),并cout<<" This is a HTTP PACKET"<<endl;而后return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);

現(xiàn)在的情況是,程序運(yùn)行起來(lái)貌似沒問題,打開百度首頁(yè)都能正常計(jì)數(shù)輸出。但是我打開像新浪這種大的門戶網(wǎng)站后因?yàn)榘臄?shù)量特別多,我刷新幾次之后電腦就會(huì)打印oops之后崩潰。這個(gè)問題困擾了好久,還望各位請(qǐng)教。
以下是源碼:

(1)netfilter內(nèi)核模塊

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/string.h>
#include <linux/kmod.h>
#include <linux/vmalloc.h>
#include <linux/workqueue.h>
#include <linux/spinlock.h>
#include <linux/socket.h>
#include <linux/net.h>
#include <linux/in.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <net/sock.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
#include <linux/if_arp.h>

//定義鉤子函數(shù)結(jié)構(gòu)體
struct nf_hook_ops  post_hook;   

//實(shí)例化鉤子函數(shù)
static unsigned int watch_out(unsigned int hooknum,
                  struct sk_buff *skb,
                  const struct net_device *in,
                  const struct net_device *out,
                  int (*okfn)(struct sk_buff *))
{
   //復(fù)制skbuff結(jié)構(gòu)體,將指針指向ip頭和tcp頭
   struct sk_buff *sk;
   struct iphdr *iph;
   struct tcphdr *tcph;
   sk = skb_copy(skb, 1);
   iph = ip_hdr(sk);
   tcph = (void *) iph + iph->ihl * 4;

   //判斷協(xié)議是否為TCP,是則繼續(xù)判斷,否則放行返回NF_ACCEPT
   if ( iph->protocol == IPPROTO_TCP)
   {
//判斷數(shù)據(jù)包是否是HTTP數(shù)據(jù)包,是則將數(shù)據(jù)包排隊(duì)NF_QUEUE等待上層空間發(fā)回響應(yīng)策略
        if(tcph->dest == htons(8080) || tcph->dest == htons(80)) //利用端口號(hào)區(qū)分服務(wù),將FTP,HTTP 數(shù)據(jù)包上傳。
       {
             return NF_QUEUE;  
       }
        else
             return NF_ACCEPT;
   }         
   else
       return NF_ACCEPT;
}

int init_module()
{
   printk("------Client_Lite_Kernel Start------\n");
   
   //將鉤子函數(shù)注冊(cè)到POST_RPOTING掛載點(diǎn)上,設(shè)置優(yōu)先級(jí)最高。
   post_hook.hook     = watch_out;
   post_hook.pf       = PF_INET;
   post_hook.priority = NF_IP_PRI_FIRST;
   post_hook.hooknum  = NF_INET_POST_ROUTING;

   nf_register_hook(&post_hook);
   
   return 0;
}

void cleanup_module()
{
   printk("------Client_Lite_Kernel finish------\n");
   //注銷鉤子函數(shù)
   nf_unregister_hook(&post_hook);
}

MODULE_INIT(init_module);
MODULE_EXIT(cleanup_module);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("zhaoyun");

(2)libnetfilter_queue上層用戶應(yīng)用

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <linux/netfilter.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <libnetfilter_queue/libnetfilter_queue.h>
#include <iostream>
#include <string.h>
#define LENGTH 4096
using namespace std;
static int count=0;
static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data)
{
    int id = 0, pload_len;
    unsigned char *pload;
    struct nfqnl_msg_packet_hdr *ph;

    //get unique ID of packet in queue
    ph = nfq_get_msg_packet_hdr(nfa);
    if(ph)
    {
        id = ntohl(ph->packet_id);
    }

    //get payload
    pload_len = nfq_get_payload(nfa, &pload);
    if(pload_len == -1)
    {
        pload_len = 0;
    }
    struct iphdr *iph = (struct iphdr *)pload;
    struct tcphdr *tcph =(struct tcphdr*)((u_int8_t*)iph + (iph->ihl<<2));

    if(tcph->dest == htons(80) || tcph->dest == htons(8080))
    {
            count++;
        cout<<count<<" This is a HTTP PACKET"<<endl;
        return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);
    }
    else
    {
        return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);
    }
}

int main(int argc, const char *argv[])
{
    int len, fd;
    char buf[LENGTH];
    struct nfq_handle *h;
    struct nfq_q_handle *qh;

    //call nfq_open() to open a NFQUEUE handler
    h = nfq_open();
    if(!h)
    {
        fprintf(stderr, "error during nfq_open()\n");
        exit(1);
    }

    //unbinging existing nf_queue handler for PE_INET(if any)
    if(nfq_unbind_pf(h, PF_INET) < 0)
    {
        fprintf(stderr, "error during nfq_unbind_pf()\n");
        exit(1);
    }

    //binding nfnetlink_queue as nf_queue handler for PF_INET
    if(nfq_bind_pf(h, PF_INET) < 0)
    {
        fprintf(stderr, "error during nfq_bind_pf()\n");
        exit(1);
    }

    //binding this socket to queue '0'
    qh = nfq_create_queue(h, 0, &cb, NULL);
    if(!qh)
    {
        fprintf(stderr,"error during nfq_create_queue()\n");
        exit(1);
    }

    //setting copy_packet mode
    if(nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff) < 0)
    {
        fprintf(stderr, "can't set packet_copy_mode\n");
        exit(1);
    }

    //get the file descriptor associated with the nfqueue handler
    fd = nfq_fd(h);

    //handle a packet received from the nfqueue subsystem
    while ((len = recv(fd, buf, sizeof(buf), 0)) && len >= 0)
    {
        nfq_handle_packet(h, buf, len);
    }

    nfq_destroy_queue(qh);
    nfq_close(h);
    return 0;
}

(3)oops信息

PS:我在Ubuntu12.04LST(內(nèi)核3.8.0-39-generic),Ubuntu10.04LTS(內(nèi)核2.6.32-38-generic),中標(biāo)麒麟V3(內(nèi)核2.6.32-220.2.1.2.ky3.2.i686),中標(biāo)麒麟V5(2.6.27.41-170.2.117_ND5_1.i686)上都測(cè)試過此代碼,雖然崩潰的時(shí)間不相同,但是都會(huì)出現(xiàn)崩潰。其中中標(biāo)麒麟打印的OOPS信息如上,Ubuntu直接卡死沒有任何輸出。

論壇徽章:
0
2 [報(bào)告]
發(fā)表于 2014-07-03 09:24 |只看該作者
沒有人接觸過libnetfilter_queue么。

論壇徽章:
0
3 [報(bào)告]
發(fā)表于 2014-07-03 11:42 |只看該作者
) 你在代碼里邊,不加規(guī)則試試程序能不能崩潰
然后一點(diǎn)一點(diǎn)加注釋,確定崩的地方

論壇徽章:
0
4 [報(bào)告]
發(fā)表于 2014-07-03 18:02 |只看該作者
回復(fù) 3# kkddkkdd11

通過看oops信息和objdump反編譯ko文件,發(fā)現(xiàn)是內(nèi)核模塊的問題,錯(cuò)誤出在skb_copy上,他有可能拷貝不成功造成sk指針為空,然后就崩潰了。我還是不明百為什么開始能拷貝成功,刷著刷著就不行了。謝謝你的回復(fù),新手小白第一次發(fā)帖,十分感動(dòng)!


   

論壇徽章:
36
IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-10 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-16 06:20:0015-16賽季CBA聯(lián)賽之廣東
日期:2016-04-16 19:59:32IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-18 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-19 06:20:00每日論壇發(fā)貼之星
日期:2016-04-19 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-25 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-06 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-08 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-13 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-28 06:20:00每日論壇發(fā)貼之星
日期:2016-05-28 06:20:00
5 [報(bào)告]
發(fā)表于 2014-07-04 00:04 |只看該作者
回復(fù) 1# zhaoyun0819

感覺你寫 QUEUE 的那個(gè) kernel module 有點(diǎn)多余啊,直接通過 iptables 下一條 NFQUEUE 的規(guī)則即可。

用戶態(tài)調(diào)用 libnetfilter_queue 獲取報(bào)文即可。

如果你要確定 skb_copy 調(diào)用是否正確,可以看一下kernel 中對(duì)于 NFQUEUE 這個(gè) target 的實(shí)現(xiàn)代碼就行了。


   

論壇徽章:
36
IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-10 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-16 06:20:0015-16賽季CBA聯(lián)賽之廣東
日期:2016-04-16 19:59:32IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-18 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-19 06:20:00每日論壇發(fā)貼之星
日期:2016-04-19 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-25 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-06 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-08 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-13 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-28 06:20:00每日論壇發(fā)貼之星
日期:2016-05-28 06:20:00
6 [報(bào)告]
發(fā)表于 2014-07-04 00:14 |只看該作者
回復(fù) 1# zhaoyun0819

你看的 kernel module 基本上可以通過類似下面一條  iptables 規(guī)則搞定
iptables -t mangle -A POSTROUTING -p tcp -m multiport --dport  80,8080  -j NFQUEUE --queue-num 10


然后專注用戶態(tài)程序即可。

   

論壇徽章:
15
射手座
日期:2014-02-26 13:45:082015年迎新春徽章
日期:2015-03-04 09:54:452015年辭舊歲徽章
日期:2015-03-03 16:54:15羊年新春福章
日期:2015-02-26 08:47:552015年亞洲杯之卡塔爾
日期:2015-02-03 08:33:45射手座
日期:2014-12-31 08:36:51水瓶座
日期:2014-06-04 08:33:52天蝎座
日期:2014-05-14 14:30:41天秤座
日期:2014-04-21 08:37:08處女座
日期:2014-04-18 16:57:05戌狗
日期:2014-04-04 12:21:33技術(shù)圖書徽章
日期:2014-03-25 09:00:29
7 [報(bào)告]
發(fā)表于 2014-07-04 09:15 |只看該作者
從最后的oops信息看,是在atomic上下文中發(fā)生了調(diào)度,從哪兒看出是skb指針為空導(dǎo)致的問題呢?

論壇徽章:
0
8 [報(bào)告]
發(fā)表于 2014-07-04 15:30 |只看該作者
回復(fù) 6# Godbach

嗯,好像是的,這個(gè)內(nèi)核模塊確實(shí)可以通過iptables規(guī)則來(lái)實(shí)現(xiàn)。是因?yàn)槲抑笤趦?nèi)核模塊還有別的代碼實(shí)現(xiàn)功能,所以簡(jiǎn)單測(cè)試一下。我把拷貝改成sk = skb_copy(skb, GFP_ATOMIC );之后就沒有問題了目前,雖然我也具體不太清楚其中的原理。十分感謝!!

   

論壇徽章:
0
9 [報(bào)告]
發(fā)表于 2014-07-04 15:35 |只看該作者
回復(fù) 7# humjb_1983


    確實(shí)是上下文,我oops沒貼全,另外一次實(shí)驗(yàn)的時(shí)候還有oops信息提示 EIP is at watch_out+0xf/0x88
    我用objdump反匯編找到了是在   iph = ip_hdr(sk);處,所以加了容錯(cuò),if(sk==NULL){printk("<0>""sk pointer is NULL \n");return NF_ACCEPT;},結(jié)果就打印了錯(cuò)誤信息,所以發(fā)現(xiàn)是sk為空,skb_copy()拷貝沒成功。

論壇徽章:
36
IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-10 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-16 06:20:0015-16賽季CBA聯(lián)賽之廣東
日期:2016-04-16 19:59:32IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-18 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-19 06:20:00每日論壇發(fā)貼之星
日期:2016-04-19 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-04-25 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-06 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-08 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-13 06:20:00IT運(yùn)維版塊每日發(fā)帖之星
日期:2016-05-28 06:20:00每日論壇發(fā)貼之星
日期:2016-05-28 06:20:00
10 [報(bào)告]
發(fā)表于 2014-07-04 16:32 |只看該作者
回復(fù) 8# zhaoyun0819

你源代碼中 skb_copy() 中第二個(gè)參數(shù)是 1,GFP_ATOMIC 的值也應(yīng)該就是 1 啊。

在中斷上下文,申請(qǐng)內(nèi)存的話,是應(yīng)該用 GFP_ATOMIC。

   
您需要登錄后才可以回帖 登錄 | 注冊(cè)

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號(hào)-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號(hào):11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報(bào)專區(qū)
中國(guó)互聯(lián)網(wǎng)協(xié)會(huì)會(huì)員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請(qǐng)注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP