【问题标题】:redirect ethernet packets through sk_buff to localhost通过 sk_buff 将以太网数据包重定向到 localhost
【发布时间】:2015-09-24 10:53:37
【问题描述】:

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

  1. 本地网络服务器的输出被引导到原始客户端

我可以通过 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 堆栈将数据包/sk_buff 推送到网络服务器进程。我尝试使用 skb->dev 作为 eth1 和 lo 的 dev_queue_xmit() 函数。我看到数据包通过 tcpdump 在 lo 或 eth1 上命中。但是数据包没有到达本地主机网络服务器。任何人都可以帮助我解决这个问题或指出一些类似的回答问题。我相信我需要调用一些接收函数而不是 dev_queue_xmit()。此外,当数据包到达 NF_INET_PREROUTING 时,以太网标头已经存在,所以我没有形成它。 我已经通过多种方式完成了上述任务,首先使用原始套接字,然后使用 nf_queue,现在我想通过这种方法看看性能。 谢谢

【问题讨论】:

  • 听起来你在做透明代理,你不能用一些现有的 iptable 模块来做吗?

标签: linux networking kernel


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-06
    • 2014-07-29
    • 2012-05-01
    • 2015-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多