为什么在VMWare的NAT模式下无法使用traceroute

traceroute是一个神奇,其历史悠久到足以跟UNIX相比肩,它工作在IP层,由于IP是一个无状态的协议,因此traceroute对其返回的结果的正确性甚至能否返回结果不予保证,这在某些场景下会造成困扰。
        最大的困扰是,它在某种场景下根本不可用,而你却无法区分这是真的不可用还是正如文档中所说,某些设备会禁止ICMP所以不会返回结果。
        我来直接切入正题,traceroute在VMWare的NAT模式下不可用。但是这是为什么?本文来解释。

1.VMWare的NAT是一个七层的NAT

我们先来做一个实验。在VMWare中telnet一个地址,我们仍以网络测试三大神器(ping,traceroute,baidu)之一的baidu为目标,在VMWare里面以及其宿主机同时抓包:

首先展示一下GuestOS Linux上的命令和抓包结果:




然后我们看一下Windows宿主机上的抓包结果:




很显然NAT转换了数据流的源地址,转成了宿主机的无线网卡的地址,然而我们注意后面这幅图上的注释,存在三处不一致,这就表明这个NAT是一个七层NAT。如果不理解这个,我就简要说明一下:
1).协议栈的IP层在每发出一个数据包时,其IPID字段在Linux实现中是针对每四层协议递增的
TCP,UDP等均会维护自身的IPID字段的空间,只要有一个TCP段发出,不管是哪个连接的,不管是不是重传的,其IPID字段均会递增地取TCP协议的ID字段空间的值。该字段是针对主机的,即IP报文被封装的那台设备。中间二层,三层路由器/交换机等均不会修改该字段,如果发现该字段在发送端和接收端对于同一个包不一致,那就有相当巨大的概率表明数据包在中间遇到了高层设备的”整改“。
2).IPTTL字段就不解释了,它只会沿途每经过IP层设备时均会递减
即便不经过IP层设备,它也不会递增。因此可以断定,宿主机肯定是对Linux发出的数据包进行了大大的整改。
3).端口号改变了
这个很正常,在经过NAT设备的时候,为了保证五元组的唯一性,源端口号是可以被修改的。


以上就可以表明VMWare的NAT确实不是一个IP层的NAT,而是一个更高层的NAT。    

        但是这不足以打消质疑者们的怀疑...
        其实,通过在Windows宿主机上执行netstat,可以很清楚地看到,是Windows宿主机自己与远端的baidu地址建立了TCP连接,而不仅仅是转换一个地址:

大家都能很清楚的看到,TCP连接的端到端是维持在baidu和Windows宿主机之间的,有了这个无需洪荒之力便可下结论:VMWare的NAT是一个七层的NAT!
        然而,除了TCP之外的其它协议怎样呢?

2.VMWare的NAT只支持比较常见的协议

我们试一下ICMP,还是用baidu,这次用ping。




具体的实验自己做一下就知道。如果你分析ICMP Reply的话,就会发现,这个Reply事实上是Windows宿主发出的。

        证明工作到此为止,下面开始阐释原理。
        细心深挖一下,我们会发现任务管理器中有一个叫做VMware_NAT_Service的服务,其实背后就是一个进程,进程的名字是vmnat,都是一回事。这个进程是干什么的呢?这就是实现NAT的所谓”代理“!
