jewson 发表于 2014-08-21 11:11

netfilter 求救

大家好,小弟最近学习netfilter遇到问题,希望CU的兄弟可以帮到我,先谢谢大家了。
先贴代码,原文可以在:http://hi.baidu.com/widebright/item/0c6c94b44e749c9619469784看到
下面的代码仅仅在原文进行修改测试。
运行测试环境:rehl5.4虚拟机内核2.6.32/*
* widebright.c
*
*Created on: 2009-10-13
*       Author: widebright
*/

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <net/tcp.h>
#include <net/udp.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <net/sock.h>

#include <net/netfilter/nf_nat.h>
#include <net/netfilter/nf_nat_helper.h>
#include <net/netfilter/nf_nat_rule.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_expect.h>

MODULE_LICENSE("GPL"); //用了nf_conntrack_tcp_update 函数要用这个遵守GPL开放协议才能编译通

typedef unsigned int   uint32;
typedef unsigned char   uchar8;

typedef struct app_detection_module_struct {
        uint32 sport;
        uint32 dport;
        uint32 saddr;
        uint32 daddr;
       
        uint32 plen;//the len not include ip header and (tcp/udp)header
uchar8* payload;//packet not include ip header and (tcp/udp)header
} APP_DATA;



static void hex_dump(const unsigned char *buf, size_t len) {
   size_t i;

   for (i = 0; i < len; i++) {
          if (i && !(i % 16))
               printk("\n");
          printk("%02x ", *(buf + i));
   }
   printk("\n");
}

char * is_mp3_request(char * start) {
   char data = ".mp3";
   char * i = start;

   i += 4; //跳过 GET
   while (*i != ' ' && *i != '\n')
          i++; //查找网络地址最后的位置

   if (*(int *) (i - 4) == *(int *) data)
          return i;
   else
          return NULL;
}

unsigned int check_link_address(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 = NULL;
    struct tcphdr *tcph = NULL;
    struct tcphdr *udph = NULL;
    uint32 i = 0;
    APP_DATA* app_data = NULL;
       int oldlen, datalen;
        struct rtable *rt = skb->rtable;
    enum ip_conntrack_info ctinfo;
    iph = ip_hdr(skb);
   
    app_data = (APP_DATA* )kmalloc(sizeof(APP_DATA), GFP_ATOMIC);
    if(app_data == NULL)
            return NF_ACCEPT;
   
    app_data->saddr = iph->saddr;
    app_data->daddr = iph->daddr;
       
       //Note that the connection tracking subsystem
   //is invoked after the raw table has been processed, but before the mangle table.
   //所以下面 要指定.priority = NF_IP_PRI_MANGLEnf_ct_get 才会返回有效的值
   struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
       
    if (iph->protocol == IPPROTO_TCP) {
   tcph = (void *) iph + iph->ihl * 4;
      
   app_data->sport = ntohs(tcph->source);        //Src端口
   app_data->dport = ntohs(tcph->dest);         //Dest端口
   app_data->payload = (char*)iph+(iph->ihl*4) + tcph->doff*4;        //从data里面偏移出前面的ip包头和tcp包头
   app_data->plen = ntohs(iph->tot_len)-(iph->ihl*4) - tcph->doff*4;        //TCP包长度
      

                  if(ntohs(app_data->dport) == 80)
                  {
                           printk("src: %u.%u.%u.%u:%u<===> dst: %u.%u.%u.%u:%u \n",NIPQUAD(app_data->saddr),ntohs(app_data->sport),NIPQUAD(app_data->daddr),ntohs(app_data->dport));
               return NF_ACCEPT;
          }
          // printk("tcp packet to : %u.%u.%u.%u:%u\n",NIPQUAD(daddr),ntohs(dport));
          // printk("---------ip total len =%d--------\n", ntohs(iph->tot_len));
          // printk("---------tcph->doff =%d--------\n", tcph->doff*4);

          /*       skb_linearize - convert paged skb to linear one
         *       If there is no free memory -ENOMEM is returned, otherwise zero
         *       is returned and the old skb data released.
         * 这一步很关键,否则后面根据 包头偏移计算出来payload 得到东西不是正确的包结构
         *2.6内核需要这么做。因为新的系统可能为了提高性能,一个网络包的内容是分成几个fragments来保存的
         *这时 单单根据 skb->data得到的只是包的第一个 fragments的东西。我见到我系统上的就是tcp头部和 tcp的payload
         *是分开保存在不同的地方的。可能ip,tcp头部等是后面系统层才加上的,和应用程序的payload来源不一样,使用不同的fragments就
         *可以避免复制数据到新缓冲区的操作提高性能。skb_shinfo(skb)->nr_frags属性指明了这个skb网络包里面包含了多少块 fragment了。
         *具体可以看《Linux Device Drivers, 3rd Editio》一书的17.5.3. Scatter/Gather I/O小节
         * 《Understanding_Linux_Network_Internals》 一书 Chapter 21. Internet Protocol Version 4 (IPv4): Transmission 一章有非常详细的介绍
         *下面使用的skb_linearize 函数则可以简单的把 多个的frag合并到一起了,我为了简单就用了它。
         */
                  
                /*
          if (0 != skb_linearize(skb)) {
               return NF_ACCEPT;
          }
                  */
                  
          // payload = (void *)tcph + tcph->doff*4; skb_linearize(skb) 调用之后,skb被重新构建了,之前的tcp指向的不是正确的地址了。
          //payload = (void *) skb->data + 40; //我的机器上tcph->doff*4 + iph->ihl*4等于40, 就是从data里面偏移出前面的ip包头和tcp包头
          //tcp 包长度 ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4
         
          app_data->payload = (void *) skb->data + 40;
              app_data->plen = ntohs(iph->tot_len)-(iph->ihl*4) - tcph->doff*4;       
                  //hex_dump(app_data->payload ,app_data->plen);

                  /*
                  if((app_data->plen)<10)
                  {
                        //printk("plen <10\n");
                        return 0;
                  }
                  */
                  if(memcmp(app_data->payload, "GET ", 4) == 0)   
                  {
                           printk("%s\n", "HTTP GET FOUND");
               char * head = is_mp3_request(app_data->payload);
               if (head) {
                          
                                        printk("%s\n", head);
                  //刚刚发现把 http://www.google.cn/1.mp3 改成    http://www.google.cn/1.%6D%70%33 就可以跳过网关的检测了,%6D%70%33 是mp3的html编码
               
                  //nf_nat_mangle_tcp_packet 是netfilter nat模块里面的导出函数,所以需要nat模块加载之后才能进行的。
                  //如果你没有配置内核自动加载这个模块,好像执行一下“sudo iptables -t nat --list” 命令就会加载起来。
               if (ct && nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
                                                 (char*) head - (char *)app_data->payload -3 , 3,
                                                 (char *) "%6D%70%33", sizeof("%6D%70%33")-1 )) {
                         printk("-----------------nf_nat_mangle_tcp_packet--------------------\n%20s\n",
                                 app_data->payload);
                         return NF_ACCEPT;
               }

               //wineshark 抓包说明后续tcp包的序号依然不对,原因是修改后,tcp的需要加上 增加的字节,但系统不知道这个改变,所以下次还是用以前的 序号来发送数据,
               //所以后面的包的序号就不对了. 在/net/ipv4/tcp_output.c 中的tcp_transmit_skb函数中,可以看到系统是如何填写这个数据的。但在hook的时候无法
               //得到tcp层的信息,本来想一劳永逸的把初始序号改正确的但无法做到。只好hook没个包的时候都把序号改正过来了。
               //nf_nat_mangle_tcp_packet修改tcp包后,会记录下需要调整的seq的序列(参考内核源代码/net/ipv4/netfilter/nf_nat_helper.c 文件爱你里面的
               //adjust_tcp_sequence函数,他把需要调整的信息记录在两个 struct nf_nat_seq结构里面了。)但没有看到自动对后续的网络国包进行处理了。
               //所以需要在另外的hook里面把标识出来的需要修复序号的包都,调用一下seq修复函数nf_nat_seq_adjust,把后面所有tcp包的seq都进行修复。
               //这个工作如果你的修改导致包的长度改变的都需要作。conntrack模块里面会调用helper module的
               //nf_nat_seq_adjust_hook函数来作这个工作的。参考 内核源代码的 /net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c 中的ipv4_confirm函数
               //但没看到调用nf_nat_seq_adjust 函数的地方,所以我自己又加了两个hook来捕获后续网络包,显示的调用nf_nat_seq_adjust 函数。
               //nf_nat_seq_adjust 函数在net/ipv4/netfilter/nf_nat_helper.c 文件的里面有,但没有导出,所以我把他复制过来了,不过 注意不同的内核扳本有所不同
               //如果编译有问题,就去把对应的内核源代码中的几个函数复制出来吧。


               return NF_ACCEPT;

               //不用 nf_nat_mangle_tcp_packet 函数来修改感到话,虽然下面修改办法没有问题,但计算tcp校验和和序列号的结果不对。
                  char *end = skb_put(skb, 9); //希望skb的buffer的容两可以继续在尾部加上9个字节的数据,不然这个会导致BUG()触发,http请求数据不会太大吧。
                  //memmove(

                  while (end > head) {
                         end--;
                         *(end + 9) = *end;
                  }
                  memcpy(head, "%6D%70%33", 9);

                  /* fix IP hdr checksum information */
                  ip_hdr(skb)->tot_len = htons(skb->len);
                  ip_send_check(ip_hdr(skb));


                  //计算校验和,参考内核源码 的net/ipv4/tcp_ipv4.c tcp_v4_send_check函数
                  //和net/ipv4/netfilter/nf_nat_helper.c nf_nat_mangle_tcp_packet 函数
                                 //和net/netfilter/xt_TCPMSS.c 的 tcpmss_mangle_packet 函数
                  datalen = skb->len - iph->ihl * 4;
                  oldlen = datalen - 9;
                  if (skb->ip_summed != CHECKSUM_PARTIAL) {
                         if (!(rt->rt_flags & RTCF_LOCAL) && skb->dev->features
                                 & NETIF_F_V4_CSUM) {
                              skb->ip_summed = CHECKSUM_PARTIAL;
                              skb->csum_start = skb_headroom(skb)
                                        + skb_network_offset(skb) + iph->ihl * 4;
                              skb->csum_offset = offsetof(struct tcphdr, check);
                              tcph->check = ~tcp_v4_check(datalen, iph->saddr,
                                        iph->daddr, 0);
                         } else {
                              tcph->check = 0;
                              tcph->check = tcp_v4_check(datalen, iph->saddr,
                                        iph->daddr, csum_partial(tcph, datalen, 0));
                         }
                  } else
                         inet_proto_csum_replace2(&tcph->check, skb, htons(oldlen),
                                 htons(datalen), 1);


                     printk("---------------------------------------\n%20s\n",
                              app_data->payload);

               }
          }

          return NF_ACCEPT;
          //return NF_DROP; /*丢掉这个包*/
   }
       else
       {
          return NF_ACCEPT;/*这个包传给下一个hook函数另有NF_QUEUE, it's queued. */
   }
       
       
    kfree(app_data);
    app_data = NULL;
   
    return NF_ACCEPT;
}


//一下3个函数是内核源代码的net/ipv4/netfilter/nf_nat_helper.c 里面的,没有导出。需要找到对应的内核扳本的才能编译通过
//在http://lxr.linux.no/上看到2.6.31 和2.6.28用到的其他函数有点变化了。下面是

/* Adjust one found SACK option including checksum correction */
static void
sack_adjust(struct sk_buff *skb,
             struct tcphdr *tcph,
             unsigned int sackoff,
             unsigned int sackend,
             struct nf_nat_seq *natseq)
{
         while (sackoff < sackend) {
               struct tcp_sack_block_wire *sack;
               __be32 new_start_seq, new_end_seq;

               sack = (void *)skb->data + sackoff;
               if (after(ntohl(sack->start_seq) - natseq->offset_before,
                           natseq->correction_pos))
                         new_start_seq = htonl(ntohl(sack->start_seq)
                                       - natseq->offset_after);
               else
                         new_start_seq = htonl(ntohl(sack->start_seq)
                                       - natseq->offset_before);

               if (after(ntohl(sack->end_seq) - natseq->offset_before,
                           natseq->correction_pos))
                         new_end_seq = htonl(ntohl(sack->end_seq)
                                       - natseq->offset_after);
               else
                         new_end_seq = htonl(ntohl(sack->end_seq)
                                       - natseq->offset_before);

               printk("sack_adjust: start_seq: %d->%d, end_seq: %d->%d\n",
                        ntohl(sack->start_seq), new_start_seq,
                        ntohl(sack->end_seq), new_end_seq);

               inet_proto_csum_replace4(&tcph->check, skb,
                                          sack->start_seq, new_start_seq, 0);
               inet_proto_csum_replace4(&tcph->check, skb,
                                          sack->end_seq, new_end_seq, 0);
               sack->start_seq = new_start_seq;
               sack->end_seq = new_end_seq;
               sackoff += sizeof(*sack);
         }
}

