My computers are sitting behind a router/firewall. How do I programmatically find out what my external IP address is. I can use http://www.whatsmyip.org/ for ad-hoc queries,
http://ipecho.net/plain appears to be a workable alternative, as whatismyip.com now requires membership for their automated link. They very kindly appear to be offering this service for free, so please don't abuse it.
If the router you are behind speak UPnP you could always use a UPnP library for whatever language you are developing in to query the router for its external ip.
Another way is if you have access to a cloud email (yahoo, google, hotmail), send yourself an email. Then view the headers and you should see your IP address in there.
I would look up the exact area but the headers may vary from each implmentation, Look for the received-by and follow that until you get to something that looks like sent-by
EDIT: This answers the how to find IP address, not the via PROGRAMMATIC approach
http://myexternalip.com provides this kind of information. To retrieve your IP you have plenty of options:
whatismyip.com or ipchicken.com are very easy to parse.
If you have a webhost or vps you can also determine it, without fear of it randomly going down leaving you stuck.
My WRT54G router tells me through its Local Router Access feature (the http(s) administration interface), and I imagine something similar could be done with many other devices. In this case, the entry page gives the octets of the IPv4 address in four lines containing this phrase:
class=num maxLength=3 size=3 value='i' name='wan_ipaddr_N' id='wan_ipaddr_N'
Where i is the octet value and N is the octet number. This bit of doggerel fetches and parses it for me, courtesy of cygwin:
#! /usr/bin/env perl
use strict;
use warnings 'all';
my( $account, $password ) = @ARGV;
open QUERY,
"curl --sslv3 --user '$account:$password' https://Linksys/ --silent |"
or die "Failed to connect to router";
my @ipaddr = ('x','x','x','x');
while( <QUERY> ) {
$ipaddr[$2] = $1 if /value='(\d+)' name='wan_ipaddr_([0-3])/;
}
close QUERY;
print join('.', @ipaddr);
There is no guarantee that this will work with all versions of the router firmware.
If your router is set to use http for this interface, drop the --sslv3 curl option, and you can use dotted-decimal notation to address the router. To use https with the curl options above, I also did this:
Used a browser to fetch the router's self-signed certificate (saved as Linksys.crt).
Added it to my CA bundle:
openssl x509 -in Linksys.crt -text >> /usr/ssl/certs/ca-bundle.crt
Alternatively, you could just use the --insecure option to bypass certificate verification, which probably makes more sense in the circumstances.