|
1 #! /usr/bin/perl |
|
2 #dig TLSA _25._tcp.ssl.schlittermann.de +dnssec +m |
|
3 #dig TLSA _25._tcp.hh.schlittermann.de |
|
4 # http://search.cpan.org/~nierlein/Monitoring-Plugin-0.39/lib/Monitoring/Plugin.pm |
|
5 # http://perldoc.perl.org/File/Basename.html |
|
6 # needs debian packet: libmonitoring-plugin-perl |
|
7 #TLSA Record generieren |
|
8 # openssl x509 -in <servername>.crt -outform DER | openssl sha256 |
|
9 # neben sha256 gibt's noch sha1 sha224 sha256 sha384 sha512 |
|
10 # sowie md2 md5 rmd160 (wobei ich diese nicht in betracht ziehe) |
|
11 # ssl certifikat von einem remote server anfordern |
|
12 # openssl s_client -showcerts -connect ssl.schlittermann.de:443 < /dev/null |
|
13 # https://github.com/monitoring-plugins |
|
14 # https://github.com/monitoring-plugins/monitoring-plugin-perl/blob/master/t/check_stuff.pl |
|
15 |
|
16 #openssl s_client -starttls smtp -connect ssl.schlittermann.de:25 | openssl x509 -pubkey | openssl rsa -pubin -inform PEM -outform DER | openssl sha256 |
|
17 #openssl s_client -starttls smtp -connect ssl.schlittermann.de:25 | openssl x509 -outform DER | openssl sha256 |
|
18 |
|
19 use strict; |
|
20 use warnings; |
|
21 use feature qw(switch); |
|
22 use if $^V >= v5.020 => (experimental => qw(smartmatch)); |
|
23 use experimental qw(smartmatch); |
|
24 use Monitoring::Plugin; |
|
25 use File::Basename; |
|
26 |
|
27 #devel |
|
28 use Data::Dumper; |
|
29 |
|
30 use constant LF => "\n"; |
|
31 |
|
32 my $VERSION = '0.1'; |
|
33 my $blurb = 'This Plugin is intendet to check TLSA Record'; |
|
34 my $url = 'https://schlittermann.de'; |
|
35 my $author = 'Heike Yvonne Pesch'; |
|
36 my $email = '<pesch@schlittermann.de>'; |
|
37 my $extra = LF.'Author: '.$author.' '.$email.LF |
|
38 . 'For more information visit '.$url; |
|
39 my $license = 'GPLv3'; |
|
40 my $usage = 'Usage: %s [ -v|--verbose ] [-H <host>] [-t <timeout>] ' |
|
41 . '[ -c|--critical=<critical threshold> ] ' |
|
42 . '[ -w|--warning=<warning threshold> ] ' |
|
43 . '[ -p|--port=<portnumber> ] ' |
|
44 . '[ -q|--queryserver=<DNS-Server-IP> ] '; |
|
45 |
|
46 my $check_tlsa = Monitoring::Plugin->new( |
|
47 usage => $usage, |
|
48 version => $VERSION, |
|
49 blurb => $blurb, |
|
50 extra => $extra, |
|
51 url => $url, |
|
52 license => $license, |
|
53 plugin => basename $0, |
|
54 timeout => 60, |
|
55 ); |
|
56 |
|
57 $check_tlsa->add_arg( |
|
58 spec => 'host|H=s', |
|
59 help => q|Host/Domain to check|, |
|
60 required => 0, |
|
61 ); |
|
62 |
|
63 $check_tlsa->add_arg( |
|
64 spec => 'hostlist|f=s', |
|
65 help => q|Host/Domainlist in file to check|, |
|
66 required => 0, |
|
67 ); |
|
68 |
|
69 $check_tlsa->add_arg( |
|
70 spec => 'expiry|e', |
|
71 help => q|check expiry of Certificate|, |
|
72 required => 0, |
|
73 ); |
|
74 |
|
75 $check_tlsa->add_arg( |
|
76 spec => 'port|p=i', |
|
77 help => q|Port of Domain to check the TLSA (default: 443)|, |
|
78 required => 0, |
|
79 default => 443, |
|
80 ); |
|
81 |
|
82 $check_tlsa->add_arg( |
|
83 spec => 'queryserver|q=s', |
|
84 help => q|DNS Server to ask to check the TLSA (default: defined in resolve.conf)|, |
|
85 required => 0, |
|
86 #default => '8.8.8.8', |
|
87 ); |
|
88 |
|
89 $check_tlsa->add_arg( |
|
90 spec => 'protocol|P=s', |
|
91 help => q|DNS Server to ask to check the TLSA (default: tcp)|, |
|
92 required => 0, |
|
93 default => 'tcp', |
|
94 ); |
|
95 |
|
96 $check_tlsa->getopts; |
|
97 |
|
98 my $domain = $check_tlsa->opts->host; |
|
99 my $domainlist = $check_tlsa->opts->hostlist; |
|
100 my $expiry = $check_tlsa->opts->expiry; |
|
101 |
|
102 if (!$domain && !$domainlist) { |
|
103 my $script = basename $0; |
|
104 my $excuse = "Please set -H <domain> or -f <domainlist>\n" |
|
105 . "For all options try $script --help"; |
|
106 |
|
107 print $excuse,LF; |
|
108 exit 1; |
|
109 } |
|
110 |
|
111 |
|
112 my $port; |
|
113 my $cert; |
|
114 my $check_date; |
|
115 |
|
116 if ( defined $domainlist && -e $domainlist){ |
|
117 print get_domains(); |
|
118 } |
|
119 else { print check_tlsa(); } |
|
120 |
|
121 sub check_tlsa { |
|
122 my $protocol = $check_tlsa->opts->protocol; |
|
123 |
|
124 $port = $check_tlsa->opts->port unless $port ; |
|
125 |
|
126 if ("$port" eq '25') { |
|
127 $cert = "openssl s_client -starttls smtp -connect $domain:$port " |
|
128 . '< /dev/null 2>/dev/null'; |
|
129 } |
|
130 else { |
|
131 #$port = $check_tlsa->opts->port; |
|
132 $cert = "openssl s_client -connect $domain:$port " |
|
133 . '< /dev/null 2>/dev/null'; |
|
134 } |
|
135 |
|
136 my $digquery = "dig TLSA _$port._$protocol.$domain +short"; |
|
137 my $diganswer = qx($digquery); |
|
138 my $dig = substr($diganswer, 6, ); |
|
139 $dig =~ s/(\S*)\s+(\S*)$/$1$2/; |
|
140 my $tlsa_usage = substr($diganswer, 0, 1); |
|
141 my $tlsa_selector = substr($diganswer, 2, 1); |
|
142 my $tlsa_match_type = substr($diganswer, 4, 1); |
|
143 my $hashit; |
|
144 |
|
145 for ($tlsa_match_type) { |
|
146 when('0') { die 'certs will be compared directly'} |
|
147 when('1') {$hashit = 'sha256'} |
|
148 when('2') {$hashit = 'sha512'} |
|
149 default {$hashit = 'sha256'} |
|
150 }; |
|
151 |
|
152 my $gentlsa = 'openssl x509 -pubkey | ' |
|
153 . 'openssl rsa -pubin -inform PEM -outform DER 2>/dev/null| ' |
|
154 . "openssl $hashit"; |
|
155 my $certtlsa = "$cert | $gentlsa"; |
|
156 |
|
157 $check_date = 'openssl x509 -noout -startdate -enddate'; |
|
158 $check_date = "$cert|$check_date"; |
|
159 |
|
160 |
|
161 my $return; |
|
162 |
|
163 my $tlsa_record = qx($certtlsa) or die "nothing found!\n"; |
|
164 $tlsa_record =~ s/^.*= (.*$)/$1/gi; |
|
165 $tlsa_record = uc($tlsa_record); |
|
166 |
|
167 if (defined $expiry) { |
|
168 print check_cert_expiry(); |
|
169 } |
|
170 |
|
171 if ("$tlsa_record" eq "$dig") { |
|
172 #$return = "TLSA record is $tlsa_record and valid"; |
|
173 #funktioniert nich nicht optimal mit hostliste |
|
174 $return = $check_tlsa->plugin_exit(OK, "$domain: TLSA record is valid") |
|
175 . "$domain: TLSA record is valid\n"; |
|
176 } |
|
177 else { |
|
178 $check_tlsa->plugin_exit(CRITICAL, "$domain: TLSA record NOT valid"); |
|
179 } |
|
180 return $return; |
|
181 #return $cert; |
|
182 } |
|
183 |
|
184 |
|
185 |
|
186 sub get_domains { |
|
187 open(my $filehandle, '<', $domainlist); |
|
188 |
|
189 my $pattern = '^(?<domain>\S*\.[a-z]{2,4}?):{0,1}(?<port>[0-9]*$)'; |
|
190 my %domain2check; |
|
191 while(<$filehandle>) { |
|
192 if (/$pattern/ig) { |
|
193 $domain = $+{domain}; |
|
194 $port = $+{port}; |
|
195 #print "nunu,file ok",LF,"port: $+{port}",LF,"domain: $+{domain}",LF; |
|
196 $domain2check{$domain} = $port; |
|
197 |
|
198 |
|
199 |
|
200 |
|
201 |
|
202 #print check_tlsa(); |
|
203 } |
|
204 else { |
|
205 die "wrong content"; |
|
206 } |
|
207 |
|
208 foreach my $key (%domain2check) |
|
209 { |
|
210 $domain = $key; |
|
211 $port = $domain2check{$key}; |
|
212 print $domain, ' ', $port,"\n"; |
|
213 |
|
214 |
|
215 if ( "$port" =~ /^\s*$/) { $port = '443'; } |
|
216 print $domain, ' ', $port,"\n"; |
|
217 |
|
218 check_tlsa($domain,$port); |
|
219 } |
|
220 |
|
221 } |
|
222 } |
|
223 |
|
224 sub check_cert_expiry { |
|
225 my $return = qx($check_date); |
|
226 return $return; |
|
227 } |
|
228 |