0

I found a post that does what I need, but on Windows:

Discovering public IP programmatically

> tracert -d www.yahoo.com

`Tracing route to www-real.wa1.b.yahoo.com [69.147.76.15]
over a maximum of 30 hops:`

1    <1 ms    <1 ms    <1 ms  192.168.14.203
2     *        *        *     Request timed out.
3     8 ms     8 ms     9 ms  68.85.228.121
4     8 ms     8 ms     9 ms  68.86.165.234
5    10 ms     9 ms     9 ms  68.86.165.237
6    11 ms    10 ms    10 ms  68.86.165.242

The 68.85.228.121 is a Comcast (my provider) router. We can ping that:

ping -r 9 68.85.228.121 -n 1

Pinging 68.85.228.121 with 32 bytes of data:

Reply from 68.85.228.121: bytes=32 time=10ms TTL=253 Route: 66.176.38.51 ->

68.85.228.121 ->

68.85.228.121 ->

192.168.14.203

Voila! The 66.176.38.51 is my public IP.

This (third) answer shows a way to get my ISP's IP and then to use ping to get my IP.

It doesn't work unmodified on Linux. Traceroute works instead of tracert, but because its output is unpredictable, I'm not sure how to parse it.

I got as far as

IP="$(traceroute -d www.yahoo.com | grep ' 2 ' | sed -e 's/.*(\(.*\)).*/\1/')"

but the grep is (poorly) hard coded. I didn't see how to get ping to work as in the example.

Any input would be appreciated.

Community
  • 1
  • 1
Joe
  • 351
  • 2
  • 16
  • That's going to be a pretty unreliable way of discovering your public IP address. What do you need it for, anyway? – Greg Hewgill May 06 '12 at 05:19
  • I want to make it a bash function. My initial use will be in a script that notifies me when a specified port changes state between open and closed and I need more than my local ip to get a real answer. – Joe May 07 '12 at 07:57
  • @nikhil ifconfig returns inet addr:192.168.1.100 Bcast:192.168.1.255 Mask:255.255.255.0 for wlan0on my WRT54GL which is attached to my cable modem. It doesn't get me past my router. – Joe May 07 '12 at 08:31

5 Answers5

4

Personally, I'd run this command:

wget -qO- whatismyip.org

paulsm4
  • 114,292
  • 17
  • 138
  • 190
  • Did you actually try that? It returns: and if I click on that in the source code, I see an image of my IP - not text. When I access that site directly from my browser and look at the source code for the page, there's an IP embedded in it, but it's not the correct one that displays on the site. – Joe May 07 '12 at 08:15
1

I just combined what @pizza said with this answer and produced the following working script. It's not as nice as using something like traceroute, but it's a lot less complicated.

   #!/bin/bash
   content="$(wget http://checkip.dyndns.org/ -q -O -)"
   myip="$(<<< "$content" sed -e 's/.*Current IP Address: //' -e 's/<.*//')"
   echo "myip = [${myip}]"

The wget command retrieves the result of asking dyndns for my IP. Then, sed chops off everything before and after the IP address dyndns returns.

As noted elsewhere, websites such as dyndns may block such requests if they are made too frequently, but since your IP should remain constant in most situations for at least the duration of your session, if not for many days, it shouldn't be necessary to run this script very often.

Joe
  • 351
  • 2
  • 16
  • Since you have commented that you may use this on many different router, you need to be aware of the double-NAT problem. CGN will kill you every time, and so will the idiots who use a firewall/route/WAP just for the wireless without setting it to bridge mode. – Ron Maupin Feb 09 '16 at 09:31
0

This is not a reliable solution, a passive way to do this is to write a script to pull your own router's "WAN" status page. You can do that as many times as you want and nobody will complain about excessive probing.

pizza
  • 7,296
  • 1
  • 25
  • 22
  • I don't know how to do that. ifconfig returns inet addr:192.168.1.100 Bcast:192.168.1.255 Mask:255.255.255.0 for wlan0 which doesn't get me past my router. I'm not sure how to actually get the webpage from the router. – Joe May 07 '12 at 08:20
  • I just went through the screens of my WRT54GL router which is attached to my cable modem and I didn't find my external IP anywhere. – Joe May 07 '12 at 08:27
  • http://htmlimg4.scribdassets.com/7khrf7awzkdywwc/images/65-a930cf711c.jpg from http://www.scribd.com/doc/21136171/Linksys-WRT54GL-router-manual – pizza May 07 '12 at 23:36
  • pizza - That's brilliant and almost wonderful. The following gets my IP: shelelia@halo:~/bin$ wget -o status.txt -O - --user my-user --password my-password http://192.168.1.1/Status_Router.asp | grep "wan_ip" | head -1 | cut -d '"' -f 2 but it has my clear text router user and password in it and it only works on that router (assuming no firmware upgrades). In short, there must be a better way! – Joe May 10 '12 at 06:01
  • This code is for use on a notebook that may talk to many routers depending on its location at the moment and I won't usually have their passwords and they won't have identical firmware anyway. – Joe May 10 '12 at 06:10
  • 1
    If you don't require this probe too excessively, you have to rely on external servers like http://checkip.dyndns.org/ , when I said your original method is not reliable, it is because some ISP filters ICMP on their routers. The other route you can use is to register one of those dynamic IP servicers and use their update methods to find out your IP. If you use an external source to find out your IP, they almost always going to filter you if you use it excessively. – pizza May 10 '12 at 21:48
  • Just got back to this after a long time. If you make the above comment an answer (or edit it into your existing answer), I will accept it. The dyndns page works nicely. Just have to run the output through a tiny bit of sed. – Joe Jul 22 '13 at 20:55
0

ok, i know this is an old thread, but this posting revealed some things to me, and combining it with what I've already learned, I think I've come up with a solid solution.

The grep you want is:

grep -m 1 -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'

My personal solution to find my external IP used to be:

curl icanhazip.com

Now it is:

ISP=`traceroute -M 2 -m 2 8.8.8.8 | grep -m 1 -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'` | ping -R -c 1 -t 1 -s 1 $ISP | grep RR | grep -m 1 -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' > .extIP

and then

cat .extIP

Have fun!

n8person
  • 1
  • 1
  • Just looked into this a bit. At first glance, my versions of traceroute and ping don't seem to support all the options you use and they both error out with usage messages. I'm not particularly familiar with either command, so I'll have to research it further. – Joe Feb 09 '16 at 08:36
  • Let me know what linux distro you're using, and I'll try to test my scripts in a linux vm today and update my post! also post any error messages you got. in the meantime, try `traceroute -f 2 -m 2 8.8.8.8` or `traceroute -S 2 -m 2 8.8.8.8` i think the "-M flag i used needs to be "-f" or "-S" in linux... type `man traceroute` and look for a flag that says "max ttl". What these flags do is show only hop 2 in the results. to see hop 3 change your flags to "-f 3 -m 3" – n8person Feb 09 '16 at 14:38
0

IF what you want is simplicity, AND you don't mind relying on other servers (or services) try:

dig +short myip.opendns.com @resolver1.opendns.com

That will spit out your address only

or,

#!/bin/bash
myip="$(dig +short myip.opendns.com @resolver1.opendns.com)"
echo "myip = [${myip}]"
n8person
  • 1
  • 1