/* TCP SACK sequence number adjustment */
static inline unsigned int
nf_nat_sack_adjust(struct sk_buff *skb,
                  struct tcphdr *tcph,
                  struct nf_conn *ct,
                  enum ip_conntrack_info ctinfo)
{
         unsigned int dir, optoff, optend;
         struct nf_conn_nat *nat = nfct_nat(ct);
                nat = nfct_nat(ct);
                if (!nat) {
                          /* NAT module was loaded late. */
                          if (nf_ct_is_confirmed(ct))
                                          return NF_ACCEPT;
                          nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC);
                       if (nat == NULL) {
                                        pr_debug("failed to add NAT extension\n");
                                        return NF_ACCEPT;
                        }
                }
               
         optoff = ip_hdrlen(skb) + sizeof(struct tcphdr);
         optend = ip_hdrlen(skb) + tcph->doff * 4;

         if (!skb_make_writable(skb, optend))
               return 0;

         dir = CTINFO2DIR(ctinfo);

         while (optoff < optend) {
               /* Usually: option, length. */
               unsigned char *op = skb->data + optoff;

               switch (op) {
               case TCPOPT_EOL:
                         return 1;
               case TCPOPT_NOP:
                         optoff++;
                         continue;
               default:
                         /* no partial options */
                         if (optoff + 1 == optend ||
                           optoff + op > optend ||
                           op < 2)
                                 return 0;
                         if (op == TCPOPT_SACK &&
                           op >= 2+TCPOLEN_SACK_PERBLOCK &&
                           ((op - 2) % TCPOLEN_SACK_PERBLOCK) == 0)
                                 sack_adjust(skb, tcph, optoff+2,
                                             optoff+op, &nat->seq[!dir]);
                         optoff += op;
               }
         }
         return 1;
}





/* TCP sequence number adjustment.Returns 1 on success, 0 on failure */
int
nf_nat_seq_adjust(struct sk_buff *skb,
                  struct nf_conn *ct,
                  enum ip_conntrack_info ctinfo)
{
        struct tcphdr *tcph;
        int dir;
        __be32 newseq, newack;
        s16 seqoff, ackoff;
        struct nf_conn_nat *nat = nfct_nat(ct);
        struct nf_nat_seq *this_way, *other_way;

        dir = CTINFO2DIR(ctinfo);

        this_way = &nat->seq;
        other_way = &nat->seq[!dir];

        if (!skb_make_writable(skb, ip_hdrlen(skb) + sizeof(*tcph)))
                return 0;

        tcph = (void *)skb->data + ip_hdrlen(skb);
        if (after(ntohl(tcph->seq), this_way->correction_pos))
                seqoff = this_way->offset_after;
        else
                seqoff = this_way->offset_before;

        if (after(ntohl(tcph->ack_seq) - other_way->offset_before,
                  other_way->correction_pos))
                ackoff = other_way->offset_after;
        else
                ackoff = other_way->offset_before;

        newseq = htonl(ntohl(tcph->seq) + seqoff);
        newack = htonl(ntohl(tcph->ack_seq) - ackoff);

        inet_proto_csum_replace4(&tcph->check, skb, tcph->seq, newseq, 0);
        inet_proto_csum_replace4(&tcph->check, skb, tcph->ack_seq, newack, 0);

        printk("Adjusting sequence number from %u->%u, ack from %u->%u\n",
               ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq),
               ntohl(newack));

        tcph->seq = newseq;
        tcph->ack_seq = newack;

        return nf_nat_sack_adjust(skb, tcph, ct, ctinfo);
}



unsigned int fix_seq(unsigned int hooknum, struct sk_buff *skb,
          const struct net_device *in, const struct net_device *out, int(*okfn)(
                  struct sk_buff *))
{


   enum ip_conntrack_info ctinfo;

   //Note that the connection tracking subsystem
   //is invoked after the raw table has been processed, but before the mangle table.
   //所以下面 要指定.priority = NF_IP_PRI_MANGLEnf_ct_get 才会返回有效的值
   struct nf_conn *ct = nf_ct_get(skb, &ctinfo);

   //调用nf_nat_seq_adjust函数,修正nf_nat_mangle_tcp_packet 之后造成的tcp包的序列号不对问题
   //这个需要在修改后的双向网络包上都要进行,所以需要hook双向的吧?,nf_nat_mangle_tcp_packet
   //中调用了adjust_tcp_sequence知识记录下了应该作的修改。
   //因为nf_nat_mangle_tcp_packet给需要进行序号修正的conntrack加上IPS_SEQ_ADJUST_BIT标志了。
   //所以这里判断是不是这个标志就进行修改。不知道这会不会和其他nat helper moudle冲突,如果别人也用这个
   //标志时就可能出现重复修改等问题,因为里面的序号调整结构都是通用的。
   //也许进行更细致的检查,比如给conntrack的ct结构加上 其他唯一的status标志比较好一点,
   //反正就是要保证我们要修复序号的包是我们前面用nf_nat_mangle_tcp_packet
   //修改过包内容的那个连接的,而不是其他的连接的包。
   //写一个nat helper module来修改tcp包也许比在这种hook module里面进行修改更合适。去看看netfilter的文档看看。
   //因为我确信自己系统没有运行nat help module,所以为了简单就这样进行修改了,测试过没有什么问题。
   //最好研究一下nat conntrack的那些代码,我也不是清楚具体的细节。

   if (ct&&test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)
             && (ctinfo != IP_CT_RELATED + IP_CT_IS_REPLY)) {
             nf_nat_seq_adjust(skb, ct, ctinfo);
   }

   return NF_ACCEPT;
   
}



static struct nf_hook_ops http_hooks = { .pf = NFPROTO_IPV4, /*IPV4 协议的*/
         .priority = NF_IP_PRI_MANGLE , // NF_IP_PRI_FIRST, //NF_IP_PRI_LAST ;NF_IP_PRI_NAT_SRC ;
          .hooknum = NF_INET_LOCAL_OUT, /* NF_IP_LOCAL_OUT 我们只处理出去的网路包 */
          .hook = check_link_address,
          .owner = THIS_MODULE, };




