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

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 1 '17 at 1:08

An alternative is Google DNS:

myip(){   dig @ -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 |
          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 @  |
          grep "^myip\.opendns\.com\."             |
          grep -o "\([0-9]\{1,3\}\.\)\{3\}\([0-9]\{1,3\}\)"  ; }

And with host:

myip(){   host myip.opendns.com  |
          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_'

Call an array address like this:

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

In some sites https may also work.

|improve this answer|||||
  • 2
    FWIW, I'm seeing about 20% of responses from 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 | awk '/has address/ { print $4; }'. – lapo Nov 15 '17 at 8:17

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.

|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy