3

I'm trying to find a way to get my router to report back my WAN IP using UPnP/SSDP, but so far I have been unable to even get a list of UPnP supporting internet access devices on my network. Here's the request I'm sending:

$ cat request.txt
M-SEARCH * HTTP/1.1
HOST: 239.255.255.250:1900
MAN: "ssdp:discover"
MX: 3
ST: urn:schemas-upnp-org:device:InternetGatewayDevice:1

With the command:

$ nc -uvv 239.255.255.250 1900 < request.txt
Connection to 239.255.255.250 1900 port [udp/ssdp] succeeded!

I just get the connnection succeded message and then nothing...

Could anyone give me any pointers (no memory addresses please!) as to what I'm doing wrong?

Update: Ok so I tried using tcpdump to get responses here's what I got:

$ sudo tcpdump -vv -A -s 0 -i en1 udp port 1900 and host 239.255.255.250 
…
NOTIFY * HTTP/1.1
Host: 239.255.255.250:1900
Cache-Control: max-age=60
Location: http://192.168.1.1:1780/InternetGatewayDevice.xml
NTS: ssdp:alive
Server: POSIX, UPnP/1.0 linux/5.100.104.2 
NT: urn:schemas-upnp-org:device:InternetGatewayDevice:1
…

I guess the next step is to parse the output of tcpdump and filter out all responses that don't contain the NT: urn:schemas-upnp-org:device:InternetGatewayDevice:1 header then make the actual SOAP request to the router.

1
  • Why does your 'nc' command use two 'v' parameters?
    – parsley72
    May 18, 2012 at 3:01

4 Answers 4

3

You'll need to use tcpdump or something similar to see the reply or replies.

nc is looking for a reply from the endpoint you sent the request to. But the endpoint you sent the request to is a generic broadcast target. The reply will come not from a generic broadcast target but from the specific device that replies.

As nc's output says, it has connected to the broadcast target. So it's not going to see the replies that come from the replying devices.

1

Although, this task is rather old, I post the answer, I was looking for, myself.

Your UPnP-reply posted the location "http://192.168.1.1:1780/InternetGatewayDevice.xml"

There you can get more info about data format. For my router: I got there more paths to xmls. Calling them, there is more UPnP info. resulting in this: I called:

POST /upnp/control?WANIPConnection HTTP/1.1
Host: 192.168.1.1
SOAPAction: "urn:schemas-upnp-org:service:WANIPConnection:1#GetExternalIPAddress"
Accept-Language: de-de;q=1, de;q=0.5
Accept-Encoding: gzip
Content-Type: text/xml; charset="utf-8"
User-Agent: gupnp-universal-cp GUPnP/0.20.10 DLNADOC/1.50
Connection: Keep-Alive
Content-Length: 281

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

and get as answer:

HTTP/1.1 200 OK
EXT:
Content-Type: text/xml; charset="utf-8"
Date: Tue, 04 Aug 2015 23:55:01 GMT
Server: servername/2.0 UPnP/1.0 UPnP-Device-Host/1.0
Content-Length: 380

<?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>123.123.123.123</NewExternalIPAddress>
        </u:GetExternalIPAddressResponse>
    </s:Body>
</s:Envelope>

I've got a lot of help from "UPnP Inspector"

1

You can use socat

$ socat -T1 STDIO UDP4-DATAGRAM:239.255.255.250:1900 < request.txt
0

Fully working BASH script:

#!/usr/bin/env bash
function wan_ip_connection() {
    local host=$1
    result=$( curl -s "http://$host/upnp/control?WANIPConnection" \
       -H 'SOAPAction: "urn:schemas-upnp-org:service:WANIPConnection:1#GetExternalIPAddress"' \
       --data-binary '<?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>'
    )

    REGEX='ExternalIPAddress>([0-9.]+)<'
    if [[ $result =~ $REGEX ]]
    then
       echo "${BASH_REMATCH[@]:1}"
    fi
}

function initial_query() {
   echo -e 'M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nMAN: "ssdp:discover"\r\nMX: 3\r\nST: urn:schemas-upnp-org:device:InternetGatewayDevice:1\r\n\r\n' |
       socat STDIO UDP4-DATAGRAM:239.255.255.250:1900
}

function main() {
   location=$( initial_query | grep LOCATION )
   location=${location%/*}
   location=${location##*/}
   ip=$( wan_ip_connection "$location" )
   echo $ip
}

main

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .