UPNP端口映射简单流程


参考文档:
1.RFC 6970
https://www.rfc-editor.org/info/rfc6970

2.《UDA1.0-ChinesePDF.pdf》
http://read.pudn.com/downloads37/doc/comm/125876/UDA1.0-ChinesePDF.pdf

3.UPnP基本原理以及在NAT中的应用
https://blog.csdn.net/wuruixn/article/details/23920871

4.UPnP的介绍和理解
https://blog.csdn.net/be_happy_mr_li/article/details/52919759

5.UPnP的工作过程
https://blog.csdn.net/ocean181/article/details/7406816

6.upnp协议简介(一)
https://blog.csdn.net/braddoris/article/details/41646789

一些词语:
control point(控制点):在本文中可以理解为需要端口映射的设备,比如内网的一些子设备
root device(根设备):提供服务的设备,在本文中可以简单理解为路由器
IGD(Internet Gateway Device):网络网关设备,比如路由器

0 简介

参考文档介绍了UPNP的相关原理,接下来进行一个简单的实战,用于练练手。
我们在内网的设备只有内网的IP:PORT,因此公网设备无法主动和内网的设备进行主动连接。一个简单的方法便是使用UPNP端口映射,将内网设备的PORT(P1)映射到公网的PORT(P2),当其他公网设备主动和P2通信后,路由会将数据转发到P1上。

下面就UPNP的端口映射功能整个流程做个梳理。

1 寻址

所谓的寻址,简单来说就是设备能够连上网络,能够获取IP。

2发现

发现设备,在《UDA1.0-ChinesePDF.pdf》中,有如下描述:

当设备被添加到网络后, UPnP 发现协议允许该设备向网络中的控制点宣告其服务。同样,当一个控制点被添加到网络后,UPnP 发现协议允许该控制点在网上搜索感兴趣的设备。

所以当控制点添加到网络中后,会搜索局域网内支持UPNP协议的设备。在本文中,可理解为发现支持UPNP端口映射的路由器。

2.1 广播

设备需要向239.255.255.250:1900发送多播信息,用于搜索周围支持UPNP的设备多播信息如下:

M-SEARCH * HTTP/1.1
HOST: 239.255.255.250:1900
ST: urn:schemas-upnp-org:device:InternetGatewayDevice:1
MAN: "ssdp:discover"
MX: 2

各个字段含义如下:

SEARCH:SSDP定义的搜索请求方法
HTTP/1.1: HTTP版本
HOST: 由IANA为SSDP保留的多播信道和端口,必须为239.255.255.250:1900
MAN: 固定为"ssdp:discover",注意双引号不可少
MX: 最长等待时间,设备会在0和这个值之间随机选择延迟的值,用于均衡负载。
ST: 搜索目标,有以下类型:
	ssdp:all
		搜索所有设备和服务。
	UPnP:rootdevice
		只搜索根设备。
	uuid:device-UUID
		搜索特殊设备。设备 UUID 由 UPnP 厂商指定。
	urn:schemas-UPnP-org:device:deviceType:v 
		搜索同类设备。设备类型与版本由 UPnP 论坛工作委员会定义。 

2.2 响应

当设备收到多播消息后,会向控制点发送多播消息的源IP:PORT发送UDP响应,并回复给控制点信息。

HTTP/1.1 200 OK
CACHE-CONTROL: max-age=100
DATE: Wed, 04 Jan 2006 00:58:36 GMT
EXT:
LOCATION: http://192.168.2.1:1900/igd.xml
SERVER: Wireless N Router WR745N, UPnP/1.0
ST: urn:schemas-upnp-org:device:InternetGatewayDevice:1
USN: uuid:upnp-InternetGatewayDevice-192168123178900001::urn:schemas-upnp-org:device:InternetGatewayDevice:1

各个字段含义如下:

CACHE-CONTROL: 表示宣告有效持续时间,如果超过此时间,控制点可以认为设备或服务不再可用
DATE: 响应生成时间,此字段可以不使用
EXT:表示上面discover中的MAN标头已经被理解
LOCATION: 表示设备的UPNP描述的URL  
SERVER:记录设备的版本信息
ST: 搜索目标,取值如下:
	ssdp:all
		如果根设备带有 d 种嵌入式设备与 s 种嵌入服务且只有 K 种不同服务类型,那么其响应次数为 3+2d+k。 ST 标头值必须与采用ssdp:alive 的 NOTIFY 消息中的 NT 标头保持统一。
	UPnP:rootdevice
		向根设备响应一次。必须是 UPnP:rootdevice。
	uuid:device-UUID 
		向每种设备(根设备或嵌入式设备)响应一次。必须是uuid:device-UUID。设备 UUID 由 UPnP 厂商指定。
	urn:schemas-UPnP-org:device:deviceType:v
		向每种设备(根设备或嵌入式设备)响应一次。必须是urn:schemas-UPnP-org:device:deviceType:v。设备类型与版本由 UPnP 论坛工作委员会定义。 
	USN:服务名称,取值如下:
		uuid:device-UUID::UPnP:rootdevice
			向根设备发送一次。设备 UUID 由 UPnP 厂商指定。
		uuid:device-UUID 
			向每种设备(根设备或嵌入式设备)发送一次。 设备 UUID 由 UPnP厂商指定。
		uuid:device-UUID::urn:schemas-UPnP-org:device:deviceType:v
			向每种设备(根设备或嵌入式设备)发送一次。 设备 UUID 由 UPnP厂商指定。设备类型与版本由 UPnP 论坛工作委员会定义。 

在上面信息中心,有一个比较重要的便是LOCATION,在下面我们会通过这个设备描述URL来获取设备的服务。

至此,整个发现过程便结束了,控制点已经获取到了局域网内的设备信息。

3 描述

在发现设备之后,我们只是发现了设备,但是并不知道设备有什么服务,有什么功能等等。因此我们需要从上面设备发现的消息中获取设备描述URL,从而来获取设备的描述。

3.1 GET描述文件

控制点会和设备描述URL中的IP:PORT建立TCP连接,并GET获取xml数据。请求如下:

GET /igd.xml HTTP/1.1
Host: 192.168.2.1:1900
Connection: Close
User-Agent: Ubuntu/12.04, UPnP/1.1, MiniUPnPc/1.9

3.2 获取并解析XML描述文件

控制点会收到如下描述文件:

HTTP/1.1 200 OK
CONTENT-LENGTH: 2746
CONTENT-TYPE: text/xml
DATE: Wed, 04 Jan 2006 00:58:40 GMT
LAST-MODIFIED: Tue, 28 Oct 2003 08:46:08 GMT
SERVER: Wireless N Router WR745N, UPnP/1.0
CONNECTION: close

<?xml version="1.0"?>
<root xmlns="urn:schemas-upnp-org:device-1-0">
<specVersion>
<major>1</major>
<minor>0</minor>
</specVersion>
<URLBase></URLBase>
<device>
<deviceType>urn:schemas-upnp-org:device:InternetGatewayDevice:1</deviceType>
<presentationURL>http://192.168.2.1:80 </presentationURL>
<friendlyName >Wireless N Router WR745N</friendlyName>
<manufacturer >TP-LINK</manufacturer>
<manufacturerURL >http://www.tp-link.com.cn</manufacturerURL>
<modelDescription >TL-WR745N 1.0</modelDescription>
<modelName >TL-WR745N</modelName>
<modelNumber >1.0</modelNumber>
<UDN>uuid:upnp-InternetGatewayDevice-192168123178900001</UDN>
<UPC>123456789001</UPC>
<serviceList>
<service>
<serviceType>urn:schemas-upnp-org:service:Layer3Forwarding:1</serviceType>
<serviceId>urn:upnp-org:serviceId:L3Forwarding1</serviceId>
<controlURL>/l3f</controlURL>
<eventSubURL>/l3f</eventSubURL>
<SCPDURL>/l3f.xml</SCPDURL>
</service>
</serviceList>
<deviceList>
<device>
<deviceType>urn:schemas-upnp-org:device:WANDevice:1</deviceType>
<friendlyName>WAN Device</friendlyName>
<manufacturer >TP-LINK</manufacturer>
<manufacturerURL >http://www.tp-link.com.cn</manufacturerURL>
<modelDescription>WAN Device</modelDescription>
<modelName>WAN Device</modelName>
<modelNumber>1</modelNumber>
<modelURL></modelURL>
<serialNumber>12345678900001</serialNumber>
<UDN>uuid:upnp-WANDevice-192168123178900001</UDN>
<UPC>123456789001</UPC>
<serviceList>
<service>
<serviceType>urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1</serviceType>
<serviceId>urn:upnp-org:serviceId:WANCommonInterfaceConfig</serviceId>
<controlURL>/ifc</controlURL>
<eventSubURL>/ifc</eventSubURL>
<SCPDURL>/ifc.xml</SCPDURL>
</service>
</serviceList>
<deviceList>
<device>
<deviceType>urn:schemas-upnp-org:device:WANConnectionDevice:1</deviceType>
<friendlyName>WAN Connection Device</friendlyName>
<manufacturer >TP-LINK</manufacturer>
<manufacturerURL >http://www.tp-link.com.cn</manufacturerURL>
<modelDescription>WAN Connection Device</modelDescription>
<modelName>WAN Connection Device</modelName>
<modelNumber>1</modelNumber>
<modelURL></modelURL>
<serialNumber>12345678900001</serialNumber>
<UDN>uuid:upnp-WANConnectionDevice-192168123178900001</UDN>
<UPC>123456789001</UPC>
<serviceList>
<service>
<serviceType>urn:schemas-upnp-org:service:WANIPConnection:1</serviceType>
<serviceId>urn:upnp-org:serviceId:WANIPConnection</serviceId>
<controlURL>/ipc</controlURL>
<eventSubURL>/ipc</eventSubURL>
<SCPDURL>/ipc.xml</SCPDURL>
</service>
</serviceList>
</device>
</deviceList>
</device>
</deviceList>
</device>
</root>

部分字段含义如下:

UDN:全球唯一设备标识符
serviceType:UPNP服务类型。 

在上面的报文中,有WANIPConnection/Layer3Forwarding/WANCommonInterfaceConfig等服务类型。其中,WANIPConnection便是我们下面端口映射需要的服务,关于这个描述,有如下定义:

此服务类型使UPnP控制点能够配置和控制符合UPnP的InternetGatewayDevice的WAN接口上的IP连接。
可以支持IP连接的任何类型的WAN接口(例如,DSL或电缆)都可以使用此服务。
[…]
为WANConnectionDevice上的每个实际Internet连接实例激活WANIPConnection服务的实例(请参阅状态变量表)。
WANIPConnection服务为LAN上的联网客户端提供了与ISP的IP级连接。

SCPDURL: 服务描述URL

WANIPConnection的服务描述URL是/ipc.xml,因此我们可以在浏览器中输入设备的URL, http://192.168.2.1:1900/ipc.xml, 便可以看到详细的信息,里面包含了许多动作,如下:
在这里插入图片描述

controlURL:控制的URL

WANIPConnection的控制URL是/ipc

至此,描述结束。在这个阶段中,我们找到了需要的服务WANIPConnection,并且获取到了控制URL:/ipc

4 控制

在上面的过程中,我们获取了设备的服务,因此接下来便可以控制设备。在本文中,我们控制设备进行端口映射,相关的控制如下:

    AddPortMapping:增加端口映射
    DeletePortMapping:删除端口映射
    GetGenericPortMappingEntry:获得端口映射信息
	GetExternalIPAddress:获取外网IP
	GetStatusInfo: 获取状态信息

4.1 获取状态信息

交互过程如下:

POST /ipc HTTP/1.1
Host: 192.168.2.1:1900
User-Agent: Ubuntu/12.04, UPnP/1.1, MiniUPnPc/1.9
Content-Length: 271
Content-Type: text/xml
SOAPAction: "urn:schemas-upnp-org:service:WANIPConnection:1#GetStatusInfo"
Connection: Close
Cache-Control: no-cache
Pragma: no-cache

<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:GetStatusInfo xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"></u:GetStatusInfo></s:Body></s:Envelope>

上面信息中有几个需要关注的点:
POST /ipc HTTP/1.1, 其中/ipc便是路径控制URL
SOAPACTION:必须是要调用的服务类型、散列符号和动作名称

HTTP/1.1 200 OK
CONNECTION: close
SERVER: Wireless N Router WR745N, UPnP/1.0
CONTENT-LENGTH: 480
CONTENT-TYPE: text/xml; charset="utf-8"

<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<u:GetStatusInfoResponse xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"><NewConnectionStatus>Connected</NewConnectionStatus><NewLastConnectionError>ERROR_NONE</NewLastConnectionError><NewUptime>3 Days, 01:46:46</NewUptime></u:GetStatusInfoResponse></SOAP-ENV:Body>
</SOAP-ENV:Envelope>

4.2 获取外网IP

POST /ipc HTTP/1.1
Host: 192.168.2.1:1900
User-Agent: Ubuntu/12.04, UPnP/1.1, MiniUPnPc/1.9
Content-Length: 285
Content-Type: text/xml
SOAPAction: "urn:schemas-upnp-org:service:WANIPConnection:1#GetExternalIPAddress"
Connection: Close
Cache-Control: no-cache
Pragma: no-cache

<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:GetExternalIPAddress xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"></u:GetExternalIPAddress></s:Body></s:Envelope>

HTTP/1.1 200 OK
CONNECTION: close
SERVER: Wireless N Router WR745N, UPnP/1.0
CONTENT-LENGTH: 402
CONTENT-TYPE: text/xml; charset="utf-8"

<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<u:GetExternalIPAddressResponse xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"><NewExternalIPAddress>192.168.100.34</NewExternalIPAddress></u:GetExternalIPAddressResponse></SOAP-ENV:Body>
</SOAP-ENV:Envelope>

NewExternalIPAddress中的值便是外网IP,因为我的路由器是多级路由,所以并没有获取到真正的公网IP

4.3 获取端口映射信息

POST /ipc HTTP/1.1
Host: 192.168.2.1:1900
User-Agent: Ubuntu/12.04, UPnP/1.1, MiniUPnPc/1.9
Content-Length: 341
Content-Type: text/xml
SOAPAction: "urn:schemas-upnp-org:service:WANIPConnection:1#GetGenericPortMappingEntry"
Connection: Close
Cache-Control: no-cache
Pragma: no-cache

<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:GetGenericPortMappingEntry xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"><NewPortMappingIndex>0</NewPortMappingIndex></u:GetGenericPortMappingEntry></s:Body></s:Envelope>

HTTP/1.1 200 OK
CONNECTION: close
SERVER: Wireless N Router WR745N, UPnP/1.0
CONTENT-LENGTH: 687
CONTENT-TYPE: text/xml; charset="utf-8"

<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<u:GetGenericPortMappingEntryResponse xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"><NewRemoteHost></NewRemoteHost><NewExternalPort>10154</NewExternalPort><NewProtocol>TCP</NewProtocol><NewInternalPort>554</NewInternalPort><NewInternalClient>192.168.2.137</NewInternalClient><NewEnabled>1</NewEnabled><NewPortMappingDescription>MasonUpnp_554_10154</NewPortMappingDescription><NewLeaseDuration>0</NewLeaseDuration></u:GetGenericPortMappingEntryResponse></SOAP-ENV:Body>
</SOAP-ENV:Envelope>

4.4端口映射

POST /ipc HTTP/1.1
Host: 192.168.2.1:1900
User-Agent: Ubuntu/12.04, UPnP/1.1, MiniUPnPc/1.9
Content-Length: 604
Content-Type: text/xml
SOAPAction: "urn:schemas-upnp-org:service:WANIPConnection:1#AddPortMapping"
Connection: Close
Cache-Control: no-cache
Pragma: no-cache

<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:AddPortMapping xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"><NewRemoteHost></NewRemoteHost><NewExternalPort>26780</NewExternalPort><NewProtocol>TCP</NewProtocol><NewInternalPort>554</NewInternalPort><NewInternalClient>192.168.2.138</NewInternalClient><NewEnabled>1</NewEnabled><NewPortMappingDescription>MasonUpnp_554_26780</NewPortMappingDescription><NewLeaseDuration>0</NewLeaseDuration></u:AddPortMapping></s:Body></s:Envelope>

上面有几个值需要关注一下:
NewExternalPort:需要映射的外网端口
NewProtocol:TCP/UDP
NewInternalPort:内部端口
NewInternalClient:内部IP,即控制点IP
NewPortMappingDescription:端口映射的描述
NewLeaseDuration:控制点活动状态持续时间,0表示无限制

HTTP/1.1 200 OK
CONNECTION: close
SERVER: Wireless N Router WR745N, UPnP/1.0
CONTENT-LENGTH: 332
CONTENT-TYPE: text/xml; charset="utf-8"

<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<u:AddPortMappingResponse xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"></u:AddPortMappingResponse></SOAP-ENV:Body>
</SOAP-ENV:Envelope>

设备返回200 OK,表示映射成功。如果是通过路由器上映射的话,我们便可以在路由器WEB页面看到相关信息。
在这里插入图片描述
以上便是UPNP端口映射的流程,本文只是简单介绍了端口映射。所以对UPNP后续的事件/展示等过程没有进行研究。

5 一些疑问

5.1 端口映射的有效期是多久?

关于端口映射的有效期是多久,了解时间太短,没有找到有效的信息。不过在miniUPnP的官网上找到了一些信息,在控制点进行端口映射的时候会有NewLeaseDuration字段,表示控制点活动状态持续时间,将这个值设置为0则表示无限制。

5.2 多级路由如何映射成功

由于UPNP只能穿透一层网络,所以如果遇到多级路由这样的复杂网络环境,虽然端口映射成功,但是并没有真正映射到公网。但是查询了一圈资料,并没有找到如何能在多级路由中映射到真正的公网,如果有了解的,麻烦告知一下,共同探讨。

6 开源库

网上有一些开源的UPNP库,可以将我们从这些繁杂的交互过程中独立出来,专注于应用。虽然了解了轮子的构造过程,但是就不需要重新造轮子了。
MiniUPnP:
https://github.com/miniupnp/miniupnp
Libupnp:
http://pupnp.sourceforge.net/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章