通过sk_buff将以太网数据包重定向到localhost

时间:2015-09-24 10:53:38

标签: linux networking kernel

我正在编写一个Linux内核模块,它将数据包重定向到localhost网络服务器,该服务器最初是通过本机使用网桥转发的。它还重定向以回复客户端。客户端忘记了重定向。所以有2个部分   1.通过网桥将所有转发的数据包重定向到本地网络服务器。

  1. localhost网络服务器的输出被引导至原始客户端
  2. 我可以通过nf_hook进行第二部分NF_INET_LOCAL_OUT

    unsigned int snoop_hook_reply( unsigned int hooknum, struct sk_buff *skb,
        const struct net_device *in, const struct net_device *out,
        int(*okfn)( struct sk_buff * ) )
    {
        int offset, len;
        struct ethhdr *ethh;
        struct iphdr *iph;
        struct tcphdr *tcph;
        bool flag = false;
        struct net_device *eth1_dev , *lo_dev;
    
        if (!skb) return NF_ACCEPT;
        iph = ip_hdr(skb);
        if (!iph) return NF_ACCEPT;
        skb_set_transport_header(skb, iph->ihl * 4);
        tcph = tcp_hdr(skb);
        /* skip lo packets */
        if (iph->saddr == iph->daddr) return NF_ACCEPT;
        if (tcph->dest == htons(80))
                flag=true;
        if(flag != true)
                return NF_ACCEPT;
    
        // correct the IP checksum
        iph->check = 0;
        ip_send_check (iph);
    
        //correct the TCP checksum
        offset = skb_transport_offset(skb);
        len = skb->len - offset;
        tcph->check = 0;
        if(skb->len > 60){
        tcph->check  = csum_tcpudp_magic((iph->saddr), (iph->daddr), len, IPPROTO_TCP, csum_partial((unsigned char *)tcph,len,0));
        }
        else{
        tcph->check  = ~csum_tcpudp_magic((iph->saddr), (iph->daddr), len, IPPROTO_TCP, 0);
        }
    
        //send to dev
        eth1_dev = dev_get_by_name(&init_net,"eth1");
        lo_dev = dev_get_by_name(&init_net,"lo");
        skb->dev = eth1_dev;
        ethh = (struct ethhdr *) skb_push(skb, ETH_HLEN);
        skb_reset_mac_header(skb);
        skb->protocol = ethh->h_proto = htons(ETH_P_IP);
        memcpy (ethh->h_source,eth1_dev->dev_addr , ETH_ALEN);
        memcpy (ethh->h_dest, d_mac, ETH_ALEN); // d_mac is mac of the gateway
        dev_queue_xmit(skb);
    
        return NF_STOLEN;
    }
    

    以上代码对我来说非常适合。一个问题是,稍后我会破坏数据包,因此需要创建一个新的sk_buff。

    我无法通过NF_INET_PRE_ROUTING执行第一部分,我无法通过TCP / IP堆栈将packet / sk_buff推送到Web服务器进程。我尝试使用dev_queue_xmit()函数和skb-> dev作为eth1和lo。我看到数据包通过tcpdump攻击lo或eth1。但是数据包没有到达localhost网络服务器。任何人都可以帮我这个或指向一些类似的回答问题。我相信而不是dev_queue_xmit()我需要调用一些接收函数。当数据包到达NF_INET_PREROUTING时,我的以太网头已经存在,所以我没有形成它。 我已经以各种方式完成了上述任务,首先使用原始套接字,然后使用nf_queue,现在我想通过这个方法看到性能。 感谢

1 个答案:

答案 0 :(得分:0)

如果要在本地接收数据包,则不能在eth1上调用dev_queue_xmit(),因为它将被发送出去。你可能需要在将skb-> dev指向eth1 / lo之后调用netif_rx()。

还有一点是,如果dest-ip不是你的本地主机ip,那么你需要再次避免路由,否则就不会使用你的拦截。 要实现这一点,您需要将数据包的目标IP修改为eth1 / lo IP或 通过使用skb_dst_set()设置" rth-> dst.input = ip_local_deliver"来欺骗IP层。将数据包接受为本地数据包。