### Install and Build ZDNS Source: https://github.com/zmap/zdns/wiki/Home Commands to clone the ZDNS repository, navigate into the directory, and build the project using make. Assumes Git and Golang are already installed. ```zsh git clone https://github.com/zmap/zdns.git cd zdns make install ``` -------------------------------- ### Check ZDNS Installation Source: https://github.com/zmap/zdns/wiki/Home Command to verify that ZDNS has been successfully installed by checking its version number. ```zsh zdns --version ``` -------------------------------- ### Check Git and Go Installation Versions Source: https://github.com/zmap/zdns/wiki/Home Shell commands to verify that Git and Golang are installed and accessible on the system by checking their respective version numbers. ```zsh git --version go version ``` -------------------------------- ### Query Multiple Names with ZDNS Source: https://github.com/zmap/zdns/wiki/Home Shows how to query DNS records for multiple domain names by listing them as arguments after the record type. This is a convenient way to perform bulk lookups for different hosts. ```zsh zdns A google.com yahoo.com ``` -------------------------------- ### Perform A Record Query with Specific Name Server using ZDNS Source: https://github.com/zmap/zdns/wiki/Home Example of querying the A record for 'google.com' using Cloudflare's recursive resolver (1.1.1.1) with ZDNS. Demonstrates basic ZDNS usage similar to 'dig'. ```zsh zdns A google.com --name-servers=1.1.1.1 ``` -------------------------------- ### ZDNS Default Output and Verbosity Example Source: https://github.com/zmap/zdns/wiki/Home Demonstrates the default behavior of ZDNS, outputting results to stdout and logs to stderr. It includes an example of using the --verbosity flag to control log levels. The output shows an INFO message, detailed DNS query results in JSON format, and scan progress summaries. ```zsh $ zdns A --input-file=list1.txt --threads=1 --iterative --verbosity=4 INFO[0000] none of the default local addresses could connect to name server 198.97.190.53:53, using local address 10.216.70.2 {"name":"google.com","results":{"A":{"data":{"answers":[{"answer":"142.250.191.46","class":"IN","name":"google.com","ttl":300,"type":"A"}],"protocol":"udp","resolver":"216.239.38.10:53"},"duration":0.270621125,"status":"NOERROR","timestamp":"2025-01-06T16:23:58-07:00"}}} {"name":"yahoo.com","results":{"A":{"data":{"answers":[{"answer":"98.137.11.163","class":"IN","name":"yahoo.com","ttl":1800,"type":"A"},{"answer":"74.6.231.20","class":"IN","name":"yahoo.com","ttl":1800,"type":"A"},{"answer":"74.6.143.26","class":"IN","name":"yahoo.com","ttl":1800,"type":"A"},{"answer":"74.6.143.25","class":"IN","name":"yahoo.com","ttl":1800,"type":"A"},{"answer":"74.6.231.21","class":"IN","name":"yahoo.com","ttl":1800,"type":"A"},{"answer":"98.137.11.164","class":"IN","name":"yahoo.com","ttl":1800,"type":"A"}],"protocol":"udp","resolver":"202.165.97.53:53"},"duration":0.226075667,"status":"NOERROR","timestamp":"2025-01-06T16:23:58-07:00"}}} 00h:00m:01s; 2 names scanned; 2.00 names/sec; 100.0% success rate; NOERROR: 2 00h:00m:01s; Scan Complete; 2 names scanned; 1.33 names/sec; 100.0% success rate; NOERROR: 2 ``` -------------------------------- ### Perform A Record Query using Default Name Servers with ZDNS Source: https://github.com/zmap/zdns/wiki/Home Example of querying the A record for 'google.com' using ZDNS without specifying a name server. ZDNS will use the system's default resolvers from '/etc/resolv.conf'. ```zsh zdns A google.com ``` -------------------------------- ### ZDNS: Query Names from StdIn using echo Source: https://github.com/zmap/zdns/wiki/Home Queries DNS records for a list of domain names provided via standard input using the `echo` command. This method is suitable for a small, predefined list of names. The output is a JSON object for each query, containing detailed DNS resolution information. ```zsh echo "google.com\nyahoo.com" | zdns A ``` -------------------------------- ### Pretty Print ZDNS Output with jq Source: https://github.com/zmap/zdns/wiki/Home Demonstrates how to pipe the JSON output of a ZDNS query to the 'jq' command for formatted and readable output. Logs and status updates are sent to stderr and are not processed by jq. ```zsh zdns A google.com | jq ``` -------------------------------- ### ZDNS Quiet Mode Example Source: https://github.com/zmap/zdns/wiki/Home Disables the per-second and end-of-scan status updates, making the output cleaner by only showing the JSON results for each queried name. This is useful when only the query results are needed and progress indicators are not required. The example shows the JSON output for a single query. ```zsh $ zdns A google.com --iterative --quiet {"name":"google.com","results":{"A":{"data":{"answers":[{"answer":"142.250.191.46","class":"IN","name":"google.com","ttl":300,"type":"A"}],"protocol":"udp","resolver":"216.239.34.10:53"},"duration":0.425099125,"status":"NOERROR","timestamp":"2025-01-06T16:46:25-07:00"}}} ``` -------------------------------- ### Install Goreleaser using Homebrew Source: https://github.com/zmap/zdns/blob/main/RELEASE.md This command installs the `goreleaser` tool, which is used to automate the release process for ZDNS. It requires Homebrew to be installed on the system. ```shell brew install goreleaser/tap/goreleaser ``` -------------------------------- ### ZDNS: Query Names from StdIn using cat Source: https://github.com/zmap/zdns/wiki/Home Queries DNS records for domain names read from one or more files specified via standard input using the `cat` command. This is useful for querying domains listed in multiple files. The output format is JSON, similar to other ZDNS queries. ```zsh $ cat list1.txt google.com yahoo.com $ cat list2.txt apple.com apnews.com $ cat list1.txt list2.txt | zdns A ``` -------------------------------- ### Query All Nameservers with ZDNS Source: https://github.com/zmap/zdns/blob/main/README.md This example illustrates how to perform a DNS query against all available nameservers for a given domain, useful for gathering comprehensive data. ```bash echo "google.com" | zdns A --all-nameservers ``` -------------------------------- ### ZDNS Input CSV Format Example Source: https://github.com/zmap/zdns/blob/main/README.md Example of an input CSV file for ZDNS, demonstrating the format for specifying domain names, optional nameservers, and triggers for module lookups. ```csv example.com,,a-trigger google.com,,a-trigger,cname-trigger example.com,1.1.1.1,aaaa-trigger yahoo.com apnews.com,1.1.1.1 ``` -------------------------------- ### Go: Basic Resolver Setup and External DNS Lookup with ZDNS Source: https://context7.com/zmap/zdns/llms.txt Demonstrates how to set up a ZDNS resolver with default configurations and perform an external DNS lookup for an A record against Cloudflare's DNS server. It covers creating a resolver, defining a question, executing the lookup, and processing the results, including status checks and answer parsing. Requires the zdns and dns libraries. ```go package main import ( "context" "fmt" "net" "github.com/zmap/dns" "github.com/zmap/zdns/v2/src/zdns" ) func main() { // Create resolver config with defaults: // - Timeout: 15s, IterativeTimeout: 4s, NetworkTimeout: 2s // - TransportMode: UDPOrTCP, Retries: 1, MaxDepth: 10 // - CacheSize: 10000, IPv4Only mode resolverConfig := zdns.NewResolverConfig() // Initialize resolver (validates config, sets up cache, connections) resolver, err := zdns.InitResolver(resolverConfig) if err != nil { panic(fmt.Sprintf("Failed to initialize resolver: %v", err)) } defer resolver.Close() // Always close to cleanup resources // Create DNS question question := &zdns.Question{ Name: "example.com", Type: dns.TypeA, // A record lookup Class: dns.ClassINET, // Internet class } // External lookup using Cloudflare DNS (1.1.1.1) nameserver := &zdns.NameServer{ IP: net.ParseIP("1.1.1.1"), Port: 53, } result, trace, status, err := resolver.ExternalLookup( context.Background(), question, nameserver, ) if err != nil { fmt.Printf("Lookup failed: %v\n", err) return } // Check status (NOERROR, NXDOMAIN, SERVFAIL, TIMEOUT, etc.) if status != zdns.StatusNoError { fmt.Printf("Non-success status: %s\n", status) return } // Process answers fmt.Printf("Found %d answers:\n", len(result.Answers)) for _, ans := range result.Answers { if a, ok := ans.(zdns.Answer); ok { fmt.Printf(" %s -> %s (TTL: %d, Type: %s)\n", a.Name, a.Answer, a.TTL, a.Type) } } // Access additional metadata fmt.Printf("Protocol: %s\n", result.Protocol) // "udp" or "tcp" fmt.Printf("Resolver: %s\n", result.Resolver) // "1.1.1.1:53" } ``` -------------------------------- ### ZDNS Multiple Module Configuration INI Example Source: https://github.com/zmap/zdns/blob/main/README.md Example of a ZDNS INI configuration file for setting up multiple modules and their associated triggers. It includes global options and module-specific trigger definitions. ```ini ; Specify Global Options here [Application Options] iterative=true prefer-ipv6-iteration="true" ; List out modules and their respective module-specific options here. A module can only be listed once [A] trigger = "a-trigger" [AAAA] trigger = "aaaa-trigger" [CNAME] trigger = "cname-trigger" ``` -------------------------------- ### ZDNS Redirect Per-Name Output to File Source: https://github.com/zmap/zdns/wiki/Home Redirects the primary DNS query results for each input name to a specified file instead of stdout. This is helpful for saving structured results for later processing or analysis. Existing files will be overwritten. ```zsh zdns A google.com --output-file=out ``` -------------------------------- ### Perform Iterative DNS Resolution with ZDNS (Go) Source: https://context7.com/zmap/zdns/llms.txt This Go code demonstrates how to perform an iterative DNS lookup using ZDNS, starting from the root servers and traversing the DNS hierarchy. It configures the resolver for iterative resolution, defines a DNS question, and then uses `IterativeLookup` to get the final answers and the resolution trace. The output includes the authoritative answers and the steps taken during resolution. ```Go package main import ( "context" "fmt" "github.com/zmap/dns" "github.com/zmap/zdns/v2/src/zdns" "time" ) func main() { config := zdns.NewResolverConfig() // Configure for iterative resolution config.IterativeTimeout = 8 * time.Second config.MaxDepth = 20 config.FollowCNAMEs = true resolver, err := zdns.InitResolver(config) if err != nil { panic(err) } defer resolver.Close() question := &zdns.Question{ Name: "www.example.com", Type: dns.TypeA, Class: dns.ClassINET, } // IterativeLookup starts at root servers and follows referrals // through TLD servers to authoritative nameservers result, trace, status, err := resolver.IterativeLookup( context.Background(), question, ) if err != nil { fmt.Printf("Iterative lookup failed: %v\n", err) return } if status != zdns.StatusNoError { fmt.Printf("Status: %s\n", status) return } // Result contains final answers from authoritative servers fmt.Printf("Authoritative answers:\n") for _, ans := range result.Answers { if a, ok := ans.(zdns.Answer); ok { fmt.Printf(" %s\n", a.Answer) } } // Trace contains the full resolution path (if enabled) // trace[0] = root server query // trace[1] = TLD server query // trace[2] = authoritative server query fmt.Printf("\nResolution trace (%d steps):\n", len(trace)) for i, step := range trace { fmt.Printf(" Step %d: %s\n", i+1, step.NameServer) } } ``` -------------------------------- ### ZDNS: Query Names from an Input File Source: https://github.com/zmap/zdns/wiki/Home Queries DNS records for domain names listed in a specified file using the `--input-file` command-line flag. This method overrides the default behavior of reading from stdin and is ideal for managing and querying larger lists of domains stored in files. The results are returned in JSON format. ```zsh $ cat list1.txt google.com yahoo.com $ zdns A --input-file=list1.txt ``` -------------------------------- ### Dig Example: Iterative Resolution Referral (Zsh) Source: https://github.com/zmap/zdns/wiki/Use-Cases This example demonstrates how to use the `dig` command to perform an iterative DNS query for an A record. It shows a scenario where a non-authoritative nameserver provides referrals to authoritative nameservers, illustrating the iterative process. ```zsh dig -t A google.com @a.gtld-servers.net ``` -------------------------------- ### Basic DNS Lookup with ZDNS Source: https://github.com/zmap/zdns/blob/main/README.md This example demonstrates a basic DNS lookup for the 'A' record of 'google.com' using ZDNS, querying specific name servers. ```bash echo "google.com" | zdns A --name-servers=8.8.8.8,8.8.4.4 ``` -------------------------------- ### Trace DNS Lookup Process with zdns Iterative Mode Source: https://github.com/zmap/zdns/wiki/Use-Cases This example demonstrates how to expose the full DNS lookup process, similar to `dig +trace`, using zdns with iterative mode and trace verbosity. The output is piped to `jq` for pretty-printing the detailed trace information. ```shell zdns A google.com --iterative --result-verbosity=trace | jq ``` ```json { "class": "IN", "name": "google.com", "results": { "A": { "data": { "answers": [ { "answer": "142.250.191.78", "class": "IN", "name": "google.com", "ttl": 300, "type": "A" } ], "flags": { "authenticated": false, "authoritative": true, "checking_disabled": false, "error_code": 0, "opcode": 0, "recursion_available": false, "recursion_desired": false, "response": true, "truncated": false }, "protocol": "udp", "resolver": "216.239.32.10:53" }, "duration": 0.073534, "status": "NOERROR", "timestamp": "2025-01-09T10:51:29-08:00", "trace": [ { "cached": false, "class": 1, "depth": 1, "layer": ".", "name": "google.com", "name_server": "192.5.5.241:53", "results": { "additionals": [ { "answer": "192.43.172.30", "class": "IN", "name": "i.gtld-servers.net", "ttl": 172800, "type": "A" }, ... ``` -------------------------------- ### ZDNS Redirect Event Logs to File Source: https://github.com/zmap/zdns/wiki/Home Redirects ZDNS event-based logs (e.g., INFO, WARNING, ERROR messages) to a specified file instead of stderr. This allows for separate analysis of operational logs. The target file will be overwritten if it already exists. ```zsh zdns A google.com --log-file=log.out ``` -------------------------------- ### ZDNS CLI: Batch DNS Lookups and Advanced Queries Source: https://context7.com/zmap/zdns/llms.txt Provides examples of using the ZDNS command-line interface for efficient batch DNS lookups. It covers basic A record lookups, performing queries from a file with custom nameservers, iterative resolution, MX lookups with IP resolution, querying multiple record types, DNS-over-HTTPS, and DNSSEC validation. ```bash # Basic A record lookup (single domain) echo "google.com" | zdns A # Lookup from file with custom nameserver zdns A --input-file=domains.txt --name-servers=1.1.1.1,8.8.8.8 --output-file=results.json # Iterative resolution from root servers cat domains.txt | zdns A --iterative --threads=1000 # MX lookup with IP resolution echo "gmail.com" | zdns MXLOOKUP --ipv4-lookup --ipv6-lookup # Multiple DNS record types at once zdns MULTIPLE --multi-config-file=config.ini --input-file=domains.txt # Config file (config.ini): # [Application Options] # iterative=true # threads=5000 # [A] # [AAAA] # [MXLOOKUP] # ipv4-lookup=true # DNS-over-HTTPS lookup echo "cloudflare.com" | zdns A --https --name-servers=1.1.1.1 # Query all nameservers at each level echo "example.com" | zdns A --iterative --all-nameservers # DNSSEC validation echo "dnssec-deployment.org" | zdns A --iterative --dnssec --validate-dnssec ``` -------------------------------- ### Perform Raw DNS 'A' Record Lookup with ZDNS CLI Source: https://github.com/zmap/zdns/blob/main/README.md This example demonstrates using the ZDNS command-line interface to perform a raw DNS query for 'A' records of a given domain. It pipes the domain name to the 'zdns' command and specifies the 'A' module. The output is in JSON format. ```bash echo "censys.io" | zdns A ``` -------------------------------- ### Go: Handle DNS Errors and Status Codes with ZDNS Source: https://context7.com/zmap/zdns/llms.txt Illustrates how to handle various DNS error conditions and status codes returned by ZDNS. The example uses a switch statement to differentiate between successful queries and specific error states like NXDOMAIN, SERVFAIL, timeouts, and refusals. It also shows how to check for network-specific errors. ```go package main import ( "context" "fmt" "net" "github.com/zmap/dns" "github.com/zmap/zdns/v2/src/zdns" ) func main() { config := zdns.NewResolverConfig() config.Retries = 3 resolver, err := zdns.InitResolver(config) if err != nil { panic(err) } defer resolver.Close() question := &zdns.Question{ Name: "nonexistent-domain-xyz123.com", Type: dns.TypeA, Class: dns.ClassINET, } nameserver := &zdns.NameServer{ IP: net.ParseIP("8.8.8.8"), Port: 53, } result, trace, status, err := resolver.ExternalLookup( context.Background(), question, nameserver, ) // Handle different status codes switch status { case zdns.StatusNoError: fmt.Println("✓ Query successful") fmt.Printf(" Answers: %d\n", len(result.Answers)) case zdns.StatusNXDomain: fmt.Println("✗ Domain does not exist (NXDOMAIN)") case zdns.StatusServFail: fmt.Println("✗ Server failure (SERVFAIL)") case zdns.StatusRefused: fmt.Println("✗ Query refused by server") case zdns.StatusTimeout: fmt.Println("✗ Query timed out") case zdns.StatusIterTimeout: fmt.Println("✗ Iterative query timed out at intermediate step") case zdns.StatusTruncated: fmt.Println("⚠ Response truncated (may need TCP)") case zdns.StatusNoAnswer: fmt.Println("⚠ No answer section in response") case zdns.StatusBlacklist: fmt.Println("✗ Server is blacklisted") case zdns.StatusAuthFail: fmt.Println("✗ DNSSEC authentication failed") default: fmt.Printf("? Unexpected status: %s\n", status) } // Handle errors separate from status if err != nil { fmt.Printf("Error details: %v\n", err) // Check error type switch e := err.(type) { case *net.OpError: fmt.Printf("Network error: %v\n", e) default: fmt.Printf("Other error: %T\n", e) } } } ``` -------------------------------- ### Name Servers Per-Domain Input (Shell) Source: https://github.com/zmap/zdns/blob/main/README.md This example shows how to specify a unique name server for each domain lookup. Input is provided as comma-separated domain-name,name-server-ip pairs, overriding any globally specified name servers. ```shell echo "google.com,1.1.1.1\nfacebook.com,8.8.8.8" | zdns A ``` -------------------------------- ### DNS-over-HTTPS (DoH) Configuration and Lookup with Go Source: https://context7.com/zmap/zdns/llms.txt Configures and performs DNS queries over HTTPS (DoH) using the zdns library. This method encrypts DNS traffic, enhancing privacy and security. The example shows how to enable DoH, set up certificate verification, and specify DoH server details. It outputs the protocol used and the number of answers received. ```go package main import ( "context" "crypto/x509" "fmt" "io/ioutil" "net" "github.com/zmap/dns" "github.com/zmap/zdns/v2/src/zdns" ) func main() { config := zdns.NewResolverConfig() // Enable DNS-over-HTTPS config.DNSOverHTTPS = true // Enable certificate verification (recommended) config.VerifyServerCert = true // Load system CA pool or custom CAs config.RootCAs = x509.NewCertPool() // Option 1: Use system CAs if systemCAs, err := x509.SystemCertPool(); err == nil { config.RootCAs = systemCAs } // Option 2: Load custom CA bundle caBundle, err := ioutil.ReadFile("/etc/ssl/certs/ca-certificates.crt") if err == nil { config.RootCAs.AppendCertsFromPEM(caBundle) } resolver, err := zdns.InitResolver(config) if err != nil { panic(err) } defer resolver.Close() question := &zdns.Question{ Name: "cloudflare.com", Type: dns.TypeA, Class: dns.ClassINET, } // DoH nameserver requires domain name for SNI and cert verification dohServer := &zdns.NameServer{ IP: net.ParseIP("1.1.1.1"), Port: 443, // HTTPS port DomainName: "cloudflare-dns.com", // Required for TLS SNI } result, _, status, err := resolver.ExternalLookup( context.Background(), question, dohServer, ) if err != nil { fmt.Printf("DoH lookup failed: %v\n", err) return } if status == zdns.StatusNoError { fmt.Printf("Protocol: %s\n", result.Protocol) // Should be "DoH" fmt.Printf("Answers: %d\n", len(result.Answers)) // Access TLS handshake details if result.TLSServerHandshake != nil { fmt.Printf("TLS connection established\n") } } } ``` -------------------------------- ### Publish ZDNS Release with Goreleaser Source: https://github.com/zmap/zdns/blob/main/RELEASE.md This command executes the full `goreleaser` release process, including building, testing, and publishing artifacts to GitHub releases and other configured destinations. The `--clean` flag ensures a fresh build environment. ```shell goreleaser release --clean ``` -------------------------------- ### ZDNS Redirect Status Updates to File Source: https://github.com/zmap/zdns/wiki/Home Redirects ZDNS status updates (per-second progress and end-of-scan messages) to a specified file instead of stderr. This is useful for capturing scan progress separately from other logs or results. Be cautious as this will overwrite the file if it exists. ```zsh zdns A google.com --status-updates-file=status.out ``` -------------------------------- ### Create and Commit Git Tag for Release Source: https://github.com/zmap/zdns/blob/main/RELEASE.md Before releasing, a new tag must be created in Git to mark the specific version being released. This tag is then used by `goreleaser` and is pushed to GitHub. ```shell git tag -a vA.B.C -m "Release A.B.C" ``` -------------------------------- ### Query All Nameservers Source: https://context7.com/zmap/zdns/llms.txt This endpoint allows you to query all nameservers at each DNS hierarchy level, starting from the root servers, then TLD servers, and finally the authoritative servers for the queried domain. It also supports querying external resolvers. ```APIDOC ## Query All Nameservers ### Description Queries all nameservers at each DNS hierarchy level (root, TLD, authoritative) and supports querying external resolvers. ### Method GET (Conceptual - actual implementation is via library functions) ### Endpoint /zmap/zdns/nameservers ### Parameters #### Path Parameters None #### Query Parameters - **domain** (string) - Required - The domain name to query. - **type** (string) - Optional - The DNS record type (e.g., A, AAAA, MX). Defaults to A if not specified. - **class** (string) - Optional - The DNS class (e.g., INET). Defaults to INET. #### Request Body None ### Request Example ```go // Example Go code snippet demonstrating usage: // resolver.LookupAllNameserversIterative(context.Background(), question, nil) // resolver.LookupAllNameserversExternal(context.Background(), question, externalServers) ``` ### Response #### Success Response (200) - **result** (object) - Contains layered responses from different DNS levels. - **LayeredResponses** (map[string][]Response) - Maps DNS layer (e.g., ".", "com.") to a list of responses. - **Response** (object) - **Resolver** (string) - The nameserver that responded. - **Status** (string) - The DNS query status. - **Answers** (array) - A list of DNS answers received. - **externalResults** (array) - A list of responses from external resolvers. - **Resolver** (string) - The external resolver's address. - **Answers** (array) - A list of DNS answers received. #### Response Example ```json { "LayeredResponses": { "com.": [ { "Resolver": "192.0.32.10", "Status": "NOERROR", "Answers": [ { "Name": "google.com.", "Type": "NS", "TTL": 172800, "Answer": "ns1.google.com." } ] } ] }, "ExternalResolvers": [ { "Resolver": "1.1.1.1", "Answers": [ { "Name": "google.com.", "Type": "A", "TTL": 300, "Answer": "142.250.183.174" } ] } ] } ``` ``` -------------------------------- ### Perform Local Iterative DNS Recursion with zdns Source: https://github.com/zmap/zdns/wiki/Use-Cases This showcases zdns performing its own iterative name resolution starting from the root servers. This method can be faster than external resolvers and avoids rate limiting. The output includes the DNS record and resolver information. ```shell zdns A google.com --iterative ``` ```json {"name":"google.com","results":{"A":{"data":{"answers":[{"answer":"142.250.191.78","class":"IN","name":"google.com","ttl":300,"type":"A"}],"protocol":"udp","resolver":"216.239.32.10:53"},"duration":0.05233175,"status":"NOERROR","timestamp":"2025-01-09T10:47:55-08:00"}}} 00h:00m:01s; 1 names scanned; 1.00 names/sec; 100.0% success rate; NOERROR: 1 00h:00m:01s; Scan Complete; 1 names scanned; 0.95 names/sec; 100.0% success rate; NOERROR: 1 ``` -------------------------------- ### Query All Nameservers with zdns (Shell) Source: https://github.com/zmap/zdns/wiki/Use-Cases Executes a DNS query for the 'A' record of 'google.com' using `zdns`. The `--all-nameservers` flag ensures that queries are sent to all provided `--name-servers`. The output is piped to `jq` for formatted JSON viewing. This command does not use iterative queries. ```zsh zdns A google.com --all-nameservers --name-servers=1.1.1.1,8.8.8.8,1.0.0.1,8.8.4.4 ``` ```zsh $ zdns A google.com --all-nameservers --name-servers=1.1.1.1,8.8.8.8,1.0.0.1,8.8.4.4 | jq { "name": "google.com", "results": { "A": { "data": [ { "additionals": [ { "flags": "", "type": "EDNS0", "udpsize": 1232, "version": 0 } ], "answers": [ { "answer": "142.250.191.78", "class": "IN", "name": "google.com", "ttl": 198, "type": "A" } ], "protocol": "udp", "resolver": "1.1.1.1:53" }, { "additionals": [ { "flags": "", "type": "EDNS0", "udpsize": 512, "version": 0 } ], "answers": [ { "answer": "142.250.191.78", "class": "IN", "name": "google.com", "ttl": 119, "type": "A" } ], "protocol": "udp", "resolver": "8.8.8.8:53" }, { "additionals": [ { "flags": "", "type": "EDNS0", "udpsize": 1232, "version": 0 } ], "answers": [ { "answer": "142.250.189.206", "class": "IN", "name": "google.com", "ttl": 187, "type": "A" } ], "protocol": "udp", "resolver": "1.0.0.1:53" }, { "additionals": [ { "flags": "", "type": "EDNS0", "udpsize": 512, "version": 0 } ], "answers": [ { "answer": "142.250.191.78", "class": "IN", "name": "google.com", "ttl": 119, "type": "A" } ], "protocol": "udp", "resolver": "8.8.4.4:53" } ], "duration": 0.084098375, "status": "NOERROR", "timestamp": "2025-01-09T11:20:10-08:00" } } } 00h:00m:01s; 1 names scanned; 1.00 names/sec; 100.0% success rate; NOERROR: 1 00h:00m:01s; Scan Complete; 1 names scanned; 0.92 names/sec; 100.0% success rate; NOERROR: 1 ``` -------------------------------- ### Query All Nameservers in Lookup Chain with zdns Source: https://github.com/zmap/zdns/wiki/Use-Cases This command uses zdns with both `--all-nameservers` and `--iterative` flags to query all nameservers at each layer of the DNS lookup chain for a given domain. The output, piped to `jq`, shows the responses from every server in the resolution path. ```shell zdns A google.com --all-nameservers --iterative | jq ``` -------------------------------- ### Set GitHub Token for Authentication Source: https://github.com/zmap/zdns/blob/main/RELEASE.md Sets the `GITHUB_TOKEN` environment variable, which is required by `goreleaser` to authenticate with GitHub and push releases or other artifacts. The token needs at least `write:packages` scope. ```shell export GITHUB_TOKEN="YOUR_GH_TOKEN" ``` -------------------------------- ### Perform MX Lookup with IPv4 Resolution using ZDNS CLI Source: https://github.com/zmap/zdns/blob/main/README.md This example shows how to use the ZDNS CLI to perform an MX lookup for a domain, including an additional IPv4 lookup for the mail exchange servers. It utilizes the 'mxlookup' module with the '--ipv4-lookup' flag. The output is a JSON object detailing the MX records and their corresponding IPv4 addresses. ```bash echo "censys.io" | zdns mxlookup --ipv4-lookup ``` -------------------------------- ### Configure ZDNS Resolver with Custom Settings (Go) Source: https://context7.com/zmap/zdns/llms.txt This Go code snippet shows how to initialize a ZDNS resolver with advanced configurations. It covers setting timeouts, retry attempts, transport modes (UDP/TCP), IP version preferences, custom nameservers, cache size, socket recycling, and CNAME following. The configuration is validated before initializing the resolver. ```Go package main import ( "fmt" "net" "time" "github.com/zmap/zdns/v2/src/zdns" ) func main() { config := zdns.NewResolverConfig() // Timeout configuration config.Timeout = 30 * time.Second // Total resolution timeout config.IterativeTimeout = 10 * time.Second // Per-iteration timeout config.NetworkTimeout = 5 * time.Second // Per-network-call timeout config.MaxDepth = 15 // Max recursion depth config.Retries = 5 // Retry attempts per query // Transport mode: UDPOrTCP (default), UDPOnly, or TCPOnly config.TransportMode = zdns.TCPOnly // IP version mode: IPv4Only (default), IPv6Only, or IPv4OrIPv6 config.IPVersionMode = zdns.IPv4OrIPv6 // For IPv4OrIPv6 mode, specify nameservers for both config.ExternalNameServersV4 = []zdns.NameServer{ {IP: net.ParseIP("1.1.1.1"), Port: 53}, // Cloudflare {IP: net.ParseIP("8.8.8.8"), Port: 53}, // Google } config.ExternalNameServersV6 = []zdns.NameServer{ {IP: net.ParseIP("2606:4700:4700::1111"), Port: 53}, // Cloudflare IPv6 } // Root servers for iterative lookups (defaults provided) config.RootNameServersV4 = zdns.RootServersV4() config.RootNameServersV6 = zdns.RootServersV6() // Cache configuration config.CacheSize = 50000 // Increase cache for large-scale lookups // Socket behavior config.ShouldRecycleSockets = true // Reuse sockets (better performance) // CNAME following in iterative mode config.FollowCNAMEs = true // Custom local addresses for source IP binding config.LocalAddrsV4 = []net.IP{ net.ParseIP("192.168.1.100"), } // Validate configuration before use if err := config.Validate(); err != nil { panic(fmt.Sprintf("Invalid config: %v", err)) } resolver, err := zdns.InitResolver(config) if err != nil { panic(err) } defer resolver.Close() // Resolver is now ready with custom configuration } ``` -------------------------------- ### Go: Manage DNS Query Context and Timeouts with Context Source: https://context7.com/zmap/zdns/llms.txt Demonstrates how to control DNS query timeouts and cancellation in Go using the `context` package. It shows setting base timeouts in `zdns.ResolverConfig`, creating contexts with deadlines or cancellation, and checking for timeout or cancellation errors after a query. This is crucial for preventing applications from hanging on unresponsive DNS servers. ```go package main import ( "context" "fmt" "time" "github.com/zmap/dns" "github.com/zmap/zdns/v2/src/zdns" "net" ) func main() { config := zdns.NewResolverConfig() // Set base timeouts in config config.Timeout = 10 * time.Second config.NetworkTimeout = 2 * time.Second resolver, err := zdns.InitResolver(config) if err != nil { panic(err) } defer resolver.Close() question := &zdns.Question{ Name: "slow-server.example.com", Type: dns.TypeA, Class: dns.ClassINET, } // Create context with timeout (overrides config timeout) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() result, _, status, err := resolver.IterativeLookup(ctx, question) // Check for timeout if ctx.Err() == context.DeadlineExceeded { fmt.Println("Query timed out (context deadline)") return } if status == zdns.StatusTimeout || status == zdns.StatusIterTimeout { fmt.Printf("Query timed out: %s\n", status) return } // Manual cancellation example ctx2, cancel2 := context.WithCancel(context.Background()) // Cancel after 100ms go func() { time.Sleep(100 * time.Millisecond) cancel2() }() result2, _, status2, err2 := resolver.ExternalLookup( ctx2, question, &zdns.NameServer{IP: net.ParseIP("8.8.8.8"), Port: 53}, ) if ctx2.Err() == context.Canceled { fmt.Println("Query was cancelled") return } if err2 == nil && status2 == zdns.StatusNoError { fmt.Printf("Query completed before cancellation\n") } } ``` -------------------------------- ### Basic Input: List of Domains via File (Shell) Source: https://github.com/zmap/zdns/blob/main/README.md This command shows how to use ZDNS to resolve A records for domains listed in a file. The `--input-file` flag specifies the path to the file containing the domain names. ```shell zdns A --input-file=list_of_domains.txt ``` -------------------------------- ### Test ZDNS Release with Goreleaser Source: https://github.com/zmap/zdns/blob/main/RELEASE.md This command runs `goreleaser` to test the release process without actually publishing the artifacts. It cleans up any previous build artifacts and ensures the release build is valid. ```shell goreleaser release --skip=publish --clean ``` -------------------------------- ### ZDNS Multiple Lookup Modules Execution Source: https://github.com/zmap/zdns/blob/main/README.md This command shows how to execute ZDNS using multiple lookup modules by providing a configuration file that specifies the modules and their options. ```bash cat 1000k_domains.txt | zdns MULTIPLE --multi-config-file="./multiple.ini" ``` -------------------------------- ### Query Specific Nameserver with zdns Source: https://github.com/zmap/zdns/wiki/Use-Cases This snippet demonstrates how to query a specific domain name using a designated nameserver. The input is a comma-separated list of domain and nameserver pairs. The output shows the domain, the queried nameserver, and its port. ```shell $ cat /tmp/specific_nameserver.txt google.com,1.1.1.1 yahoo.com,8.8.8.8 apnews.com,1.0.0.1 ``` ```shell $ cat /tmp/specfic_nameservers.txt| zdns A | jq -r '.name + ", " + .results.A.data.resolver' google.com, 1.1.1.1:53 apnews.com, 1.0.0.1:53 yahoo.com, 8.8.8.8:53 00h:00m:00s; Scan Complete; 3 names scanned; 109.90 names/sec; 100.0% success rate; NOERROR: 3 ``` -------------------------------- ### Basic Input: List of Domains via Stdin (Shell) Source: https://github.com/zmap/zdns/blob/main/README.md This command demonstrates how to provide a list of domain names to ZDNS for A record lookups using standard input. It reads domain names separated by newlines from stdin. ```shell echo "google.com\nyahoo.com" | zdns A ``` ```shell cat list_of_domains.txt | zdns A ``` -------------------------------- ### ZDNS Command Line Execution for Multiple Modules Source: https://github.com/zmap/zdns/blob/main/README.md Shell command to run ZDNS using a multi-config file and an input file, enabling the lookup of domains with specified modules and triggers. ```shell zdns MULTIPLE --multi-config-file="./multiple.ini" --input-file="input.csv" ``` -------------------------------- ### ALOOKUP Module: Enhanced A/AAAA Resolution with Go Source: https://context7.com/zmap/zdns/llms.txt Utilizes the ALOOKUP module in Go to perform enhanced A and AAAA record lookups, automatically following CNAME records to retrieve the final IP addresses. It takes context, domain, nameserver configuration, iterative flag, and flags for IPv4/IPv6 lookups as input. The output includes resolved IPs and a trace of the resolution path. ```go package main import ( "context" "fmt" "github.com/zmap/zdns/v2/src/zdns" ) func main() { config := zdns.NewResolverConfig() resolver, err := zdns.InitResolver(config) if err != nil { panic(err) } defer resolver.Close() domain := "www.github.com" // Often has CNAME to CDN // DoTargetedLookup follows CNAMEs and returns final IPs // Parameters: context, domain, nameserver, isIterative, lookupIPv4, lookupIPv6 ipResult, trace, status, err := resolver.DoTargetedLookup( context.Background(), domain, nil, // nil = use default nameservers from config false, // false = external lookup, true = iterative true, // lookupIPv4 = perform A lookups true, // lookupIPv6 = perform AAAA lookups ) if err != nil { fmt.Printf("Lookup failed: %v\n", err) return } if status != zdns.StatusNoError { fmt.Printf("Status: %s\n", status) return } // IPResult contains all resolved addresses fmt.Printf("IPv4 Addresses for %s:\n", domain) for _, ip := range ipResult.IPv4Addresses { fmt.Printf(" %s\n", ip) } fmt.Printf("\nIPv6 Addresses for %s:\n", domain) for _, ip := range ipResult.IPv6Addresses { fmt.Printf(" %s\n", ip) } // Trace shows CNAME chain followed during resolution fmt.Printf("\nResolution trace: %d steps\n", len(trace)) } ```