7

This question: "How can I get my external IP address in bash?"

Solves the question with a call to dig:

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

that is the fastest resolution possible, as it involves a single udp packet.

However, that is only one site: OpenDNS, Is there any alternative?

And, makes use of dig, that is not available by default. Again, Is there an alternative?


Note: I needed to solve this problem as the OpenDNS service didn't work locally due to a (also local) redirect of port 53. I finally found out the reason (I had forgotten about the redirect). First, by using this command to find if dnssec is working (locally missing ad flag):

dig pir.org +dnssec +multi

And also using this command to find out if your ISP is redirecting OpenDNS resolutions:

host -t txt which.opendns.com 208.67.220.220

If being redirected, you will get an answer of: "I am not an OpenDNS resolver."

  • Just an FYI regarding public resolution using OpenDNS. An alternative (any equally as simple as using dig) is to use: curl diagnostic.opendns.com/myip – Travis Clarke Feb 01 '17 at 01:08

3 Answers3

11

An alternative is Google DNS:

myip(){   dig @8.8.8.8 -t txt o-o.myaddr.l.google.com |
          grep "client-subnet" |
          grep -o "\([0-9]\{1,3\}\.\)\{3\}\([0-9]\{1,3\}\)" ;   }

If your system does not have dig, then host will be exactly equivalent:

myip(){   host -t txt o-o.myaddr.l.google.com 8.8.8.8 |
          grep -oP "client-subnet \K(\d{1,3}\.){3}\d{1,3}";   }

Both GNU grep (Perl-like -P) and basic (BRE) regex are shown.

And, of course the original site, will also work.
With dig:

myip(){   dig myip.opendns.com @208.67.220.222  |
          grep "^myip\.opendns\.com\."             |
          grep -o "\([0-9]\{1,3\}\.\)\{3\}\([0-9]\{1,3\}\)"  ; }

And with host:

myip(){   host myip.opendns.com 208.67.220.222  |
          grep -oP "^myip\.opendns\.com.* \K(\d{1,3}\.){3}(\d{1,3})" ; }

The two snippets above will work with any of this four OpenDNS resolver addresses:

echo 208.67.22{0,2}.22{0,2}

If the direct DNS solution fails in the future, use curl to one of this sites (urls):

IFS=$'\n' read -d '' -a urls <<-'_end_of_text_'
api.ipify.org
bot.whatismyipaddress.com/
canhazip.com/
checkip.dyndns.com/
corz.org/ip
curlmyip.com/
eth0.me/
icanhazip.com/
ident.me/
ifcfg.me/
ifconfig.me/
ip.appspot.com/
ipecho.net/plain
ipof.in/txt
ip.tyk.nu/
l2.io/ip
tnx.nl/ip
wgetip.com/
whatismyip.akamai.com/
_end_of_text_

Call an array address like this:

$ i=5; curl -m10 -L "http://${urls[i]}"
116.132.27.203

In some sites https may also work.

  • 2
    FWIW, I'm seeing about 20% of responses from 8.8.8.8 containing an edns0-client-subnet value that is not my address. Google might be doing some fuzzing or CDN-geared optimization, but this does not seem to produce accurate results. – Grisha Levit Mar 14 '17 at 11:53
  • Myself I'm using host myip.opendns.com 208.67.222.222 | awk '/has address/ { print $4; }'. – lapo Nov 15 '17 at 08:17
  • For the opendns resolver you can avoid using grep just by passing the +short flag to dig: dig myip.opendns.com @208.67.220.222 +short – Chris Nov 29 '21 at 03:28
2

I've concluded that many of these items are beacons that can identify you to somebody sniffing your network traffic and/or the service you are requesting this information from.

I recommend an HTTPS query to a service that preserves your privacy:

wget -qqO- 'https://duckduckgo.com/?q=what+is+my+ip' \
  | grep -Pow 'Your IP address is \K[0-9.]+'

(In the event you're on an embedded or other limited system and don't have grep -P (libpcre), use
… | grep -ow 'Your IP address is [0-9.]*[0-9]' | grep -ow '[0-9][0-9.]*'  instead).

If you (and/or others on your IP) don't use the privacy-conscientious DuckDuckGo search engine, then perhaps even that is a beacon (though your query is itself indecipherable to a third party, perhaps the fact that there was any query is too much?). You can do the same thing with Google, though Google expressly denies access to wget and similar utilities, so you have to forge your User Agent:

wget -U Mozilla/5.0 -qqO- 'https://www.google.com/search?q=what+is+my+ip' \
  | grep -Po '>\K[0-9.]{7,}(?=<.{0,99}>Your public IP)'

This may violate Google's terms of use.

Presumably, you'll have to change the regex class from [0-9.] to [0-9a-f:] for IPv6. I don't know what it'll look like if you're dual-stack.

Adam Katz
  • 3,965
0

I use the following:

dig @1.1.1.1 TXT whoami.cloudflare.com +short | tr -d \"

Or, with host:

$ host=whoami.cloudflare.com
$ host -t TXT "$host" 1.1.1.1 | sed -En "s/^$host.+"'"([^"]*)"/\1/p'
Tom Hale
  • 30,455