5

For monitoring purposes, I'd like to find out all public IPv4 and IPv6 addresses of a mobile-warrior UNIX box.

Note that this is different from Finding the Public IP address in a shell script because of the following extra requirements:

  • the mobile warrior itself probably does not have any public IPv4 addresses at all;
  • it may or may not have IPv6 (but we're only interested in active ones that would be used in actual outgoing connections);
  • the underlying internet connection might be load-balanced, details unknown, where a combination of UDP, TCP, ICMP and source/destination IP address, may determine which upstream will be used; we need to try our best to find out all such IP addresses for a complete picture on the underlying internet connectivity of the gateway, without having direct access to the gateway itself.
5

Explanation

We can determine the public IP address through DNS with dig (the DNS lookup utility from BIND), this lets us try out both UDP (with the +notcp option) and TCP (+tcp option), leaving only ICMP behind. However, we can try sending all these queries to multiple independent destination IPv4 and IPv6 addresses, making it more likely that the load-balancing of the connection will take place, returning more unique responses.

It would appear that the positioning of the -4 and -6 options with dig might also be handled differently depending on the order of the arguments — if positioned right after dig before the @ specifier, then it's enforced as a hard requirement; if positioned past the @ specifier and/or as a final argument, then it's enforced as a soft requirement (IPv4 will be used if IPv6 connectivity is missing); the snippet below uses it as a soft requirement to avoid having to implement error-handling.

We can use GNU Parallel to mix-and-match several commands and options that are at stake here.

Solution

Here's the full solution:

parallel -kj16 dig -t txt o-o.myaddr.l.google.com +short \
::: @ns{1,2,3,4}.google.com ::: -4 -6 ::: +notcp +tcp

Here's the same snippet as a single line:

parallel -kj16 dig -t txt o-o.myaddr.l.google.com +short ::: @ns{1,2,3,4}.google.com ::: -4 -6 ::: +notcp +tcp

Here's the same snippet SO inline:

parallel -kj16 dig -t txt o-o.myaddr.l.google.com +short ::: @ns{1,2,3,4}.google.com ::: -4 -6 ::: +notcp +tcp


Testing

Here's a demonstration of what the above parallel invocation would work to accomplish:

% parallel -k echo dig -t txt o-o.myaddr.l.google.com +short \
? ::: @ns{1,2,3,4}.google.com ::: -4 -6 ::: +notcp +tcp
dig -t txt o-o.myaddr.l.google.com +short @ns1.google.com -4 +notcp
dig -t txt o-o.myaddr.l.google.com +short @ns1.google.com -4 +tcp
dig -t txt o-o.myaddr.l.google.com +short @ns1.google.com -6 +notcp
dig -t txt o-o.myaddr.l.google.com +short @ns1.google.com -6 +tcp
dig -t txt o-o.myaddr.l.google.com +short @ns2.google.com -4 +notcp
dig -t txt o-o.myaddr.l.google.com +short @ns2.google.com -4 +tcp
dig -t txt o-o.myaddr.l.google.com +short @ns2.google.com -6 +notcp
dig -t txt o-o.myaddr.l.google.com +short @ns2.google.com -6 +tcp
dig -t txt o-o.myaddr.l.google.com +short @ns3.google.com -4 +notcp
dig -t txt o-o.myaddr.l.google.com +short @ns3.google.com -4 +tcp
dig -t txt o-o.myaddr.l.google.com +short @ns3.google.com -6 +notcp
dig -t txt o-o.myaddr.l.google.com +short @ns3.google.com -6 +tcp
dig -t txt o-o.myaddr.l.google.com +short @ns4.google.com -4 +notcp
dig -t txt o-o.myaddr.l.google.com +short @ns4.google.com -4 +tcp
dig -t txt o-o.myaddr.l.google.com +short @ns4.google.com -6 +notcp
dig -t txt o-o.myaddr.l.google.com +short @ns4.google.com -6 +tcp
%

P.S. More of GNU Parallel

To extend on our solution above, the following could be used to perform whois and rDNS lookups on all found addresses; note that for IPv6 lookups to work on BSDs and macOS, one might have to specify -a for ARIN, -A for APNIC or -r for RIPE as an option to whois:

parallel -kj16 dig -t txt o-o.myaddr.l.google.com +short ::: @ns{1,2,3,4}.google.com ::: -4 -6 ::: +notcp +tcp | sort -n | uniq | parallel -vk ::: "echo" "host" "whois -a" :::: /dev/stdin

  • 1
    :::: /dev/stdin can also be written :::: - which will also work on systems that do not support /dev/stdin. – Ole Tange Dec 16 '19 at 16:24

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.