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