K
kkkchenA
Unregistered / Unconfirmed
GUEST, unregistred user!
3.3 UDP hole punching
第三种技术,也是这篇文章的一个重要点之一,就是被称为"UDP Hole Punching"的技术。当两个需要通讯的主机可能都在middlebox后面的时候,UDP hole punching依赖于cone NAT和普通防火墙的一些特性,允许合适的P2P应用程序以"punch holes"方式通过middlebox并且建立彼此之间直接的连接。这种技术在RFC 3027[NAT- PORT]的5.1节中简要的提及,并且在英特网[KEGEL]非证实的提到,也在最近的一些协议[TEREDO, ICE]中用到。正如名字中的所提到的,这种技术只能用于UDP连接。
我们将会考虑两个特别情况,并且考虑应用程序如何完善的处理两者之间的握手连接。第一种情况下,也是较为普通的情况,两个在不通的NAT后面的客户端要求直接的进行P2P连接。第二种情况,两台客户端位于同一个NAT后面,但不能肯定(两台客户端位于同一个NAT后面)。
3.3.1 位于不同NAT后面(Peers behind different NATs)
假设客户端A和B都有自己的私有IP地址,也都位于不同的NAT后面。P2P应用程序在A、B和服务器S上运行,用的都是UDP端口1234。A和B各自和服务器S建立UDP通讯连接,使NAT A为A的连接分配一个自己的公共端口62000,而NAT B为B的连接分配的是31000端口。
Server S
18.181.0.31:1234
|
|
+----------------------+----------------------+
| |
NAT A NAT B
155.99.25.11:62000 138.76.29.7:31000
| |
| |
Client A Client B
10.0.0.1:1234 10.1.1.3:1234
现在推想一下,客户端A想要直接和B建立一个UDP通讯会话。假设A简单的发一个UDP信息包到B的公共地址138.76.29.7:31000,然而NAT B将会丢弃这些进入的数据信息(除非它是一个FULL cone NAT),原因是NAT B和S已经建立的外部会话,而A发送的信息中的源地址和端口号是和S不匹配的(可以参照一下上面的内容,匹配才能接受)。同样,假如B发送一个条UDP数据包给A的公网地址,NAT A也会丢弃。
但是,假设A发出一个UDP数据信息给B的公网IP地址,同时也通过服务器S传递一个请求给B,要求B也发一个UDP信息给A的公网IP地址。A直接向B的公共IP地址(138.76.29.7:31000)发送的数据包会让NAT A在A的私有地址和B的公网地址之间建立了一个新的连接会话。同时,B到A的公网地址(155.99.25.11:62000)的信息会导致NAT B在B的私有地址和A的公共地址之间建立一个新的连接会话。一旦这种新的UDP连接在两者之间建立起来,客户端A和B就不需要服务器S的"介绍"就能彼此直接通讯了。
UDP hole punching技术有几个很有用的特点。一旦在两个位于middlebox后面的客户端建立了一个直接的P2P连接,在连接中的任何一方都可以扮演一个"介绍人"的角色,依次继续和另一个客户端建立连接,减少了最初的服务器S的负担。如果说有[STUN]的话,假如两个中的任意一个或两个都碰巧不在middlebox后面,上述应用程序将同样可以建立P2P通讯通道,应用程序不需要尝试明确middlebox的类型。Hole punching技术甚至可以自动的运用在多级NAT下面,多重NAT就是那些客户端需要经历多级地址转换才能进入公网。
3.3.2 位于同一NAT后(Peers behind the same NAT)
现在考虑两台客户端(但并不确定)都在同一个NAT后面的情况,因此会有私有IP地址空间。客户端A与服务器S建立一个UDP会话,NAT会分配一个公共端口62000。客户端B与服务器S也建立一个简单的连接,NAT为此分配一个公共端口62001。
Server S
18.181.0.31:1234
|
|
NAT
A-S 155.99.25.11:62000
B-S 155.99.25.11:62001
|
+----------------------+----------------------+
| |
Client A Client B
10.0.0.1:1234 10.1.1.3:1234
假想A和B使用UDP hole punching技术与服务器S的建立一个外部的通讯路线做为中间介绍。然后A和B将可以通过服务器S得到各自公共IP地址和端口号,然后使用这些地址各自向对方发送数据。两个客户能够以这种方式彼此通讯,只要NAT不仅仅允许外网上的主机可以和内网上的主机进行UDP传输会话,也可以允许内网上的主机可以和其他内网的主机进行UDP会话。我们在"loopback translation"中设计到这种情况,因为来自私有网络的数据包到达NAT后,会"looped back"到私有网络上就象从公网来的一样。例如,当A向B的公共IP地址发送一个UDP包,这个包的包头有一个源IP地址和端口,是10.0.0.1:1234,而目的地址是155.99.25.11.62001。NAT接受到这个包,会把源地址转换(映射)为155.99.25.11:62000(就是A的公网地址),把目的地址转换为10.1.1.3:1234,然后发给B。即使NAT支持回环映射,NAT的转换和发送步骤看上去是多余的,在A和B通讯时似乎为NAT添加了潜在的负担。
这个问题的解决方法是直接的。当A和B一开始在服务器S上交换地址信息时,它们就可以包含他们自己的IP地址和端口号,并且是可见的,对服务器S也是可见的。客户端根据它们得到的地址同时开始向对方发数据包,并建立成功的通讯。假如这两个客户端都在同一NAT后面,数据包象通讯一开始就能直接到达,而不需要通过NAT就能建立直接连接。假如这两个客户端位于不同的NAT后,到达彼此私有地址的数据包会被丢弃,但是客户端可以通过各自的公共地址来建立连接。重要的是这些数据包需要通过一些方法去鉴别,然而,在这种情况下,A发到B的私有地址的数据包完全有可能到达A私网内其他无关的终端,B发到A的包也是这样。
第三种技术,也是这篇文章的一个重要点之一,就是被称为"UDP Hole Punching"的技术。当两个需要通讯的主机可能都在middlebox后面的时候,UDP hole punching依赖于cone NAT和普通防火墙的一些特性,允许合适的P2P应用程序以"punch holes"方式通过middlebox并且建立彼此之间直接的连接。这种技术在RFC 3027[NAT- PORT]的5.1节中简要的提及,并且在英特网[KEGEL]非证实的提到,也在最近的一些协议[TEREDO, ICE]中用到。正如名字中的所提到的,这种技术只能用于UDP连接。
我们将会考虑两个特别情况,并且考虑应用程序如何完善的处理两者之间的握手连接。第一种情况下,也是较为普通的情况,两个在不通的NAT后面的客户端要求直接的进行P2P连接。第二种情况,两台客户端位于同一个NAT后面,但不能肯定(两台客户端位于同一个NAT后面)。
3.3.1 位于不同NAT后面(Peers behind different NATs)
假设客户端A和B都有自己的私有IP地址,也都位于不同的NAT后面。P2P应用程序在A、B和服务器S上运行,用的都是UDP端口1234。A和B各自和服务器S建立UDP通讯连接,使NAT A为A的连接分配一个自己的公共端口62000,而NAT B为B的连接分配的是31000端口。
Server S
18.181.0.31:1234
|
|
+----------------------+----------------------+
| |
NAT A NAT B
155.99.25.11:62000 138.76.29.7:31000
| |
| |
Client A Client B
10.0.0.1:1234 10.1.1.3:1234
现在推想一下,客户端A想要直接和B建立一个UDP通讯会话。假设A简单的发一个UDP信息包到B的公共地址138.76.29.7:31000,然而NAT B将会丢弃这些进入的数据信息(除非它是一个FULL cone NAT),原因是NAT B和S已经建立的外部会话,而A发送的信息中的源地址和端口号是和S不匹配的(可以参照一下上面的内容,匹配才能接受)。同样,假如B发送一个条UDP数据包给A的公网地址,NAT A也会丢弃。
但是,假设A发出一个UDP数据信息给B的公网IP地址,同时也通过服务器S传递一个请求给B,要求B也发一个UDP信息给A的公网IP地址。A直接向B的公共IP地址(138.76.29.7:31000)发送的数据包会让NAT A在A的私有地址和B的公网地址之间建立了一个新的连接会话。同时,B到A的公网地址(155.99.25.11:62000)的信息会导致NAT B在B的私有地址和A的公共地址之间建立一个新的连接会话。一旦这种新的UDP连接在两者之间建立起来,客户端A和B就不需要服务器S的"介绍"就能彼此直接通讯了。
UDP hole punching技术有几个很有用的特点。一旦在两个位于middlebox后面的客户端建立了一个直接的P2P连接,在连接中的任何一方都可以扮演一个"介绍人"的角色,依次继续和另一个客户端建立连接,减少了最初的服务器S的负担。如果说有[STUN]的话,假如两个中的任意一个或两个都碰巧不在middlebox后面,上述应用程序将同样可以建立P2P通讯通道,应用程序不需要尝试明确middlebox的类型。Hole punching技术甚至可以自动的运用在多级NAT下面,多重NAT就是那些客户端需要经历多级地址转换才能进入公网。
3.3.2 位于同一NAT后(Peers behind the same NAT)
现在考虑两台客户端(但并不确定)都在同一个NAT后面的情况,因此会有私有IP地址空间。客户端A与服务器S建立一个UDP会话,NAT会分配一个公共端口62000。客户端B与服务器S也建立一个简单的连接,NAT为此分配一个公共端口62001。
Server S
18.181.0.31:1234
|
|
NAT
A-S 155.99.25.11:62000
B-S 155.99.25.11:62001
|
+----------------------+----------------------+
| |
Client A Client B
10.0.0.1:1234 10.1.1.3:1234
假想A和B使用UDP hole punching技术与服务器S的建立一个外部的通讯路线做为中间介绍。然后A和B将可以通过服务器S得到各自公共IP地址和端口号,然后使用这些地址各自向对方发送数据。两个客户能够以这种方式彼此通讯,只要NAT不仅仅允许外网上的主机可以和内网上的主机进行UDP传输会话,也可以允许内网上的主机可以和其他内网的主机进行UDP会话。我们在"loopback translation"中设计到这种情况,因为来自私有网络的数据包到达NAT后,会"looped back"到私有网络上就象从公网来的一样。例如,当A向B的公共IP地址发送一个UDP包,这个包的包头有一个源IP地址和端口,是10.0.0.1:1234,而目的地址是155.99.25.11.62001。NAT接受到这个包,会把源地址转换(映射)为155.99.25.11:62000(就是A的公网地址),把目的地址转换为10.1.1.3:1234,然后发给B。即使NAT支持回环映射,NAT的转换和发送步骤看上去是多余的,在A和B通讯时似乎为NAT添加了潜在的负担。
这个问题的解决方法是直接的。当A和B一开始在服务器S上交换地址信息时,它们就可以包含他们自己的IP地址和端口号,并且是可见的,对服务器S也是可见的。客户端根据它们得到的地址同时开始向对方发数据包,并建立成功的通讯。假如这两个客户端都在同一NAT后面,数据包象通讯一开始就能直接到达,而不需要通过NAT就能建立直接连接。假如这两个客户端位于不同的NAT后,到达彼此私有地址的数据包会被丢弃,但是客户端可以通过各自的公共地址来建立连接。重要的是这些数据包需要通过一些方法去鉴别,然而,在这种情况下,A发到B的私有地址的数据包完全有可能到达A私网内其他无关的终端,B发到A的包也是这样。