digツールはdoggoが便利
Table of Contents
背景・動機
インフラ構築する時にdigを叩くことは必須なのだが、2025年にdigコマンドをそのまま使うのは流石に辛い。 もう少しリッチなものがないか調べた所、doggoが良さそうだったので導入してみた。
試したこと・やったこと
0. ツール選定
Rust製のツールに dog というものがあるが、最終更新が2021年前と期間が空いてる。
後継にあたるツールがないかなと思って調査した所、Golang製の doggo というツールがあった。
It’s totally inspired by dog which is written in Rust. I wanted to add some features to it but since I don’t know Rust, I found it as a nice opportunity to experiment with writing a DNS Client from scratch in Go myself. Hence the name dog + go => doggo.
Nixでパッケージングされているし、CLIとしての完成度も高く、アクティブなプロジェクトだったので導入した。
1. home-manager module用意
特に設定項目がないのでshell completionだけ有効にしている。
{
pkgs,
lib,
config,
...
}:
let
cfg = config.programs.doggo;
in
with lib;
{
options.programs.doggo = {
enable = mkEnableOption "Command-line DNS Client for Humans. Written in Golang";
package = mkPackageOption pkgs "doggo" { };
enableBashIntegration = lib.hm.shell.mkBashIntegrationOption { inherit config; };
enableZshIntegration = lib.hm.shell.mkZshIntegrationOption { inherit config; };
enableFishIntegration = lib.hm.shell.mkFishIntegrationOption { inherit config; };
};
config = mkIf cfg.enable {
home.packages = [ cfg.package ];
programs = {
bash.initExtra = mkIf (cfg.enableBashIntegration && cfg.package != null) ''
eval "$(${getExe cfg.package} completions bash)"
'';
zsh.initContent = mkIf (cfg.enableZshIntegration && cfg.package != null) ''
eval "$(${getExe cfg.package} completions zsh)"
'';
fish.interactiveShellInit = mkIf (cfg.enableFishIntegration && cfg.package != null) ''
${getExe cfg.package} completions fish | source
'';
};
};
}
あとは programs.doggo.enable = true; で有効にするだけで使えるようになる。
2. 実際に使ってみる
helpを引くとquicやtlsにも対応してることが分かる。
NAME:
doggo üê∂ DNS Client for Humans
USAGE:
doggo [--] [query options] [arguments...]
VERSION:
v1.1.2 - unknown
EXAMPLES:
doggo mrkaran.dev Query a domain using defaults.
doggo mrkaran.dev CNAME Query for a CNAME record.
doggo mrkaran.dev MX @9.9.9.9 Uses a custom DNS resolver.
doggo -q mrkaran.dev -t MX -n 1.1.1.1 Using named arguments.
doggo mrkaran.dev --aa --ad Query with Authoritative Answer and Authenticated Data flags set.
doggo mrkaran.dev --cd --do Query with Checking Disabled and DNSSEC OK flags set.
doggo mrkaran.dev --gp-from Germany Query using Globalping API from a specific location.
FREE FORM ARGUMENTS:
Supply hostnames, query types, and classes without flags. Example:
doggo mrkaran.dev A @1.1.1.1
TRANSPORT OPTIONS:
Specify the protocol with a URL-type scheme.
UDP is used if no scheme is specified.
@udp:// eg: @1.1.1.1 initiates a UDP query to 1.1.1.1:53.
@tcp:// eg: @tcp://1.1.1.1 initiates a TCP query to 1.1.1.1:53.
@https:// eg: @https://cloudflare-dns.com/dns-query initiates a DOH query to Cloudflare via DoH.
@tls:// eg: @tls://1.1.1.1 initiates a DoT query to 1.1.1.1:853.
@sdns:// initiates a DNSCrypt or DoH query using a DNS stamp.
@quic:// initiates a DOQ query.
SUBCOMMANDS:
completions [bash|zsh|fish] Generate the shell completion script for the specified shell.
QUERY OPTIONS:
-q, --query=HOSTNAME Hostname to query the DNS records for (eg mrkaran.dev).
-t, --type=TYPE Type of the DNS Record (A, MX, NS etc).
-n, --nameserver=ADDR Address of a specific nameserver to send queries to (9.9.9.9, 8.8.8.8 etc).
-c, --class=CLASS Network class of the DNS record (IN, CH, HS etc).
-x, --reverse Performs a DNS Lookup for an IPv4 or IPv6 address. Sets the query type and class to PTR and IN respectively.
--any Query all supported DNS record types (A, AAAA, CNAME, MX, NS, PTR, SOA, SRV, TXT, CAA).
RESOLVER OPTIONS:
--strategy=STRATEGY Specify strategy to query nameserver listed in etc/resolv.conf. (all, random, first).
--ndots=INT Specify ndots parameter. Takes value from /etc/resolv.conf if using the system namesever or 1 otherwise.
--search Use the search list defined in resolv.conf. Defaults to true. Set --search=false to disable search list.
--timeout=DURATION Specify timeout for the resolver to return a response (e.g., 5s, 400ms, 1m).
-4, --ipv4 Use IPv4 only.
-6, --ipv6 Use IPv6 only.
--tls-hostname=HOSTNAME Provide a hostname for verification of the certificate if the provided DoT nameserver is an IP.
--skip-hostname-verification Skip TLS Hostname Verification in case of DOT Lookups.
QUERY FLAGS:
--aa Set Authoritative Answer flag.
--ad Set Authenticated Data flag.
--cd Set Checking Disabled flag.
--rd Set Recursion Desired flag (default: true).
--z Set Z flag (reserved for future use).
--do Set DNSSEC OK flag.
EDNS OPTIONS:
--nsid Request Name Server Identifier (NSID) to identify the nameserver.
--cookie Request DNS Cookie for enhanced security and protection against spoofing.
--padding Request EDNS padding for privacy. Helps mitigate traffic analysis attacks.
--ede Request Extended DNS Errors for detailed error information.
--ecs=SUBNET EDNS Client Subnet (e.g., '192.0.2.0/24' or '2001:db8::/32'). Send client subnet for geo-aware responses.
OUTPUT OPTIONS:
-J, --json Format the output as JSON.
--short Short output format. Shows only the response section.
--color Defaults to true. Set --color=false to disable colored output.
--debug Enable debug logging.
--time Shows how long the response took from the server.
GLOBALPING OPTIONS:
--gp-from=Germany Query using Globalping API from a specific location.
--gp-limit=INT Limit the number of probes to use from Globalping.
雑に takeokunn.org のNSを引くとこんな感じで出力される。
$ doggo takeokunn.org NS
NAME TYPE CLASS TTL ADDRESS NAMESERVER
takeokunn.org. NS IN 3600s bob.ns.cloudflare.com. 192.168.2.1:53
takeokunn.org. NS IN 3600s mina.ns.cloudflare.com. 192.168.2.1:53
bob.ns.cloudflare.com. A IN 3041s 108.162.193.104 192.168.2.1:53
bob.ns.cloudflare.com. A IN 3041s 172.64.33.104 192.168.2.1:53
bob.ns.cloudflare.com. A IN 3041s 173.245.59.104 192.168.2.1:53
mina.ns.cloudflare.com. A IN 3366s 108.162.194.251 192.168.2.1:53
mina.ns.cloudflare.com. A IN 3366s 162.159.38.251 192.168.2.1:53
mina.ns.cloudflare.com. A IN 3366s 172.64.34.251 192.168.2.1:53
bob.ns.cloudflare.com. AAAA IN 3041s 2606:4700:58::adf5:3b68 192.168.2.1:53
bob.ns.cloudflare.com. AAAA IN 3041s 2803:f800:50::6ca2:c168 192.168.2.1:53
bob.ns.cloudflare.com. AAAA IN 3041s 2a06:98c1:50::ac40:2168 192.168.2.1:53
mina.ns.cloudflare.com. AAAA IN 3366s 2606:4700:50::a29f:26fb 192.168.2.1:53
mina.ns.cloudflare.com. AAAA IN 3366s 2803:f800:50::6ca2:c2fb 192.168.2.1:53
mina.ns.cloudflare.com. AAAA IN 3366s 2a06:98c1:50::ac40:22fb 192.168.2.1:53
takeokunn.org. NS IN 3600s bob.ns.cloudflare.com. 192.168.2.1:53
takeokunn.org. NS IN 3600s mina.ns.cloudflare.com. 192.168.2.1:53
bob.ns.cloudflare.com. A IN 3041s 108.162.193.104 192.168.2.1:53
bob.ns.cloudflare.com. A IN 3041s 172.64.33.104 192.168.2.1:53
bob.ns.cloudflare.com. A IN 3041s 173.245.59.104 192.168.2.1:53
mina.ns.cloudflare.com. A IN 3366s 108.162.194.251 192.168.2.1:53
mina.ns.cloudflare.com. A IN 3366s 162.159.38.251 192.168.2.1:53
mina.ns.cloudflare.com. A IN 3366s 172.64.34.251 192.168.2.1:53
bob.ns.cloudflare.com. AAAA IN 3041s 2606:4700:58::adf5:3b68 192.168.2.1:53
bob.ns.cloudflare.com. AAAA IN 3041s 2803:f800:50::6ca2:c168 192.168.2.1:53
bob.ns.cloudflare.com. AAAA IN 3041s 2a06:98c1:50::ac40:2168 192.168.2.1:53
mina.ns.cloudflare.com. AAAA IN 3366s 2606:4700:50::a29f:26fb 192.168.2.1:53
mina.ns.cloudflare.com. AAAA IN 3366s 2803:f800:50::6ca2:c2fb 192.168.2.1:53
mina.ns.cloudflare.com. AAAA IN 3366s 2a06:98c1:50::ac40:22fb 192.168.2.1:53
takeokunn.org. NS IN 3600s mina.ns.cloudflare.com. [2408:210:102:4b00:32be:3bff:fe16:7102]:53
takeokunn.org. NS IN 3600s bob.ns.cloudflare.com. [2408:210:102:4b00:32be:3bff:fe16:7102]:53
bob.ns.cloudflare.com. A IN 3041s 108.162.193.104 [2408:210:102:4b00:32be:3bff:fe16:7102]:53
bob.ns.cloudflare.com. A IN 3041s 172.64.33.104 [2408:210:102:4b00:32be:3bff:fe16:7102]:53
bob.ns.cloudflare.com. A IN 3041s 173.245.59.104 [2408:210:102:4b00:32be:3bff:fe16:7102]:53
mina.ns.cloudflare.com. A IN 3366s 108.162.194.251 [2408:210:102:4b00:32be:3bff:fe16:7102]:53
mina.ns.cloudflare.com. A IN 3366s 162.159.38.251 [2408:210:102:4b00:32be:3bff:fe16:7102]:53
mina.ns.cloudflare.com. A IN 3366s 172.64.34.251 [2408:210:102:4b00:32be:3bff:fe16:7102]:53
bob.ns.cloudflare.com. AAAA IN 3041s 2606:4700:58::adf5:3b68 [2408:210:102:4b00:32be:3bff:fe16:7102]:53
bob.ns.cloudflare.com. AAAA IN 3041s 2803:f800:50::6ca2:c168 [2408:210:102:4b00:32be:3bff:fe16:7102]:53
bob.ns.cloudflare.com. AAAA IN 3041s 2a06:98c1:50::ac40:2168 [2408:210:102:4b00:32be:3bff:fe16:7102]:53
mina.ns.cloudflare.com. AAAA IN 3366s 2606:4700:50::a29f:26fb [2408:210:102:4b00:32be:3bff:fe16:7102]:53
mina.ns.cloudflare.com. AAAA IN 3366s 2803:f800:50::6ca2:c2fb [2408:210:102:4b00:32be:3bff:fe16:7102]:53
mina.ns.cloudflare.com. AAAA IN 3366s 2a06:98c1:50::ac40:22fb [2408:210:102:4b00:32be:3bff:fe16:7102]:53
json出力も可能。
$ doggo --json takeokunn.org A | jq .responses.[0]
{
"answers": [
{
"name": "takeokunn.org.",
"type": "A",
"class": "IN",
"ttl": "261s",
"address": "185.199.111.153",
"status": "",
"rtt": "9ms",
"nameserver": "192.168.2.1:53"
},
{
"name": "takeokunn.org.",
"type": "A",
"class": "IN",
"ttl": "261s",
"address": "185.199.110.153",
"status": "",
"rtt": "9ms",
"nameserver": "192.168.2.1:53"
},
{
"name": "takeokunn.org.",
"type": "A",
"class": "IN",
"ttl": "261s",
"address": "185.199.108.153",
"status": "",
"rtt": "9ms",
"nameserver": "192.168.2.1:53"
},
{
"name": "takeokunn.org.",
"type": "A",
"class": "IN",
"ttl": "261s",
"address": "185.199.109.153",
"status": "",
"rtt": "9ms",
"nameserver": "192.168.2.1:53"
}
],
"authorities": null,
"questions": [
{
"name": "takeokunn.org.",
"type": "A",
"class": "IN"
}
]
}
得られた結果・所感
digよりも圧倒的に読み易くなったし、tlsやquicにも対応してるのはありがたい。
今後の展開・検討事項
digツールは自分でも自作できるのでいつかやってみたい。