只要存在 Symmetric NAT 就无法打洞(穿透)了对吗?

2017-02-09 22:01:56 +08:00
 RE

1. 不算猜端口;

2. 不算中转服务器流量转发;

是不是只要某一方是 Symmetric NAT 就无法打洞(穿透)?
如果确实是这样,那希望后来者看到这篇文章之后,不用跟我一样执念于寻找 NAT 穿透方案了

15722 次点击
所在节点    问与答
9 条回复
zk8802
2017-02-10 06:08:55 +08:00
猜端口应该是唯一的解决方案了。但是猜端口的成功率也可以很高的,参见 http://www.goto.info.waseda.ac.jp/~wei/file/wei-apan-v10.pdf
RE
2017-02-10 14:02:55 +08:00
@zk8802 但网上有个说法是猜端口就算猜到了,能用多久也要看 NAT 设备,有可能就只有几分钟。而且如果双方都是 Symmetric NAT 则连猜端口都不行。
zk8802
2017-02-11 06:19:28 +08:00
你可以自己试一下。我之前尝试的时候没遇到你所说的问题。

> 而且如果双方都是 Symmetric NAT 则连猜端口都不行。

为什么?根据我的理解,只有对称 NAT 才需要猜端口吧?
linxy19957
2017-04-09 11:55:05 +08:00
如果有一方是完全锥形,我觉得应该还是可以的吧
A 是完全锥形, B 是对称
A 向公网服务器发送数据包,打洞
公网服务器告诉 B A 的地址和端口
B 连接 A , A 接收到 B 的包,也就知道了 B 的地址和端口
RE
2017-04-09 12:04:21 +08:00
@linxy19957 主题里有两行加粗的,不看吗……
linxy19957
2017-04-09 12:08:35 +08:00
@RE 没懂,我没有猜端口,公网服务器也只是沟通一下双方地址端口,不是在转发流量呀
newbie666
2017-09-13 08:08:19 +08:00
一楼 pdf 中介绍的对称 NAT 的穿透方法,我找到了具体实现的源码。
看了下源码,就是用了端口预测还有生日攻击算法。
https://github.com/jflyup/nat_traversal
我下载后进行了测试,但源码只实现了两个对称 nat 之间的打洞。
而我的环境,一个是 symmetric NAT,另外一个是 port-restricted cone。用以上的代码测试没有成功。
看哪位大牛再能修改完善下,再做成一个库,那就完美了。
foxset
2020-02-20 16:25:15 +08:00
自己是对称型 NAT,如果对方是全锥型、限制锥型,还是可以打通的
但是对方是对称型、端口限制锥型,那就只能靠猜了
AlexGuo1998
2021-06-28 16:54:46 +08:00
前几天刚好发现这个问题,仔细研究了一下。
如果允许猜测的话,不妨把对称性 NAT 分为端口有规律和无规律两种,其中端口有规律定义为“可以在一定程度上预测下几次连接的外部端口”,端口无规律定义为“多次连接中内部端口、目标 IP 、目标端口任意一个变化时,外部端口在几乎全部范围内随机变化”,则一共有五种 NAT 。
甲:全锥形 乙:IP 限制锥形 丙:IP 和端口限制锥形 丁:有规律对称性 戊:无规律对称性(用甲乙丙丁戊来标识是为了防止和别处定义的 NAT 类型混淆)
甲和乙自然不必多说,可以和任意其他 NAT 连接;丙和丙之间也没有问题。剩下五组传统意义上都是不可能的,考虑猜测和概率的情况分别讨论:

丙丁:丙针对某一内部端口有确定的外部端口( a ),丁可以预测下一次连接的外部端口( b )。丙用 a 连接丁的 b,丁连接丙的 a 。此时很有可能丁使用的外部端口是 b,即打通。
为了增加成功率,丙可以用 a 连接多个丁的外部预测端口( b1, b2...),则丁使用任意一个外部端口时都可打通。

丁丁:两边都用多个内部端口连接对方的预测外部端口(不一定是下一次的外部端口,可能是几次后的)。
不妨记丁 1 的预测端口为 a,丁 2 的预测端口为 b,开始连接时,因为使用不同的内部端口,对称 NAT 会分配不同的外部端口,即丁 1 用( a1, a2...)连接丁 2 的 b,丁 2 用( b1, b2...)连接丁 1 的 a 。
只要 a 在( a1, a2...)中且 b 在( b1, b2...)中,即打通。
这就是一楼论文说的“两个对称 NAT 连接”的方法,据作者所说,测试成功率非常高,接近 100%。我这里没有实测过。
顺便论文链接挂掉了,这里好像还能下载到: https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.455.3700

丙戊:理论上是可行的,但是需要同时开大量(几百个)端口,且与概率相关。
丙用同一个外部端口( a )连接多个戊的外部端口( c1, c2...),戊用多个内部端口连接丙的外部端口( a )。
戊的内部端口不重要,重要的是 NAT 对这些端口分配了不同的外部端口( b1, b2...)。这样只要( b1, b2...)和( c1, c2...)中有一个重叠即打通。
听起来概率好像很低,但是实际上算一下还是可能的:设丙开启 m 个连接,戊开启 n 个连接,可以用以下递推公式算出打通的概率:
P(m,n) = P(m,n-1) + (1-P(m,n-1))*m/(65535-(n-1)),其中 P(m,0) = 0 。取几个数字:m=n=213 时 P=50.07%; m=n=300 时 P=74.83%; m=n=500 时 P=97.86%; m=n=600 时 P=99.61%; m=n=700 时 P=99.95%。
经过仿真,公式计算结果与仿真结果一致。不过我这里没有做实际的测试,也许会遇到开太多端口被临时封杀的情况。

丁戊:在可操作的范围内可能性很低。
我唯一能想到的方法就是丁连接戊的多个随机端口( d1, d2...),戊按顺序连接丁的多个预测端口( c1, c2...)。
记丁实际使用的外部端口为( a1, a2...),戊实际使用的外部端口为( b1, b2...),即丁第 m 次连接使用外部端口 a_m 连接 d_m,戊第 n 次连接使用外部端口 b_n 连接 c_n 。
因为丁可预测,可知( a1, a2...)与( c1, c2...)之间有较大部分重叠,取使 a_m 与 c_n 相同的 mn,判断 d_m 和 b_n 是否相同,如果相同则打通。
如果预测足够精准,每次 d_m 和 b_n 相等的概率就是 1/65535,而次数之间独立,P(m)=1-(1-1/65535)^m 。m=45425 时 P=50%。
不过两边都不需要同时打开上千个端口,可能和下面相比还算有一点微小的可能性——

戊戊:在可操作的范围内不可能。因为两边都是对不同目标端口随机选择外部端口,要打通约等于两只无头苍蝇撞上。单次连接成功的概率为 1/(65535^2)。
(当然如果两边都开 65535 个端口还不被封杀,概率还是比较高的。仿真结果不到 50%)

纯手打,如果有错还请大家纠正。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/339415

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX