lontivero / Open.NAT

Lightweight and easy-to-use class library to allow port forwarding in NAT devices with UPNP and/or PMP
MIT License
419 stars 99 forks source link

Incorrect ServiceType from Netgear WNR2000v5 #66

Open sheindel opened 7 years ago

sheindel commented 7 years ago

Netgear WNR2000v5 reports the following to SSDP response

HTTP/1.1 200 OK
Cache-Control: max-age=1800
ST: urn:schemas-upnp-org:service:WANIPConnection:1
USN: uuid:12345678-0000-0000-0000-00000000abcf::urn:schemas-upnp-org:service:WANIPConnection:1
EXT:
Server: WNR2000v5 UPnP/1.0 miniupnpd/1.0
Location: http://192.168.2.1:5555/rootDesc.xml

And the following router device list response

<device>
    <deviceType>urn:schemas-upnp-org:device:WANDevice:1</deviceType>
    <friendlyName>WAN Device</friendlyName>
    <manufacturer>NETGEAR</manufacturer>
    <manufacturerURL>http://www.netgear.com</manufacturerURL>
    <modelDescription>WAN Device on NETGEAR WNR2000v5 Wireless Router</modelDescription>
    <modelName>RangeMax N300 Wireless Router</modelName>
    <modelNumber>WNR2000v5</modelNumber>
    <modelURL>http://www.netgear.com</modelURL>
    <serialNumber>v1</serialNumber>
    <UDN>uuid:12345678-0000-0000-0000-00000000abce</UDN>
    <UPC>WNR2000v5</UPC>
    <serviceList>
        <service>
            <serviceType>urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1</serviceType>
            <serviceId>urn:upnp-org:serviceId:WANCommonIFC1</serviceId>
            <controlURL>/ctl/CommonIfCfg</controlURL>
            <eventSubURL>/evt/CommonIfCfg</eventSubURL>
            <SCPDURL>/WANCfg.xml</SCPDURL>
        </service>
    </serviceList>
    <deviceList>
        <device>
            <deviceType>urn:schemas-upnp-org:device:WANConnectionDevice:1</deviceType>
            <friendlyName>WAN Connection Device</friendlyName>
            <manufacturer>NETGEAR</manufacturer>
            <manufacturerURL>http://www.netgear.com</manufacturerURL>
            <modelDescription>WANConnectionDevice on NETGEAR WNR2000v5 Wireless Router</modelDescription>
            <modelName>RangeMax N300 Wireless Router</modelName>
            <modelNumber>WNR2000v5</modelNumber>
            <modelURL>http://www.netgear.com</modelURL>
            <serialNumber>v1</serialNumber>
            <UDN>uuid:12345678-0000-0000-0000-00000000abcf</UDN>
            <UPC>WNR2000v5</UPC>
            <serviceList>
                <service>
                    <serviceType>urn:schemas-upnp-org:service:WANEthernetLinkConfig:1</serviceType>
                    <serviceId>urn:upnp-org:serviceId:WANEthLinkC1</serviceId>
                    <controlURL>/ctl/WanEth</controlURL>
                    <eventSubURL>/evt/WanEth</eventSubURL>
                    <SCPDURL>/WanEth.xml</SCPDURL>
                </service>
                <service>
                    <serviceType>urn:schemas-upnp-org:service:WANPPPConnection:1</serviceType>
                    <serviceId>urn:upnp-org:serviceId:WANPPPConn1</serviceId>
                    <controlURL>/ctl/PPPConn</controlURL>
                    <eventSubURL>/evt/PPPConn</eventSubURL>
                    <SCPDURL>/WANPPPCn.xml</SCPDURL>
                </service>
            </serviceList>
        </device>
    </deviceList>
</device>

When calling GetAllMappingsAsync(), the following data is returned

<?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:GetGenericPortMappingEntryResponse xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1">
            <NewRemoteHost/>
            <NewExternalPort>10034</NewExternalPort>
            <NewProtocol>TCP</NewProtocol>
            <NewInternalPort>10034</NewInternalPort>
            <NewInternalClient>192.168.2.2</NewInternalClient>
            <NewEnabled>1</NewEnabled>
            <NewPortMappingDescription>Open.NAT</NewPortMappingDescription>
            <NewLeaseDuration>0</NewLeaseDuration>
        </u:GetGenericPortMappingEntryResponse>
    </s:Body>
</s:Envelope>
<?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:GetGenericPortMappingEntryResponse xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1">
            <NewRemoteHost/>
            <NewExternalPort>12867</NewExternalPort>
            <NewProtocol>TCP</NewProtocol>
            <NewInternalPort>12867</NewInternalPort>
            <NewInternalClient>192.168.2.2</NewInternalClient>
            <NewEnabled>1</NewEnabled>
            <NewPortMappingDescription>Open.NAT</NewPortMappingDescription>
            <NewLeaseDuration>0</NewLeaseDuration>
        </u:GetGenericPortMappingEntryResponse>
    </s:Body>
</s:Envelope>

As can be seen, the ServiceType that is returned with the mapping is urn:schemas-upnp-org:service:WANIPConnection:1

But when the UPnP device info was set up, it found ServiceType urn:schemas-upnp-org:service:WANPPPConnection:1 (per UPnPSearcher.cs, BuildUpnpNatDeviceInfo(IPAddress localAddress, Uri location)) as the ServiceType. As such, GetPortMappingEntryResponseMessage constructor throws an exception at XmlNode data = GetNode(); because that function uses the ServiceType to get the root of the mapping response data, and in this case the servicetype is not there.

Are you aware if the disparity between the SSDP ServiceType and the router device list ServiceType is a discrepancy or does each implementation still confirm the to the spec? If so, this would be a bug in the firmware and I would be open to suggestions to get around it for the time being. If this is in line with the spec, can we always use the SSDP reported service type or would it be better to store both names to use one as a "fallback"? Or perhaps just reference the child element without specifying the ServiceType in the XPath so it isn't an issue?

lontivero commented 7 years ago

@sheindel thanks for reporting this issue.

When we send a SDDP query, the ST header specifies the Service Type we are looking for. That means that any discoverable server that offers that service type has to respond with the an url to the device definition (containing its list of services).

What I see here is that your server responds with a Hi, i provide the kind of service that you are looking for (urn:schemas-upnp-org:service:WANIPConnection:1) and gives you a url to a device that doesn't provide that ST. This is because your router uses miniupnpd software and that only works with WANIPConnection, anway, it seems a bit wierd that the service description announces a WANPPPConnection.

Q: Are you sure the device description that you've shared here (the XML) is the one available in http://192.168.2.1:5555/rootDesc.xml? Please, paste the url in your browser and check it by yourself.

I would need to review the log files. Could you share that here? (of course remove all the info you don't want to publish)

sheindel commented 7 years ago

Here is the exact rootDesc.xml. The framework chooses WANIPConnection:1 when we in fact get WANPPPConnection:1

So again, either the SSDP server or the UPnP server is reporting the wrong service type... I might just implement a workaround for now that uses the ServiceType from the SSDP server as a fallback.

Open to other suggestions.

Service Definition ```xml 1 0 http://192.168.2.1:5555 VEN_01f2&DEV_0004&REV_05 VEN_01f2&DEV_8000&REV_01 VEN_0033&DEV_0008&REV_01 urn:schemas-upnp-org:device:InternetGatewayDevice:1 NetworkInfrastructure.Router Network.Router.Wireless urn:schemas-upnp-org:device:InternetGatewayDevice:1 WNR2000v5 (Gateway) NETGEAR, Inc. http://www.netgear.com NETGEAR WNR2000v5 RangeMax N300 Wireless Router RangeMax N300 Wireless Router WNR2000v5 http://www.netgear.com/home/products/wirelessrouters v1 uuid:12345678-0000-0000-0000-00000000abcd WNR2000v5 urn:schemas-upnp-org:service:Layer3Forwarding:1 urn:upnp-org:serviceId:L3Forwarding1 /ctl/L3Forwarding /evt/L3Forwarding /Layer3F.xml urn:schemas-upnp-org:device:WANDevice:1 WAN Device NETGEAR http://www.netgear.com WAN Device on NETGEAR WNR2000v5 Wireless Router RangeMax N300 Wireless Router WNR2000v5 http://www.netgear.com v1 uuid:12345678-0000-0000-0000-00000000abce WNR2000v5 urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1 urn:upnp-org:serviceId:WANCommonIFC1 /ctl/CommonIfCfg /evt/CommonIfCfg /WANCfg.xml urn:schemas-upnp-org:device:WANConnectionDevice:1 WAN Connection Device NETGEAR http://www.netgear.com WANConnectionDevice on NETGEAR WNR2000v5 Wireless Router RangeMax N300 Wireless Router WNR2000v5 http://www.netgear.com v1 uuid:12345678-0000-0000-0000-00000000abcf WNR2000v5 urn:schemas-upnp-org:service:WANEthernetLinkConfig:1 urn:upnp-org:serviceId:WANEthLinkC1 /ctl/WanEth /evt/WanEth /WanEth.xml urn:schemas-upnp-org:service:WANPPPConnection:1 urn:upnp-org:serviceId:WANPPPConn1 /ctl/PPPConn /evt/PPPConn /WANPPPCn.xml http://www.routerlogin.net ```

And here is an snippet response of one of the port mappings

GetGenericPortMappingEntryResponse response ```xml 11699 TCP 11699 192.168.2.2 1 CTMobileServer 0 ```
lontivero commented 7 years ago

I think that by the moment you can do what you say: use the ST from de SSDP as fallback or, use the one in the response. In pseudocoude:

var st = responseText.Match("WAN[IP|PPP]Connection").Text;

For a better solution I have to review the miniupnpd server code in order to understand why it behaves as it does.