- 论坛徽章:
- 0
|
正在做一个项目 里面需要有这样一个步骤
1.在网络层将数据包截住并修改
2.重新把修改后的数据包交付给协议栈底端 让它重新经过协议栈
开始阶段 为了实现简单 用ICMP报文作为拦截对象 且截住的数据包不做过多修改 只将协议头部若干指针修改 让它的报文头状态变为好像刚刚从网卡到来的时候一样
实现的时候 用的是netfilter的PRE_ROUTING钩子 检查每一个数据包 如果是ICMP报文且类型为8 即ECHO报文 就将报文截获 复制一个 修改头部信息 然后重新调用netif_rx 让协议栈接收 原来的报文使用NF_STOLEN处理
注册在PRE_ROUTING钩子处的回调函数如下
- static unsigned int pre_routing_hook(unsigned int hooknum, struct sk_buff **pskb, const struct net_device *in, \
- const struct net_device *out, int (*okfn)(struct sk_buff *))
- {
- struct sk_buff *skb;
- struct sk_buff *new_skb;
- //unsigned char src_ip[4];
- //unsigned char dst_ip[4];
- //
- struct icmphdr *icmp_hdr;
- int icmp_hdr_off;
- //
- struct iphdr *ip_hdr;
- int ip_hdr_off;
- struct ethhdr *eth_hdr;
-
- struct net_device *NIC = NULL;
- const char nic[5] = "eth0";
- // printk(KERN_INFO "inside the filter\n");
-
- int index;
-
- int rx_ret;
-
- skb = skb_copy(*pskb, GFP_ATOMIC);
- NIC = dev_get_by_name(nic);
-
- if (!NIC) {
- return NF_ACCEPT;
- }
-
- if (skb->nh.iph->protocol == IPPROTO_ICMP) {
- // get ip header
- ip_hdr = (struct iphdr *)skb->nh.iph;
- // calcutate ip header length
- ip_hdr_off = ip_hdr->ihl << 2;
-
- // get icmp header
- icmp_hdr = (struct icmphdr *)(skb->data + ip_hdr_off);
-
- // only modify icmp request
- // #define ICMP_ECHO 8 /* Echo Request */
- // in <linux/icmp/h>
- if (icmp_hdr->type == ICMP_ECHO) {
- new_skb = alloc_skb(skb->len + 5 + ETH_HLEN, GFP_ATOMIC);
- skb_reserve(new_skb, 2);
- skb_put(new_skb, skb->len + ETH_HLEN);
- memcpy(new_skb->data, skb->data - ETH_HLEN, skb->len + ETH_HLEN);
- new_skb->mac.raw = new_skb->data;
- // commented
- //skb_pull(new_skb, ETH_HLEN);
-
- new_skb->mac_len = ETH_HLEN;
- new_skb->len = skb->len + ETH_HLEN;
-
- new_skb->ip_summed = CHECKSUM_UNNECESSARY;
- new_skb->pkt_type = PACKET_HOST;
- new_skb->protocol = htons(ETH_P_IP);
- new_skb->dev = NIC;
- skb_shinfo(new_skb)->nr_frags = 0;
- skb_shinfo(new_skb)->frag_list = NULL;
- skb_shinfo(new_skb)->frags[0].page = NULL;
-
- rx_ret = netif_rx(new_skb);
- NIC->last_rx = jiffies;
- kfree_skb(skb);
- return NF_STOLEN;
- }
- }
- kfree_skb(skb);
- return NF_ACCEPT;
- }
复制代码 现在的情况是 将修改的数据包送给netif_rx函数 通过Wireshark截包 可以看到原来的ICMP报文以及复制后重新交给协议栈的数据包
由于ping命令是在Windows里发出的 默认是4个ICMP request报文 所以在Wireshark里看到的是8个ICMP request报文
但是 复制修改后重新交给协议栈的ICMP request报文并没有得到上层的回应 因为没有ICMP reply报文发出 原有的ICMP request被NF_STOLEN处理 因此也不会被回应 没有ICMP reply
情况如下图
请教各位 如何才能让我自己复制并交给协议栈的ICMP request报文得到上层的回应?
是我调用netif_rx的方式不对?还是我复制的sk_buff 修改包头指针时候出现了错误?或者是什么其他错误?
还有一个问题 我查了很多论坛 有的人说 传给netif_rx的sk_buff是网络层的 没有eth_hdr 有人说是链路层的 应该包含eth_hdr 到底哪个才是正确的呢? |
|