P2P 之 UDP穿透NAT的原理与实现(附源代码)
星期二, 十一月 9. 2004
原创:shootingstars 来自:p2p中国
参考:http://midcom-p2p.sourceforge.net/draft-ford-midcom-p2p-01.txt
有没有见过P2P的木马啊?代码我缩减了~由于BLOG看不了这么多
首先先先容一些基本观点:
NAT(Network Address Translators),网络地点转换:网络地点转换是在IP地点日益缺乏的情况下产生的,它的主要目标就是为了可以或许地点重用。NAT分为两大类,基本的NAT和NAPT(Network Address/Port Translator)。
最开端NAT是运行在路由器上的一个功效模块。
最先提出的是基本的NAT,它的产生基于如下究竟:一个私有网络(域)中的节点中只有很少的节点需要与外网毗连(呵呵,这是在上世纪90年月中期提出的)。那么这个子网中其实只有少数的节点需要环球唯一的IP地点,其他的节点的IP地点应该是可以重用的。
因而,基本的NAT完成的功效很简单,在子网内使用一个保存的IP子网段,这些IP对外是不可见的。子网内只有少数一些IP地点可以对应到真正环球唯一的IP地点。要是这些节点需要访问外部网络,那么基本NAT就负责将这个节点的子网内IP转化为一个环球唯一的IP然后发送出去。(基本的NAT会转变IP包中的原IP地点,但是不会转变IP包中的端口)
关于基本的NAT可以参看RFC 1631
别的一种NAT叫做NAPT,从名称上我们也可以看得出,NAPT不但会转变经过这个NAT设备的IP数据报的IP地点,还会转变IP数据报的TCP/UDP端口。基本NAT的设备可能我们见的不多(呵呵,我没有见到过),NAPT才是我们真正讨论的配角。看下图:
Server S1
18.181.0.31:1235
|
^ Session 1 (A-S1) ^ |
| 18.181.0.31:1235 | |
v 155.99.25.11:62000 v |
|
NAT
155.99.25.11
|
^ Session 1 (A-S1) ^ |
| 18.181.0.31:1235 | |
v 10.0.0.1:1234 v |
|
Client A
10.0.0.1:1234
有一个私有网络10.*.*.*,Client A是其中的一台盘算机,这个网络的网关(一个NAT设备)的外网IP是155.99.25.11(应该另有一个内网的IP地点,比如10.0.0.10)。要是Client A中的某个历程(这个历程创建了一个UDP Socket,这个Socket绑定1234端口)想访问外网主机18.181.0.31的1235端口,那么当数据包通过NAT时会发生什么事变呢?
首先NAT会转变这个数据包的原IP地点,改为155.99.25.11。接着NAT会为这个传输创建一个Session(Session是一个抽象的观点,要是是TCP,大概Session是由一个SYN包开端,以一个FIN包竣事。而UDP呢,以这个IP的这个端口的第一个UDP开端,竣事呢,呵呵,大概是几分钟,大概是几小时,这要看具体的完成了)并且给这个Session分配一个端口,比如62000,然后转变这个数据包的源端口为62000。以是本来是(10.0.0.1:1234->18.181.0.31:1235)的数据包到了互联网上变为了(155.99.25.11:62000->18.181.0.31:1235)。
一旦NAT创建了一个Session后,NAT会记着62000端口对应的是10.0.0.1的1234端口,以后从18.181.0.31发送到62000端口的数据会被NAT自动的转发到10.0.0.1上。(注意:这里是说18.181.0.31发送到62000端口的数据会被转发,其他的IP发送到这个端口的数据将被NAT抛弃)如许Client A就与Server S1建立以了一个毗连。
呵呵,上面的基础知识可能很多人都知道了,那么下面是要害的部门了。
看看下面的情况:
Server S1 Server S2
18.181.0.31:1235 138.76.29.7:1235
| |
| |
+----------------------+----------------------+
|
^ Session 1 (A-S1) ^ | ^ Session 2 (A-S2) ^
| 18.181.0.31:1235 | | | 138.76.29.7:1235 |
v 155.99.25.11:62000 v | v 155.99.25.11:62000 v
|
Cone NAT
155.99.25.11
|
^ Session 1 (A-S1) ^ | ^ Session 2 (A-S2) ^
| 18.181.0.31:1235 | | | 138.76.29.7:1235 |
v 10.0.0.1:1234 v | v 10.0.0.1:1234 v
|
Client A
10.0.0.1:1234
接上面的例子,要是Client A的原来谁人Socket(绑定了1234端口的谁人UDP Socket)又接着向别的一个Server S2发送了一个UDP包,那么这个UDP包在通过NAT时会怎样样呢?
这时可能会有两种情况发生,一种是NAT再次创建一个Session,并且再次为这个Session分配一个端口号(比如:62001)。别的一种是NAT再次创建一个Session,但是不会新分配一个端口号,而是用原来分配的端口号62000。前一种NAT叫做Symmetric NAT,后一种叫做Cone NAT。我们盼望我们的NAT是第二种,呵呵,要是你的NAT恰好是第一种,那么很可能会有很多P2P软件失灵。(可以庆幸的是,现在绝大少数的NAT属于后者,即Cone NAT)
好了,我们看到,通过NAT,子网内的盘算机向外保持是很容易的(NAT相称于通明的,子网内的和外网的盘算机不消知道NAT的情况)。
但是要是外部的盘算机想访问子网内的盘算机就比力困难了(而这正是P2P所需要的)。
那么我们要是想从外部发送一个数据报给内网的盘算机有什么措施呢?首先,我们必须在内网的NAT上打上一个“洞”(也就是前面我们说的在NAT上建立一个Session),这个洞不克不及由外部来打,只能由内网内的主机来打。并且这个洞是有偏向的,比如从外部某台主机(比如:192.168.0.10)向外部的某个IP(比如:219.237.60.1)发送一个UDP包,那么就在这个内网的NAT设备上打了一个偏向为219.237.60.1的“洞”,(这就是称为UDP Hole Punching的技能)以后219.237.60.1就可以通过这个洞与内网的192.168.0.10联系了。(但是其他的IP不克不及利用这个洞)。
呵呵,现在该轮到我们的正题P2P了。有了上面的理论,完成两个内网的主机通讯就差最后一步了:那就是鸡生蛋照旧蛋生鸡的问题了,双方都无法自动收回毗连请求,谁也不知道谁的公网地点,那我们如何来打这个洞呢?我们需要一个中心人来联系这两个内网主机。
现在我们来看看一个P2P软件的流程,以下图为例:
Server S (219.237.60.1)
|
|
+----------------------+----------------------+
| |
NAT A (外网IP:202.187.45.3) NAT B (外网IP:187.34.1.56)
| (内网IP:192.168.0.1) | (内网IP:192.168.0.1)
| |
Client A (192.168.0.20:4000) Client B (192.168.0.10:40000)
首先,Client A登录办事器,NAT A为这次的Session分配了一个端口60000,那么Server S收到的Client A的地点是202.187.45.3:60000,这就是Client A的外网地点了。异样,Client B登录Server S,NAT B给这次Session分配的端口是40000,那么Server S收到的B的地点是187.34.1.56:40000。
此时,Client A与Client B都可以与Server S通信了。要是Client A此时想直接发送信息给Client B,那么他可以从Server S那边获得B的公网地点187.34.1.56:40000,是不是Client A向这个地点发送信息Client B就能收到了呢?答案是不可,由于要是如许发送信息,NAT B会将这个信息抛弃(由于如许的信息是不速之客的,为了宁静,大少数NAT都会执行抛弃行动)。现在我们需要的是在NAT B上打一个偏向为202.187.45.3(即Client A的外网地点)的洞,那么Client A发送到187.34.1.56:40000的信息,Client B就能收到了。这个打洞命令由谁来发呢,呵呵,当然是Server S。
总结一下这个过程:要是Client A想向Client B发送信息,那么Client A发送命令给Server S,请求Server S命令Client B向Client A偏向打洞。呵呵,是不是很绕口,不过没干系,想一想就很明白了,何况另有源代码呢(侯老师说过:在源代码面前没有机密 8)),然后Client A就可以通过Client B的外网地点与Client B通信了。
注意:以上过程只适合于Cone NAT的情况,要是是Symmetric NAT,那么当Client B向Client A打洞的端口已经重新分配了,Client B将无法知道这个端口(要是Symmetric NAT的端口是次序分配的,那么我们或许可以推测这个端口号,但是由于可能导致失败的要素太多,我们不保举这种推测端口的要领)。
下面是一个模仿P2P谈天的过程的源代码,过程很简单,P2PServer运行在一个拥有公网IP的盘算机上,P2PClient运行在两个不同的NAT后(注意,要是两个客户端运行在一个NAT后,本程序很可能不克不及运行正常,这取决于你的NAT是否支持loopback translation,详见http://midcom-p2p.sourceforge.net/draft-ford-midcom-p2p-01.txt,当然,此问题可以通过双方先尝试毗连对方的内网IP来解决,但是这个代码只是为了验证原理,并没有处理这些问题),后登录的盘算机可以获得先登录盘算机的用户名,后登录的盘算机通过send username message的款式来发送音讯。要是发送乐成,阐明你已取得了直接与对方毗连的乐成。
程序现在支持三个命令:send , getu , exit
send款式:send username message
功效:发送信息给username
getu款式:getu
功效:获恰以后办事器用户列表
exit款式:exit
功效:注销与办事器的毗连(办事器不会自动监测客户是否吊线)
代码很短,相信很容易懂,要是有什么问题,可以给我发邮件zhouhuis22@sina.com 或者在CSDN上发送短音讯。同时,接待转发此文,但希望保存作者版权8-)。
http://www.ppcn.net/upload/2004_05/04052509317298.rar
- 文章作者: 福州军威计算机技术有限公司
军威网络是福州最专业的电脑维修公司,专业承接福州电脑维修、上门维修、IT外包、企业电脑包年维护、局域网网络布线、网吧承包等相关维修服务。
版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章原始出处 、作者信息和声明。否则将追究法律责任。
TAG:
评论加载中...
|