NetFilter挂钩中的数据包处理?

时间:2011-11-23 06:08:10

标签: linux-kernel kernel

寻找有关NF_STOLEN的信息。

从NET-FILTER窃取数据包后;我正在通过扩展SKUBUFFER来添加IP头。之后;想要将数据包发送到相应的接口。我们应该用这个步骤做什么功能???或者,如果我们说; NF_ACCEPT。,我们能否确保内核处理Manipulated Packet正确地将其转发到正确的接口?

期待回复!!!

-Thanks in Advance, VKS

1 个答案:

答案 0 :(得分:4)

是的,如果你改变了skbuff结构并计算了适当的校验和,你只需要返回NF_ACCEPT。内核将为您处理剩下的事情。

我在论文中做到了这一点。这里是我已经完成的一些代码(它没有扩展或修改skbuff,但它改变了应用程序有效负载中的一个字段。但是,我还做了一些扩展skbuff的代码,理论是相同的):

unsigned int pre_routing_hook(filter_specs* sp, 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 udphdr* udp;
    __tp(pdu)* pdu;

    /*Omitted some sanity checks */

    iph = ip_hdr(skb);
    udp = (struct udphdr*) (((char*) iph) + (iph->ihl << 2));

    //I didn't care about udp checksum so I've stored zero in this field.
    udp->check = 0;

    switch (iph->protocol) {
    case IPPROTO_UDP:
          pdu = (__tp(pdu)*) (((char*) iph) + (iph->ihl << 2)
                               + sizeof(struct udphdr));

          swap_pdu_byte_order(pdu);

          pdu->timestamp = get_kernel_current_time() - 
                           (pdu->timestamp + pdu->rtt * 1000); 

          swap_pdu_byte_order(pdu);
          break;
    default:
            printk("\tProtocol not supported.\n");
    }
    return NF_ACCEPT;
}

编辑:我已经看了你发布的代码,这就是我想出的代码。它对我有用:

#include <linux/ip.h>
#include <linux/in.h>


static uint16_t csum(uint16_t* buff, int nwords) {
    uint32_t sum;
    for (sum = 0; nwords > 0; nwords--)
            sum += *buff++;
    sum = (sum >> 16) + (sum & 0xffff);
    sum += (sum >> 16);

    return ((uint16_t) ~sum);
}

//I'm assuming this will run in PRE_ROUTING                                                                                                  
unsigned int main_hook(unsigned int hooknum,
            struct sk_buff *skb, const struct net_device *in,
                   const struct net_device *out, int(*okfn)(struct sk_buff*)) {
  uint16_t lets_keep_the_original_size;
  struct in_device* ipa;

  iph = ip_hdr(sock_buff);

  lets_keep_the_original_size = ntohs(iph->tot_len);

  if(iph->protocol == 1) {
    if(skb_headroom(skb) < sizeof(struct iphdr)) {
      if( 0 != pskb_expand_head(skb, (sizeof(struct iphdr))- 
                                skb_headroom(skb),0,GFP_ATOMIC) ){
        kfree_skb(skb);
        return NF_STOLEN;
    }
  }

  iph = (struct iphdr*) skb_push(skb, sizeof(struct iphdr)); 
  iph->proto = IPPROTO_IP;
  iph->ihl = 5;
  iph->version = 4;
  iph->tos = 0;
  iph->tot_len = htons(lets_keep_the_original_size + sizeof(struct iphdr));
  iph->id = 0;
  iph->frag_off = 0;
  iph->ttl = 60;

  //This must be zero to be able to calculate it with csum above.                                                                          
  iph->check = 0;
  //in is the interface where the packet arrived, provided by netfilters. 
  //In PRE_ROUTING there is no out interface yet so you'll need to add 
  //the ip manually:                                                                                                                          
  ipa = (struct in_device*) in->ip_ptr;
  iph->saddr = ipa->ifa_list->ifa_address;

  //in_aton already gives you the address in network byte order .                                                                          
  //You can just add an integer, but I've chosen to use in_aton                                                                            
  //so the code is more readable                                                                                                           
  iph->daddr = in_aton("192.168.1.1");

  //Here is the important part.                                                                                                            
  iph->check = csum((uint16_t*) iph, (iph->ihl << 1));

  //Let the kernel deal with the rest for us.                                                                                              
  return NF_ACCEPT;
 }
 return NF_ACCEPT;
}

如果有什么我可以帮助您,请告诉我。