免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 2942 | 回复: 13
打印 上一主题 下一主题

[内核模块] 在模块加载时构造SYN包并发送到本机 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2016-05-06 23:17 |只看该作者 |倒序浏览
Hi 大大们,在下初学 Netfilter 遇到一个问题,麻烦大家帮帮忙,在此先谢谢了~

有一台客户端机器为 Win7 系统,服务器为 RHEL-6.2 x86_64 系统,现在在服务器上编写了一个内核模块,并在加载时向服务器上层发送 SYN 包,源地址、端口为客户端地址 172.30.40.26:1234, 目标地址为服务器地址 172.30.40.90:80,
并且在服务器上已开启 80 端口。我的代码如下,在客户端上使用 Wireshark 抓包,测试结果:
1. 调用 dev_queue_xmit(skb) 时能在客户端抓到抓,由于目标地址不为客户端,所以客户端无响应;
2. 调用 dst_input(skb) 时,在客户端不能抓到来自服务端响应的 SYN_ACK;
3. 调用 netif_rx(skb) 与第 2 点测试情况相同;

skb 中加入 MAC 头或不加,测试结果相同。
请各位高手帮忙一下,看看代码哪里有问题?非常谢谢~

  1. int SendTcpPacket(__be32 sip, __be16 sport, __be32 dip, __be16 dport, __be32 seq, __u8 syn, __u8 fin, __u8 rst, __u8 ack, __be32 seq_ack)
  2. {
  3.         struct dst_entry* dest = NULL;
  4.         struct sk_buff *skb;
  5.         struct tcphdr* tcph;
  6.         struct iphdr *iph;
  7.         struct ethhdr *ethh;
  8.         int ip_payload_size;
  9.         int result;

  10.         unsigned char mac_source[ETH_ALEN] = {0xC0, 0x3F, 0xD5, 0x71, 0x97, 0xA5};
  11.         unsigned char mac_dest[ETH_ALEN]   = {0x00, 0x0C, 0x29, 0x51, 0x97, 0xA7};

  12.         skb = alloc_skb(MAX_TCP_HEADER + 128, GFP_ATOMIC|__GFP_ZERO);
  13.         if (skb == NULL)
  14.         {
  15.                 printk(KERN_ALERT"Failed to alloc_skb\n");
  16.                 return -1;
  17.         }
  18.         skb_reserve(skb, MAX_TCP_HEADER);

  19.         // TCP header
  20.         tcph = (struct tcphdr *)skb_push(skb, sizeof(struct tcphdr));
  21.         tcph->source  = sport;
  22.         tcph->dest    = dport;
  23.         tcph->doff    = (sizeof(struct tcphdr) >> 2);
  24.         tcph->seq     = seq;
  25.         tcph->syn     = syn;
  26.         tcph->fin     = fin;
  27.         tcph->rst     = rst;
  28.         tcph->ack     = ack;
  29.         tcph->ack_seq = seq_ack;
  30.         tcph->window   = htons(0xFFFF);
  31.         skb_reset_transport_header(skb);

  32.         // IP Header
  33.         iph = (struct iphdr *)skb_push(skb, sizeof(struct iphdr));
  34.         iph->ihl      = (sizeof(struct iphdr) >> 2);
  35.         iph->version  = 4;
  36.         iph->tot_len  = htons(skb->len);
  37.         iph->ttl      = 64;
  38.         iph->protocol = IPPROTO_TCP;
  39.         iph->saddr    = sip;
  40.         iph->daddr    = dip;
  41.         ip_send_check(iph);
  42.         skb_reset_network_header(skb);

  43.         // MAC header
  44.         ethh = (struct ethhdr *)skb_push(skb, sizeof(struct ethhdr));
  45.         memcpy(ethh->h_source, mac_source, ETH_ALEN);
  46.         memcpy(ethh->h_dest, mac_dest, ETH_ALEN);
  47.         ethh->h_proto = __constant_htons(ETH_P_IP);
  48.         skb_reset_mac_header(skb);

  49.         ip_payload_size = skb->len - sizeof(struct ethhdr) - sizeof(struct iphdr);
  50.         skb->csum = skb_checksum(skb, sizeof(struct ethhdr) + sizeof(struct iphdr), ip_payload_size, 0);
  51.         tcph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, ip_payload_size, iph->protocol, skb->csum);
  52.         skb->ip_summed = CHECKSUM_UNNECESSARY;
  53.         skb->pkt_type = PACKET_HOST;

  54.         if (0 != get_dest(sip, &dest))
  55.         {
  56.                 printk(KERN_ALERT"Failed to get_dest\n");
  57.                 return -1;
  58.         }

  59.         skb->dev = dest->dev;
  60.         skb_dst_set(skb, dest);

  61.         result = dev_queue_xmit(skb);
  62. //        result = dst_input(skb);
  63. //        result = dst_output(skb);
  64. //        result = netif_rx(skb);
  65.         if (result != NET_RX_SUCCESS)
  66.         {
  67.                 kfree_skb(skb);
  68.                 printk(KERN_ALERT"Failed to send packet. ErrCode=%d\n", result);
  69.         }
  70.         else
  71.         {
  72.                 printk(KERN_ALERT"Send packet succeeded from %pI4:%d to %pI4:%d\n", &sip, ntohs(sport), &dip, ntohs(dport));
  73.         }

  74.         return 0;
  75. }
