1. UPnP协议

1.1 协议:

SSDP: (Simple Service Discovery Protocol,简单服务发现协议),发现本地网络上的UPnP设备
SCPD: (Service Control Point Definition,服务控制端点定义),定义各种服务执行动作
SOAP: (Simple Object Access Protocol,简单对象访问协议),执行动作1

UPnP回话流程:
UPnP
使用SSDP发现网络上可用的设备,这些设备返回一个定义了每个设备所提供服务的XML文件的位置。接下来,使用SCPD发现每个服务提供的动作。从本质上讲,SCPD是描述一个基于xml的SOAP api的协议。最后,我们使用SOAP调用与服务交互。

1.1.1 网络发现

python模拟代码test.py文件内容[8]:

import socket

msg = \
    'M-SEARCH * HTTP/1.1\r\n' \
    'HOST:239.255.255.250:1900\r\n' \
    'ST:upnp:rootdevice\r\n' \
    'MX:2\r\n' \
    'MAN:"ssdp:discover"\r\n'

# Set up UDP socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
s.settimeout(2)
s.sendto(msg, ('239.255.255.250', 1900) )

try:
    while True:
        data, addr = s.recvfrom(65507)
        print addr, data
except socket.timeout:
    pass

命令行执行脚本:

# python test.py
('192.168.0.1', 1900) HTTP/1.1 200 OK
CACHE-CONTROL: max-age=60
DATE: Wed, 03 May 2017 05:29:13 GMT
EXT:
LOCATION: http://192.168.0.1:1900/igd.xml
SERVER: vxWorks/5.5 UPnP/1.0 TL-WR842N/8.0
ST: upnp:rootdevice
USN: uuid:8c15e41f-3d83-41c1-b35d-5D2A648FD020::upnp:rootdevice

tcpdump抓包报文:

# sudo tcpdump -i enp0s3 -Avvvn 'udp and port 1900'
13:29:13.794476 IP (tos 0x0, ttl 1, id 58129, offset 0, flags [DF], proto UDP (17), length 123)
    192.168.0.117.37768 > 239.255.255.250.1900: [bad udp cksum 0xb190 -> 0xe37a!] UDP, length 95
E..{..@....H...u.......l.g..M-SEARCH * HTTP/1.1
HOST:239.255.255.250:1900
ST:upnp:rootdevice
MX:2
MAN:"ssdp:discover"

13:29:13.796616 IP (tos 0x0, ttl 64, id 13827, offset 0, flags [none], proto UDP (17), length 290)
    192.168.0.1.1900 > 192.168.0.117.37768: [udp sum ok] UDP, length 262
E.."6...@..........u.l......HTTP/1.1 200 OK
CACHE-CONTROL: max-age=60
DATE: Wed, 03 May 2017 05:29:13 GMT
EXT:
LOCATION: http://192.168.0.1:1900/igd.xml
SERVER: vxWorks/5.5 UPnP/1.0 TL-WR842N/8.0
ST: upnp:rootdevice
USN: uuid:8c15e41f-3d83-41c1-b35d-5D2A648FD020::upnp:rootdevice

下载设备描述文件igd.xml:

# wget  http://192.168.0.1:1900/igd.xml
# cat igd.xml

浏览igd.xml文件:

<?xml version="1.0"?>
<root xmlns="urn:schemas-upnp-org:device-1-0">
    <specVersion>
        <major>1</major>
        <minor>0</minor>
    </specVersion>
    <device>
        <deviceType>urn:schemas-upnp-org:device:InternetGatewayDevice:1</deviceType>
        <presentationURL>http://192.168.0.1:80</presentationURL>
        <friendlyName>Wireless N Router TL-WR842N</friendlyName>
        <manufacturer>TP-LINK</manufacturer>
        <manufacturerURL>http://www.tp-link.com.cn</manufacturerURL>
        <modelDescription>TL-WR842N 8.0</modelDescription>
        <modelName>TL-WR842N</modelName>
        <modelNumber>8.0</modelNumber>
        <UDN>uuid:8c15e41f-3d83-41c1-b35d-5D2A648FD020</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.0</modelNumber>
                <modelURL></modelURL>
                <serialNumber>12345678900001</serialNumber>
                <UDN>uuid:8c15e41f-3d83-41c1-b35d-5D2A648FD020</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:8c15e41f-3d83-41c1-b35d-5D2A648FD020</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>

得到设备所提供的服务描述,在刚才的设备描述中有一个ServiceList节点,该节点下每个Service节点都包含一个SCPDURL节点,这个就是服务描述文件所在的位置2.

第三层转发配置文件:

#  wget  http://192.168.0.1:1900/l3f.xml
# cat l3f.xml

浏览服务描述文件l3f.xml:

<?xml version="1.0"?>
<scpd xmlns="urn:schemas-upnp-org:service-1-0">
    <specVersion>
        <major>1</major>
        <minor>0</minor>
    </specVersion>
    <actionList>
        <action>
            <name>SetDefaultConnectionService</name>
            <argumentList>
                <argument>
                    <name>NewDefaultConnectionService</name>
                    <direction>in</direction>
                    <relatedStateVariable>DefaultConnectionService</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>GetDefaultConnectionService</name>
            <argumentList>
                <argument>
                    <name>NewDefaultConnectionService</name>
                    <direction>out</direction>
                    <relatedStateVariable>DefaultConnectionService</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
    </actionList>
    <serviceStateTable>
        <stateVariable sendEvents="yes">
            <name>DefaultConnectionService</name>
            <dataType>string</dataType>
        </stateVariable>
    </serviceStateTable>
</scpd>

广域网公共接口配置描述文件:

# wget  http://192.168.0.1:1900/ifc.xml
# cat ifc.xml

浏览描述文件ifc.xml:

<?xml version="1.0"?>
<scpd xmlns="urn:schemas-upnp-org:service-1-0">
    <specVersion>
        <major>1</major>
        <minor>0</minor>
    </specVersion>
    <actionList>
        <action>
            <name>GetCommonLinkProperties</name>
            <argumentList>
                <argument>
                    <name>NewWANAccessType</name>
                    <direction>out</direction>
                    <relatedStateVariable>WANAccessType</relatedStateVariable>
                </argument>
                <argument>
                    <name>NewLayer1UpstreamMaxBitRate</name>
                    <direction>out</direction>
                    <relatedStateVariable>Layer1UpstreamMaxBitRate</relatedStateVariable>
                </argument>
                <argument>
                    <name>NewLayer1DownstreamMaxBitRate</name>
                    <direction>out</direction>
                    <relatedStateVariable>Layer1DownstreamMaxBitRate</relatedStateVariable>
                </argument>
                <argument>
                    <name>NewPhysicalLinkStatus</name>
                    <direction>out</direction>
                    <relatedStateVariable>PhysicalLinkStatus</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>GetTotalBytesSent</name>
            <argumentList>
                <argument>
                    <name>NewTotalBytesSent</name>
                    <direction>out</direction>
                    <relatedStateVariable>TotalBytesSent</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>GetTotalBytesReceived</name>
            <argumentList>
                <argument>
                    <name>NewTotalBytesReceived</name>
                    <direction>out</direction>
                    <relatedStateVariable>TotalBytesReceived</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>GetTotalPacketsSent</name>
            <argumentList>
                <argument>
                    <name>NewTotalPacketsSent</name>
                    <direction>out</direction>
                    <relatedStateVariable>TotalPacketsSent</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
        <action>
            <name>GetTotalPacketsReceived</name>
            <argumentList>
                <argument>
                    <name>NewTotalPacketsReceived</name>
                    <direction>out</direction>
                    <relatedStateVariable>TotalPacketsReceived</relatedStateVariable>
                </argument>
            </argumentList>
        </action>
    </actionList>
    <serviceStateTable>
        <stateVariable sendEvents="no">
            <name>WANAccessType</name>
            <dataType>string</dataType>
            <allowedValueList>
                <allowedValue>DSL</allowedValue>
                <allowedValue>POTS</allowedValue>
                <allowedValue>Cable</allowedValue>
                <allowedValue>Ethernet</allowedValue>
                <allowedValue>Other</allowedValue>
            </allowedValueList>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>Layer1UpstreamMaxBitRate</name>
            <dataType>ui4</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>Layer1DownstreamMaxBitRate</name>
            <dataType>ui4</dataType>
        </stateVariable>
        <stateVariable sendEvents="yes">
            <name>PhysicalLinkStatus</name>
            <dataType>string</dataType>
            <allowedValueList>
                <allowedValue>Up</allowedValue>
                <allowedValue>Down</allowedValue>
                <allowedValue>Initializing</allowedValue>
                <allowedValue>Unavailable</allowedValue>
            </allowedValueList>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>MaximumActiveConnections</name>
            <dataType>ui2</dataType>
            <allowedValueRange>
                <minimum>1</minimum>
                <maximum>2</maximum>
                <step>1</step>
            </allowedValueRange>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>TotalBytesSent</name>
            <dataType>ui4</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>TotalBytesReceived</name>
            <dataType>ui4</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>TotalPacketsSent</name>
            <dataType>ui4</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>TotalPacketsReceived</name>
            <dataType>ui4</dataType>
        </stateVariable>
    </serviceStateTable>
</scpd>

广域网网络连接描述文件:

# wget  http://192.168.0.1:1900/ipc.xml
# cat ipc.xml

浏览ipc.xml文件:

<?xml version="1.0"?>
<scpd xmlns="urn:schemas-upnp-org:service-1-0">
    <specVersion>
        <major>1</major>
        <minor>0</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>ForceTermination</name>
        </action>
        <action>
            <name>RequestConnection</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>
        </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>Connected</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>
            <allowedValueList>
                <allowedValue>ERROR_NONE</allowedValue>
                <allowedValue>ERROR_UNKNOWN</allowedValue>
            </allowedValueList>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>RSIPAvailable</name>
            <dataType>boolean</dataType>
        </stateVariable>
        <stateVariable sendEvents="no">
            <name>NATEnabled</name>
            <dataType>boolean</dataType>
        </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>
        </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>
        </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>

ipc.xml文件中定义了soap api,发起一个soap service调用:

import urllib2

soap_body = """
<!--?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>   
"""

soap_action = "urn:schemas-upnp-org:service:WANIPConnection:1#GetExternalIPAddress"
headers = {
    'SOAPAction': u'"%s"' % (soap_action),
    'Host': u'192.168.0.1:1900',
    'Content-Type': 'text/xml',
    'Content-Length': len(soap_body),
}

ctrl_url = "http://192.168.0.1:1900/ipc"

request = urllib2.Request(ctrl_url, soap_body, headers)
response = urllib2.urlopen(request)

print response.read()

执行脚本:

# python soap_call.py

执行返回结果:

<?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:GetExternalIPAddressResponse xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1">
            <NewExternalIPAddress>100.64.172.239</NewExternalIPAddress>
        </u:GetExternalIPAddressResponse>
    </s:Body>
</s:Envelope>

tcpdump抓取报文:

18:24:53.487269 IP (tos 0x0, ttl 64, id 9843, offset 0, flags [DF], proto TCP (6), length 60)
sackOK,TS val 7356036 ecr 0,nop,wscale 7], length 0
E..<&s@.@......u.....f.lz.........r............
.p>.........
18:24:53.487756 IP (tos 0x0, ttl 64, id 37392, offset 0, flags [DF], proto TCP (6), length 60)
1460,nop,wscale 0,nop,nop,TS val 46794066 ecr 7356036], length 0
E..<..@.@.&........u.l.f.U..z.....@..d.............
...R.p>.
18:24:53.487780 IP (tos 0x0, ttl 64, id 9844, offset 0, flags [DF], proto TCP (6), length 52)
l 7356036 ecr 46794066], length 0
E..4&t@.@......u.....f.lz....U.............
.p>....R
18:24:53.488790 IP (tos 0x0, ttl 64, id 9845, offset 0, flags [DF], proto TCP (6), length 624)
TS val 7356036 ecr 46794066], length 572
E..p&u@.@..L...u.....f.lz....U.......).....
.p>....RPOST /ipc HTTP/1.1
Accept-Encoding: identity
Content-Length: 321
Soapaction: "urn:schemas-upnp-org:service:WANIPConnection:1#GetExternalIPAddress"
Connection: close
User-Agent: Python-urllib/2.7
Host: 192.168.0.1:1900
Content-Type: text/xml


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

18:24:53.497455 IP (tos 0x0, ttl 64, id 37393, offset 0, flags [DF], proto TCP (6), length 218)
6794066 ecr 7356036], length 166
E.....@.@.&F.......u.l.f.U..z..4..@........
...R.p>.HTTP/1.1 200 OK
Content-Type: text/xml;charset=UTF-8
Content-Length: 360
Connection: close
Cache-control: no-cache
Server: vxWorks/5.5 UPnP/1.0 TL-WR842N/8.0


18:24:53.497788 IP (tos 0x0, ttl 64, id 9846, offset 0, flags [DF], proto TCP (6), length 52)
S val 7356039 ecr 46794066], length 0
E..4&v@.@......u.....f.lz..4.U.{...........
.p>....R
18:24:53.498268 IP (tos 0x0, ttl 64, id 37394, offset 0, flags [DF], proto TCP (6), length 412)
 46794066 ecr 7356036], length 360
E.....@.@.%........u.l.f.U.{z..4..@.b......
...R.p>.<?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:GetExternalIPAddressResponse xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1">
      <NewExternalIPAddress>100.64.172.239</NewExternalIPAddress>
    </u:GetExternalIPAddressResponse>
  </s:Body>
</s:Envelope>

18:24:53.498272 IP (tos 0x0, ttl 64, id 37395, offset 0, flags [DF], proto TCP (6), length 52)
94066 ecr 7356036], length 0
E..4..@.@.&........u.l.f.U..z..4..@........
...R.p>.
18:24:53.498509 IP (tos 0x0, ttl 64, id 9847, offset 0, flags [DF], proto TCP (6), length 52)
S val 7356039 ecr 46794066], length 0
E..4&w@.@......u.....f.lz..4.U.............
.p>....R
18:24:53.498666 IP (tos 0x0, ttl 64, id 9848, offset 0, flags [DF], proto TCP (6), length 52)
TS val 7356039 ecr 46794066], length 0
E..4&x@.@......u.....f.lz..4.U.............
.p>....R
18:24:53.499362 IP (tos 0x0, ttl 64, id 37396, offset 0, flags [DF], proto TCP (6), length 52)
4066 ecr 7356039], length 0
E..4..@.@.&........u.l.f.U..z..5..?........
...R.p>.