本文内容主要整理自胡军、周剑扬、师佳三位老师的论文《P2P 网络中 UPnP 穿越 NAT 的研究与实现》,并结合个人理解进行排版优化,仅供学习使用。
0. 引言
在 IPv4 的地址空间日益紧张的背景下,网络地址转换(NAT)技术被广泛应用以实现 IP 地址的重用。这虽然缓解了地址枯竭问题,但也给 P2P (Peer-to-Peer) 应用带来了巨大的通信障碍:
- 单向访问:位于 NAT 后面的内网节点(拥有私有 IP)可以主动访问公网,但公网节点无法主动访问内网节点。
- 服务限制:内网节点无法作为服务端为公网提供服务。
为了解决这些问题,学术界和工业界提出了多种 NAT 穿越方案,如服务器转发、反向连接以及 UDP 打洞等。本文将重点介绍一种利用 UPnP (Universal Plug and Play) 技术,通过其自动端口映射 (Auto-Port-Mapping) 功能来实现 NAT 穿越的方案。
1. UPnP 穿越 NAT 的原理与实现
1.1 核心原理
UPnP 穿越 NAT 的核心思想是:在 NAT 设备上动态地创建一个临时的”端口转发”规则。
具体流程如下:
- 内网的客户端程序通过 UPnP 协议,请求其所在的 NAT 设备(通常是路由器)将某个公网端口(如
8081)的所有流量,转发到该客户端的内网 IP 和指定端口(如192.168.1.100:8080)。 - 客户端将这个成功映射的公网 IP 和端口(
公网IP:8081)注册到一个公网服务器上。 - 当另一个 P2P 节点(例如节点 B)想要与这个客户端(节点 A)通信时,它从公网服务器获取节点 A 注册的公网地址信息。
- 节点 B 直接向节点 A 的
公网IP:8081发送数据,NAT 设备会根据之前创建的映射规则,自动将数据转发给内网的节点 A,从而实现穿越。
1.2 自动端口映射的程序设计
根据 UPnP 规范,实现自动端口映射主要涉及以下几个步骤:
发现 (Discovery)
- 客户端向 UPnP 的标准多播地址
239.255.255.250:1900发送一个M-SEARCH查找请求。 - 网络中支持 UPnP 的 NAT 设备(路由器)会响应这个请求,并回复一个包含设备描述文件 URL 的消息。
- 客户端向 UPnP 的标准多播地址
描述 (Description)
- 客户端通过上一步获取的 URL,下载一个 XML 格式的设备描述文件。
- 解析这个 XML 文件,可以得到设备的详细信息,包括设备类型、服务列表以及最重要的——控制 URL。
控制 (Control)
- 客户端向第二步获取的控制 URL 发送一个遵循 SOAP 协议的 XML 控制消息。
- 通过发送不同的控制消息,可以实现端口映射的增加 (AddPortMapping)、删除 (DeletePortMapping) 或查询 (GetPortMapping) 等操作。
原论文作者将这些功能用 C++ 封装成了一个名为 upnpd.dll 的动态链接库,以便于客户端程序调用。
2. 系统两端的程序设计
2.1 服务器端
服务器在整个方案中扮演”中间人”的角色,其功能相对简单:
- 记录所有客户端登录时注册的公网端口映射信息。
- 处理客户端的登录、登出请求。
- 响应客户端获取其他在线用户列表的请求。
这种方式极大地减轻了服务器的负担,避免了在服务器上直接转发所有 P2P 流量,节约了服务器资源和带宽。
2.2 客户端
客户端的功能则相对复杂:
- 启动后,创建一个本地 Socket 并绑定到固定端口(如
8080)。 - 连接公网服务器,并从服务器获取经过 NAT 转换后的公网 IP 和端口(如
公网IP:8081)。 - 判断自身是否位于 NAT 之后。如果是,则调用
AddPortMapping函数,请求路由器将公网端口8081映射到内网端口8080。 - 通过
Getu命令从服务器获取在线用户列表。 - 通过
Send命令与其他客户端直接通信。 - 退出时,通过
Exit命令调用DeletePortMapping函数,删除之前建立的端口映射。
3. 结论
使用 UPnP 的自动端口映射功能进行 NAT 穿越,是一种高效且可靠的 P2P 通信方案。它适用于客户端位于单个 NAT 之后的多种网络情况。
此方案建立的端口映射通常是静态的,即使用户在一段时间内没有数据收发,映射关系也不会被 NAT 设备自动收回。这保证了 P2P 连接的稳定性和可靠性,是实现真正意义上直接通信的关键。
4. 参考文献
- UPnP 论坛贡献成员. PnP 设备架构[S]. UPnP 标准组织委员会, 2000: 2-11.
- 林丽闽, 别红霞等译. 标准 C++宝典[M]. 北京: 电子工业出版社, 2001.
- Bryan Ford, Pyda Srisuresh, Dan Kegel. Peer-to-Peer(P2P) Communication Across Network Address Translators(NATs) [DB/OL]. 2004-12-12.
- 李河, 王树明. P2P 网络中使用 UDP 穿越 NAT 的方法研究[J]. 吉林大学学报(信息科学版), 2003, 21(3).
- 刘扬, 董开坤, 刘杨, 迟乐军. 对等网络中穿越 NAT 解决方案的研究[J]. 计算机工程与设计, 2008, 6(29).