协议-upnp

upnp访问过程

#随笔

udp访问239.255.255.250的1900端口,ssdp协议

import socket
import re

ANY = "0.0.0.0"
DES_IP = "239.255.255.250"
PORT = 1900
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)

通过这种方式可以获取到同网下的其他upnp设备信息

('10.0.0.1', 35150)

b'NOTIFY * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nCACHE-CONTROL: max-age=3600\r\nLOCATION: http://10.0.0.1:56688/rootDesc.xml\r\nSERVER: OpenWRT/OpenWrt UPnP/1.1 MiniUPnPd/2.0\r\nNT: upnp:rootdevice\r\nUSN: uuid:97fd7581-d522-415d-bfae-a51ac69e4b55::upnp:rootdevice\r\nNTS: ssdp:alive\r\nOPT: "http://schemas.upnp.org/upnp/1/0/"; ns=01\r\n01-NLS: 1693189369\r\nBOOTID.UPNP.ORG: 1693189369\r\nCONFIGID.UPNP.ORG: 1337\r\n\r\n'

('10.0.0.1', 60956)

b'NOTIFY * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nCACHE-CONTROL: max-age=1801\r\nNTS: ssdp:alive\r\nLOCATION: http://10.0.0.1:49153/wps_device.xml\r\nSERVER: Unspecified, UPnP/1.0, Unspecified\r\nNT: urn:schemas-wifialliance-org:service:WFAWLANConfig:1\r\nUSN: uuid:dd20a05f-a846-47cf-b976-047083022a1d::urn:schemas-wifialliance-org:service:WFAWLANConfig:1\r\n\r\n'

现在是以10.0.0.1做演示

信息中能发现LOCATION

http://10.0.0.1:49153/wps_device.xml

http://10.0.0.1:56688/rootDesc.xml

rootDesc.xml文件

This XML file does not appear to have any style information associated with it. The document tree is shown below.

<root  xmlns="urn:schemas-upnp-org:device-1-0"  configId="1337">
  <specVersion><major>1</major><minor>1</minor>
  </specVersion>
  <device><deviceType>urn:schemas-upnp-org:device:InternetGatewayDevice:1</deviceType><friendlyName>RAX40 (Gateway)</friendlyName><manufacturer>Netgear, Inc.</manufacturer><manufacturerURL>http://www.NETGEAR.com</manufacturerURL><modelDescription>OpenWRT router</modelDescription><modelName>RAX40</modelName><modelNumber>RAX40</modelNumber><modelURL>http://www.netgear.com/home</modelURL><serialNumber>5UP299WPA0C55</serialNumber><UDN>uuid:97fd7581-d522-415d-bfae-a51ac69e4b55</UDN><serviceList><service><serviceType>urn:schemas-upnp-org:service:Layer3Forwarding:1</serviceType><serviceId>urn:upnp-org:serviceId:L3Forwarding1</serviceId><SCPDURL>/L3F.xml</SCPDURL><controlURL>/ctl/L3F</controlURL><eventSubURL>/evt/L3F</eventSubURL></service></serviceList><deviceList><device><deviceType>urn:schemas-upnp-org:device:WANDevice:1</deviceType><friendlyName>WANDevice</friendlyName><manufacturer>MiniUPnP</manufacturer><manufacturerURL>http://miniupnp.free.fr/</manufacturerURL><modelDescription>WAN Device</modelDescription><modelName>WAN Device</modelName><modelNumber>20220318</modelNumber><modelURL>http://miniupnp.free.fr/</modelURL><serialNumber>5UP299WPA0C55</serialNumber><UDN>uuid:97fd7581-d522-415d-bfae-a51ac69e4b56</UDN><UPC>000000000000</UPC><serviceList><service><serviceType>urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1</serviceType><serviceId>urn:upnp-org:serviceId:WANCommonIFC1</serviceId><SCPDURL>/WANCfg.xml</SCPDURL><controlURL>/ctl/CmnIfCfg</controlURL><eventSubURL>/evt/CmnIfCfg</eventSubURL></service></serviceList><deviceList><device><deviceType>urn:schemas-upnp-org:device:WANConnectionDevice:1</deviceType><friendlyName>WANConnectionDevice</friendlyName><manufacturer>MiniUPnP</manufacturer><manufacturerURL>http://miniupnp.free.fr/</manufacturerURL><modelDescription>MiniUPnP daemon</modelDescription><modelName>MiniUPnPd</modelName><modelNumber>20220318</modelNumber><modelURL>http://miniupnp.free.fr/</modelURL><serialNumber>5UP299WPA0C55</serialNumber><UDN>uuid:97fd7581-d522-415d-bfae-a51ac69e4b57</UDN><UPC>000000000000</UPC><serviceList><service><serviceType>urn:schemas-upnp-org:service:WANIPConnection:1</serviceType><serviceId>urn:upnp-org:serviceId:WANIPConn1</serviceId><SCPDURL>/WANIPCn.xml</SCPDURL><controlURL>/ctl/IPConn</controlURL><eventSubURL>/evt/IPConn</eventSubURL></service></serviceList></device></deviceList></device></deviceList><presentationURL>http://www.routerlogin.net</presentationURL>
  </device>
