Chinaunix首页 | 论坛 | 博客
  • 博客访问: 134900
  • 博文数量: 12
  • 博客积分: 550
  • 博客等级: 中士
  • 技术积分: 151
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-14 12:19
文章分类

全部博文(12)

文章存档

2014年(2)

2012年(1)

2010年(9)

我的朋友

分类: LINUX

2010-09-19 15:54:20

本文档的Copyleft归necofang所有,使用GPL发布,可以自由拷贝,转载,转载时请保持文档的完整性,严禁用于任何商业用途。
msn : 
 
  近来做一个产品需要在网关上获取特定UDP端口(假设是1000端口)的报文,并将其转发给其它设备的1000端口。虽然此类文章网上已经有很多了,但我还是贴上来,这样自己也做下记录,大家也多一份参考。
下面只给出了代码片段,自己慢慢调试。
 
我们假设网络拓扑如下所示:
 
                       LINUX                                    
  +---------+       +---------+        +---------+        
  |  PC-1   |-------| Server  | -------| DataSrv |        
  +---------+       +---------+        +---------+ 
                                                                 
                        
pc-1发送udp报文到server的1000端口时,我们将报文拷贝一份并发送给DataSrv的1000端口。
   报文的获取,我们采用netfilter hook. 我们将hook钩到 NF_IP_LOCAL_IN,优先级别设置成NF_IP_PRI_FIRST。
   为什么hook到NF_IP_LOCAL_IN 而不是PERROUTING呢? 这是因为hook到 LOCAL_IN的话,我们就不用去考虑报文的重组了。如下图:
 
         ip_rcv ------> ip_local_deliver ----------> netfilter
                              |-----------ip_defrag-------^             
                               
 
   为什么优先级别设置成最高了,这样可以防止udp的穿透。
   这里我们不详细描述netfilter hook如何编写。下面我们来看获取到skb(重组好了的)的报文后,我们如何处理。
   首先,我们假设DataSrv的ip地址为 192.168.1.254/24;Server的ip地址为 192.168.1.253/24。
 
  
 
 
 
 

#define TEST_XMIT(skb, rt) \
 NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, (skb), NULL, \
  (rt)->u.dst.dev, dst_output);

#define IP_PARTS_NATIVE(n) \
  (unsigned int)((n)&0xFF), \
    (unsigned int)((n)>>8)&0xFF, \
    (unsigned int)((n)>>16)&0xFF, \
    (unsigned int)((n)>>24)&0xFF

#define TEST_BUG() BUG()
#define TEST_ERR(msg...) printk(KERN_ERR "TEST: " msg)
#define TEST_INFO(msg...) printk(KERN_INFO "TEST: " msg)
#define TEST_WARNING(msg...) printk(KERN_WARNING "TEST: " msg)
#define TEST_ERR_RL(msg...) \
  do { \
    if (net_ratelimit()) \
      printk(KERN_ERR "TEST: " msg); \
  } while (0)

//调用test_pop前 需要 拷贝或克隆 skb,然后再传入
static inline int TEST_pop (struct sk_buff * skb)
{
  struct iphdr * iph = NULL;
  struct rtable * rt = NULL;
  struct ethhdr * ethh = NULL;
  struct flowi fl;
  unsigned long ulpeerip = 0;
  unsigned int udphoff = 0;
  
  fl.oif = 0;
  fl.nl_u.ip4_u.daddr = in_aton ("192.168.1.254");
  fl.nl_u.ip4_u.saddr = in_aton ("192.168.1.253");
  fl.nl_u.ip4_u.tos = RT_TOS(0);

  
//查找出口路由

  if (unlikely (ip_route_output_key(&rt, &fl))) {
    TEST_ERR("%s no route from 192.168.1.253 to 192.168.1.254 (%s:%d)\n",
     __FUNCTION__, __FILE__, __LINE__);
    return (1);
  }
  
  
//修改IP头

  iph = skb->nh.iph;
  iph-

阅读(2558) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~