]>
git.siccegge.de Git - tools.git/blob - dnssec-check
3 from __future__
import print_function
5 from unbound
import ub_ctx
, idn2dname
, ub_strerror
6 from unbound
import RR_TYPE_SOA
, RR_TYPE_DNSKEY
, RR_TYPE_RRSIG
, RR_TYPE_NS
7 from unbound
import RR_TYPE_A
, RR_TYPE_AAAA
8 from optparse
import OptionParser
10 from datetime
import datetime
, timedelta
12 def parse_rrsig_expire(expirestring
):
13 expires
= datetime(int(expirestring
[:4]),
14 int(expirestring
[4:6]),
15 int(expirestring
[6:8]),
16 int(expirestring
[8:10]),
17 int(expirestring
[10:12]),
18 int(expirestring
[12:14]))
20 delta
= expires
- datetime
.utcnow()
23 def check_dnssec_expire(resolver
, name
, warn
, crit
):
24 for rrtype
in [RR_TYPE_SOA
, RR_TYPE_DNSKEY
]:
25 s
, result
= resolver
.resolve(name
, rrtype
=rrtype
)
31 print("CRIT (does not verify) %s" % (name
, ))
34 s
, packet
= ldns
.ldns_wire2pkt(result
.packet
)
35 rrsigs
= packet
.rr_list_by_type(RR_TYPE_RRSIG
, ldns
.LDNS_SECTION_ANSWER
).rrs()
38 delta
= parse_rrsig_expire(str(rrsig
.rrsig_expiration()))
41 print("CRIT (expires in %s) %s" % (delta
, name
))
44 print("WARN (expires in %s) %s" % (delta
, name
))
48 def check_zone_synced(resolver
, name
):
49 s
, result
= resolver
.resolve(name
, RR_TYPE_NS
)
55 print("CRIT (does not verify) %s" % (name
, ))
58 nameservers
= result
.data
.as_domain_list()
60 for nameserver
in nameservers
:
61 for rrtype
in [RR_TYPE_AAAA
, RR_TYPE_A
]:
62 s
, result
= resolver
.resolve(nameserver
, rrtype
=rrtype
)
66 nsips
= nsips
+ result
.data
.as_address_list()
72 s
, result
= newres
.resolve(name
, rrtype
=RR_TYPE_SOA
)
77 s
, result
= ldns
.ldns_wire2pkt(result
.packet
)
78 soas
= list(result
.rr_list_by_type(RR_TYPE_SOA
,
79 ldns
.LDNS_SECTION_ANSWER
).rrs())
83 serial
= str(soas
[0]).split()[6]
84 results
[serial
] = results
.get(serial
, []) + [ip
]
89 print("CRIT (different SOAs): %s", results
)
93 parser
= OptionParser()
94 parser
.add_option("-n", "--name",
95 action
="append", type="string", dest
="names",
96 help="DNS Names to check")
97 parser
.add_option("-a", "--ancor",
98 action
="store", type="string", dest
="ancor",
99 default
="/etc/unbound/root.key",
100 help="DNSSEC root ancor")
101 parser
.add_option("-w", "--warning-days",
102 action
="store", type=int, dest
="warn", default
=5,
103 help="minimum remaining validity in days before a warning is issued")
104 parser
.add_option("-c", "--critical-days",
105 action
="store", type=int, dest
="crit", default
=2,
106 help="minimum remaining validity in days before a warning is issued")
107 parser
.add_option("-v", action
="store_true", dest
="verbose", default
=False)
108 parser
.add_option("-q", action
="store_false", dest
="verbose")
110 opts
, _args
= parser
.parse_args()
112 parser
.error("needs at least one DNS name")
115 resolver
.add_ta_file(opts
.ancor
)
116 encoding
= sys
.getfilesystemencoding()
119 for name
in opts
.names
:
120 name
= idn2dname(name
.decode(encoding
))
121 result1
= check_zone_synced(resolver
, name
)
124 elif result1
== 1 and final
!= 2:
126 elif result1
== 3 and final
not in [1, 2]:
129 result2
= check_dnssec_expire(resolver
, name
,
130 timedelta(opts
.warn
), timedelta(opts
.crit
))
131 if result1
+ result2
== 0 and opts
.verbose
:
132 print("OK %s" % name
)
135 elif result2
== 1 and final
!= 2:
137 elif result2
== 3 and final
not in [1, 2]:
142 if __name__
== "__main__":