7 unstable releases (3 breaking)
Uses new Rust 2024
| new 0.6.0 | Feb 12, 2026 |
|---|---|
| 0.5.0 | Oct 7, 2025 |
| 0.4.1 | Jun 27, 2024 |
| 0.3.3 | Apr 7, 2024 |
| 0.3.1 | Oct 16, 2023 |
#159 in Text processing
37KB
399 lines
dug
An exhaustive name resolution aggregator
Synopsis
Usage: dug [OPTIONS] <HOSTNAMES>...
Description
dug is designed to be an exhaustive name lookup tool, looking up the given hostname(s)
using any method available in the tool or on the system.
Resolvers are tried concurrently where possible.
Some methods/sources used are:
- The local host's configured resolver
- e.g., gethostname(3), gethostbyname(3), getnameinfo(3), etc.
- Major public DNS resolvers:
- Cloudflare
- Quad9
- A simulated nslookup
- Works by parsing
/etc/resolv.conf(if present) and querying the hosts found. - May be significantly different from OS-based resolution.
- Works by parsing
dug will also use external utilities such as dig (from BIND9) or drill (from
ldns) if found on the $PATH.
Output formats
The following output formats are available:
- Table - a pretty-printed table of results
- ASCII -
grepandawk-friendly ASCII text - JSON - JSON array of results suitable for use with
jq
See the examples for more information.
Installation
Build from source
If you already have a Rust toolchain installed, you can simply:
cargo install dug
The simplest way to install a Rust toolchain is with rustup.
Examples
Table output
$ dug wikipedia.org www.kame.net
┌wikipedia.org───────────┬────────────────────┐
│ Cloudflare 443/https │ 198.35.26.96 │
│ │ 2620:0:863:ed1a::1 │
├────────────────────────┼────────────────────┤
│ Cloudflare 53/udp │ 2620:0:863:ed1a::1 │
│ │ 198.35.26.96 │
├────────────────────────┼────────────────────┤
│ Cloudflare 853/tls │ 198.35.26.96 │
│ │ 2620:0:863:ed1a::1 │
├────────────────────────┼────────────────────┤
│ Google 443/https │ 198.35.26.96 │
│ │ 2620:0:863:ed1a::1 │
├────────────────────────┼────────────────────┤
│ Google 53/udp │ 198.35.26.96 │
│ │ 2620:0:863:ed1a::1 │
├────────────────────────┼────────────────────┤
│ Google 853/tls │ 198.35.26.96 │
│ │ 2620:0:863:ed1a::1 │
├────────────────────────┼────────────────────┤
│ Quad9 443/https │ 198.35.26.96 │
│ │ 2620:0:863:ed1a::1 │
├────────────────────────┼────────────────────┤
│ Quad9 53/udp │ 2620:0:863:ed1a::1 │
│ │ 198.35.26.96 │
├────────────────────────┼────────────────────┤
│ Quad9 853/tls │ 198.35.26.96 │
│ │ 2620:0:863:ed1a::1 │
├────────────────────────┼────────────────────┤
│ dig │ 198.35.26.96 │
│ │ 2620:0:863:ed1a::1 │
├────────────────────────┼────────────────────┤
│ drill │ 198.35.26.96 │
│ │ 2620:0:863:ed1a::1 │
├────────────────────────┼────────────────────┤
│ nslookup │ 198.35.26.96 │
├────────────────────────┼────────────────────┤
│ resolv.conf[10.77.0.1] │ 198.35.26.96 │
│ │ 2620:0:863:ed1a::1 │
├────────────────────────┼────────────────────┤
│ system │ 198.35.26.96 │
└────────────────────────┴────────────────────┘
┌www.kame.net────────────┬────────────────────────────────────┐
│ Cloudflare 443/https │ 2001:2f0:0:8800::1:1 │
│ │ 2001:2f0:0:8800:226:2dff:fe0b:4311 │
│ │ 210.155.141.200 │
├────────────────────────┼────────────────────────────────────┤
│ Cloudflare 53/udp │ 210.155.141.200 │
│ │ 2001:2f0:0:8800:226:2dff:fe0b:4311 │
│ │ 2001:2f0:0:8800::1:1 │
├────────────────────────┼────────────────────────────────────┤
│ Cloudflare 853/tls │ 210.155.141.200 │
│ │ 2001:2f0:0:8800:226:2dff:fe0b:4311 │
│ │ 2001:2f0:0:8800::1:1 │
├────────────────────────┼────────────────────────────────────┤
│ Google 443/https │ 210.155.141.200 │
│ │ 2001:2f0:0:8800:226:2dff:fe0b:4311 │
│ │ 2001:2f0:0:8800::1:1 │
├────────────────────────┼────────────────────────────────────┤
│ Google 53/udp │ 2001:2f0:0:8800::1:1 │
│ │ 2001:2f0:0:8800:226:2dff:fe0b:4311 │
│ │ 210.155.141.200 │
├────────────────────────┼────────────────────────────────────┤
│ Google 853/tls │ 210.155.141.200 │
│ │ 2001:2f0:0:8800::1:1 │
│ │ 2001:2f0:0:8800:226:2dff:fe0b:4311 │
├────────────────────────┼────────────────────────────────────┤
│ Quad9 443/https │ 210.155.141.200 │
│ │ 2001:2f0:0:8800::1:1 │
│ │ 2001:2f0:0:8800:226:2dff:fe0b:4311 │
├────────────────────────┼────────────────────────────────────┤
│ Quad9 53/udp │ 2001:2f0:0:8800:226:2dff:fe0b:4311 │
│ │ 2001:2f0:0:8800::1:1 │
│ │ 210.155.141.200 │
├────────────────────────┼────────────────────────────────────┤
│ Quad9 853/tls │ 2001:2f0:0:8800::1:1 │
│ │ 2001:2f0:0:8800:226:2dff:fe0b:4311 │
│ │ 210.155.141.200 │
├────────────────────────┼────────────────────────────────────┤
│ dig │ mango.itojun.org. │
│ │ 210.155.141.200 │
│ │ mango.itojun.org. │
│ │ 2001:2f0:0:8800:226:2dff:fe0b:4311 │
│ │ 2001:2f0:0:8800::1:1 │
├────────────────────────┼────────────────────────────────────┤
│ drill │ mango.itojun.org. │
│ │ 210.155.141.200 │
│ │ mango.itojun.org. │
│ │ 2001:2f0:0:8800::1:1 │
│ │ 2001:2f0:0:8800:226:2dff:fe0b:4311 │
├────────────────────────┼────────────────────────────────────┤
│ nslookup │ 210.155.141.200 │
├────────────────────────┼────────────────────────────────────┤
│ resolv.conf[10.77.0.1] │ 2001:2f0:0:8800::1:1 │
│ │ 2001:2f0:0:8800:226:2dff:fe0b:4311 │
│ │ 210.155.141.200 │
├────────────────────────┼────────────────────────────────────┤
│ system │ 210.155.141.200 │
└────────────────────────┴────────────────────────────────────┘
JSON output
$ dug -j iccf-holland.org
[
{
"name": "iccf-holland.org",
"source": "Google 53/udp",
"records": [
"185.104.29.172",
"2a06:2ec0:1::169"
]
},
{
"name": "iccf-holland.org",
"source": "Quad9 53/udp",
"records": [
"185.104.29.172",
"2a06:2ec0:1::169"
]
},
{
"name": "iccf-holland.org",
"source": "Quad9 443/https",
"records": [
"185.104.29.172",
"2a06:2ec0:1::169"
]
},
{
"name": "iccf-holland.org",
"source": "Cloudflare 53/udp",
"records": [
"2a06:2ec0:1::169",
"185.104.29.172"
]
},
{
"name": "iccf-holland.org",
"source": "Cloudflare 443/https",
"records": [
"2a06:2ec0:1::169",
"185.104.29.172"
]
},
{
"name": "iccf-holland.org",
"source": "Google 853/tls",
"records": [
"2a06:2ec0:1::169",
"185.104.29.172"
]
},
{
"name": "iccf-holland.org",
"source": "Quad9 853/tls",
"records": [
"185.104.29.172",
"2a06:2ec0:1::169"
]
},
{
"name": "iccf-holland.org",
"source": "Cloudflare 853/tls",
"records": [
"185.104.29.172",
"2a06:2ec0:1::169"
]
},
{
"name": "iccf-holland.org",
"source": "Google 443/https",
"records": [
"185.104.29.172",
"2a06:2ec0:1::169"
]
},
{
"name": "iccf-holland.org",
"source": "system",
"records": [
"185.104.29.172"
]
},
{
"name": "iccf-holland.org",
"source": "nslookup",
"records": [
"185.104.29.172"
]
},
{
"name": "iccf-holland.org",
"source": "resolv.conf[10.77.0.1]",
"records": [
"2a06:2ec0:1::169",
"185.104.29.172"
]
},
{
"name": "iccf-holland.org",
"source": "dig",
"records": [
"185.104.29.172",
"2a06:2ec0:1::169"
]
},
{
"name": "iccf-holland.org",
"source": "drill",
"records": [
"185.104.29.172",
"2a06:2ec0:1::169"
]
}
]
ASCII text output
$ dug -a wikipedia.org | sort -k2
wikipedia.org 198.35.26.96 Cloudflare 443/https
wikipedia.org 198.35.26.96 Cloudflare 53/udp
wikipedia.org 198.35.26.96 Cloudflare 853/tls
wikipedia.org 198.35.26.96 Google 443/https
wikipedia.org 198.35.26.96 Google 53/udp
wikipedia.org 198.35.26.96 Google 853/tls
wikipedia.org 198.35.26.96 Quad9 443/https
wikipedia.org 198.35.26.96 Quad9 53/udp
wikipedia.org 198.35.26.96 Quad9 853/tls
wikipedia.org 198.35.26.96 dig
wikipedia.org 198.35.26.96 drill
wikipedia.org 198.35.26.96 nslookup
wikipedia.org 198.35.26.96 resolv.conf[10.77.0.1]
wikipedia.org 198.35.26.96 system
wikipedia.org 2620:0:863:ed1a::1 Cloudflare 443/https
wikipedia.org 2620:0:863:ed1a::1 Cloudflare 53/udp
wikipedia.org 2620:0:863:ed1a::1 Cloudflare 853/tls
wikipedia.org 2620:0:863:ed1a::1 Google 443/https
wikipedia.org 2620:0:863:ed1a::1 Google 53/udp
wikipedia.org 2620:0:863:ed1a::1 Google 853/tls
wikipedia.org 2620:0:863:ed1a::1 Quad9 443/https
wikipedia.org 2620:0:863:ed1a::1 Quad9 53/udp
wikipedia.org 2620:0:863:ed1a::1 Quad9 853/tls
wikipedia.org 2620:0:863:ed1a::1 dig
wikipedia.org 2620:0:863:ed1a::1 drill
wikipedia.org 2620:0:863:ed1a::1 resolv.conf[10.77.0.1]
Get only the Google DNS results for a set of hostnames
$ dug -j abc.com cbs.com nbc.com | jq -cr \
'map(select(.source | contains("Google")))[] | "\(.name)\t\(.records | join(" "))"'
abc.com 18.155.202.44 18.155.202.58 18.155.202.108 18.155.202.100
cbs.com 100.28.104.175 98.83.184.133 54.157.108.158 2600:1f18:297:ba24:b508:76de:f4a:df34 2600:1f18:297:ba0e:7900:f622:48a8:f266 2600:1f18:297:ba18:6ddc:5d8f:6053:f003
nbc.com 23.44.229.217 23.44.229.205
Extract only the resolved IPs with jq
$ dug -j google.com | jq -r 'map(select(.records).records) | flatten | unique | .[]'
142.250.189.174
142.251.32.46
142.251.46.174
142.251.46.238
2607:f8b0:4005:802::200e
2607:f8b0:4005:811::200e
2607:f8b0:4005:813::200e
This looks busy, but here's what jq is doing:
map(...): for each result in the array...select(.records): select only objects where therecordsproperty is truthy (strippingnull).records: ...and extract therecordsproperty from the selected objectsflattenthe nested of arrays into a single array of all resolved IPsuniqueremoves all duplicate values.[]converts the array into a sequence of strings, one per line-rremoves the quotation marks (") from around the result strings
License
The MIT License (MIT)
Copyright © 2024 Tim Hammerquist tim@penryu.dev
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Dependencies
~26–42MB
~613K SLoC