先罗列下我的需求,有两台机器,一台windows 7,另一台mac,现在想在这两个机器间自动同步文件。两台机器位于不同的私有子网段,也就是说,躲在两个不同的路由器后面接入公网。

因为nat的存在,使得两台机器间直接建立tcp连接成为不可能,想了几个方案:

第一,通过一台有公网ip的机器中转,两台机器同时跟这台服务器建立tcp连接,定时交换文件时间戳并相应的更新。这种方案存在巨大的弊端,我的服务器在美国,两台挨在一起的机器,传送数据居然需要绕过层层路由跨过海底光缆传送到大洋彼端然后再传回来,速度慢,占带宽,太折腾。

第二种就是udp打洞了,假设两台机器分别为A和B,中转机器为S,这样A和B都可以向S发送UDP数据包了,S可以得到NAT转换后的ip和端口号,由于UDP不是面向连接的,任何主机都可以向这个ip和端口号发送数据。理论上讲,只要S把这些信息告诉A和B,这两台机器就可以直接通信了。但是因为安全性的考虑,如果这个数据包的ip和端口号不是先前发给S的那个地址,就会被路由器丢弃。如何取得路由器的信任,是打洞最需要解决的问题。一个简单的想法是,A向B的NAT转换后的地址发送一个udp包,这样A的NAT对于B的这个地址就是敞开的了,如果B能发出具有这样地址的包,二者之间的连接就能建立起来。

今天花了一个下午编写调试相应的代码,A和B之间的数据包始终不能成功接收,后来才意识到,A向B再次发送数据包的时候,NAT路由器会重新生成不同的端口号,换了个端口向S发包测试打印地址印证了这个想法,这个端口号似乎是随机生成的。

google了下,有些路由器确实是这样实现的,这种情况下UDP打洞基本不可行。

总之,问题没那么圆满的解决,最终还是使用方案一中转,先只同步小文件吧,至少比手动拷方便些。

客观评价下NAT对互联网的影响吧,好的方面:解决了ip地址快速耗尽的问题,估计延缓了一二十年。也提高了安全性,某种程度把病毒隔离在一个个子网范围内。

另一方面,把端口号扩展为ip地址的一部分,本身就是一种很踅脚的做法,增加了软件的复杂度。一个好的设计应该简单统一,不应该让人在实现的时候感到头疼。

在已有系统上缝缝补补,用最简单的改变来适应环境,是生物的进化的基本特征。互联网在遇到问题时的解决方案似乎也在重复着大自然的脚步。

还是希望ipv6早日普及吧。


发表评论

邮箱地址不会被公开。 必填项已用*标注