If this example doesn't work for you in Linux don't fret (read on).

I wanted to do a works-everywhere example using nc and tcpdump, but since the behavior varies quite wildly between OS X, Linux, and BSD, and because different UPnP Gateways may be more strict or lenient, I had to chunk it out into a few different articles.

See also:

Anyway, if the tcpdump + netcat method fails you, try out the node.js example (above) or adapt that example to python, ruby, or whatever.

Find your Internet Gateway (router) with a UPnP Search Broadcast

1. Listen with tcpdump

When it comes to udp, netcat is a little too smart for its own good.

You will send a message with netcat to the special UPnP broadcast address The response, however, will come from your router's IP address. Because of this mismatch, netcat will ignore the response.

You need two listeners:

# Listen for all UPnP broadcasts (including yourself)
sudo tcpdump -vv -A -s 0 'port 1900 and host and udp'
# Find your router's IP (probably or
route -n get default

# Listen for inbound messages from your router 
sudo tcpdump -vv -A -s 0 "src host and udp"

2. put the UPnP Gateway Search request in a file

IMPORTANT: Strict implementations require CRLF (\r\n), not just any old newline. You might get lucky, but don't count on it.

You should download my example, which has the appropriate CRLF line endings:

wget https://coolaj86.com/assets/media/examples/upnp-gateway-search.txt

Just so you know what the message looks like (or if you want to write it yourself in an editor you know how to force-save with CRLF), here she be:

MAN: "ssdp:discover"
MX: 1
ST: urn:schemas-upnp-org:device:InternetGatewayDevice:1

NOTE: There is a second newline after the last line \r\n\r\n, just like the HTTP spec.

3. Use GNU netcat to Broadcast the UPnP search request

IMPORTANT: OS X, BSD, and various flavors of Linux use very different versions of netcat, but -u is pretty much universal for udp mode.

nc -u 1900 < upnp-search.txt

NOTE: If your netcat supports it, using verbose mode (-vv) might benefit you.

NOTE: In some versions of netcat you can add the -c argument instructs netcat to send \r\n (meaning CRLF) instead of the operating system default, but in other versions it is used to execute shell commands... bad news bears. Use at your own risk.

4. Look for the response

Note that you'll see broadcasts from many computers and devices on the network.

You should try to find the one that has the stuff you need.

The outgoing message will look like this:

22:47:44.094582 IP (tos 0x0, ttl 1, id 13417, offset 0, flags [none], proto UDP (17), length 165)
    my-compy.58838 > [udp sum ok] UDP, length 137
    ..^...........E...4i.........w.......l.._.M-SEARCH * HTTP/1.1
    MAN: "ssdp:discover"
    MX: 1
    ST: urn:schemas-upnp-org:device:InternetGatewayDevice:1

The response will look like this:

22:49:29.631626 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 379)
    my-router.ssdp > my-compy.49639: [udp sum ok] UDP, length 351
    .......@......E..{..@.@..........w.l...g..HTTP/1.1 200 OK
    Cache-Control: max-age=300
    Date: Sun, 08 Feb 2015 04:49:34 GMT
    Server: POSIX UPnP/1.0 DD-WRT Linux/V24
    ST: urn:schemas-upnp-org:device:InternetGatewayDevice:1
    USN: uuid:A94F38D6-4529-3394-5DF5-0916F5DCF020::urn:schemas-upnp-org:device:InternetGatewayDevice:1

The Location it what's important. Each router may use a different port

Apple Airport Extreme and Apple Airport Express

These DO NOT support UPnP SSDP. They support Bonjour (ZeroConf / mDNS) NAT-PMP instead.

I intend to update this with a link to another article once I figure out how to do gateway discovery with that.


More fun with UPnP and cURL

Continue on to Adventures in UPnP with cURL and netcat.

By AJ ONeal

If you loved this and want more like it, sign up!

Did I make your day?
Buy me a coffeeBuy me a coffee  

(you can learn about the bigger picture I'm working towards on my patreon page )