彻底理解Cisco NAT内部的一些事
2013-09-08 13:09 3599人阅读 评论(3) 收藏举报
目录(?)[+]
为了配一条NAT,发生了很多事。
一.Inside和Outside
很多在Cisco配置过NAT的人都有过一个疑问,那就是inside和outside的区别!以下是Cisco官方文档上关于NAT执行顺序的说明:

注意红和蓝圈住的部分,对于inside-outside而言,NAT发生在路由之后,而对于outside-inside而言,NAT发生在路由之前。这是目前为止,我们唯一需要记住的。
1.问题
迷 惑的原因不在别的,就在inside,outside这个名字不好,实际上如果将inside-outside换成POST-ROUTING,将 outside-inside换成PRE-ROUTING的话,就非常好理解了,最重要的是,换了名字之后,NAT看起来不再和设备的 inside/outside网口域相关,而和“路由”发生了关系,虽然本质上没有任何变化。
        后面会介绍,实际上,在理解Cisco的NAT的时候,根本不能将inside和outside单独拿出来理解,inside和outside仅仅是一个 位置限定词,代表“某地”,而具体的是“到某地去”还是“从某地来”,还需要一个副词,这就是source和destination。在详述这个之前,姑 且先将inside和outside单独拿出来使用。
        接下来我来说明一下NAT和路由的关系是多么重要!考虑以下的数据流,我以“路由”这个动作为中心:
正向包:-->NAT point1-->路由-->NAT point2-->
返回包:<--NAT point1<--路由<--NAT point2<--
我 们看一下在NAT point1和NAT point2上要做些什么动作才合理。首先我们先考虑转换正
向包的源IP地址发生在NAT point2,那么对于返回包,目标地址转换就发生在NAT point2,返回包转换完目标地址后,发生路由查询,数据包正常返回,没有任何问题。现在考虑正向包的源IP地址转换发生在NAT point1,那么按照将NAT钩子操作安装在数据流同一位置的原则,返回包的目标地址转换只能发生在NAT point1,此时已经经过了路由查询,路由查询是基于目标地址转换前的目标地址来的,也就是说这个路由结果并非真正的路由结果,真正要想将返回数据包送 到目的地,必须基于转换后目标地址来查询路由表才可以,然而即便这个针对转换前目标的路由查询结果实际上是个假的结果,你也要必须把它映射成一个真的结果 (这就是ip nat outside source中add-route参数要做的事情,下面的例子详述)。以下给出一个实例:
为了使得返回包能到达1.1.1.2,必须将到达2.2.2.4的路由映射到E0那一侧才行,因此必须增加一条:
ip route 2.2.2.4 255.255.255.255 1.1.1.2
也就是说将到达目标地址转换前的下一跳设置成目标地址转换后的下一跳。
        这就是NAT和路由的联动关系。Cisco中如果你用ip nat outside source设置NAT的时候,就会碰到上面的这个问题,你可以手工添加一条反向包的地址转换前路由映射,也可以通过命令行后面加add-route参数 解决,add-route参数会自动为你添加那条路由,实际上它做的就是:
a.根据NAT映射表查询目的地址B转换后的目的地址A;
b.查目的地址A查询到达A的下一跳C;
c.将到达B的下一条设置到C。
        我们看到在outside上,即PRE-ROUTING上做源地址转换确实会有问题,但是可以通过add-route参数进行路由重新映射来解决之。正常 合理的情况就是在inside上,即POST-ROUTING上做源地址转换。事实上,我们虽然在做源地址转换,但是问题总是出在反向数据包的目标地址转 换上,合理的情况就是要将目标地址转换放在路由之前进行,反推正向
数据,那就是将源地址转换放在路由之后进行,如果不了解Cisco Domain概念的话,一定会认为:不要在outside上作源地址转换!
        目前为止,我来总结一下。Cisco完全割裂了路由和NAT的关系,不像Linux那样DNAT永远在路由之前进行,不管是配置的DNAT,还是SNAT 的反向DNAT,都在路由前,这样就可以针对转换后的目标地址做路由查询,如果这么理解是对的,你会惊讶,Cisco竟然可以在 PREROUTING(outside)做SNAT(ip nat outside source),导致反向包在POSTROUTING做但是事情不是这么简单!
        Cisco不会由于犯错而设计出如此不合理又容易把人搞晕的NAT架构的,它这么设计必然有自己的理由,是什么理由呢?下面2,3两小节给出了一些提示。
2.关于policy routing
我们知道,标准的IP路由是基于目标地址的,但是为了增加更多的策略,policy routing可以用源地址来影响路由查询结果。在这种意义上,源地址转换在路由之前就是必要的,然而这样就会导致反向的目标地址地址转换发生在路由之后!到底是:
a.为了policy routing将SNAT置于路由之前
b.为了不必add-route(虽然它确实不是什么问题,而且是自动的),将DNAT置于路由之前
需要一个权衡!然而Cisco不像Linux那样去对称设计那5个HOOK点,Cisco的方式就划分Domain的,即inside和outside
3.关于Domain和NAT domain
Cisco 设备一般连接两种网络环境,一种是自己内部的,另一种是外部公共的,这就将接口分为了两个域,一个是内部域,即inside,另外一种为外部域,即 outside!这种分法的名字叫得特别好,以至于它被用在了很多的领域,比如nat,然而一旦用在了nat方面,就让人糊涂了。因此我提议,对 Cisco架构不是很理解的,请尝试用POST/PRE ROUTING来理解inside和outside。但是本小节想做的就是阐明使用inside和outside是合理的。
        对于NAT来讲,转换的是IP地址,而IP地址可以分为Global地址以及Local地址,前者是公网可路由的地址,后者是私有地址。从inside域 到outside域,需要将所有的Local地址转换为Global地址,一个首要原则就是,Global的地址在未经允许是不能出现在inside域和 DMZ域(路由器可能没有)的!决策点就是路由!因此outside到inside方向的地址转换必然要在路由之前完成。这就要求inside到 outside方向的地址转换必然要在路由之后完成。即:
ip nat inside source
必然发生在路由之后,而:
ip nat outside source
必然发生在路由之前。
如 果你定义了某个接口比如FE0/0为outside,那么需要在接口上使能ip nat outside,这样的话,从该接口进入的包就会在路由之前去查询NAT表,如果到对应的表项,就会执行NAT。同理如果定义某接口比如FE0/1为 inside,那么需要在接口上使能ip nat inside,这样的话,从该接口进入的包先执行路由查,然后去查询NAT表,如果到对应的表项,则执行NAT操作。
3.1.转换方向以及转换点-Cisco NAT的设计
这 个小节涉及到了对Domain的使用以及如何解读ip nat inside|outside source|destination命令。本小节总结了Cisco NAT设计的终极理论。为了简单,我不再引入Cisco定义的那四种地址以及它们和源/目标IP地址,方向的关联,这些概念都是额外的概念,最容易使人跑 偏而最终陷进去。
        Cisco没有像Linux那样使用“pre/post路由”这么技术化的术语来定义NAT的行为,而是完全根据Domain来定义,所谓的 Domain,即路由器两边一边属于inside,另一边属于outside。那么所有的NAT无外乎就以下4种类型:
1>从inside到outside时转换源地址
2>从inside到outside时转换目标地址
3>从outside到inside时转换源地址
4>从outside到inside时转换目标地址
其中1和4互相隐含,2和3互相隐含。到此为止,我们发现Cisco的NAT并没有像Linux那么简单,Linux实际上就定义了两种NAT,即:
i> SNAT,源地址转换
ii>DNAT,目标地址转换
然后其它的约束都是设计的时候内置的:
路由前执行DNAT,路由后执行SNAT,包含隐含规则。
这 就是Cisco和Linux的NAT设计的终极区别!它们侧重点不同,Cisco强调使用者的使用域,Linux强调技术本身的合理性(如何配置就需要发 挥想象力了)。我们先看一下Linux的N
AT设计基准是什么。Linux的NAT是全局生效的,没有“将NAT应用于接口”的说法,因此接口就成了一个 match。因此管理员只需要写match/target就可以了。
        对于Cisco而言,为了将4种NAT配置界面全部导出给工程师,需要一个前提操作,那就是定义inside接口和outside接口,即在哪个接口上应 用inside nat,在哪个接口上应用outside nat。到此,所有的4种NAT都必须能和任意类型(inside/outside)的接口单独组合。这就打破了平衡点,变成了马鞍面,你无法到一个 点,在PRE ROUTING和POST ROUTING中完成一切,举例,如果接口E1使能inside nat,E0使能outside nat,说明E1是inside接口,E0是outside接口,那么我们考虑从inside到outside方向的两种转换,一种是转换源地址,另一种 是转换目标地址,我们把它们放在一个位置还是放在一个“虚拟的平衡点”(不一定是routing)两边,即两个位置呢?我们看下面的两个图,实际上代表了 两种约束:
这 两个图展开后是个典型的马鞍面,原点就是路由,之所以要有个原点,是因为基于Domain的配置中,数据包从inside到outside或者反过来必然 要经过一个点,从本文最上面的那幅Cisco网站上的图,我们看到基于Domain的NAT行为不仅仅是一个NAT,它需要和ACL匹配,加解密等操作联 动,这些操作所依赖的IP地址和NAT发生了关联,因此基于Domain的NAT行为一定要位于路由行为的两边。由于Cisco是按照Domain即 inside/outside来进行配置的(在接口上应用特定Domain的规则),因此必然是这种设计方式,而对于Linux,NAT是全局的,接口只 是一个match而已,因此就完全按照路由的约束来设计。
        现在,我们可以来总结一下ip nat inside|outside source|destination的含义了。我把这个命令公式化:
ip nat P H
其 中H代表要做源转换还是要做目标转换,H还有一个更加隐蔽的含义,那就是它和P指名了数据的方向,也就是说:数据是以P为H的。举例,ip nat inside destination表示数据是以inside为目标的(来自outside),做目标地址转换;ip nat outside source表示数据是以outside为源发往inside的,做源地址转换。
4.Cisco的destination转换
但 是,但是如何对目标地址进行转换,即将访问一个公共Global地址时,将其转到一个内部的Local地址,这就是目的地址转换,也叫地址映 射,Cisco如何来做呢?实际上,很多Cisco设备的ISO版本不允许你像Linux那样无限制做DNAT,而仅仅允许映射特定的IP地 址+TCP/UDP端口对或者全IP。这肯定是在outside上做目标地址转换了,在相反的方向就是在inside上做源地址转换,即:
ip nat inside source static tcp $local_ip $local_port $global_ip $global_port
注意,必须是static的NAT,这涉及到下一节要说的“如何安装NAT”
        对于TCP负载均衡做的ip nat inside destination这种定制化的NAT则不在本文讨论范围内。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。