【发布时间】:2015-09-24 10:53:37
【问题描述】:
我正在编写一个 Linux 内核模块,它将一个数据包重定向到 localhost 网络服务器,它最初是使用桥接通过这台机器转发的。它还重定向以回复客户端。客户端忘记了重定向。所以有2部分 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