UDP打洞的一种简单实现

于近日, 差不多制作完成了一台对于一部分NAT适用(绝非普适)的打洞机, 现简述工作流程如下

设客户端: C1, C2, 打洞服务器: S。

1. C1 & C2请求连接S, 并且验证连接密码等信息。

S返回相应ID值给C1 & C2, C1 & C2记录。

2. C1 & C2凭ID使用UDP向S发送一个数据报, S记录它们的Endpoint。

以C1主动向S发起向C2的连接请求为例。

3. C1主动向S发起向C2的连接请求, S回复C1一个ack, 并将C2的Endpoint告知C1, 同时将C1的Endpoint告知C2。

4. C1 & C2同时开始接受UDP数据报

C1 & C2同时开始向对方发送数据报。

C1的NAT(可能不止一层)感觉到了C1发给C2(的NAT(可能不止一层))的数据报, 于是给C2(的NAT(可能不止一层))开放了C1向S提交所用的端口(有的NAT好像会变端口)。

C2同理, 于是C1的NAT(可能不止一层)和C2的NAT(可能不止一层)互相开放了端口, 于是打洞成功。

可是某些NAT可能会改变端口, 所以我们需要C1 & C2定时(间隔很小)发送心跳包给对方, 接收到心跳包要返回ack, 顺便记录接收到的Endpoint以便下次发送之用。

UDP也许不稳定, 于是需要自己撰写个简单的比较可靠的基于UDP的传送数据报的协议, 我的实现大概是如下:

1. C1发送数据给C2, 并开始等待ack

2.1. C2收到数据, 校验通过后发给C1一个ack

C1收到ack, 完

2.2. C2没有收到数据或者发送的ack丢了或者网速太慢以至于C1超时, C1回到1步骤。

不用UPnP原因:

1. 好像不支持多重NAT

2. NAT关闭UPnP服务就完蛋了

3. UPnP被妖怪利用就不好了

好像还有个NAT-PMP, 不过好像支持它的路由器不多。

TCP打洞已跪。

发表评论?

7 条评论。

  1. 欢迎一起讨论有关p2p的想法。

  2. 请问楼主心跳包是指的是在客户端间互相发送心跳包吗?还是在客户端向服务端发送?

发表评论

注意 - 你可以用以下 HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

:wink: :twisted: :roll: :oops: :mrgreen: :lol: :idea: :evil: :cry: :arrow: :?: :-| :-x :-o :-P :-D :-? :) :( :!: 8-O 8)

本文链接:https://twd2.me/archives/4397QrCode