static struct nf_hook_opsseq_adjust[] = {

         {
               .hook            = fix_seq,
               .owner         = THIS_MODULE,
               .pf            = PF_INET,
               .hooknum         = NF_INET_POST_ROUTING,
               .priority      = NF_IP_PRI_MANGLE,//NF_IP_PRI_CONNTRACK_CONFIRM,
         },
         {
               .hook            = fix_seq,
               .owner         = THIS_MODULE,
               .pf            = PF_INET,
               .hooknum         = NF_INET_LOCAL_IN,
               .priority      = NF_IP_PRI_MANGLE,//NF_IP_PRI_CONNTRACK_CONFIRM,
         },
};


static int __init widebright_init(void)
{
      int ret = 0;
      ret = nf_register_hooks(seq_adjust,
                                 ARRAY_SIZE(seq_adjust));

         if (ret < 0) {
            return ret;
         }
       printk("insert test.ko\n");
   return nf_register_hook(&http_hooks);

}

static void __exit widebright_cleanup(void)
{
   nf_unregister_hooks(seq_adjust,
                                 ARRAY_SIZE(seq_adjust));
   nf_unregister_hook(&http_hooks);
      
        printk("remove test.ko\n");
}

module_init(widebright_init);
module_exit(widebright_cleanup);
错误日志如下:HTTP GET FOUND
HTTP/1.1
Host: www.baidu.com
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.12) Gecko/2009070811 Red Hat/3.0.12-1.el5_3 Firefox/3.0.12
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Proxy-Connection: keep-alive
Cookie: BAIDUID=1D0A4FC00A04363B537ED1730413ADB0:FG=1; BD_UPN=1333


