How do I ask "dig" to only return the IP from a CNAME record?
The dig +short
command (such as described in "dig show only answer") is great for batch processing names into IP addresses. It does a simple job and does it well.
Unfortunately when there's a CNAME even +short
isn't short enough. For example:
$ dig +short docs.sbonds.org
ghs.google.com.
173.194.69.121
I've tried +noall
but it doesn't seem like it changes the behavior of +short
. I've also tried specifying -t a
just to ensure it didn't think I meant an A record or CNAME, but that (unsurprisingly) changes nothing.
$ dig +noall +short docs.sbonds.org
ghs.google.com.
173.194.69.121
I'm using RedHat 7's dig
:
# dig -v
DiG 9.9.4-RedHat-9.9.4-73.el7_6
I can filter out the CNAMEs with trusty grep
, but it seems like dig should have some way to give "Just the IP, ma'am."
What is that way?
dig
is a troubleshooting tool, so it sends DNS queries and receives DNS answers and as Andreas said the answer is both CNAME and A records, as designed. Your wish is to give "Just the IP, ma'am.", so that is not a DNS troubleshooting, it is "just" the resolution, for which dig
is too much.
nslookup
nslookup
is inferior to dig
but will still give you too much:
$ nslookup docs.sbonds.org
Server: 192.0.2.254
Address: 192.0.2.254#53
Non-authoritative answer:
docs.sbonds.org canonical name = ghs.google.com.
Name: ghs.google.com
Address: 172.217.4.179
host
host
is simpler but will still return "too much" for you (but note that it returns also the IPv6 address which is good):
$ host docs.sbonds.org
docs.sbonds.org is an alias for ghs.google.com.
ghs.google.com has address 172.217.15.83
ghs.google.com has IPv6 address 2607:f8b0:4004:815::2013
getent
Depending on your Unix system, getent
can be used. Note however that this may or may not do a DNS query because you configure in /etc/nsswitch.conf
the source of data per service, and for hosts
it will probably be a mix of both files
(which is the venerable /etc/hosts
) and the DNS.
$ getent hosts docs.sbonds.org
2607:f8b0:4007:801::2013 ghs.google.com docs.sbonds.org
Observe also that on a proper Unix setup it will favor IPv6 over IPv4 so that may be a problem for you (this should depend on the configuration in /etc/gai.conf
)
In fact hosts
does not honor /etc/gai.conf
, you need to use ahosts
instead, which will use getaddrinfo
and hence gai.conf
. Observe that you get a list (whose order depends on gai.conf
configuration):
$ getent ahosts docs.sbonds.org
172.217.4.179 STREAM ghs.google.com
172.217.4.179 DGRAM
172.217.4.179 RAW
2607:f8b0:4007:801::2013 STREAM
2607:f8b0:4007:801::2013 DGRAM
2607:f8b0:4007:801::2013 RAW
Perl
If you are allowed to write a simple script, you have many solutions, like:
$ perl -MSocket -E 'say inet_ntoa(inet_aton("docs.sbonds.org"))'
172.217.4.179
DOH
Or use any DOH (DNS over HTTPS) endpoint (or similar) with any HTTP client. Examples:
$ curl --silent 'https://dns.google.com/resolve?name=docs.sbonds.org&type=A' | jq -c '.Answer[] | select(.type == 1) | .data'
"172.217.3.83"
$ curl --silent -H 'accept: application/dns-json' 'https://cloudflare-dns.com/dns-query?name=docs.sbonds.org&type=A' | jq -c '.Answer[] | select(.type == 1) | .data'
"172.217.12.147"
Systemd
Systemd has its own resolver application:
$ systemd-resolve docs.sbonds.org
docs.sbonds.org: 172.217.9.51
2607:f8b0:4009:801::2013
(ghs.google.com)
-- Information acquired via protocol DNS in 239.1ms.
-- Data is authenticated: no
You still need to parse it in some way, but it does give the direct final IP addresses (there is a flag when you invoke it to make it not follow CNAME
records for whatever use cases that need that)
Both the CNAME and the corresponding A (or whatever type you asked for) belong to the answer-section. As such there is no dig option (at least not in RHEL7's dig) that could filter out the CNAME response.
I think you will have to rely on dig +short [...] | grep -v '\.$'
to remove the CNAME responses.