</root>

其中可以获取设备名称制造商各种服务等信息

L3Forwarding1

<service><serviceType>urn:schemas-upnp-org:service:Layer3Forwarding:1</serviceType><serviceId>urn:upnp-org:serviceId:L3Forwarding1</serviceId><SCPDURL>/L3F.xml</SCPDURL><controlURL>/ctl/L3F</controlURL><eventSubURL>/evt/L3F</eventSubURL>

</service>

WANCommonIFC1

<service><serviceType>urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1</serviceType><serviceId>urn:upnp-org:serviceId:WANCommonIFC1</serviceId><SCPDURL>/WANCfg.xml</SCPDURL><controlURL>/ctl/CmnIfCfg</controlURL><eventSubURL>/evt/CmnIfCfg</eventSubURL>

</service>

WANIPConn1

<service><serviceType>urn:schemas-upnp-org:service:WANIPConnection:1</serviceType><serviceId>urn:upnp-org:serviceId:WANIPConn1</serviceId><SCPDURL>/WANIPCn.xml</SCPDURL><controlURL>/ctl/IPConn</controlURL><eventSubURL>/evt/IPConn</eventSubURL>

</service>

通过访问SCPDURL可以获取服务的具体行为,以WANIPConn1为例

访问http://10.0.0.1:56688/WANIPCn.xml

This XML file does not appear to have any style information associated with it. The document tree is
shown below.
<scpd  xmlns="urn:schemas-upnp-org:service-1-0">
  <specVersion><major>1</major><minor>1</minor>
  </specVersion>
  <actionList><action><name>SetConnectionType</name><argumentList><argument><name>NewConnectionType</name><direction>in</direction><relatedStateVariable>ConnectionType</relatedStateVariable></argument></argumentList></action><action><name>GetConnectionTypeInfo</name><argumentList><argument><name>NewConnectionType</name><direction>out</direction><relatedStateVariable>ConnectionType</relatedStateVariable></argument><argument><name>NewPossibleConnectionTypes</name><direction>out</direction><relatedStateVariable>PossibleConnectionTypes</relatedStateVariable></argument></argumentList></action><action><name>RequestConnection</name></action><action><name>ForceTermination</name></action><action><name>GetStatusInfo</name><argumentList><argument><name>NewConnectionStatus</name><direction>out</direction><relatedStateVariable>ConnectionStatus</relatedStateVariable></argument><argument><name>NewLastConnectionError</name><direction>out</direction><relatedStateVariable>LastConnectionError</relatedStateVariable></argument><argument><name>NewUptime</name><direction>out</direction><relatedStateVariable>Uptime</relatedStateVariable></argument></argumentList></action><action><name>GetNATRSIPStatus</name><argumentList><argument><name>NewRSIPAvailable</name><direction>out</direction><relatedStateVariable>RSIPAvailable</relatedStateVariable></argument><argument><name>NewNATEnabled</name><direction>out</direction><relatedStateVariable>NATEnabled</relatedStateVariable></argument></argumentList></action><action><name>GetGenericPortMappingEntry</name><argumentList><argument><name>NewPortMappingIndex</name><direction>in</direction><relatedStateVariable>PortMappingNumberOfEntries</relatedStateVariable></argument><argument><name>NewRemoteHost</name><direction>out</direction><relatedStateVariable>RemoteHost</relatedStateVariable></argument><argument><name>NewExternalPort</name><direction>out</direction><relatedStateVariable>ExternalPort</relatedStateVariable></argument><argument><name>NewProtocol</name><direction>out</direction><relatedStateVariable>PortMappingProtocol</relatedStateVariable></argument><argument><name>NewInternalPort</name><direction>out</direction><relatedStateVariable>InternalPort</relatedStateVariable></argument><argument><name>NewInternalClient</name><direction>out</direction><relatedStateVariable>InternalClient</relatedStateVariable></argument><argument><name>NewEnabled</name><direction>out</direction><relatedStateVariable>PortMappingEnabled</relatedStateVariable>