关于具体的原理,我还是希望能从我在2012年的时候几篇文章中得到启发:
深入浅出VMware的组网模式
vmware的vmnet-感官和视觉上的效果
VMware Fusion中使用迅雷的问题
然而,你能指望vmnat这个进程实现所有的TCP/IP协议族的地址转换吗?事实上这是不可能的!即便是操作系统的协议栈,在NAT这个话题上也会面临不少问题,以Linux为例,其NAT依赖nf_conntrack这个Netfilter HOOK,它对大部分协议支持的很好,但是你要知道的是,之所以可以支持大部分协议是因为nf_conntrack维护的五元组信息可以映射大部分的双向流量,然而总有例外,我们来考虑一些带外流量,即中间设备或者目的地发出的那种”并非请求协议本身的但是与其相关的控制报文“,典型的如ICMP数据。比如如果一个telnet 1.1.1.1 80的SYN经过这么一个设备,如果返回了1.1.1.1 80的SYN-ACK,那么根据conntrack表项信息可以将地址很完美的映射回去,然而如果返回的不是SYN-ACK,而是ICMP Port unreachable信息的话,怎么确保这个ICMP可以跟之前保存的那个telnet 1.1.1.1 80的SYN创建的conntrack表项对应从而将其路由给正确的源,这就是问题。
        Linux是怎么解决这个问题的呢?请思考!
        ...(此处我也不知道该略去多少字...虽然我可以自称Netfilter以及nf_conntrack专家,但是我却从来没有写过关于带外的ICMP数据包反向NAT的文章)
        Linux完美解决了这个问题,总结一句话就是:基于状态的NAT要记录发起者的五元组信息,因此对于带外流量,困境就是“正向方向转换源地址容易,反向的带外流量转换目标地址难”,Linux的解决方案是,使用related表!
        vmnat必须也面临这个问题!遗憾的是,vmnat并没有解决它。
        我准备在另外的文章中详细阐述Linux nf_conntrack对带外ICMP信息的处理,因此本文就此打住!(对于好酒之徒,且距离相近,当面聊这些要比写文章轻松得多!)

3.VMWare在NAT模式下的traceroute

现在我们来解开谜底。
        首先,我来纠正几个错误。
        很多人都发现了这个问题,但是解决的人并不多,也有人提出了自己的猜想,但是这种猜想是错误的。很多人发现了VMWare的NAT会整个的替换IP协议头,但是却不曾想过它替换头的操作实际上是通过socket完成的。正常的NAT是不会触动除了IP地址和端口之外的其它字段的!即便是在国外的论坛上,当有人提到VMWare下无法使用traceroute的时候,也没有人能点到痛处。
        很多人的回答是“Windows使用ICMP作为探测,而Linux使用UDP,只要使用-I参数就好了...”但是这解决不了问题,不信你自己在VMWare的NAT模式下试试...

        大部分人认为,作为宿主机的Windows(其实MacOS或者Linux也一样),其vmnat进程会替换掉整个IP头,忽略了这是一个traceroute探测这么“应用层”的语义,然后就把TTL换成自己的默认值了,比如这个在Windows上是128,因此你会发现,不管在Guest上traceroute谁,都是两跳直达!这个解释很合理,然而本着工匠精神,我们最有力的证据就是数据包,通过数据包,我们可以发现,vmnat并没有修改TTL,TTL exceeded这个ICMP error确实也回到了宿主机,之所以NAT后面的Guest无法正确显示,是因为:vmnat没有将这个信息转发给Guest!在VMWare的Guest主机内来执行traceroute,很自然,我们依然用baidu:



很多细节我并没有用带有颜色框框把它框住,看到此处的人一定知道自己该注意什么。只是看我的分析没有用,自己动手做一下就什么都明白了。
        我们猜想一下,为什么vmnat没有将这个ICMP time exceeded信息路由给GuestOS。原因很简单,是因为这个并不是很容易!然而也不是很难的事。以Linux的做法为经验完全可以分分钟搞定。vmnat收到的ICMP time exceeded信息的发起源并不是真实目标,而是IP路径当中的某一个设备的IP地址,试问仅仅依靠ICMP头怎么跟“保存在vmnat内部的conntrack表对应”?其实很简单,了解ICMP的都知道,ICMP天生就携带了出错包的原始片段(ECHO除外!),只需要进一步解析其内容就好了嘛!下面是一个解释:



这个问题我在2013年的时候曾经反馈给了VMWare,得到的答复是让我使用Bridge,毕竟是财大气粗的公司啊,如此霸气!我可以说我不用VMWare吗?不能,因为我买不起物理机!再说Bridge模式更加适合组网模式,它几乎完全等同于物理子网,然而NAT模式却受制于一个VMWare公司自己的vmnat进程(MacOS/Linux下好像叫做xxnatd,我面对迅雷问题的时候折腾过这),这怎么看也是不值得信任的。

        如此,我们知道了在使用VMWare NAT模式的时候,traceroute是不会正常工作的,而且我们也知道了其实VMWare的NAT是由一个应用进程完成的,这显然是它实现功能不完全的一个借口。
        然而,也许你会进一步去怀疑Linux是怎么做的,它的做法完美吗,它又是怎么将一个ICMP错误信息关联到一个TCP流或者UDP包的,这个且听下回分解。
  • 11
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值