复制代码

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
2 [报告]
发表于 2016-05-06 23:29 |只看该作者
回复 1# 世事皆虚幻

你在服务器上构造 SYN 包,然后发给上层,那还要让走 dev_queue_xmit() 啊?


   

论坛徽章:
0
3 [报告]
发表于 2016-05-06 23:38 |只看该作者
回复 2# Godbach


    谢谢关注,我是调了一下这个函数测试一下在客户端抓包,Wireshark 分析出计算的 checksum 是正确的,先保证一下构造的 sk_buff 内容是正确的。

论坛徽章:
0
4 [报告]
发表于 2016-05-06 23:53 |只看该作者
回复 2# Godbach


    麻烦版主帮忙看看,谢谢~

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
5 [报告]
发表于 2016-05-07 00:14 |只看该作者
回复 3# 世事皆虚幻

你构造包到底发给谁,发给 server 的话,为什么还要走 dev_queue_xmit ?

   

论坛徽章:
0
6 [报告]
发表于 2016-05-07 00:19 |只看该作者
回复 5# Godbach


    多谢版主回复,我是要在服务器中运行内核模块,发送给本机。其实我是想调用 dst_input(skb) 函数,理论上发送到上层后,服务器会向源地址回应 SYN_ACK, 但是我在客户端上抓不到包。

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
7 [报告]
发表于 2016-05-07 00:34 |只看该作者
回复 1# 世事皆虚幻

1. 调用 dev_queue_xmit(skb) 时能在客户端抓到抓,由于目标地址不为客户端,所以客户端无响应;


你构造的 SYN 包源 IP 是 client 的 IP 吗。

不太清楚你写这个程序,要是做什么的。就算是构造包,用的环境感觉也有些非常规。
   

论坛徽章:
0
8 [报告]
发表于 2016-05-07 00:41 |只看该作者
回复 7# Godbach


    多谢回复。我是这个需求,有二台服务器,实现主备,当主服务器宕机时,将客户端的 TCP 连接转移至备机。
目前在主备上部署 heartbeat 模块,实现宕机后的 IP 漂移。在这二台服务器上,运行着二个相同的内核模块,有客户端连接时,主服务器会将连接信息通过 UDP 同步至备机,一旦主机挂掉,备机会切为主机,备机会与上层发送 SYN 报文,并拦截上层的 SYN_ACK, 回复 ACK 后 NF_DROP 掉,这样的话,便可以保证该 TCP 连接相对于客户端来说是未断开的。

目前阻塞在备机向上层发送 SYN 报文这儿,SYN 报文里填写的源地址是客户端的 IP。

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
9 [报告]
发表于 2016-05-07 00:49 |只看该作者
回复 8# 世事皆虚幻

你发 syn 包的话,相当于初始连接。而大多时候,主机 down 掉了,现有的了连接要是在备机上维持,要保证 seq/ack 等信息都一样的。



   

论坛徽章:
0
10 [报告]
发表于 2016-05-07 00:52 |只看该作者
回复 9# Godbach


    这个没问题,主机上客户端的发送序号和服务端的发送序号都同步过去了,在我的模块中都会转换。
现在我的问题是,构造出一个 SYN 报文的 skb, 用 dst_input() 函数发给上层没反应,不知哪儿出问题了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP