Nmap dns-check-zone NSE Script


This page contains detailed information about how to use the dns-check-zone NSE script. For list of all NSE scripts, visit the Nmap NSE Library.

Select:
Overview
Error Messages

Script Overview


Script source code: https://github.com/nmap/nmap/tree/master/scripts/dns-check-zone.nse
Script categories: discovery, safe, external
Target service / protocol: -
Target network port(s): -
List of CVEs: -

Script Description


The dns-check-zone.nse script checks DNS zone configuration against best practices, including RFC 1912. The configuration checks are divided into categories which each have a number of different tests.

Dns-check-zone NSE Script Arguments


This is a full list of arguments supported by the dns-check-zone.nse script:

dns-check-zone.domain

The dns zone to check

- - -
To use this script argument, add it to Nmap command line like in this example:

nmap --script=dns-check-zone --script-args dns-check-zone.domain=value <target>

Dns-check-zone NSE Script Example Usage


Here's an example of how to use the dns-check-zone.nse script:

nmap -sn -Pn ns1.example.com --script dns-check-zone --script-args='dns-check-zone.domain=example.com'

Dns-check-zone NSE Script Example Output


Here's a sample output from the dns-check-zone.nse script:

| dns-check-zone:
| DNS check results for domain: example.com
|   SOA
|     PASS - SOA REFRESH
|       SOA REFRESH was within recommended range (7200s)
|     PASS - SOA RETRY
|       SOA RETRY was within recommended range (3600s)
|     PASS - SOA EXPIRE
|       SOA EXPIRE was within recommended range (1209600s)
|     FAIL - SOA MNAME entry check
|       SOA MNAME record is NOT listed as DNS server
|     PASS - Zone serial numbers
|       Zone serials match
|   MX
|     ERROR - Reverse MX A records
|       Failed to retrieve list of mail servers
|   NS
|     PASS - Recursive queries
|       None of the servers allow recursive queries.
|     PASS - Multiple name servers
|       Server has 2 name servers
|     PASS - DNS name server IPs are public
|       All DNS IPs were public
|     PASS - DNS server response
|       All servers respond to DNS queries
|     PASS - Missing nameservers reported by parent
|       All DNS servers match
|     PASS - Missing nameservers reported by your nameservers
|_      All DNS servers match

Dns-check-zone NSE Script Example XML Output


There is no sample XML output for this module. However, by providing the -oX <file> option, Nmap will produce a XML output and save it in the file.xml file.

Author


  • Patrik Karlsson

References


See Also


Related NSE scripts to the dns-check-zone.nse script:

Visit Nmap NSE Library for more scripts.

The dns-check-zone.nse script may fail with the following error messages. Check for the possible causes by using the code snippets highlighted below found in the script source code. This can often times help in identifying the root cause of the problem.

Failed to retrieve list of DNS servers


Here is a relevant code snippet related to the "Failed to retrieve list of DNS servers" error message:

78:	      func = function(domain, server)
79:	        local status, res = dns.query(domain, { host = server, dtype='NS', retAll = true })
80:	        local result = {}
81:	
82:	        if ( not(status) ) then
83:	          return false, "Failed to retrieve list of DNS servers"
84:	        end
85:	        for _, srv in ipairs(res or {}) do
86:	          local status, res = dns.query(PROBE_HOST, { host = srv, dtype='A' })
87:	          if ( status ) then
88:	            table.insert(result, res)

Failed to retrieve list of DNS servers


Here is a relevant code snippet related to the "Failed to retrieve list of DNS servers" error message:

