]>
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
)
54 nameservers
= result
.data
.as_domain_list()
56 for nameserver
in nameservers
:
57 for rrtype
in [RR_TYPE_AAAA
, RR_TYPE_A
]:
58 s
, result
= resolver
.resolve(nameserver
, rrtype
=rrtype
)
62 nsips
= nsips
+ result
.data
.as_address_list()
68 s
, result
= newres
.resolve(name
, rrtype
=RR_TYPE_SOA
)
73 s
, result
= ldns
.ldns_wire2pkt(result
.packet
)
74 soas
= list(result
.rr_list_by_type(RR_TYPE_SOA
,
75 ldns
.LDNS_SECTION_ANSWER
).rrs())
79 serial
= str(soas
[0]).split()[6]
80 results
[serial
] = results
.get(serial
, []) + [ip
]
85 print("CRIT (different SOAs): %s", results
)
89 parser
= OptionParser()
90 parser
.add_option("-n", "--name",
91 action
="append", type="string", dest
="names",
92 help="DNS Names to check")
93 parser
.add_option("-a", "--ancor",
94 action
="store", type="string", dest
="ancor",
95 default
="/etc/unbound/root.key",
96 help="DNSSEC root ancor")
97 parser
.add_option("-w", "--warning-days",
98 action
="store", type=int, dest
="warn", default
=5,
99 help="minimum remaining validity in days before a warning is issued")
100 parser
.add_option("-c", "--critical-days",
101 action
="store", type=int, dest
="crit", default
=2,
102 help="minimum remaining validity in days before a warning is issued")
103 parser
.add_option("-v", action
="store_true", dest
="verbose", default
=False)
104 parser
.add_option("-q", action
="store_false", dest
="verbose")
106 opts
, _args
= parser
.parse_args()
108 parser
.error("needs at least one DNS name")
111 resolver
.add_ta_file(opts
.ancor
)
112 encoding
= sys
.getfilesystemencoding()
115 for name
in opts
.names
:
116 name
= idn2dname(name
.decode(encoding
))
117 result1
= check_zone_synced(resolver
, name
)
120 elif result1
== 1 and final
!= 2:
122 elif result1
== 3 and final
not in [1, 2]:
125 result2
= check_dnssec_expire(resolver
, name
,
126 timedelta(opts
.warn
), timedelta(opts
.crit
))
127 if result1
+ result2
== 0 and opts
.verbose
:
128 print("OK %s" % name
)
131 elif result2
== 1 and final
!= 2:
133 elif result2
== 3 and final
not in [1, 2]:
138 if __name__
== "__main__":