Skip to content

Gandi/dnsknife

Folders and files

NameName
Last commit message
Last commit date

Latest commit

78c557c · Sep 14, 2021

History

72 Commits
Oct 10, 2016
Jun 6, 2021
Jun 7, 2016
Apr 25, 2016
Oct 30, 2017
Apr 25, 2016
Oct 16, 2019

Repository files navigation

dnsknife: a DNS tool

Quick overview:

>>> from dnsknife import resolver
>>> ans = resolver.query('example.com', 'A', dnssec=True)

Specific queries shortcuts:

>>> import dnsknife
>>> print dnsknife.Checker('example.com').mx()
[]

>>> print dnsknife.Checker('example.com').spf()
None

>>> print dnsknife.Checker('example.com').txt()
$Id: example.com 4415 2015-08-24 20:12:23Z davids $
v=spf1 -all

Checking a domain TXT record is installed, looking at each domain NS (no local caches) for a match:

>>> from dnsknife import Checker
>>> Checker('example.com', direct=True).has_txt('dbef8938bef', ignore_case=True)
False

Or, if you are into domain challenges:

>>> from dnsknife import Checker

>>> Checker('example.com').has_challenge('secretkey')
False

>>> Checker('example.com').challenge('secretkey')
'f1ef9be83f844d64f8f2bea8bcfb9f7f4cf0792487ae24707937344dbec8f4fb'

Querying a few dozen things at the same time:

>>> from dnsknife.resolver import Resolver
>>> with Resolver(timeout=2) as r:
        a = r.query_at('www.example.com', 'A', '1.2.3.4')
        ...
        x = r.query_at('www.example.com', 'A', '1.2.3.4')

>>> print a.get()
<dns.resolver.Answer at 0x7f6e3d398ad0>

>>> print x.get()
<dns.resolver.Answer at 0x7f6e3d398bd0>

Scanning a zone:

In [16]: from dnsknife.scanner import Scanner
In [9]: time list(Scanner('google.com').scan())
CPU times: user 476 ms, sys: 28 ms, total: 504 ms
Wall time: 2.4 s
Out[9]:
[<DNS mail.google.com. IN CNAME RRset>,
 <DNS support.google.com. IN CNAME RRset>,
 <DNS google.com. IN A RRset>,
 <DNS google.com. IN AAAA RRset>,
 <DNS google.com. IN NS RRset>,
 <DNS google.com. IN MX RRset>,
 <DNS google.com. IN TXT RRset>,
 <DNS www.google.com. IN A RRset>,
 <DNS www.google.com. IN AAAA RRset>,
 <DNS googlemail.l.google.com. IN A RRset>,
 <DNS googlemail.l.google.com. IN AAAA RRset>,
 <DNS mail.google.com. IN TXT RRset>,
 <DNS corp.google.com. IN A RRset>,
 <DNS corp.google.com. IN AAAA RRset>,
 <DNS corp.google.com. IN NS RRset>,
 <DNS admin.google.com. IN A RRset>,
 <DNS admin.google.com. IN AAAA RRset>,
 <DNS www3.l.google.com. IN A RRset>,
 <DNS www3.l.google.com. IN AAAA RRset>,
 <DNS googlemail.l.google.com. IN A RRset>,
 <DNS googlemail.l.google.com. IN AAAA RRset>,
 <DNS www3.l.google.com. IN A RRset>,
 <DNS www3.l.google.com. IN AAAA RRset>,
 <DNS ns4.google.com. IN A RRset>,
 <DNS ns2.google.com. IN A RRset>,
 <DNS ns1.google.com. IN A RRset>,
 <DNS ns3.google.com. IN A RRset>,
 <DNS alt4.aspmx.l.google.com. IN A RRset>,
 <DNS alt4.aspmx.l.google.com. IN AAAA RRset>,
 <DNS aspmx.l.google.com. IN A RRset>,
 <DNS aspmx.l.google.com. IN AAAA RRset>,
 <DNS alt2.aspmx.l.google.com. IN A RRset>,
 <DNS alt2.aspmx.l.google.com. IN AAAA RRset>,
 <DNS alt1.aspmx.l.google.com. IN A RRset>,
 <DNS alt1.aspmx.l.google.com. IN AAAA RRset>,
 <DNS alt3.aspmx.l.google.com. IN A RRset>,
 <DNS alt3.aspmx.l.google.com. IN AAAA RRset>,
 <DNS ns2.google.com. IN A RRset>,
 <DNS ns1.google.com. IN A RRset>,
 <DNS ns3.google.com. IN A RRset>,
 <DNS ns4.google.com. IN A RRset>]

It can be used for DNSSEC lookups, implements a few CDS/CDNSKEY drafts:

>>> c = Checker('example.com', dnssec=True)
>>> print c.spf()
None

>>> Checker('ten.pm').cdnskey()

---------------------------------------------------------------------------
BadCDNSKEY                                Traceback (most recent call last)
...

BadCDNSKEY: 1324 did not sign DNSKEY RR
>>> from dnsknife import dnssec, resolver
>>> keys = resolver.query('example.com', 'DNSKEY')
>>> dnssec.signed_by(ans, keys[0])
True
>>> dnssec.signers(dnsknife.Checker('pm.', dnssec=True)
                   .query_relative('', 'DNSKEY'))
{<DNS name pm.>: [35968, 60859]}
>>> dnssec.trusted(ans)
True

Finally it implements TPDA - the draft can be found in docs.

A third party provider wanting to change customer NS:

>>> from dnsknife import tpda

>>> # initialize with private key from repo:
>>> client = tpda.Client('ten.pm', 'dnsknife/tests/test.key')

>>> # generate url for domain
>>> URI = client.nameservers_uri('whe.re', ['ns1.ten.pm','ns2.ten.pm'])

A DNS operator/registrar validating inbound params:

>>> tpda.validate_URI(URI)
'http://partners.gandi.net/nameservers/v1?source=ten.pm&domain=whe.re&expires=20160415000918&ns=ns1.ten.pm&ns=ns2.ten.pm'