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.example.com 443

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

./get-dane.pl mail.example.com 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.