經常用到內網穿透,對UPNP也有所了解,但是具體的報文每次都去抓顯然浪費時間。因此記錄在下面。
報文是開啟BitComet時抓取的,前面的python代碼是自己用來獲取NOTIFY消息的代碼。
連接到組播地址接收NOTIFY消息
import socket
import re
ANY = "0.0.0.0"
DES_IP = "239.255.255.250"
PORT = 1900
# xml_str = b'<?xml version="1.0" encoding="utf-8"?><Probe><Uuid>B2D5D4D2-808C-40F6-87CD-694C05C2B274</Uuid><Types>inquiry</Types></Probe> '
# xml_str = b'<?xml version="1.0" encoding="utf-8"?><Probe><Uuid>CB09F608-E016-4EE8-869A-CA186852F12E</Uuid><Types>inquiry</Types></Probe> '
xml_str = b'M-SEARCH * HTTP/1.1\r\n' \
+ b'HOST: 239.255.255.250:1900\r\n' \
+ b'MAN: "ssdp:discover"\r\n' \
+ b'MX: 1\r\n' \
+ b'ST: urn:dial-multiscreen-org:service:dial:1\r\n' \
+ b'USER-AGENT: Google Chrome/87.0.4280.88 Windows\r\n\r\n\r\n'
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((ANY, PORT))
s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255)
s.setsockopt(
socket.IPPROTO_IP,
socket.IP_ADD_MEMBERSHIP,
socket.inet_aton(DES_IP) + socket.inet_aton(ANY)
)
s.setblocking(False)
s.sendto(xml_str, (DES_IP, PORT))
while True:
try:
data, address = s.recvfrom(2048)
except Exception as e:
pass
else:
print(address)
print(data)
接收到的NOTIFY報文
NOTIFY * HTTP/1.1
HOST: 239.255.255.250:1900
CACHE-CONTROL: max-age=100
LOCATION: http://192.168.1.1:1900/igd.xml
NT: upnp:rootdevice
NTS: ssdp:alive
SERVER: Mercury Router MR808, UPnP/1.0
USN: uuid:upnp-InternetGatewayDevice-192168115678900001::upnp:rootdevice
NOTIFY * HTTP/1.1
HOST: 239.255.255.250:1900
CACHE-CONTROL: max-age=100
LOCATION: http://192.168.1.1:1900/igd.xml
NT: uuid:upnp-InternetGatewayDevice-192168115678900001
NTS: ssdp:alive
SERVER: Mercury Router MR808, UPnP/1.0
USN: uuid:upnp-InternetGatewayDevice-192168115678900001
NOTIFY * HTTP/1.1
HOST: 239.255.255.250:1900
CACHE-CONTROL: max-age=100
LOCATION: http://192.168.1.1:1900/igd.xml
NT: urn:schemas-upnp-org:device:InternetGatewayDevice:1
NTS: ssdp:alive
SERVER: Mercury Router MR808, UPnP/1.0
USN: uuid:upnp-InternetGatewayDevice-192168115678900001::urn:schemas-upnp-org:device:InternetGatewayDevice:1
NOTIFY * HTTP/1.1
HOST: 239.255.255.250:1900
CACHE-CONTROL: max-age=100
LOCATION: http://192.168.1.1:1900/igd.xml
NT: urn:schemas-upnp-org:service:Layer3Forwarding:1
NTS: ssdp:alive
SERVER: Mercury Router MR808, UPnP/1.0
USN: uuid:upnp-InternetGatewayDevice-192168115678900001::urn:schemas-upnp-org:service:Layer3Forwarding:1
NOTIFY * HTTP/1.1
HOST: 239.255.255.250:1900
CACHE-CONTROL: max-age=100
LOCATION: http://192.168.1.1:1900/igd.xml
NT: uuid:upnp-WANDevice-192168115678900001
NTS: ssdp:alive
SERVER: Mercury Router MR808, UPnP/1.0
USN: uuid:upnp-WANDevice-192168115678900001
NOTIFY * HTTP/1.1
HOST: 239.255.255.250:1900
CACHE-CONTROL: max-age=100
LOCATION: http://192.168.1.1:1900/igd.xml
NT: urn:schemas-upnp-org:device:WANDevice:1
NTS: ssdp:alive
SERVER: Mercury Router MR808, UPnP/1.0
USN: uuid:upnp-WANDevice-192168115678900001::urn:schemas-upnp-org:device:WANDevice:1
NOTIFY * HTTP/1.1
HOST: 239.255.255.250:1900
CACHE-CONTROL: max-age=100
LOCATION: http://192.168.1.1:1900/igd.xml
NT: urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1
NTS: ssdp:alive
SERVER: Mercury Router MR808, UPnP/1.0
USN: uuid:upnp-WANDevice-192168115678900001::urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1
NOTIFY * HTTP/1.1
HOST: 239.255.255.250:1900
CACHE-CONTROL: max-age=100
LOCATION: http://192.168.1.1:1900/igd.xml
NT: uuid:upnp-WANConnectionDevice-192168115678900001
NTS: ssdp:alive
SERVER: Mercury Router MR808, UPnP/1.0
USN: uuid:upnp-WANConnectionDevice-192168115678900001
NOTIFY * HTTP/1.1
HOST: 239.255.255.250:1900
CACHE-CONTROL: max-age=100
LOCATION: http://192.168.1.1:1900/igd.xml
NT: urn:schemas-upnp-org:device:WANConnectionDevice:1
NTS: ssdp:alive
SERVER: Mercury Router MR808, UPnP/1.0
USN: uuid:upnp-WANConnectionDevice-192168115678900001::urn:schemas-upnp-org:device:WANConnectionDevice:1
NOTIFY * HTTP/1.1
HOST: 239.255.255.250:1900
CACHE-CONTROL: max-age=100
LOCATION: http://192.168.1.1:1900/igd.xml
NT: urn:schemas-upnp-org:service:WANIPConnection:1
NTS: ssdp:alive
SERVER: Mercury Router MR808, UPnP/1.0
USN: uuid:upnp-WANConnectionDevice-192168115678900001::urn:schemas-upnp-org:service:WANIPConnection:1
請求igd.xml
GET /igd.xml HTTP/1.1
Cache-Control: no-cache
Connection: Close
Pragma: no-cache
Accept: text/xml, application/xml
Host: 192.168.1.1:1900
User-Agent: Microsoft-Windows/10.0 UPnP/1.0
HTTP/1.1 200 OK
CONTENT-LENGTH: 2746
CONTENT-TYPE: text/xml
DATE: Thu, 07 Jan 2021 02:03:00 GMT
LAST-MODIFIED: Tue, 28 Oct 2003 08:46:08 GMT
SERVER: Mercury Router MR808, UPnP/1.0
CONNECTION: close
<?xml version="1.0"?>
<root xmlns="urn:schemas-upnp-org:device-1-0">
......
</root>
igd.xml的詳細內容如下
<?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.1.1:80 </presentationURL>
<friendlyName >Mercury Router MR808</friendlyName>
<manufacturer >Mercury</manufacturer>
<manufacturerURL >http://www.mercurycom.com.cn</manufacturerURL>
<modelDescription >MR808 2.0</modelDescription>
<modelName >MR808</modelName>
<modelNumber >2.0</modelNumber>
<UDN>uuid:upnp-InternetGatewayDevice-192168115678900001</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 >Mercury</manufacturer>
<manufacturerURL >http://www.mercurycom.com.cn</manufacturerURL>
<modelDescription>WAN Device</modelDescription>
<modelName>WAN Device</modelName>
<modelNumber>1</modelNumber>
<modelURL></modelURL>
<serialNumber>12345678900001</serialNumber>
<UDN>uuid:upnp-WANDevice-192168115678900001</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 >Mercury</manufacturer>
<manufacturerURL >http://www.mercurycom.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-192168115678900001</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>
請求ipc.xml的報文
GET /ipc.xml HTTP/1.1
Cache-Control: no-cache
Connection: Close
Pragma: no-cache
Accept: text/xml, application/xml
User-Agent: Microsoft-Windows/10.0 UPnP/1.0
Host: 192.168.1.1:1900
HTTP/1.1 200 OK
CONTENT-LENGTH: 8689
CONTENT-TYPE: text/xml
DATE: Thu, 07 Jan 2021 02:03:00 GMT
LAST-MODIFIED: Sat, 25 Oct 2003 03:22:56 GMT
SERVER: Mercury Router MR808, UPnP/1.0
CONNECTION: close
<?xml version="1.0"?>
<scpd xmlns="urn:schemas-upnp-org:service-1-0">
......
</scpd>
IPC返回的是以xml方式呈現的接口詳情,整理之后如下:
SetConnectionType
SetConnectionType
|--param:NewConnectionType
|--param:NewConnectionType
GetConnectionTypeInfo
GetConnectionTypeInfo
|--param:NewConnectionType
|--param:NewConnectionType
|--param:NewPossibleConnectionTypes
|--param:NewPossibleConnectionTypes
ForceTermination
ForceTermination
RequestConnection
RequestConnection
GetStatusInfo
GetStatusInfo
|--param:NewConnectionStatus
|--param:NewConnectionStatus
|--param:NewLastConnectionError
|--param:NewLastConnectionError
|--param:NewUptime
|--param:NewUptime
GetNATRSIPStatus
GetNATRSIPStatus
|--param:NewRSIPAvailable
|--param:NewRSIPAvailable
|--param:NewNATEnabled
|--param:NewNATEnabled
GetGenericPortMappingEntry
GetGenericPortMappingEntry
|--param:NewPortMappingIndex
|--param:NewPortMappingIndex
|--param:NewRemoteHost
|--param:NewRemoteHost
|--param:NewExternalPort
|--param:NewExternalPort
|--param:NewProtocol
|--param:NewProtocol
|--param:NewInternalPort
|--param:NewInternalPort
|--param:NewInternalClient
|--param:NewInternalClient
|--param:NewEnabled
|--param:NewEnabled
|--param:NewPortMappingDescription
|--param:NewPortMappingDescription
|--param:NewLeaseDuration
|--param:NewLeaseDuration
GetSpecificPortMappingEntry
GetSpecificPortMappingEntry
|--param:NewRemoteHost
|--param:NewRemoteHost
|--param:NewExternalPort
|--param:NewExternalPort
|--param:NewProtocol
|--param:NewProtocol
|--param:NewInternalPort
|--param:NewInternalPort
|--param:NewInternalClient
|--param:NewInternalClient
|--param:NewEnabled
|--param:NewEnabled
|--param:NewPortMappingDescription
|--param:NewPortMappingDescription
|--param:NewLeaseDuration
|--param:NewLeaseDuration
AddPortMapping
AddPortMapping
DeletePortMapping
DeletePortMapping
GetExternalIPAddress
GetExternalIPAddress
|--param:NewExternalIPAddress
|--param:NewExternalIPAddress
ConnectionType
ConnectionType
PossibleConnectionTypes
PossibleConnectionTypes
ConnectionStatus
ConnectionStatus
Uptime
Uptime
LastConnectionError
LastConnectionError
RSIPAvailable
RSIPAvailable
NATEnabled
NATEnabled
ExternalIPAddress
ExternalIPAddress
PortMappingNumberOfEntries
PortMappingNumberOfEntries
PortMappingEnabled
PortMappingEnabled
PortMappingLeaseDuration
PortMappingLeaseDuration
RemoteHost
RemoteHost
ExternalPort
ExternalPort
InternalPort
InternalPort
PortMappingProtocol
PortMappingProtocol
InternalClient
InternalClient
PortMappingDescription
PortMappingDescription
調用ipc的接口報文
POST /ipc HTTP/1.1
Cache-Control: no-cache
Connection: Close
Pragma: no-cache
Content-Type: text/xml; charset="utf-8"
User-Agent: Microsoft-Windows/10.0 UPnP/1.0
SOAPAction: "urn:schemas-upnp-org:service:WANIPConnection:1#AddPortMapping"
Content-Length: 1127
Host: 192.168.1.1:1900
<?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><m:AddPortMapping xmlns:m="urn:schemas-upnp-org:service:WANIPConnection:1"><NewRemoteHost xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="string"></NewRemoteHost><NewExternalPort xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="ui2">16849</NewExternalPort><NewProtocol xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="string">UDP</NewProtocol><NewInternalPort xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="ui2">16849</NewInternalPort><NewInternalClient xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="string">192.168.1.100</NewInternalClient><NewEnabled xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="boolean">1</NewEnabled><NewPortMappingDescription xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="string">BitComet UDP</NewPortMappingDescription><NewLeaseDuration xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="ui4">0</NewLeaseDuration></m:AddPortMapping></SOAP-ENV:Body></SOAP-ENV:Envelope>
HTTP/1.1 200 OK
CONNECTION: close
SERVER: Mercury Router MR808, 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>
調用的ipc的接口和接口順序如下
調用ipc接口之后的結果
結論
添加映射的主要操作是POST的方式調用AddPortMapping接口。
顯然libtorrent在這之前要先通過M-SEARCH和NOTIFY的UDP報文找到路由器,通過igd找ipc,通過ipc接口操作刪除或添加映射。
添加完映射要用GetExternalIPAddress獲取外網地址,這樣就能把地址傳給別人讓別人找到你。
參考網址
www.upnp.org已經面目全非了,只能借助weiki的存檔才能看見
https://web.archive.org/web/20050708020002/http://www.upnp.org/
https://web.archive.org/web/20051104061236if_/http://www.upnp.org:80/standardizeddcps/upnpresource20050517.zip
upnpresource20050517/documents/UPnP_Vendor_Implementation_Guide_Jan2001.htm
upnpresource20050517/documents/UPnPDA10_20000613.htm
https://github.com/jupnp/jupnp
https://github.com/hubing8658/UPnP-DLNA-Demo