Skip to content

Commit 220930f

Browse files
committed
Added DNS resolver checker + cleanups
1 parent adf4262 commit 220930f

File tree

6 files changed

+149
-6
lines changed

6 files changed

+149
-6
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
*.pyc
2+
axfr.db

README.md

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ was written because we knew there was a better way to do this.
1212
* JSON & text output
1313
* Progress bar
1414
* Tunable concurrency & timeout
15+
* DNS resolver checker
1516

16-
## Usage
17+
## DNSbrute Usage
1718

1819
```
1920
$ python -mdnsbrute
@@ -50,4 +51,27 @@ optional arguments:
5051
Concurrent DNS requests, default: 50
5152
-T SECS, --timeout SECS
5253
Timeout for DNS request in seconds, default: 1.5
54+
```
55+
56+
### checkresolvers usage
57+
58+
```
59+
$ python -mdnsbrute.checkresolvers
60+
usage: checkresolvers.py [-h] [-o OUTFILE] [-D] [-T SECS] [-q] [-v] [--debug]
61+
[-r RESOLVERS_FILE]
62+
63+
DNS resolver list checker
64+
65+
optional arguments:
66+
-h, --help show this help message and exit
67+
-o OUTFILE, --output OUTFILE
68+
Output results to file
69+
-D, --download Download new list of resolvers from public-dns.info
70+
-T SECS, --timeout SECS
71+
Timeout for DNS request in seconds, default: 0.5
72+
-q, --quiet Don't print results to console
73+
-v, --verbose Log informational messages
74+
--debug Log debugging messages
75+
-r RESOLVERS_FILE, --resolvers RESOLVERS_FILE
76+
Load DNS resolver servers from file
5377
```

axfr/verify-axfr.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,8 @@
88
99
The following SQL query will provide the top 1000 most effective subdomains:
1010
11-
SELECT nom, GROUP_CONCAT(rec), SUM(vfy) AS total_cfy SUM(cnt) as total_cnt
12-
FROM axfr_counts
13-
GROUP BY nom
14-
ORDER BY total_very
15-
DESC LIMIT 1000;
11+
SELECT nom, GROUP_CONCAT(rec), SUM(vfy) AS total_vfy, SUM(cnt) as total_cnt
12+
FROM axfr_counts GROUP BY nom ORDER BY total_vfy DESC LIMIT 1000;
1613
"""
1714
from __future__ import print_function
1815
import sys

dnsbrute/__main__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from . import DNSBrute
77

88

9+
910
def main():
1011
parser = argparse.ArgumentParser(description='DNS sub-domain brute forcer')
1112
parser.add_argument('-p', '--progress', action='store_true',

dnsbrute/checkresolvers.py

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
from __future__ import print_function
2+
import sys
3+
import argparse
4+
import logging
5+
import random
6+
import time
7+
import requests
8+
import pkg_resources
9+
import progressbar
10+
from dns.resolver import Resolver, Answer
11+
from dns.exception import DNSException
12+
from . import rand_name
13+
14+
15+
LOG = logging.getLogger(__name__)
16+
17+
18+
# http://stackoverflow.com/questions/287871/print-in-terminal-with-colors-using-python
19+
class bcolors:
20+
HEADER = '\033[95m'
21+
OKBLUE = '\033[94m'
22+
OKGREEN = '\033[92m'
23+
WARNING = '\033[93m'
24+
FAIL = '\033[91m'
25+
ENDC = '\033[0m'
26+
BOLD = '\033[1m'
27+
UNDERLINE = '\033[4m'
28+
29+
30+
def mean(numbers):
31+
return float(sum(numbers)) / max(len(numbers), 1)
32+
33+
34+
def check_results(results):
35+
avg = mean([X for X, _ in results])
36+
return avg, all([isinstance(X, Answer) for _, X in results])
37+
38+
39+
def time_resolve(args, server, name, rectype, tries=3):
40+
"""
41+
Time how long it takes to resolve a name using the server
42+
"""
43+
resolver = Resolver()
44+
resolver.timeout = args.timeout
45+
resolver.lifetime = args.timeout
46+
resolver.nameservers = [server]
47+
results = []
48+
while tries > 0:
49+
start = time.time()
50+
try:
51+
result = resolver.query(name, rectype)
52+
except DNSException as ex:
53+
end = time.time()
54+
LOG.debug("%s failed in %.2fs", server, end - start)
55+
result = ex
56+
else:
57+
end = time.time()
58+
LOG.debug("%s resolved %s %s in %.2fs", server, name, rectype, end - start)
59+
results.append((end - start, result))
60+
tries -= 1
61+
return server, check_results(results), results
62+
63+
64+
def download_resolvers():
65+
resp = requests.get('http://public-dns.info/nameservers.txt')
66+
resp.raise_for_status()
67+
return map(str.strip, filter(None, str(resp.text).split("\n")))
68+
69+
70+
def load_resolvers(handle):
71+
return map(str.strip, filter(None, handle.read().split("\n")))
72+
73+
74+
def run(args):
75+
if args.download:
76+
resolvers = download_resolvers()
77+
else:
78+
resolvers = load_resolvers(args.resolvers)
79+
random.shuffle(resolvers)
80+
81+
bar = progressbar.ProgressBar(redirect_stdout=True, redirect_stderr=True)
82+
for resolver in bar(resolvers):
83+
server, (avgtime, isgood), results = time_resolve(args, resolver, "example.com", "A")
84+
if args.output and isgood:
85+
args.output.write(server + "\n")
86+
args.output.flush()
87+
if not args.quiet:
88+
color = bcolors.OKGREEN if isgood else bcolors.FAIL
89+
print("%s%s (%.2fs)%s" % (color, server, avgtime, bcolors.ENDC))
90+
91+
def main():
92+
parser = argparse.ArgumentParser(description='DNS resolver list checker')
93+
parser.add_argument('-o', '--output', metavar='OUTFILE',
94+
type=argparse.FileType('w+'),
95+
help="Output results to file")
96+
parser.add_argument('-D', '--download', action='store_true',
97+
help='Download new list of resolvers from public-dns.info')
98+
parser.add_argument('-T', '--timeout', default=0.5, type=float, metavar='SECS',
99+
help="Timeout for DNS request in seconds, default: 0.5")
100+
parser.add_argument('-q', '--quiet', action='store_true',
101+
help="Don't print results to console")
102+
parser.add_argument('-v', '--verbose', action='store_const',
103+
dest="loglevel", const=logging.INFO,
104+
help="Log informational messages")
105+
parser.add_argument('--debug', action='store_const', dest="loglevel",
106+
const=logging.DEBUG, default=logging.WARNING,
107+
help="Log debugging messages")
108+
parser.add_argument('-r', '--resolvers', metavar='RESOLVERS_FILE',
109+
default=pkg_resources.resource_stream(__name__, "resolvers.txt"),
110+
type=argparse.FileType('r'),
111+
help="Load DNS resolver servers from file")
112+
args = parser.parse_args()
113+
logging.basicConfig(level=args.loglevel)
114+
run(args)
115+
116+
117+
if __name__ == "__main__":
118+
main()

requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
gevent
22
pycares
3+
dnspython
4+
requests
35
git+https://github.com/WoLpH/python-progressbar.git@develop

0 commit comments

Comments
 (0)