{"id":13540003,"url":"https://github.com/zmap/zdns","last_synced_at":"2025-05-14T17:07:53.639Z","repository":{"id":40244197,"uuid":"62467269","full_name":"zmap/zdns","owner":"zmap","description":"Fast DNS Lookup Library and CLI Tool","archived":false,"fork":false,"pushed_at":"2025-05-01T22:09:08.000Z","size":14785,"stargazers_count":986,"open_issues_count":4,"forks_count":133,"subscribers_count":34,"default_branch":"main","last_synced_at":"2025-05-01T23:20:14.999Z","etag":null,"topics":["dns","research","scanner"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zmap.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2016-07-02T19:47:57.000Z","updated_at":"2025-05-01T22:09:13.000Z","dependencies_parsed_at":"2023-02-13T00:46:16.619Z","dependency_job_id":"7a8f59b4-0e79-4a32-a520-31c9db2fa97e","html_url":"https://github.com/zmap/zdns","commit_stats":{"total_commits":339,"total_committers":42,"mean_commits":8.071428571428571,"dds":0.551622418879056,"last_synced_commit":"c19204421de5f3e28c9d88b9d9353148643f0cd8"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zmap%2Fzdns","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zmap%2Fzdns/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zmap%2Fzdns/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zmap%2Fzdns/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zmap","download_url":"https://codeload.github.com/zmap/zdns/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254190396,"owners_count":22029632,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dns","research","scanner"],"created_at":"2024-08-01T09:01:37.132Z","updated_at":"2025-05-14T17:07:53.620Z","avatar_url":"https://github.com/zmap.png","language":"Go","funding_links":[],"categories":["\u003ca id=\"a76463feb91d09b3d024fae798b92be6\"\u003e\u003c/a\u003e侦察\u0026\u0026信息收集\u0026\u0026子域名发现与枚举\u0026\u0026OSINT","Go","Go (134)","Weapons","Go (531)","\u003ca id=\"170048b7d8668c50681c0ab1e92c679a\"\u003e\u003c/a\u003e工具"],"sub_categories":["\u003ca id=\"a695111d8e30d645354c414cb27b7843\"\u003e\u003c/a\u003eDNS","Tools"],"readme":"ZDNS\n====\n\n[![Go Report Card](https://goreportcard.com/badge/github.com/zmap/zdns)](https://goreportcard.com/report/github.com/zmap/zdns)\n\nZDNS is a command-line utility that provides high-speed DNS lookups. ZDNS is\nwritten in Go and contains its own recursive resolution code and a cache\noptimized for performing lookups of a diverse set of names. We use\nhttps://github.com/zmap/dns to construct and parse raw DNS packets.\nFor more information about ZDNS's architecture and performance, check out the following [paper](https://lizizhikevich.github.io/assets/papers/ZDNS.pdf) appearing at ACM's Internet Measurement Conference '22.\n\n\u003e [!TIP]\n\u003e The [ZDNS Wiki](https://github.com/zmap/zdns/wiki) contains additional information on ZDNS and walks thru use-cases and examples.\n\nInstall\n=======\n\nZDNS can be installed by checking out the repository and running `make install`.\n\n```bash\ngit clone https://github.com/zmap/zdns.git\ncd zdns\nmake install\n```\n\nUsage\n=====\n\nZDNS was originally built as a CLI tool only. Work has been done to convert\nthis [library](github.com/zmap/zdns/src/zdns) into a standalone library and let a separate [CLI](github.com/zmap/zdns/src/cli) wrap the library.\n\nThe library consists of a `ResolverConfig` struct which will contain all config options for all lookups made.\nThe `ResolverConfig` is used to create 1+ `Resolver` struct(s) which will make all lookups. A `Resolver`\nshould only make a single lookup at a time (it is not thread-safe) and multiple `Resolver` structs should be\nused for parallelism. See our [examples](github.com/zmap/zdns/examples) for how to use the\nlibrary. [Modules](github.com/zmap/zdns/src/modules) are used to define the behavior of the lookups.\n\nZDNS provides several types of modules:\n\n- *Raw DNS modules* provide the raw DNS response from the server similar to dig,\n  but in JSON. There is a module for (nearly) every type of DNS record\n\n- *Lookup modules* provide more helpful responses when multiple queries are\n  required (e.g., completing additional `A` lookup for IP addresses if a `NS` is \n  received in `NSLOOKUP`)\n\n- *Misc modules* provide other additional means of querying servers (e.g.,\n  `bind.version`)\n\nWe detail the modules below:\n\nRaw DNS Modules\n---------------\n\nThe A, AAAA, AFSDB, ANY, ATMA, AVC, AXFR, BINDVERSION, CAA, CDNSKEY, CDS, CERT,\nCNAME, CSYNC, DHCID, DMARC, DNSKEY, DS, EID, EUI48, EUI64, GID, GPOS, HINFO,\nHIP, HTTPS, ISDN, KEY, KX, L32, L64, LOC, LP, MB, MD, MF, MG, MR, MX, NAPTR,\nNID, NINFO, NS, NSAPPTR, NSEC, NSEC3, NSEC3PARAM, NSLOOKUP, NULL, NXT,\nOPENPGPKEY, PTR, PX, RP, RRSIG, RT, SVCBS, MIMEA, SOA, SPF, SRV, SSHFP, TALINK,\nTKEY, TLSA, TXT, UID, UINFO, UNSPEC, and URI modules provide the raw DNS\nresponse in JSON form, similar to dig.\n\nFor example, the command:\n\n\techo \"censys.io\" | zdns A\n\nreturns:\n```json\n{\n   \"name\": \"censys.io\",\n   \"results\": {\n      \"A\": {\n         \"data\": {\n            \"additionals\": [\n               {\n                  \"flags\": \"\",\n                  \"type\": \"EDNS0\",\n                  \"udpsize\": 512,\n                  \"version\": 0\n               }\n            ],\n            \"answers\": [\n               {\n                  \"answer\": \"104.18.10.85\",\n                  \"class\": \"IN\",\n                  \"name\": \"censys.io\",\n                  \"ttl\": 300,\n                  \"type\": \"A\"\n               },\n               {\n                  \"answer\": \"104.18.11.85\",\n                  \"class\": \"IN\",\n                  \"name\": \"censys.io\",\n                  \"ttl\": 300,\n                  \"type\": \"A\"\n               }\n            ],\n            \"protocol\": \"udp\",\n            \"resolver\": \"[2603:6013:9d00:3302::1]:53\"\n         },\n         \"duration\": 0.285295416,\n         \"status\": \"NOERROR\",\n         \"timestamp\": \"2024-08-23T13:12:43-04:00\"\n      }\n   }\n}\n```\n\nLookup Modules\n--------------\n\nRaw DNS responses frequently do not provide the data you _want_. For example,\nan MX response may not include the associated A records in the additional\nsection requiring an additional lookup. To address this gap and provide a\nfriendlier interface, we also provide several _lookup_ modules: `alookup`,\n`mxlookup`, and `nslookup`.\n\n`alookup` acts similar to nslookup and will follow CNAME records.\n`mxlookup` will additionally do an A lookup for the IP addresses that correspond with an exchange record.\n`nslookup` will additionally do an A/AAAA lookup for IP addresses that correspond with an NS record\n\nFor example,\n\n\techo \"censys.io\" | zdns mxlookup --ipv4-lookup\n\nreturns:\n```json\n{\n   \"name\": \"censys.io\",\n   \"results\": {\n      \"MXLOOKUP\": {\n         \"data\": {\n            \"exchanges\": [\n               {\n                  \"class\": \"IN\",\n                  \"ipv4_addresses\": [\n                     \"209.85.202.27\"\n                  ],\n                  \"name\": \"alt1.aspmx.l.google.com\",\n                  \"preference\": 5,\n                  \"ttl\": 300,\n                  \"type\": \"MX\"\n               },\n               {\n                  \"class\": \"IN\",\n                  \"ipv4_addresses\": [\n                     \"142.250.31.26\"\n                  ],\n                  \"name\": \"aspmx.l.google.com\",\n                  \"preference\": 1,\n                  \"ttl\": 300,\n                  \"type\": \"MX\"\n               }\n            ]\n         },\n         \"duration\": 0.154786958,\n         \"status\": \"NOERROR\",\n         \"timestamp\": \"2024-08-23T13:10:11-04:00\"\n      }\n   }\n}\n```\n\nOther DNS Modules\n-----------------\n\nZDNS also supports special \"debug\" DNS queries. Modules include: `BINDVERSION`.\n\nInput Formats\n-------------\nZDNS supports providing input in a variety of formats depending on the desired behavior.\n\n### Basic Input\n\nThe most basic input is a list of names separated by newlines. For example:\n\nFrom stdin:\n```\necho \"google.com\\nyahoo.com\" | zdns A\ncat list_of_domains.txt | zdns A\n```\n\nFrom a file\n```shell\nzdns A --input-file=list_of_domains.txt\n```\n\n\n### Dig-style Input\nIf you don't need to resolve many domains, providing the domain as CLI argument, similar to `dig`, is supported for ease-of-use.\n\nFor example:\n```bash\nzdns A google.com --name-servers=1.1.1.1\n````\nEquivalent to `dig -t A google.com @1.1.1.1`\n\n### Name Servers per-domain\nNormally, ZDNS will choose a random nameserver for each domain lookup from `--name-servers`. If instead you want to specify\na different name server for each domain, you can do so by providing domainName,nameServerIP pairs seperated by newlines.\nThis will override any nameservers provided with `--name-servers`.\n\nFor example:\n```\necho \"google.com,1.1.1.1\\nfacebook.com,8.8.8.8\" | zdns A\n```\n\nYou can see the `resolver` is as specified for each domain in the output (additionals/answers redacted for brevity):\n```shell\n$ echo \"google.com,1.1.1.1\\nfacebook.com,8.8.8.8\" | zdns A\n{\"name\":\"google.com\",\"results\":{\"A\":{\"data\":{\"additionals\":...,\"answers\":[...],\"protocol\":\"udp\",\"resolver\":\"1.1.1.1:53\"},\"duration\":0.030490042,\"status\":\"NOERROR\",\"timestamp\":\"2024-09-13T09:51:34-04:00\"}}}\n{\"name\":\"facebook.com\",\"results\":{\"A\":{\"data\":{\"additionals\":[...],\"answers\":[...],\"protocol\":\"udp\",\"resolver\":\"8.8.8.8:53\"},\"duration\":0.061365459,\"status\":\"NOERROR\",\"timestamp\":\"2024-09-13T09:51:34-04:00\"}}}\n````\n\nLocal Recursion\n---------------\n\nZDNS can either operate against a recursive resolver (e.g., an organizational\nDNS server) [default behavior] or can perform its own recursion internally. If\nyou are performing a small number of lookups (i.e., millions) and using a less\nthan 10,000 go routines, it is typically fastest to use one of the common\nrecursive resolvers like Cloudflare or Google. Cloudflare is nearly always\nfaster than Google. This is particularly true if you're looking up popular\nnames because they're cached and can be answered in a single round trip.\nWhen using tens of thousands of concurrent threads, consider performing\niteration internally in order to avoid  DOS'ing and/or rate limiting your\nrecursive resolver.\n\nTo perform local recursion, run zdns with the `--iterative` flag. When this\nflag is used, ZDNS will round-robin between the published root servers (e.g.,\n198.41.0.4). In iterative mode, you can control the size of the local cache by\nspecifying `--cache-size` and the timeout for individual iterations by setting\n`--iteration-timeout`. The `--timeout` flag controls the timeout of the entire\nresolution for a given input (i.e., the sum of all iterative steps).\n\n\n###\nThreads, Sockets, and Performance\n---------------------------------\n\nZDNS performance stems from massive parallelization using light-weight Go\nroutines. This architecture has several caveats:\n\n* Every Go routine uses its own dedicated network socket. Thus, you need to be\n  able to open as many sockets (in terms of both max file descriptors and\n  ephemeral ports) as you have threads specified (via `--threads`). By default,\n  ZDNS uses 1,000 threads, which is less than Linux's default max number of 1024\n  open FDs. However, it is greater than Mac OS's default of 256. You can view\n  the maximum number of open FDs (and thus sockets) permitted by running `ulimit -n`. If\n  you want to run with a greater number of threads than this number, you need to\n  increase the number of open files at the OS level. If you fail to do this,\n  you'll encounter a fatal error similar to `FATA[0000] unable to create\n   socketlisten udp \u003cclient IP address\u003e:0: socket: too many open files`. If you\n  want to run more threads than you have ephemeral ports available, you will need\n  to use multiple client IP addresses: `--local-addr=A,B,C`.\n\n* By default, ZDNS \"reuses\" UDP sockets by creating an unbound UDP socket for\n  each light-weight routine at launch and using it for all queries (regardless\n  of destination IP). This dramatically improves performance because ZDNS and the\n  host OS don't need to setup and tear down a socket to send each individual\n  packet (since DNS queries/responses tend to be one packet each).  However, this\n  means that ZDNS will preallocate a socket for each thread at launch. This may not\n  be optimal if you're only looking up a small number of names.  For example, if\n  you only need to lookup 100 names, but use the default 1,000 threads, you'll\n  bind but never use 900 UDP sockets. Instead, of worrying about recycling\n  sockets, we recommend that you specify a reasonable number of threads for your\n  use case (since this also foregoes any work to start those threads in the first place).\n  This is why, though, you can get an error about being unable to open a large\n  number of sockets even though you're only looking up a single name. If it's important\n  to create a fresh socket for each query, you can disable this reuse by specifying\n  `--recycle-sockets=false`.\n\n* Go is happy to use all CPU cores that are available to it, and can use a\n  tremendous amount of CPU if you specify a large number of threads. CPU is\n  primarily used for parsing and JSON encoding. If you want to limit the number\n  of CPU cores, you can do so by including the `--go-processes=n` flag or setting\n  the `GOMAXPROCS` environment variable.\n\n* It's difficult to recommend a precise amount of `--threads` as it depends on several\n  factors. The graph below shows how a sample workflow has lower runtime but higher rates of name resolution failure as the number of threads increases.\n\n\u003cimg src=\"./docs/threads_vs_runtime.png\" alt=\"threads_vs_runtime\" width=\"700\"/\u003e\n\n  Much of the performance that you'll see depends on your workflow, hardware, and how many name servers the load is spread out on. If you're looking to maximize performance\n  for your workflow/hardware, we recommend starting at 100 threads and increasing until you start to see an increase in name resolution failures.\n  To help with this, you can use `--output-file=output.jsonl` and `grep -v \"NOERROR\" output.jsonl | wc -l` to count the number of names that failed to resolve.\n  Flags that may be of use in tuning performance are:\n\n  * `--timeout` The maximum amount of time ZDNS will spend on a single name\n  * `--iteration-timeout` The maximum amount of time ZDNS will spend on a single iteration step (ex: resolving google.com at the .com layer)\n  * `--network-timeout` The maximum amount of time ZDNS will wait for a response from a nameserver\n  * `--retries=N` If a connection to a specific nameserver fails in `--iterative`, ZDNS will retry with another un-queried name server at that layer.\n  Retries are per-name, so if `--retries=1` then ZDNS will retry a name against a new nameserver once during it's full iteration process. If all nameservers have been queried\n  then a random nameserver will be chosen.\n  * `--name-servers` The list of nameservers to use for lookups, mostly useful with `--iterative=false`\n\n\nOutput Verbosity\n----------------\n\nDNS includes a lot of extraneous data that is not always useful. There are four\nresult verbosity levels: `short`, `normal` (default), `long`, and `trace`:\n\n* `short`: Short is the most terse result output. It contains only information about the responses\n* `normal`: Normal provides everything included in short as well as data about the responding server\n* `long`: Long outputs everything the server included in the DNS packet, including flags.\n* `trace`: Trace outputs everything from every step of the recursion process\n\nUsers can also include specific additional fields using the `--include-fields`\nflag and specifying a list of fields, e.g., `--include-fields=flags,resolver`.\nAdditional fields are: class, protocol, ttl, resolver, flags, dnssec.\n\nName Server Mode\n----------------\n\nBy default ZDNS expects to receive a list of names to lookup on a small number\nof name servers. For example:\n\n```echo \"google.com\" | zdns A --name-servers=8.8.8.8,8.8.4.4```\n\nHowever, there are times where you instead want to lookup the same name across\na large number of servers. This can be accomplished using _name server mode_.\nFor example:\n\n```echo \"8.8.8.8\" | zdns A --name-server-mode --override-name=\"google.com\"```\n\nHere, every line piped in ZDNS is sent an A query for `google.com`. ZDNS also\nsupports mixing and matching both modes by piping in a comma-delimited list of\n`name,nameServer`. For example:\n\n```echo \"google.com,8.8.8.8\" | zdns A``` will send an `A` query for\n`google.com` to `8.8.8.8` regardless of what name servers are specified by\n`--name-servers=` flag. Lines that do not explicitly specify a name server will\nuse the servers specified by the OS or `--name-servers` flag as would normally\nhappen.\n\nQuerying all Nameservers\n----------------\nThere is a feature available to perform a certain DNS query against all nameservers. For example, you might want to get the A records from all nameservers of a certain domain. To do so, you can do:\n\n```echo \"google.com\" | zdns A --all-nameservers```\n\nMultiple Lookup Modules\n-----------------------\nZDNS supports using multiple lookup modules in a single invocation. For example, let's say you want to perform an A, \nAAAA, and MXLOOKUP for a set of domains and you want to perform them with iterative resolution. You will need to use the\n`MULTIPLE` module and provide a config file with the modules and module-specific flags you want to use.\n\nPlease see `zdns --help` and `zdns \u003cMODULE_NAME\u003e --help` for Global and Module-specific options that can be used in the config file.\n\nFor example:\n\n```\ncat 1000k_domains.txt | zdns MULTIPLE --multi-config-file=\"./multiple.ini\"\n```\nWhere `multiple.ini` is a file that looks like:\n```\n; Specify Global Options here\n[Application Options]\niterative=true\n; List out modules and their respective module-specific options here. A module can only be listed once\n[MXLOOKUP]\nipv4-lookup = true\n; You can use default values and just list modules if you don't need to specify any options\n[A]\n[AAAA]\n```\n\nA sample `multiple.ini` file is provided in [src/cli/multiple.ini](src/cli/multiple.ini)\n\nRunning ZDNS\n------------\n\nBy default, ZDNS will operate with 1,000 light-weight go routines. If you're\nnot careful, this will overwhelm many upstream DNS providers. We suggest that\nusers coordinate with local network administrators before performing any scans.\nYou can control the number of concurrent connections with the `--threads` and\n`--go-processes` command line arguments. Alternate name servers can be\nspecified with `--name-servers`. ZDNS will rotate through these servers when\nmaking requests. We have successfully run ZDNS with tens of thousands of\nlight-weight routines.\n\nUnsupported Types\n-----------------\n\nIf zdns encounters a record type it does not support it will generate an output\nrecord with the `type` field set correctly and a representation of the\nunderlying data structure in the `unparsed_rr` field. Do not rely on the\npresence or structure of this field. This field (and its existence) may change\nat any time as we expand support for additional record types. If you find\nyourself using this field, please consider submitting a pull-request adding\nparser support.\n\nBenchmark for ZDNS\n------------------\nThere is a benchmark available in `benchmark/` that can be used to run ZDNS in a predictable fashion and print out some statistics about the run.\nThis can be useful for comparing performance before and after a change to ZDNS.\nSee more details in the [benchmark README](./benchmark/README.md).\n\nContributing\n============\n\nIf you're interested in contributing to ZDNS, see [CONTRIBUTING](./CONTRIBUTING.md).\n\nContact\n=======\n- Please use [Github issues](https://github.com/zmap/zdns/issues) for filing bugs.\n\nLicense\n=======\n\nZDNS Copyright 2020 Regents of the University of Michigan\n\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use\nthis file except in compliance with the License. You may obtain a copy of the\nLicense at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed\nunder the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\nCONDITIONS OF ANY KIND, either express or implied. See LICENSE for the specific\nlanguage governing permissions and limitations under the License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzmap%2Fzdns","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzmap%2Fzdns","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzmap%2Fzdns/lists"}