How can I get my external IP address in a shell script?

  • I need to find my external IP address from a shell script. At the moment I use this function:

    myip () { 
        lwp-request -o text checkip.dyndns.org | awk '{ print $NF }'
    }
    

    But it depends on perl-libwww, perl-html-format, perl-html-tree installed. What other ways can I get my external IP?

    What do you mean by the external IP? The two answers so far use HTTP. The response may end up being the IP of your ISP's proxy server. (Which may be what you want.)

    @billpg: I mean the IP of the NAT router

    Then you'll need a what-is-my-IP web service that uses HTTPS. Alas, I don't know of any.

    http://checkip.amazonaws.com/ use this from well known provider

  • Timo Tijhof

    Timo Tijhof Correct answer

    7 years ago

    I'd recommend getting it directly from a DNS server.

    Most of the other answers below all involve going over HTTP to a remote server. Some of them required parsing of the output, or relied on the User-Agent header to make the server respond in plain text. Those change quite frequently (go down, change their name, put up ads, might change output format etc.).

    1. The DNS response protocol is standardised (the format will stay compatible).
    2. Historically, DNS services (OpenDNS, Google Public DNS, ..) tend to survive much longer and are more stable, more scalable, and generally more looked-after than whatever new hip whatismyip.com HTTP service is hot today.
    3. This method is inherently faster (be it only by a few milliseconds!).

    Using dig with OpenDNS as resolver:

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

    Perhaps alias it in your bashrc so it's easy to remember

    alias wanip='dig @resolver1.opendns.com ANY myip.opendns.com +short'
    

    Responds with a plain ip address:

    $ wanip
    80.100.192.168 # or, 2606:4700:4700::1111
    

    Syntax

    (Abbreviated from https://ss64.com/bash/dig.html):

    usage:  dig [@global-dnsserver] [q-type] <hostname> <d-opt> [q-opt]
    
        q-type   one of (A, ANY, AAAA, TXT, MX, ...). Default: A.
    
        d-opt    ...
                 +[no]short          (Display nothing except short form of answer)
                 ...
    
        q-opt    one of:
                 -4                  (use IPv4 query transport only)
                 -6                  (use IPv6 query transport only)
                 ...
    

    The ANY query type returns either an AAAA or an A record. To prefer IPv4 or IPv6 connection specifically, use the -4 or -6 options accordingly.

    To require the response be an IPv4 address, replace ANY with A; for IPv6, replace it with AAAA.Note that it can only return the address used for the connection. For example, when connecting over IPv6, it cannot return the A address.

    Alternative servers and examples

    In addition to OpenDNS, there are similar DNS services provided by Akamai and Google:

    $ dig @ns1-1.akamaitech.net ANY whoami.akamai.net +short
    80.100.192.168
    
    $ dig @ns1.google.com TXT o-o.myaddr.l.google.com +short
    "80.100.192.168"
    

    Example alias that specifically requests an IPv4 address:

    alias wanip4='dig @resolver1.opendns.com A myip.opendns.com +short -4'
    
    $ wanip4
    80.100.192.168
    

    And for IPv6:

    alias wanip6='dig @resolver1.opendns.com AAAA myip.opendns.com +short -6'
    
    $ wanip6
    2606:4700:4700::1111
    

    Troubleshooting

    If the command is not working for some reason, there may be a problem with the upstream provider, the command-line tool, or something else. To help understand why it is not working, run the command without the +short option to reveal the details of the DNS query. For example:

    $ dig @resolver1.opendns.com ANY myip.opendns.com
    
    ;; Got answer: ->>HEADER<<- opcode: QUERY, status: NOERROR
    
    ;; QUESTION SECTION:
    ;myip.opendns.com.      IN  ANY
    
    ;; ANSWER SECTION:
    myip.opendns.com.   0   IN  AAAA    2606:4700:4700::1111
    
    ;; Query time: 4 msec
    ;; WHEN: Fri Apr 11 00:00:01 GMT 2011
    

    you are right it's too fast..

    sounds like a good approach, but as of now, for my current IP in indonesia, it returns no result, whereas http based mechanisms are working.

    @Krinkle that's an excellent answer. Is there an equivalent for `myip.opendns.com` in Googles Public DNS ?

    I found this to be ~19x faster than `curl http://canhazip.com`. See http://askubuntu.com/a/427092/2273

    Love this clean / no dependencies approach much better than all other proposals, unless you're bound to port 80

    Very useful answer, working great when programmatically doing a DNS lookup as well. I would definitely rely on resolver1.opendns.com more than the random "getmyip" type websites. The only thing I don't like is any official documentation on this feature, though I trust it won't disappear anytime soon. I would also like to know if any other DNS servers have a similar feature, like Googles?

    This didn't work for me on my rackspace cloud server.. it returned the LAN IP for some reason, whereas using whatismijnip.nl (the next answer) worked correctly. I'm not sure why this is but this is certainly worth taking into account.

    Are there any other providers for this method? Also, how does it compare to the `nslookup . ifcfg.me` method as in Eun's comment above? Isn't that also using DNS?

    @JamesHaigh < they are plenty of providers, see http://serverfault.com/a/560059

    It's more elegant to put bash aliases in `~/.bash_aliases` instead directly placing them in `~/.bashrc`.

    upvoted for sheer elegance and flawless reasoning. (however, for super pointless geek mode, i changed the cmd order to match the `man` page)

    Upvoted because it has the least dependencies. Dig seems to be present on almost any system in comparison to curl, externalip, wget, .... etc.

    Please note that in some cases the routers that provide NAT will also translate DNS responses (you can take a look at http://wiki.nil.com/Network_address_translation_of_DNS_responses); in this case you should fallback to some answer that recommends other approach than DNS.

    This doesn't work when behind my company proxy.

    `ip route get 8.8.8.8 | head -1 | cut -d" " -f8` should do.

    @tonythomas01 ip route get 8.8.8.8 | awk '{print $NF; exit}'

    can you elaborate on that command scheme ? do other servers also support "myip." ?

    @elig The protocol being used is standard DNS. The name "myip" is not part of this principle, rather it is only the name of a specific OpenDNS.com service. If other providers also offer this service, they may use a different subdomain name.

    For IPv6: `dig +short myip.opendns.com AAAA @resolver1.ipv6-sandbox.opendns.com`

    This is so fast! But what is `wan` though?

    No longer get a response on `DiG 9.12.3` on OSX. Someone has the same problem?

    @lony I've had the same issue. I've updated the command to explicitly request the "AAAA" record over DNS (previously implied), and now it works again. This also matches recommendations from the OpenDNS support community.

    You will probably want to add `+tcp` to the `dig` command, to prevent funny results from intermediate boxes

    I assumed AAAA is only needed if I use IPv6. Even with it, I do not have a consistent result both at work and at home. Sometimes it works with and sometimes without :(

License under CC-BY-SA with attribution


Content dated before 6/26/2020 9:53 AM