11
11
GOOGLE_DNS = ['8.8.8.8' , '8.8.4.4' ]
12
12
13
13
DEFAULT_RESOLVER = dns .resolver .Resolver (configure = True )
14
+ DEFAULT_RESOLVER .timeout , DEFAULT_RESOLVER .lifetime = 2 , 2
14
15
15
16
16
17
# Max length of four dot-separated octets (e.g. 255.255.255.255)
19
20
IN_ADDR = '.in-addr.arpa.'
20
21
21
22
22
- def debug_print (text , arguments ):
23
+ def debug_print (text , * args ):
23
24
if DEBUG :
24
- print '[D] {}' .format (text ).format (* arguments )
25
+ print '[D] {}' .format (text ).format (* args )
25
26
26
27
27
- def parse_args ():
28
+ def _parse_args ():
28
29
29
30
parser = argparse .ArgumentParser (description = "Perform DNS Queries." )
30
31
parser .add_argument (
@@ -65,7 +66,7 @@ def print_response(ip, name, type, error_msg='', error_type=''):
65
66
print response
66
67
67
68
68
- def get_host_type (query , query_type = 'A' ):
69
+ def _get_host_type (query , query_type = 'A' ):
69
70
'''
70
71
Determine the type of host provided by user. Object will default to
71
72
dns.name.Name as last resort.
@@ -81,29 +82,72 @@ def get_host_type(query, query_type='A'):
81
82
try :
82
83
return ipaddress .ip_address (query ), 'PTR'
83
84
except ValueError :
84
- debug_print ('get_host_type : {} not an IPv4Address.' , query )
85
+ debug_print ('_get_host_type : {} not an IPv4Address.' , query )
85
86
86
87
try :
87
88
return ipaddress .ip_network (query ), 'PTR'
88
89
except ValueError :
89
- debug_print ('get_host_type : {} not an IPv4Network.' , query )
90
+ debug_print ('_get_host_type : {} not an IPv4Network.' , query )
90
91
91
92
# Sanity check - must be IP Address to use reversename PTR type
92
93
if query_type is 'PTR' :
93
94
query_type = 'A'
94
95
95
- debug_print ('get_host_type : {} defaulted to Name type.' , query )
96
+ debug_print ('_get_host_type : {} defaulted to Name type.' , query )
96
97
return dns .name .from_text (query ), query_type
97
98
98
99
99
- def dns_lookup (query , query_type = 'A' , resolver = DEFAULT_RESOLVER ):
100
+ def _parse_nameserver (nameserver ):
101
+
102
+ nameserver = _get_host_type (nameserver )[0 ]
103
+ debug_print ('nameserver type: {}' , (str (type (nameserver ))))
104
+
105
+ if isinstance (nameserver , ipaddress .IPv4Address ):
106
+ return [nameserver .exploded ]
107
+
108
+ if isinstance (nameserver , ipaddress .IPv4Network ):
109
+ return [ip .exploded for ip in nameserver ]
110
+
111
+ if isinstance (nameserver , dns .name .Name ):
112
+ try :
113
+ return [str (server ) for server in nameserver_query (nameserver )]
114
+
115
+ except dns .resolver .NoAnswer :
116
+ print '[x] Cannot resolve nameserver to IP address, ' \
117
+ 'exiting... [{}]' .format (nameserver )
118
+
119
+ return list ()
120
+
121
+
122
+ def _valid_nameservers (nameservers ):
123
+
124
+ valid_servers = []
125
+ resolver = dns .resolver .Resolver ()
126
+ resolver .timeout , resolver .lifetime = 2 , 2
127
+
128
+ debug_print ('_valid_nameservers nameservers: {}' , nameservers )
129
+ # Test if nameservers are valid using nameserver as query
130
+ for nameserver in nameservers :
131
+ resolver .nameservers = [nameserver ]
132
+ debug_print ('\t _valid_nameservers resolver.nameservers: {}' ,
133
+ resolver .nameservers )
134
+ nameserver_query (_get_host_type (nameserver )[0 ], 'PTR' , resolver )
135
+ valid_servers .append (nameserver )
136
+
137
+ debug_print ('\t _valid_nameservers valid_servers: {}' , valid_servers )
138
+
139
+ return valid_servers
140
+
141
+
142
+ def nameserver_query (query , query_type = 'A' , my_resolver = DEFAULT_RESOLVER ):
100
143
101
144
# Convert IP to reverse-map domain name
102
145
if query_type is 'PTR' :
103
146
query = dns .reversename .from_address (query .exploded )
104
147
105
- response = resolver .query (query , query_type )
106
- return [answer for answer in response ]
148
+ debug_print ('nameserver_query query: {} query_type: {}' , query , query_type )
149
+ query_response = my_resolver .query (query , query_type )
150
+ return [answer for answer in query_response ]
107
151
108
152
109
153
def dnslookup (hostname = '' , query_type = 'A' , nameserver = '' , subnet = False ,
@@ -118,51 +162,31 @@ def dnslookup(hostname='', query_type='A', nameserver='', subnet=False,
118
162
119
163
# Sanitize input host
120
164
if hostname :
121
- host , host_type = get_host_type (hostname , query_type )
165
+ debug_print ('supplied hostname: {}' , hostname )
166
+ host , host_type = _get_host_type (hostname , query_type )
122
167
123
168
if isinstance (host , ipaddress .IPv4Network ):
124
169
if subnet :
125
170
queries += [(ip , 'PTR' ) for ip in host ]
126
171
else :
127
- queries .append (get_host_type (hostname .partition ('/' )[0 ]))
172
+ queries .append (_get_host_type (hostname .partition ('/' )[0 ]))
128
173
else :
129
174
queries .append ((host , host_type ))
130
175
131
- debug_print ('args. host: {} args.type : {}' , ( host , host_type ) )
176
+ debug_print ('host: {} host_type : {}' , host , host_type )
132
177
133
178
# Parse nameserver argument to determine if valid
134
179
if nameserver :
135
-
136
- supplied_nameserver = get_host_type (nameserver )[0 ]
137
- debug_print ('nameserver type: {}' , type (supplied_nameserver ))
138
- if isinstance (supplied_nameserver , ipaddress .IPv4Address ):
139
- my_resolver .nameservers = [supplied_nameserver .exploded ]
140
-
141
- if isinstance (supplied_nameserver , dns .name .Name ):
142
- try :
143
- my_resolver .nameservers = map (str , dns_lookup (supplied_nameserver ))
144
- except dns .resolver .NoAnswer :
145
- print '[x] Cannot resolve nameserver to IP address, ' \
146
- 'exiting... [{}]' .format (supplied_nameserver )
147
- quit ()
148
-
149
- # Test if nameserver is valid using nameserver as query
150
- reversename = dns .reversename .from_address (
151
- my_resolver .nameservers [0 ])
152
- try :
153
- dns_lookup (reversename , 'PTR' )
154
- except dns .resolver .Timeout :
155
- print '[x] Connection timed out; no servers could be reached' \
156
- ' [{}]' .format (supplied_nameserver )
180
+ nameservers = _parse_nameserver (nameserver )
181
+ my_resolver .nameservers = _valid_nameservers (nameservers )
182
+ if not my_resolver .nameservers :
157
183
quit ()
158
184
159
- debug_print ('nameserver: {}' , my_resolver .nameservers [0 ])
160
-
161
185
# Parse file if -f flag set
162
186
if filename :
163
187
with open (filename , 'r' ) as in_file :
164
188
for line in in_file :
165
- query = get_host_type (line .strip ())
189
+ query = _get_host_type (line .strip ())
166
190
167
191
if isinstance (query , ipaddress .IPv4Network ):
168
192
queries .append ((query , 'PTR' ))
@@ -175,23 +199,24 @@ def dnslookup(hostname='', query_type='A', nameserver='', subnet=False,
175
199
debug_print ('Entering query lookup loop... ' , '' )
176
200
for items in queries :
177
201
query , query_type = items
178
- debug_print ('\t query: {} query type: {} record type: {}' , (
179
- query , type (query ), query_type ) )
202
+ debug_print ('\t query: {} query type: {} record type: {}' ,
203
+ query , type (query ), query_type )
180
204
181
205
try :
182
- response = dns_lookup (query , query_type )
206
+ response = nameserver_query (query , query_type )
183
207
except dns .resolver .NXDOMAIN :
184
- print 'NXDOMAIN [{}]' .format (query )
208
+ response = ['NXDOMAIN' ]
209
+
185
210
for item in response :
186
- print item
187
- debug_print ('\t dns_lookup.response: {}' , (response ))
211
+ print '\t Response: {}\t {}' .format (query , item )
188
212
189
213
return response
190
214
191
215
if __name__ == '__main__' :
192
216
193
- args = parse_args ()
217
+ args = _parse_args ()
194
218
219
+ print args
195
220
response = dnslookup (
196
221
hostname = args .host ,
197
222
query_type = args .type ,
@@ -201,9 +226,13 @@ def dnslookup(hostname='', query_type='A', nameserver='', subnet=False,
201
226
202
227
203
228
""" To Do List:
204
- Work more on nameservers, stuff missing
229
+ Work more on nameservers, add try statements
205
230
Determine if reverse flag is still necessary
206
231
Fix -f flag for ipv4networks
207
232
Breakout functions into private helper functions
233
+ Consider changing queries from tuple to an object
234
+ Possibly rethink what _get_host_type returns to be more generic,
235
+ deal with specifics outside the function
236
+ Determine a better way to deal with resolvers
208
237
209
238
"""
0 commit comments