check_tlsa
changeset 2 523934592a76
parent 1 1ce9659ddc4f
child 3 10ee65f99a7d
equal deleted inserted replaced
1:1ce9659ddc4f 2:523934592a76
       
     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