BUG: unable to handle kernel NULL pointer dereference at 00000044
IP: [<f80a2178>] nf_nat_mangle_tcp_packet+0xeb/0x26f
*pde = 7f489067
Oops: 0000 [#4] SMP
last sysfs file: /sys/devices/pci0000:00/0000:00:11.0/0000:02:03.0/local_cpus
Modules linked in: test iptable_nat nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 autofs4 lockd sunrpc ip_tables ip6_tables x_tables vmhgfs vsock vmmemctl acpiphp dm_mirror dm_multipath scsi_dh video output sbs sbshc battery ipv6 lp sg joydev snd_ens1371 gameport snd_rawmidi snd_ac97_codec ac97_bus snd_seq_dummy ac snd_seq_oss snd_seq_midi_event snd_seq tpm_tis snd_seq_device snd_pcm_oss snd_mixer_oss tpm snd_pcm serio_raw snd_timer tpm_bios i2c_piix4 button pcnet32 ide_cd_mod cdrom snd soundcore snd_page_alloc pcspkr floppy mii parport_pc i2c_core parport rtc_cmos rtc_core rtc_lib vmci vmxnet pvscsi vmxnet3 dm_region_hash dm_log dm_mod ata_piix libata mptspi mptscsih mptbase scsi_transport_spi sd_mod scsi_mod ext3 jbd uhci_hcd ohci_hcd ehci_hcd

Pid: 28685, comm: firefox Tainted: G      D    (2.6.32.63 #2) VMware Virtual Platform
EIP: 0060:[<f80a2178>] EFLAGS: 00210246 CPU: 1
EIP is at nf_nat_mangle_tcp_packet+0xeb/0x26f
EAX: 00000000 EBX: f6aa30c4 ECX: ffffbbc8 EDX: 654ade00
ESI: f6b18134 EDI: 000001ff EBP: 0000020d ESP: f1d0db80
DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
Process firefox (pid: 28685, ti=f1d0d000 task=f40e0cc0 task.ti=f1d0d000)
Stack:
00000014 00000000 f1e33464 f6aa30d8 f1e4acc0 00000000 0000001e f1daf90a
<0> f4665200 f82f56d0 f82f55b4 0000001b 00000003 f82f56d4 00000009 f6b18134
<0> 0000d14b f1daf8d8 f1e33464 00d0dc18 f82f5778 f1d0dc1c 00000003 f6b18134
Call Trace:
[<f82f55b4>] ? fix_seq+0x248/0x26c
[<c06282c4>] ? nf_iterate+0x30/0x61
[<c0634318>] ? dst_output+0x0/0x7
[<c0634318>] ? dst_output+0x0/0x7
[<c0628487>] ? nf_hook_slow+0x41/0x99
[<c0634318>] ? dst_output+0x0/0x7
[<c0635567>] ? __ip_local_out+0x8b/0x91
[<c0634318>] ? dst_output+0x0/0x7
[<c0635575>] ? ip_local_out+0x8/0x17
[<c0636059>] ? ip_queue_xmit+0x2e8/0x32c
[<c04aaca0>] ? pollwake+0x0/0x56
[<c0610648>] ? dev_hard_start_xmit+0x23b/0x2e7
[<c061fa69>] ? sch_direct_xmit+0x6c/0x105
[<c0648d7d>] ? tcp_v4_send_check+0x7a/0xb0
[<c0644b37>] ? tcp_transmit_skb+0x56c/0x59f
[<c0645dbe>] ? tcp_write_xmit+0x758/0x816
[<c060a27b>] ? __alloc_skb+0x49/0x10c
[<c0645e9a>] ? __tcp_push_pending_frames+0x1e/0x70
[<c063c6e6>] ? tcp_sendmsg+0x7c8/0x8b6
[<c06043b8>] ? sock_sendmsg+0xc7/0xe1
[<c0441fd8>] ? autoremove_wake_function+0x0/0x2d
[<c04aace9>] ? pollwake+0x49/0x56
[<c04266ea>] ? default_wake_function+0x0/0x8
[<c041f94b>] ? __wake_up_common+0x2e/0x58
[<c0604d53>] ? sys_sendto+0x105/0x130
[<c049e0fe>] ? do_sync_write+0xbf/0xfe
[<c0441fd8>] ? autoremove_wake_function+0x0/0x2d
[<c0604d97>] ? sys_send+0x19/0x1d
[<c0605698>] ? sys_socketcall+0xda/0x1aa
[<c0402804>] ? sysenter_do_call+0x12/0x22
Code: 83 e0 0f 0f b6 c0 c1 e0 02 83 c4 0c 29 c7 88 d0 83 e0 0c 3c 0c 0f 84 c7 00 00 00 8b 44 24 10 83 b8 d4 00 00 00 00 78 72 8b 46 14 <f6> 40 44 0e 74 69 83 ca 0c 8b 8e a8 00 00 00 88 56 64 8b 96 94
EIP: [<f80a2178>] nf_nat_mangle_tcp_packet+0xeb/0x26f SS:ESP 0068:f1d0db80
CR2: 0000000000000044
---[ end trace e586f0509fd5abb4 ]---
我知道错误在nf_nat_mangle_tcp_packet,但是却不知道怎么处理,望CU的兄弟给与支持,先谢谢了。

jewson 发表于 2014-08-21 11:34

没有人会吗?自己顶一个。。

Godbach 发表于 2014-08-21 12:52

回复 1# jewson



BUG: unable to handle kernel NULL pointer dereference at 00000044
IP: [<f80a2178>] nf_nat_mangle_tcp_packet+0xeb/0x26f

典型的 NULL pointer 解引用。


   

jewson 发表于 2014-08-21 12:58

是的,我知道是空指针错误,但不知道怎么解决?望Godbach指点

jewson 发表于 2014-08-21 13:34

是这个问题太基础了,还是?给位大哥帮帮忙啊:dizzy:
页: [1]
查看完整版本: netfilter 求救