Chinaunix

标题: 熟悉nat和conntrack的高手进来指导下,谢谢! [打印本页]

作者: shaohui973    时间: 2013-11-20 15:47
标题: 熟悉nat和conntrack的高手进来指导下,谢谢!
环境背景:
                                                     linux服务器
话机1   ------------------------
                                           |fm1-gb0 --- fm1-gb1| ----------------------dsp
话机2   ------------------------

使用服务器隔离dsp和外部网络,话机1和话机2都处在外部网络。
话机1:  10.0.1.60
话机2:  10.0.1.50

服务器:对外网口 10.0.1.10
             对内网口  192.100.1.1

dsp:   192.100.1.100

linux version: 2.6.38

现象(以话机2发送RTP为例说明):
   1) 如果在话机发送第一个RTP或RTCP之前,先配置NAT规则:
      iptables -t nat -A PREROUTING -d 10.0.1.10 -p udp --dport 10000 -j DNAT --to-destination 192.100.1.100:10000
      iptables -t nat -A POSTROUTING -s 10.0.1.50 -p udp --sport 11780 -j SNAT --to-source 192.100.1.1:10000
      则,话机2发送的RTP包可以通过NAT规则的转换,并将包发往DSP

    2)如果在话机发送第一个包之后才设置NAT规则,则话机2发送的RTP包无法通过NAT规则的转换,最终死在路由的结果上,返回icmp,code = 3, type =3 (目的端口不可达)

追踪内核源码,发现如下:
当收到第一个包时,新建了链接跟踪(nf_conntrack_in),然后进入NAT表在PREROUTING链路上的操作。
在nf_nat_fn中
nf_nat_fn()
{
      switch(ctinfo)
      {
              case  IP_CT_NEW:
              {
                      /* ct->staus 在进行了一次nat match匹配后,会调用target函数 ipt_snat_table或者ipt_dnat_table来设置
                       * ,并且将转换操作的规则信息nat_info转换成一个tuple,挂到ct上,后续的NAT转换就不用再查NAT规则了。
                       */
                     if(!nf_nat_initalized())   /* 第一包会进入 */
                     {
                            nf_nat_rule_find();
                     }
              }
      }

     nf_nat_packet(); /* 会调用manip_pkt()来修改ip和port */
}

nf_nat_rule_find()
{
      ret = ipt_do_table();
      if (NF_ACCEPT == ret)
              if(!nf_initialized())
                      ret = alloc_null_binding();
      
      return ret;
}

在ipt_do_table中,由于我们刚启动时,清空了nat规则表,所以查match时,是没有任何能匹配的,acpar.hotdrop == false。
这个查找应该返回NF_DROP(直接丢弃,后面的操作也不用了),并且,ct->status的SNAT和DNAT应该不会被设置啊。但是,从我在nf_nat_find中的打印来看,后续的包好像都没进入这个nf_nat_find函数,这个怎么解释呢???
作者: 独孤九贱    时间: 2013-11-22 16:36
shaohui973 发表于 2013-11-20 15:47
环境背景:
                                                     linux服务器
话机1   -------------- ...
2)如果在话机发送第一个包之后才设置NAT规则,则话机2发送的RTP包无法通过NAT规则的转换,最终死在路由的结果上,返回icmp,code = 3, type =3 (目的端口不可达)


或许是我没有完全明白你的意思。

但是我的理解的,第二个包本来就不应该去查NAT规则,所以当然就不会进行地址转换了。
作者: shaohui973    时间: 2013-11-22 21:54
回复 2# 独孤九贱

第二个包为什么不去查?第一包到达时,由于此时还没有设置NAT规则,则nf_find_rule查找匹配失败,返回NF_ACCEPT;由于是查找失败的,所以没有机会调用对应的target函数---ipt_snat_target或ipt_dnat_target,也就没有机会设置ct->status为DNAT或者SNAT。既然没机会设置,那第二包到达时,它判断ct->status没有设置DNAT或SNAT,不是还会调用nf_find_rule去查找规则。

或许,是不是还有什么地方会设置这个ct->status???


   
作者: 瀚海书香    时间: 2013-11-23 10:16
回复 3# shaohui973
第二个包为什么不去查?第一包到达时,由于此时还没有设置NAT规则,则nf_find_rule查找匹配失败,返回NF_ACCEPT;由于是查找失败的,所以没有机会调用对应的target函数---ipt_snat_target或ipt_dnat_target,也就没有机会设置ct->status为DNAT或者SNAT。既然没机会设置,那第二包到达时,它判断ct->status没有设置DNAT或SNAT,不是还会调用nf_find_rule去查找规则。

或许,是不是还有什么地方会设置这个ct->status???


呵呵。你应该仔细看看代码,nat的PREROUTING只对NEW state的数据包操作,也就是说只对链接的第一个数据包操作,之后的数据包都之间走conntrack,不会再走nat规则。
   
作者: 独孤九贱    时间: 2013-11-23 14:13
楼上说得很正确。
简单地讲,nat信息放在conntrack中的,如果一个流已经有了conntrack,但是conntrack中没有nat信息,直接就走了,否则就进行nat,只有新建会话的报文才会进行规则的匹配。
作者: shaohui973    时间: 2013-11-24 16:32
回复 4# 瀚海书香


    你是说,第一个包之后,CT就不是NEW状态了吗?我对CT这块没了解,指导下我,谢谢。

    如果按你说的,第一个包到达时,如果没有NAT规则,则CT中是没有nat信息的,然后路由之后,linux回复icmp也算是CT的另一个方向有数据包经过,CT就进入另一个状态???照这么解释的话,在nf_nat_fn进入的是default分支.
作者: 瀚海书香    时间: 2013-11-24 19:26
回复 1# shaohui973
你是说,第一个包之后,CT就不是NEW状态了吗?我对CT这块没了解,指导下我,谢谢。

是的。

   




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2