DANE Records erzeugen

Submitted by admin on So, 11.12.2016 - 11:31

DANE (RFC 6698) ist eine überaus nützliche Methode, um die Echtheit von Serverzertifikaten online zu überprüfen. Es ist weiterhin geeignet, eine Alternative zu den bekannten PKIs. Das folgende Skript ist eine Methode, um TLSA Records im DNS zu erstellen. Es ist in Perl geschrieben und benötigt eine OpenSSL Installation, die bei den meisten Linux oder BSD Installationen ohnehin vorhanden sein dürfte. Weiterhin muss eine aktuelle GnuTLS Installation vorhanden sein, mit danetool, das Bestandteil von GnuTLS wird nämlich der TLSA RR generiert.

#!/usr/bin/env perl

use strict;

my $host=shift;
my $port=shift;
my @openssl_args=@ARGV;

if (!defined($host) || !defined($port)) {
  usage();
}


my $cmdline="echo | openssl  s_client -servername ${host} -connect ${host}:${port} -showcerts @{openssl_args} 2>&1";
my $cmd;
open ($cmd,"$cmdline|") || die "cannot exec $cmdline";
my $pem;
my $loadcert=0;
while (my $line=<$cmd>) {
  chomp $line;
  if ($line=~/-----BEGIN CERTIFICATE-----/) {
    $loadcert=1;
    $pem="-----BEGIN CERTIFICATE-----\n";
  } elsif ($line=~/-----END CERTIFICATE-----/) {
    $pem.="-----END CERTIFICATE-----\n";
    $loadcert=0;
    if (isCa($pem)) {
      analyze("--ca", "$pem","$host","$port");
    } else {
      analyze("", "$pem","$host","$port");
    }
  } elsif ($loadcert) {
    $pem.="$line\n";
  }
}
close $cmd;


sub usage {
  die "usage: $0 <host> <port>\n";
}


sub isCa {
  my ($pem)=@_;

  my $cmdline="echo \"$pem\" | openssl x509 -noout -text";
  my $cmd;
  open ($cmd,"$cmdline|") || die "cannot exec $cmdline";
  while (my $line=<$cmd>) {
    chomp $line;
    if ($line=~/CA:FALSE/) {
      return 0;
    } elsif ($line=~/CA:TRUE/) {
      return 1;
    }
  }
  close $cmd;
}


sub analyze {
  my ($ca,$pem,$host,$port)=@_;
  my $cmdline="echo \"$pem\" | openssl x509 -pubkey -noout";
  my $cmd;
  open ($cmd,"$cmdline|") || die "cannot exec $cmdline";
  my $pubkeyFile="/tmp/pubkey.pem.$$";
  open OUT,">$pubkeyFile" || die "cannot open $pubkeyFile for write\n";
  while (my $line=<$cmd>) {
    chomp $line;
    print OUT "$line\n";
  }
  close OUT;
  close $cmd;

  $cmdline="/opt/gnutls-3.3.0/bin/danetool --tlsa-rr $ca --host=${host} --port ${port} --proto=tcp --load-pubkey=${pubkeyFile}";
  open ($cmd,"$cmdline|") || die "cannot exec $cmdline";
  while (my $line=<$cmd>) {
    chomp $line;
    print "$line\n";
  }
  close $cmd;
  unlink "$pubkeyFile";
}

Verwendung

TLSA Record für einen https Server ermitteln:

./get-dane.pl www.ip6.li 443

TLSA Record für eine starttls Anwendung, wie z.B. SMTP ermitteln:

./get-dane.pl mail.taunusstein.net 25 -starttls smtp

Man kann ggf. noch andere OpenSSL Parameter angeben.

Das Skript erzeugt einen TLSA Typ 2 Record, d.h. der RR bezieht sich auf die verwendete CA. Bei dieser Methode ist der TLSA RR für alle Zertifikate gültig, die von der CA, auf die sich der TLSA Eintrag bezieht, signiert wurden. Soll das Skript nur TLSA RRs erzeugen, die für das betreffende Zertifikat gelten, dann muss danetool ohne den Parameter --ca aufgerufen werden.

Die Ausgabe dieses Skripts kann direkt in das Zonenfile der betreffenden Domain eingetragen werden, der RR wird von Bind9 korrekt verarbeitet.