{"id":20357867,"url":"https://github.com/gandi/dnsknife","last_synced_at":"2025-04-12T03:14:53.202Z","repository":{"id":47068659,"uuid":"56191186","full_name":"Gandi/dnsknife","owner":"Gandi","description":"DNS lookup tools","archived":false,"fork":false,"pushed_at":"2021-09-14T23:28:32.000Z","size":94,"stargazers_count":30,"open_issues_count":1,"forks_count":10,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-04-12T03:14:48.692Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Gandi.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-04-13T22:49:56.000Z","updated_at":"2022-11-15T09:39:50.000Z","dependencies_parsed_at":"2022-09-04T22:23:53.367Z","dependency_job_id":null,"html_url":"https://github.com/Gandi/dnsknife","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gandi%2Fdnsknife","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gandi%2Fdnsknife/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gandi%2Fdnsknife/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gandi%2Fdnsknife/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Gandi","download_url":"https://codeload.github.com/Gandi/dnsknife/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248510001,"owners_count":21116130,"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":[],"created_at":"2024-11-14T23:24:13.820Z","updated_at":"2025-04-12T03:14:53.182Z","avatar_url":"https://github.com/Gandi.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\ndnsknife: a DNS tool\n====================\n\nQuick overview:\n---------------\n\n.. code:: python\n\n    \u003e\u003e\u003e from dnsknife import resolver\n    \u003e\u003e\u003e ans = resolver.query('example.com', 'A', dnssec=True)\n\nSpecific queries shortcuts:\n\n.. code:: python\n\n    \u003e\u003e\u003e import dnsknife\n    \u003e\u003e\u003e print dnsknife.Checker('example.com').mx()\n    []\n\n    \u003e\u003e\u003e print dnsknife.Checker('example.com').spf()\n    None\n\n    \u003e\u003e\u003e print dnsknife.Checker('example.com').txt()\n    $Id: example.com 4415 2015-08-24 20:12:23Z davids $\n    v=spf1 -all\n\n\nChecking a domain TXT record is installed, looking at each domain NS (no\nlocal caches) for a match:\n\n.. code:: python\n\n    \u003e\u003e\u003e from dnsknife import Checker\n    \u003e\u003e\u003e Checker('example.com', direct=True).has_txt('dbef8938bef', ignore_case=True)\n    False\n\nOr, if you are into domain challenges:\n\n.. code:: python\n\n    \u003e\u003e\u003e from dnsknife import Checker\n\n    \u003e\u003e\u003e Checker('example.com').has_challenge('secretkey')\n    False\n\n    \u003e\u003e\u003e Checker('example.com').challenge('secretkey')\n    'f1ef9be83f844d64f8f2bea8bcfb9f7f4cf0792487ae24707937344dbec8f4fb'\n\nQuerying a few dozen things at the same time:\n\n.. code:: python\n\n    \u003e\u003e\u003e from dnsknife.resolver import Resolver\n    \u003e\u003e\u003e with Resolver(timeout=2) as r:\n            a = r.query_at('www.example.com', 'A', '1.2.3.4')\n            ...\n            x = r.query_at('www.example.com', 'A', '1.2.3.4')\n\n    \u003e\u003e\u003e print a.get()\n    \u003cdns.resolver.Answer at 0x7f6e3d398ad0\u003e\n\n    \u003e\u003e\u003e print x.get()\n    \u003cdns.resolver.Answer at 0x7f6e3d398bd0\u003e\n\nScanning a zone:\n\n.. code:: python\n\n    In [16]: from dnsknife.scanner import Scanner\n    In [9]: time list(Scanner('google.com').scan())\n    CPU times: user 476 ms, sys: 28 ms, total: 504 ms\n    Wall time: 2.4 s\n    Out[9]: \n    [\u003cDNS mail.google.com. IN CNAME RRset\u003e,\n     \u003cDNS support.google.com. IN CNAME RRset\u003e,\n     \u003cDNS google.com. IN A RRset\u003e,\n     \u003cDNS google.com. IN AAAA RRset\u003e,\n     \u003cDNS google.com. IN NS RRset\u003e,\n     \u003cDNS google.com. IN MX RRset\u003e,\n     \u003cDNS google.com. IN TXT RRset\u003e,\n     \u003cDNS www.google.com. IN A RRset\u003e,\n     \u003cDNS www.google.com. IN AAAA RRset\u003e,\n     \u003cDNS googlemail.l.google.com. IN A RRset\u003e,\n     \u003cDNS googlemail.l.google.com. IN AAAA RRset\u003e,\n     \u003cDNS mail.google.com. IN TXT RRset\u003e,\n     \u003cDNS corp.google.com. IN A RRset\u003e,\n     \u003cDNS corp.google.com. IN AAAA RRset\u003e,\n     \u003cDNS corp.google.com. IN NS RRset\u003e,\n     \u003cDNS admin.google.com. IN A RRset\u003e,\n     \u003cDNS admin.google.com. IN AAAA RRset\u003e,\n     \u003cDNS www3.l.google.com. IN A RRset\u003e,\n     \u003cDNS www3.l.google.com. IN AAAA RRset\u003e,\n     \u003cDNS googlemail.l.google.com. IN A RRset\u003e,\n     \u003cDNS googlemail.l.google.com. IN AAAA RRset\u003e,\n     \u003cDNS www3.l.google.com. IN A RRset\u003e,\n     \u003cDNS www3.l.google.com. IN AAAA RRset\u003e,\n     \u003cDNS ns4.google.com. IN A RRset\u003e,\n     \u003cDNS ns2.google.com. IN A RRset\u003e,\n     \u003cDNS ns1.google.com. IN A RRset\u003e,\n     \u003cDNS ns3.google.com. IN A RRset\u003e,\n     \u003cDNS alt4.aspmx.l.google.com. IN A RRset\u003e,\n     \u003cDNS alt4.aspmx.l.google.com. IN AAAA RRset\u003e,\n     \u003cDNS aspmx.l.google.com. IN A RRset\u003e,\n     \u003cDNS aspmx.l.google.com. IN AAAA RRset\u003e,\n     \u003cDNS alt2.aspmx.l.google.com. IN A RRset\u003e,\n     \u003cDNS alt2.aspmx.l.google.com. IN AAAA RRset\u003e,\n     \u003cDNS alt1.aspmx.l.google.com. IN A RRset\u003e,\n     \u003cDNS alt1.aspmx.l.google.com. IN AAAA RRset\u003e,\n     \u003cDNS alt3.aspmx.l.google.com. IN A RRset\u003e,\n     \u003cDNS alt3.aspmx.l.google.com. IN AAAA RRset\u003e,\n     \u003cDNS ns2.google.com. IN A RRset\u003e,\n     \u003cDNS ns1.google.com. IN A RRset\u003e,\n     \u003cDNS ns3.google.com. IN A RRset\u003e,\n     \u003cDNS ns4.google.com. IN A RRset\u003e]\n\n\nIt can be used for DNSSEC lookups, implements a few CDS/CDNSKEY drafts:\n-----------------------------------------------------------------------\n\n.. code:: python\n\n    \u003e\u003e\u003e c = Checker('example.com', dnssec=True)\n    \u003e\u003e\u003e print c.spf()\n    None\n\n    \u003e\u003e\u003e Checker('ten.pm').cdnskey()\n\n    ---------------------------------------------------------------------------\n    BadCDNSKEY                                Traceback (most recent call last)\n    ...\n\n    BadCDNSKEY: 1324 did not sign DNSKEY RR\n\n.. code:: python\n\n    \u003e\u003e\u003e from dnsknife import dnssec, resolver\n    \u003e\u003e\u003e keys = resolver.query('example.com', 'DNSKEY')\n    \u003e\u003e\u003e dnssec.signed_by(ans, keys[0])\n    True\n\n.. code:: python\n\n    \u003e\u003e\u003e dnssec.signers(dnsknife.Checker('pm.', dnssec=True)\n                       .query_relative('', 'DNSKEY'))\n    {\u003cDNS name pm.\u003e: [35968, 60859]}\n\n.. code:: python\n\n    \u003e\u003e\u003e dnssec.trusted(ans)\n    True\n\n\nFinally it implements TPDA - the draft_ can be found in docs_.\n----------------------------------------------------------------\n\n.. _docs: docs/\n.. _draft: docs/extending_registrar_functions.txt\n\nA third party provider wanting to change customer NS:\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n.. code:: python\n\n    \u003e\u003e\u003e from dnsknife import tpda\n\n    \u003e\u003e\u003e # initialize with private key from repo:\n    \u003e\u003e\u003e client = tpda.Client('ten.pm', 'dnsknife/tests/test.key')\n\n    \u003e\u003e\u003e # generate url for domain\n    \u003e\u003e\u003e URI = client.nameservers_uri('whe.re', ['ns1.ten.pm','ns2.ten.pm'])\n\nA DNS operator/registrar validating inbound params:\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n.. code:: python\n\n    \u003e\u003e\u003e tpda.validate_URI(URI)\n    'http://partners.gandi.net/nameservers/v1?source=ten.pm\u0026domain=whe.re\u0026expires=20160415000918\u0026ns=ns1.ten.pm\u0026ns=ns2.ten.pm'\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgandi%2Fdnsknife","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgandi%2Fdnsknife","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgandi%2Fdnsknife/lists"}