102:	      desc = "Multiple name servers",
103:	      func = function(domain, server)
104:	        local status, res = dns.query(domain, { host = server, dtype='NS', retAll = true })
105:	
106:	        if ( not(status) ) then
107:	          return false, "Failed to retrieve list of DNS servers"
108:	        end
109:	
110:	        local status = Status.FAIL
111:	        if ( 1 < #res ) then
112:	          status = Status.PASS

Failed to retrieve list of DNS servers


Here is a relevant code snippet related to the "Failed to retrieve list of DNS servers" error message:

119:	      desc = "DNS name server IPs are public",
120:	      func = function(domain, server)
121:	
122:	        local status, res = dns.query(domain, { host = server, dtype='NS', retAll = true })
123:	        if ( not(status) ) then
124:	          return false, "Failed to retrieve list of DNS servers"
125:	        end
126:	
127:	        local result = {}
128:	        for _, srv in ipairs(res or {}) do
129:	          local status, res = dns.query(srv, { dtype='A', retAll = true })

Failed to retrieve IP for DNS: %s


Here is a relevant code snippet related to the "Failed to retrieve IP for DNS: %s" error message:

126:	
127:	        local result = {}
128:	        for _, srv in ipairs(res or {}) do
129:	          local status, res = dns.query(srv, { dtype='A', retAll = true })
130:	          if ( not(status) ) then
131:	            return false, ("Failed to retrieve IP for DNS: %s"):format(srv)
132:	          end
133:	          for _, ip in ipairs(res) do
134:	            if ( ipOps.isPrivate(ip) ) then
135:	              table.insert(result, ip)
136:	            end

Failed to retrieve list of DNS servers


Here is a relevant code snippet related to the "Failed to retrieve list of DNS servers" error message:

152:	    {
153:	      desc = "DNS server response",
154:	      func = function(domain, server)
155:	        local status, res = dns.query(domain, { host = server, dtype='NS', retAll = true })
156:	        if ( not(status) ) then
157:	          return false, "Failed to retrieve list of DNS servers"
158:	        end
159:	
160:	        local result = {}
161:	        for _, srv in ipairs(res or {}) do
162:	          local status, res = dns.query(domain, { host = srv, dtype='SOA', retPkt = true })

Failed to retrieve list of TLD DNS servers


Here is a relevant code snippet related to the "Failed to retrieve list of TLD DNS servers" error message:

178:	      desc = "Missing nameservers reported by parent",
179:	      func = function(domain, server)
180:	        local tld = domain:match("%.(.*)$")
181:	        local status, res = dns.query(tld, { dtype = "NS", retAll = true })
182:	        if ( not(status) ) then
183:	          return false, "Failed to retrieve list of TLD DNS servers"
184:	        end
185:	
186:	        local status, parent_res = dns.query(domain, { host = res, dtype = "NS", retAll = true, retPkt = true, noauth = true } )
187:	        if ( not(status) ) then
188:	          return false, "Failed to retrieve a list of parent DNS servers"

Failed to retrieve a list of parent DNS servers


Here is a relevant code snippet related to the "Failed to retrieve a list of parent DNS servers" error message:

183:	          return false, "Failed to retrieve list of TLD DNS servers"
184:	        end
185:	
186:	        local status, parent_res = dns.query(domain, { host = res, dtype = "NS", retAll = true, retPkt = true, noauth = true } )
187:	        if ( not(status) ) then
188:	          return false, "Failed to retrieve a list of parent DNS servers"
189:	        end
190:	
191:	        if ( not(status) or not(parent_res) or type(parent_res.auth) ~= "table"  ) then
192:	          return false, "Failed to retrieve a list of parent DNS servers"
193:	        end

Failed to retrieve a list of parent DNS servers


Here is a relevant code snippet related to the "Failed to retrieve a list of parent DNS servers" error message:

187:	        if ( not(status) ) then
188:	          return false, "Failed to retrieve a list of parent DNS servers"
189:	        end
190:	
191:	        if ( not(status) or not(parent_res) or type(parent_res.auth) ~= "table"  ) then
192:	          return false, "Failed to retrieve a list of parent DNS servers"
193:	        end
194:	
195:	        local parent_dns = {}
196:	        for _, auth in ipairs(parent_res.auth) do
197:	          parent_dns[auth.domain] = true

Failed to retrieve a list of DNS servers


Here is a relevant code snippet related to the "Failed to retrieve a list of DNS servers" error message:

197:	          parent_dns[auth.domain] = true
198:	        end
199:	
200:	        status, res = dns.query(domain, { host = server, dtype = "NS", retAll = true } )
201:	        if ( not(status) ) then
202:	          return false, "Failed to retrieve a list of DNS servers"
203:	        end
204:	
205:	        local domain_dns = {}
206:	        for _,srv in ipairs(res) do domain_dns[srv] = true end
207:	

Failed to retrieve list of TLD DNS servers


Here is a relevant code snippet related to the "Failed to retrieve list of TLD DNS servers" error message:

226:	      desc = "Missing nameservers reported by your nameservers",
227:	      func = function(domain, server)
228:	        local tld = domain:match("%.(.*)$")
229:	        local status, res = dns.query(tld, { dtype = "NS", retAll = true })
230:	        if ( not(status) ) then
231:	          return false, "Failed to retrieve list of TLD DNS servers"
232:	        end
233:	
234:	        local status, parent_res = dns.query(domain, { host = res, dtype = "NS", retAll = true, retPkt = true, noauth = true } )
235:	        if ( not(status) ) then
236:	          return false, "Failed to retrieve a list of parent DNS servers"

Failed to retrieve a list of parent DNS servers


Here is a relevant code snippet related to the "Failed to retrieve a list of parent DNS servers" error message:

231:	          return false, "Failed to retrieve list of TLD DNS servers"
232:	        end
233:	
234:	        local status, parent_res = dns.query(domain, { host = res, dtype = "NS", retAll = true, retPkt = true, noauth = true } )
235:	        if ( not(status) ) then
236:	          return false, "Failed to retrieve a list of parent DNS servers"
237:	        end
238:	
239:	        if ( not(status) or not(parent_res) or type(parent_res.auth) ~= "table"  ) then
240:	          return false, "Failed to retrieve a list of parent DNS servers"
241:	        end

Failed to retrieve a list of parent DNS servers


Here is a relevant code snippet related to the "Failed to retrieve a list of parent DNS servers" error message:

235:	        if ( not(status) ) then
236:	          return false, "Failed to retrieve a list of parent DNS servers"
237:	        end
238:	
239:	        if ( not(status) or not(parent_res) or type(parent_res.auth) ~= "table"  ) then
240:	          return false, "Failed to retrieve a list of parent DNS servers"
241:	        end
242:	
243:	        local parent_dns = {}
244:	        for _, auth in ipairs(parent_res.auth) do
245:	          parent_dns[auth.domain] = true

Failed to retrieve a list of DNS servers


Here is a relevant code snippet related to the "Failed to retrieve a list of DNS servers" error message:

245:	          parent_dns[auth.domain] = true
246:	        end
247:	
248:	        status, res = dns.query(domain, { host = server, dtype = "NS", retAll = true } )
249:	        if ( not(status) ) then
250:	          return false, "Failed to retrieve a list of DNS servers"
251:	        end
252:	
253:	        local domain_dns = {}
254:	        for _,srv in ipairs(res) do  domain_dns[srv] = true end
255:	

Failed to retrieve SOA record


Here is a relevant code snippet related to the "Failed to retrieve SOA record" error message:

276:	    {
277:	      desc = "SOA REFRESH",
278:	      func = function(domain, server)
279:	        local status, res = dns.query(domain, { host = server, dtype='SOA', retPkt=true })
280:	        if ( not(status) or not(isValidSOA(res)) ) then
281:	          return false, "Failed to retrieve SOA record"
282:	        end
283:	
284:	        local refresh = tonumber(res.answers[1].SOA.refresh)
285:	        if ( not(refresh) ) then
286:	          return false, "Failed to retrieve SOA REFRESH"

Failed to retrieve SOA REFRESH


Here is a relevant code snippet related to the "Failed to retrieve SOA REFRESH" error message:

281:	          return false, "Failed to retrieve SOA record"
282:	        end
283:	
284:	        local refresh = tonumber(res.answers[1].SOA.refresh)
285:	        if ( not(refresh) ) then
286:	          return false, "Failed to retrieve SOA REFRESH"
287:	        end
288:	
289:	        if ( refresh < 1200 or refresh > 43200 ) then
290:	          return true, { status = Status.FAIL, output = ("SOA REFRESH was NOT within recommended range (%ss)"):format(refresh) }
291:	        else

SOA REFRESH was NOT within recommended range (%ss)


Here is a relevant code snippet related to the "SOA REFRESH was NOT within recommended range (%ss)" error message:

285:	        if ( not(refresh) ) then
286:	          return false, "Failed to retrieve SOA REFRESH"
287:	        end
288:	
289:	        if ( refresh < 1200 or refresh > 43200 ) then
290:	          return true, { status = Status.FAIL, output = ("SOA REFRESH was NOT within recommended range (%ss)"):format(refresh) }
291:	        else
292:	          return true, { status = Status.PASS, output = ("SOA REFRESH was within recommended range (%ss)"):format(refresh) }
293:	        end
294:	      end
295:	    },

Failed to retrieve SOA record


Here is a relevant code snippet related to the "Failed to retrieve SOA record" error message:

297:	    {
298:	      desc = "SOA RETRY",
299:	      func = function(domain, server)
300:	        local status, res = dns.query(domain, { host = server, dtype='SOA', retPkt=true })
301:	        if ( not(status) or not(isValidSOA(res)) ) then
302:	          return false, "Failed to retrieve SOA record"
303:	        end
304:	
305:	        local retry = tonumber(res.answers[1].SOA.retry)
306:	        if ( not(retry) ) then
307:	          return false, "Failed to retrieve SOA RETRY"

Failed to retrieve SOA RETRY


Here is a relevant code snippet related to the "Failed to retrieve SOA RETRY" error message:

302:	          return false, "Failed to retrieve SOA record"
303:	        end
304:	
305:	        local retry = tonumber(res.answers[1].SOA.retry)
306:	        if ( not(retry) ) then
307:	          return false, "Failed to retrieve SOA RETRY"
308:	        end
309:	
310:	        if ( retry < 180 ) then
311:	          return true, { status = Status.FAIL, output = ("SOA RETRY was NOT within recommended range (%ss)"):format(retry) }
312:	        else

SOA RETRY was NOT within recommended range (%ss)


Here is a relevant code snippet related to the "SOA RETRY was NOT within recommended range (%ss)" error message:

306:	        if ( not(retry) ) then
307:	          return false, "Failed to retrieve SOA RETRY"
308:	        end
309:	
310:	        if ( retry < 180 ) then
311:	          return true, { status = Status.FAIL, output = ("SOA RETRY was NOT within recommended range (%ss)"):format(retry) }
312:	        else
313:	          return true, { status = Status.PASS, output = ("SOA RETRY was within recommended range (%ss)"):format(retry) }
314:	        end
315:	      end
316:	    },

Failed to retrieve SOA record


Here is a relevant code snippet related to the "Failed to retrieve SOA record" error message:

318:	    {
319:	      desc = "SOA EXPIRE",
320:	      func = function(domain, server)
321:	        local status, res = dns.query(domain, { host = server, dtype='SOA', retPkt=true })
322:	        if ( not(status) or not(isValidSOA(res)) ) then
323:	          return false, "Failed to retrieve SOA record"
324:	        end
325:	
326:	        local expire = tonumber(res.answers[1].SOA.expire)
327:	        if ( not(expire) ) then
328:	          return false, "Failed to retrieve SOA EXPIRE"

Failed to retrieve SOA EXPIRE


Here is a relevant code snippet related to the "Failed to retrieve SOA EXPIRE" error message:

323:	          return false, "Failed to retrieve SOA record"
324:	        end
325:	
326:	        local expire = tonumber(res.answers[1].SOA.expire)
327:	        if ( not(expire) ) then
328:	          return false, "Failed to retrieve SOA EXPIRE"
329:	        end
330:	
331:	        if ( expire < 1209600 or expire > 2419200 ) then
332:	          return true, { status = Status.FAIL, output = ("SOA EXPIRE was NOT within recommended range (%ss)"):format(expire) }
333:	        else

SOA EXPIRE was NOT within recommended range (%ss)


Here is a relevant code snippet related to the "SOA EXPIRE was NOT within recommended range (%ss)" error message:

327:	        if ( not(expire) ) then
328:	          return false, "Failed to retrieve SOA EXPIRE"
329:	        end
330:	
331:	        if ( expire < 1209600 or expire > 2419200 ) then
332:	          return true, { status = Status.FAIL, output = ("SOA EXPIRE was NOT within recommended range (%ss)"):format(expire) }
333:	        else
334:	          return true, { status = Status.PASS, output = ("SOA EXPIRE was within recommended range (%ss)"):format(expire) }
335:	        end
336:	      end
337:	    },

Failed to retrieve SOA record


Here is a relevant code snippet related to the "Failed to retrieve SOA record" error message:

339:	    {
340:	      desc = "SOA MNAME entry check",
341:	      func = function(domain, server)
342:	        local status, res = dns.query(domain, { host = server, dtype='SOA', retPkt=true })
343:	        if ( not(status) or not(isValidSOA(res)) ) then
344:	          return false, "Failed to retrieve SOA record"
345:	        end
346:	        local mname = res.answers[1].SOA.mname
347:	
348:	        status, res = dns.query(domain, { host = server, dtype='NS', retAll = true })
349:	        if ( not(status) ) then

Failed to retrieve list of DNS servers


Here is a relevant code snippet related to the "Failed to retrieve list of DNS servers" error message:

345:	        end
346:	        local mname = res.answers[1].SOA.mname
347:	
348:	        status, res = dns.query(domain, { host = server, dtype='NS', retAll = true })
349:	        if ( not(status) ) then
350:	          return false, "Failed to retrieve list of DNS servers"
351:	        end
352:	
353:	        for _, srv in ipairs(res or {}) do
354:	          if ( srv == mname ) then
355:	            return true, { status = Status.PASS, output = "SOA MNAME record is listed as DNS server" }

SOA MNAME record is NOT listed as DNS server


Here is a relevant code snippet related to the "SOA MNAME record is NOT listed as DNS server" error message:

353:	        for _, srv in ipairs(res or {}) do
354:	          if ( srv == mname ) then
355:	            return true, { status = Status.PASS, output = "SOA MNAME record is listed as DNS server" }
356:	          end
357:	        end
358:	        return true, { status = Status.FAIL, output = "SOA MNAME record is NOT listed as DNS server" }
359:	      end
360:	    },
361:	
362:	    {
363:	      desc = "Zone serial numbers",

Failed to retrieve list of DNS servers


Here is a relevant code snippet related to the "Failed to retrieve list of DNS servers" error message:

362:	    {
363:	      desc = "Zone serial numbers",
364:	      func = function(domain, server)
365:	        local status, res = dns.query(domain, { host = server, dtype='NS', retAll = true })
366:	        if ( not(status) ) then
367:	          return false, "Failed to retrieve list of DNS servers"
368:	        end
369:	
370:	        local result = {}
371:	        local serial
372:	

Failed to retrieve SOA record


Here is a relevant code snippet related to the "Failed to retrieve SOA record" error message:

371:	        local serial
372:	
373:	        for _, srv in ipairs(res or {}) do
374:	          local status, res = dns.query(domain, { host = srv, dtype='SOA', retPkt = true })
375:	          if ( not(status) or not(isValidSOA(res)) ) then
376:	            return false, "Failed to retrieve SOA record"
377:	          end
378:	
379:	          local s = res.answers[1].SOA.serial
380:	          if ( not(serial) ) then
381:	            serial = s

Different zone serials were detected


Here is a relevant code snippet related to the "Different zone serials were detected" error message:

378:	
379:	          local s = res.answers[1].SOA.serial
380:	          if ( not(serial) ) then
381:	            serial = s
382:	          elseif( serial ~= s ) then
383:	            return true, { status = Status.FAIL, output = "Different zone serials were detected" }
384:	          end
385:	        end
386:	
387:	        return true, { status = Status.PASS, output = "Zone serials match" }
388:	      end,

Failed to retrieve list of mail servers


Here is a relevant code snippet related to the "Failed to retrieve list of mail servers" error message:

394:	    {
395:	      desc = "Reverse MX A records",
396:	      func = function(domain, server)
397:	        local status, res = dns.query(domain, { host = server, dtype='MX', retAll = true })
398:	        if ( not(status) ) then
399:	          return false, "Failed to retrieve list of mail servers"
400:	        end
401:	
402:	        local result = {}
403:	        for _, record in ipairs(res or {}) do
404:	          local prio, mx = record:match("^(%d*):([^:]*)")

Failed to retrieve A records for MX


Here is a relevant code snippet related to the "Failed to retrieve A records for MX" error message:

403:	        for _, record in ipairs(res or {}) do
404:	          local prio, mx = record:match("^(%d*):([^:]*)")
405:	          local ips
406:	          status, ips = dns.query(mx, { dtype='A', retAll=true })
407:	          if ( not(status) ) then
408:	            return false, "Failed to retrieve A records for MX"
409:	          end
410:	
411:	          for _, ip in ipairs(ips) do
412:	            local status, res = dns.query(dns.reverse(ip), { dtype='PTR' })
413:	            if ( not(status) ) then

ERROR - %s


Here is a relevant code snippet related to the "ERROR - %s" error message:

438:	      local status, res = check.func(arg_domain, server)
439:	      if ( status ) then
440:	        local test_res = ("%s - %s"):format(res.status, check.desc)
441:	        table.insert(group_output, { name = test_res, res.output })
442:	      else
443:	        local test_res = ("ERROR - %s"):format(check.desc)
444:	        table.insert(group_output, { name = test_res, res })
445:	      end
446:	    end
447:	    table.insert(output, group_output)
448:	  end

Version


This page has been created based on Nmap version 7.92.

Go back to menu.