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/

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