​        </argument
​        <argument><name>NewPortMappingDescription</name><direction>out</direction><relatedStateVariable>PortMappingDescription</relatedStateVariable></argument><argument><name>NewLeaseDuration</name><direction>out</direction><relatedStateVariable>PortMappingLeaseDuration</relatedStateVariable></argument></argumentList></action><action><name>GetSpecificPortMappingEntry</name><argumentList><argument><name>NewRemoteHost</name><direction>in</direction
​          <relatedStateVariable>RemoteHost</relatedStateVariable></argument><argument><name>NewExternalPort</name><direction>in</direction><relatedStateVariable>ExternalPort</relatedStateVariable></argument><argument><name>NewProtocol</name><direction>in</direction><relatedStateVariable>PortMappingProtocol</relatedStateVariable></argument><argument><name>NewInternalPort</name><direction>out</direction><relatedStateVariable>InternalPort</relatedStateVariable></argument><argument><name>NewInternalClient</name><direction>out</direction><relatedStateVariable>InternalClient</relatedStateVariable></argument><argument><name>NewEnabled</name><direction>out</direction><relatedStateVariable>PortMappingEnabled</relatedStateVariable></argument><argument><name>NewPortMappingDescription</name><direction>out</direction><relatedStateVariable>PortMappingDescription</relatedStateVariable></argument><argument><name>NewLeaseDuration</name><direction>out</direction><relatedStateVariable>PortMappingLeaseDuration</relatedStateVariable></argument></argumentList></action><action><name>AddPortMapping</name><argumentList><argument><name>NewRemoteHost</name><direction>in</direction><relatedStateVariable>RemoteHost</relatedStateVariable></argument><argument><name>NewExternalPort</name><direction>in</direction><relatedStateVariable>ExternalPort</relatedStateVariable></argument><argument><name>NewProtocol</name><direction>in</direction><relatedStateVariable>PortMappingProtocol</relatedStateVariable></argument><argument><name>NewInternalPort</name><direction>in</direction><relatedStateVariable>InternalPort</relatedStateVariable></argument><argument><name>NewInternalClient</name><direction>in</direction><relatedStateVariable>InternalClient</relatedStateVariable></argument><argument><name>NewEnabled</name><direction>in</direction><relatedStateVariable>PortMappingEnabled</relatedStateVariable></argument><argument><name>NewPortMappingDescription</name><direction>in</direction><relatedStateVariable>PortMappingDescription</relatedStateVariable></argument><argument><name>NewLeaseDuration</name><direction>in</direction><relatedStateVariable>PortMappingLeaseDuration</relatedStateVariable></argument></argumentList></action><action><name>DeletePortMapping</name><argumentList><argument><name>NewRemoteHost</name><direction>in</direction><relatedStateVariable>RemoteHost</relatedStateVariable></argument><argument><name>NewExternalPort</name><direction>in</direction><relatedStateVariable>ExternalPort</relatedStateVariable></argument><argument><name>NewProtocol</name><direction>in</direction><relatedStateVariable>PortMappingProtocol</relatedStateVariable></argument></argumentList></action><action><name>GetExternalIPAddress</name><argumentList><argument><name>NewExternalIPAddress</name><direction>out</direction><relatedStateVariable>ExternalIPAddress</relatedStateVariable></argument></argumentList></action>
  </actionList>
  <serviceStateTable><stateVariable  sendEvents="no"><name>ConnectionType</name><dataType>string</dataType><defaultValue>IP_Routed</defaultValue></stateVariable><stateVariable  sendEvents="yes"
​      <name>PossibleConnectionTypes</name><dataType>string</dataType><allowedValueList><allowedValue>Unconfigured</allowedValue><allowedValue>IP_Routed</allowedValue><allowedValue>IP_Bridged</allowedValue></allowedValueList></stateVariable><stateVariable  sendEvents="yes"><name>ConnectionStatus</name><dataType>string</dataType><defaultValue>Unconfigured</defaultValue><allowedValueList><allowedValue>Unconfigured</allowedValue><allowedValue>Connecting</allowedValue><allowedValue>Connected</allowedValue><allowedValue>PendingDisconnect</allowedValue><allowedValue>Disconnecting</allowedValue><allowedValue>Disconnected</allowedValue></allowedValueList></stateVariable><stateVariable  sendEvents="no"><name>Uptime</name><dataType>ui4</dataType></stateVariable><stateVariable  sendEvents="no"><name>LastConnectionError</name><dataType>string</dataType><defaultValue>ERROR_NONE</defaultValue><allowedValueList><allowedValue>ERROR_NONE</allowedValue></allowedValueList></stateVariable><stateVariable  sendEvents="no"><name>RSIPAvailable</name><dataType>boolean</dataType><defaultValue>0</defaultValue></stateVariable><stateVariable  sendEvents="no"><name>NATEnabled</name><dataType>boolean</dataType><defaultValue>1</defaultValue></stateVariable><stateVariable  sendEvents="yes"><name>ExternalIPAddress</name><dataType>string</dataType></stateVariable><stateVariable  sendEvents="yes"><name>PortMappingNumberOfEntries</name><dataType>ui2</dataType></stateVariable><stateVariable  sendEvents="no"><name>PortMappingEnabled</name><dataType>boolean</dataType></stateVariable><stateVariable  sendEvents="no"><name>PortMappingLeaseDuration</name><dataType>ui4</dataType><defaultValue>3600</defaultValue><allowedValueRange><minimum>0</minimum><maximum>604800</maximum></allowedValueRange></stateVariable><stateVariable  sendEvents="no"><name>RemoteHost</name><dataType>string</dataType></stateVariable><stateVariable  sendEvents="no"><name>ExternalPort</name><dataType>ui2</dataType></stateVariable><stateVariable  sendEvents="no"><name>InternalPort</name><dataType>ui2</dataType><allowedValueRange><minimum>1</minimum><maximum>65535</maximum></allowedValueRange></stateVariable><stateVariable  sendEvents="no"><name>PortMappingProtocol</name><dataType>string</dataType><allowedValueList><allowedValue>TCP</allowedValue><allowedValue>UDP</allowedValue></allowedValueList></stateVariable><stateVariable  sendEvents="no"><name>InternalClient</name><dataType>string</dataType></stateVariable><stateVariable  sendEvents="no"><name>PortMappingDescription</name><dataType>string</dataType></stateVariable>
  </serviceStateTable>
</scpd>

分类统计有以下几种:

SetConnectionType,GetConnectionTypeInfo,RequestConnection,ForceTermination,GetStatusInfo,GetNATRSIPStatus,GetGenericPortMappingEntry,GetSpecificPortMappingEntry,AddPortMapping,DeletePortMapping,GetExternalIPAddress

通过构造POST请求,访问controlURL:http://10.0.0.1:56688/ctl/IPConn

POST /ctl/IPConn HTTP/1.1
Host: 10.0.0.1:56688
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 Edg/116.0.1938.62
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
SOAPAction: "urn:schemas-upnp-org:service:WANIPConnection:1#GetExternalIPAddress"
Connection: close
Content-Length: 260

<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>

重要的有head中的SOAPAction,构造方式为serviceType#action即:urn:schemas-upnp-org:service:WANIPConnection:1#GetExternalIPAddress

post参数来源action中的direction为in的参数,如果只有out参数,即可不用构造post参数,直接获取。

in参数的数据类型在serviceStateTable中可以获取

POST /ctl/IPConn HTTP/1.1
Accept-Encoding: identity
User-Agent: Python-urllib/3.11
Host: 10.0.0.1:56688
Content-Length: 358
Content-Type: text/xml; charset="utf-8"
Soapaction: "urn:schemas-upnp-org:service:WANIPConnection:1#DeletePortMapping"
Connection: close


<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<u:DeletePortMapping xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1">
<NewRemoteHost>AAAA</NewRemoteHost>
<NewExternalPort>AAAA</NewExternalPort>
<NewProtocol>TCP</NewProtocol>
</u:DeletePortMapping>
</s:Body>
</s:Envelope>

通过gdb调试可以发现,可以获取到

image-20230829175431203

python中又个upnpy库,可以很方便的执行上述步骤。

python3 -m pip install upnpy

使用方式

import upnpy

\#获取upnp
upnp = upnpy.UPnP()

\#扫描,返回一个设备列表
devices = upnp.discover()

\#确定设备,两种方式都可以
devide = devices[0]
device = upnp.get_igd()

\#获取服务列表
services = device.get_services()

\#确定服务,同两种方式均可
service = services[0] 
service = device['WANPPPConnection.1'] #service id

\#获取服务的actions,返回一个action列表
service.get_actions()

\#通过service.action['name']()可以执行
service.GetExternalIPAddress() #{'NewExternalIPAddress': '10.100.40.182'}

\#通过service.action['name'].get_input_arguments()可以获取参数
service.DeletePortMapping.get_input_arguments()
\#[{'name': 'NewRemoteHost', 'data_type': 'string', 'allowed_value_list': []}, {'name': 'NewExternalPort', 'data_type': 'ui2', 'allowed_value_list': []}, {'name': 'NewProtocol', 'data_type': 'string', 'allowed_value_list': ['TCP', 'UDP']}]

\#发送服务
service.AddPortMapping(
  NewRemoteHost='',
  NewExternalPort=80,
  NewProtocol='TCP',
  NewInternalPort=8000,
  NewInternalClient='192.168.1.3',
  NewEnabled=1,
  NewPortMappingDescription='Test port mapping entry from UPnPy.',
  NewLeaseDuration=0
)

协议-upnp
http://example.com/article/697ff101.html
Author
p1yang
Posted on
August 29, 2023
Licensed under