News
Das Neuste aus der Welt von Adfinis SyGroup
Manchmal wäre es doch praktisch, wenn man nicht im Büro sitzt, die Kiste schön brav abgestellt ist zum Strom sparen und man einfach einem Kollegen sagen könnte, er solle mal den Rechner hochfahren. Man könnte danach die wunderbare Technologie namens SSH benutzen. Leider macht einem da die verschlüsselte Festplatte einen Strich durch die Rechnung: Um die Verschlüsselung aufzuheben, muss jemand die Passphrase eintippen.
Abhilfe hierfür bietet der lightweight SSH-Server Dropbear, welchen man im initramfs installieren kann. Zusätzlich sorgt man dafür, dass das Netzwerk-Interface gestartet wird und gibt die verschlüsselte Partition an.
Auf meinem Arch Linux waren hierfür folgende Schritte nötig:
Dropbear installieren und konfigurieren
Als erstes müssen aus dem AUR die Pakete mkinitcpio-utils und mkinitcpio-dropbear installiert werden:
$ yaourt -S mkinitcpio-dropbear mkinitcpio-utils
Diese installieren die nötigen Hooks für das initramfs. Im Anhang ist ein Link zu einem Beispiel, wie in Ubuntu ein solcher Hook gemacht werden kann.
Als nächstes muss der Public Key, mit dem man sich später am System anmelden will, in der Datei /etc/dropbear/root_key
hinterlegt werden. Die Datei ist aufgebaut wie die bekannten authorized_key Dateien unter ~/.ssh/
, es können also mehrere Keys angefügt werden. Bei jedem neuen Key muss aber das initfamfs neu gebaut werden!
mkinitcpio.conf vorbereiten
Als nächstes wird die /etc/mkinitcpio.conf
angepasst. Einerseits muss das Kernel-Modul für den Netzwerkchip unter MODULES=""
hinzugefügt werden. Um das Modul herauszufinden, kann lspci
benutzt werden:
$ lspci -k
Unter den jeweiligen Devices findet man das dafür geladene Modul in der Zeile Kernel modules
. Andererseits muss in den Hooks netconf
, dropbear
und encryptssh
vor filesystems
hinzugefügt werden.
Das Ganze sieht danach ungefähr so aus:
[..]
MODULES="r8169"
HOOKS="base udev autodetect modconf block netconf dropbear encryptssh filesystems keyboard fsck"
Anschliessend muss das initramfs neu gebaut werden:
$ mkinitcpio -p linux
Bootloader konfigurieren
Im Bootloader müssen dem Linux-Kernel noch Optionen zur Kernel-Zeile hinzugefügt werden. In meinem Fall (systemd-boot) ist dies unter /boot/loader/entries/arch.conf
zu finden. Bei GRUB kann dies über Variablen in der Datei /etc/default/grub
gemacht werden (siehe Arch Linux Wiki).
Die eine Option ist cryptdevice
, womit angegeben wird, welches Device (sprich: Partition) überhaupt entschlüsselt werden soll. Am besten gibt man hier die UUID (ls -l /dev/disk/by-uuid/
) an, im Format UUID=<effektive-uuid>
und nicht der Blockdevice Name unter /dev, da sich dieser ändern kann.
Die andere Option sagt dem Kernel, wie das Netzwerk konfiguriert werden soll. Diese Option heisst schlicht ip
und kann entweder per DHCP oder manuell konfiguriert werden. Um DHCP zu verwenden, kann einfach ip=:::::eth0:dhcp
angegeben werden. In meinem Falle wollte ich jedoch eine statische Konfiguration, damit ich weiss, wohin ich per SSH verbinden muss. Das Format dafür ist folgendermassen: ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>:<dns0-ip>:<dns1-ip>
(siehe auch die Kernel-Dokumentation), wobei dies bei mir nicht vollständig zutraf. Den letzten Doppelpunkt musste ich auslassen, damit es funktioniert. Zu beachten ist auch, dass für <device>
der Kernel-Name (ethX) und nicht der Udev-Name verwendet werden muss:
dmesg | grep eno1
16.593465] r8169 0000:03:00.0 eno1: renamed from ==eth0==
Das Resultat sieht so aus:
title Arch Linux
linux /vmlinuz-linux
initrd /initramfs-linux.img
options ip=10.9.4.70::10.9.1.1:255.255.0.0:huckfinn:eth0:none: cryptdevice=UUID=9c53e8b6-07bf-4e9d-bb3e-feaf55c02f41 root=/dev/sda2 rw
Crypttab
Ich hatte vorher in meinem Boot-Prozess im /etc/crypttab
meine verschlüsselte Partition zur Entschlüsslung angegeben. Da die Partition bereits mit dem Parameter cryptdevice
definiert wird, ist keine crypttab Konfiguration mehr nötig. Der Eintrag muss dort deshalb entfernt werden, da die Partition ja bereits geöffnet ist. In der fstab kann nun auch nicht mehr /dev/mapper/XYZ verwendet werden; wenn man die UUID benutzt, funktioniert es aber ohne Probleme.
Nun ist es an der Zeit, sich mit dem Live-Boot USB Stick zu bewaffnen und den Rechner neu zu starten. Im Idealfall sollte es etwa folgendermassen aussehen:
Hat man sich in der IP-Konfiguration vertan, ist dies weniger schlimm: Die Fehlermeldung sollte recht aufschlussreich sein, man kann einfach weiter booten und die Anpassung vornehmen. Ist hingegen der cryptdevice-Parameter falsch, kommt man in einen Zustand, in dem es nicht weiter geht. Dann heisst es, Live-System booten, Partition, auf der die Konfiguration liegt, mounten und den Parameter korrigieren.
Weiterführende Links
Soll nicht die YubiCloud für das Validieren von Yubico One-time Passwörtern (OTP) genutzt werden, können die Validation Server auch selber betrieben werden. Dies ist grundsätzlich nicht sehr schwer, jedoch ist das redundante Setup eher dürftig dokumentiert.
Überblick
Als Backend wird MySQL und als Frontend Apache eingesetzt. Die zwei Komponenten yubikey-val und yubikey-ksm sind simple PHP Applikationen, welche aus ein paar wenigen Dateien bestehen.
Installation
Webserver
Als erstes sollte Apache, PHP und MySQL installiert werden. Aufgrund der Paket Dependency von yubikey-ksm und yubikey-val kann kein MariaDB Server genutzt werden.
Danach sollten zwei Datenbanken (ykksm und ykval) mit dazugehörigen Benutzern (ykksm_reader und ykval_verifier) erstellt werden.
yubikey_ksm
Im Yubikey Key Storage Module (KSM) werden die einzelnen Yubikeys gespeichert, sprich hier sind alle Daten (inkl. des geheimen AES Keys) aller Yubikeys erfasst. Der Service kann dazu genutzt werden, zu verifizieren, ob ein Yubikey mit dazugehörigem One-Time Passwort (OTP) gültig ist, jedoch nicht ob es eine Replay Attacke ist.
Da die Software keinen Mechanismus kennt, wie die Server synchronisiert werden können, wird dies mit einem MySQL Master-Slave Setup gelöst. Eine entsprechende Anleitung, wie dies gemacht werden kann, ist z.B. auf DigitalOcean vorhanden. Zu beachten ist, dass nur die Datenbank ykksm gesynct werden sollte (binlog_do_db = ykksm
).
Auf einem Debian ist die Software yubikey_ksm simpel per apt install yubikey-ksm
installiert. Danach ist der Apache und die Datenbank auch schon konfiguriert. Wer die Konfiguration nachträglich noch ändern will, findet die entsprechenden Dateien in /etc/yubico/ksm/
. Eine umfassendere Installations Anleitung ist bei Yubico zu finden.
Apache ist so konfiguriert, dass es einen globalen Alias /wsapi/decrypt
als /usr/share/yubikey-ksm/ykksm-decrypt.php
gibt, falls auf dem Apache mehrere VirtualHosts vorhanden sind, sollten diese in der Konfiguration deaktiviert und nur den für yubikey_ksm benötigten VirtualHost aktiviert werden.
Neue Yubikeys können mit dem Tool ykksm-gen-keys erstellt werden. Dies gibt folgenden Output:
$ ykksm-gen-keys 1
1,cccccccccccb,42e31d069785,cf00b1f4c2c80e395b5e7532a5929cba,d05f7e394f0e,2016-03-22T13:12:25,
In der Datenbank ist die Tabelle yubikeys vorhanden. Diese hat folgendes Schema:
CREATE TABLE `yubikeys` (
`serialnr` int(11) NOT NULL,
`publicname` varchar(16) NOT NULL,
`created` varchar(24) NOT NULL,
`internalname` varchar(12) NOT NULL,
`aeskey` varchar(32) NOT NULL,
`lockcode` varchar(12) NOT NULL,
`creator` varchar(8) NOT NULL,
`active` tinyint(1) DEFAULT '1',
`hardware` tinyint(1) DEFAULT '1',
PRIMARY KEY (`publicname`),
UNIQUE KEY `publicname` (`publicname`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Sollen neue Yubikeys erstellt und gerade in die Datenbank hinterlegt werden, kann dies mit folgendem Script erledigt werden:
#!/bin/bash
MYSQL='mysql'
NEXTID=$(echo "SELECT t1.serialnr + 1 FROM ykksm.yubikeys t1 WHERE NOT EXISTS (SELECT serialnr FROM ykksm.yubikeys t2 WHERE t2.serialnr = t1.serialnr + 1) LIMIT 1;" | $MYSQL | tail -n 1)
if [ -z "${NEXTID}" ]; then
NEXTID='1'
fi
KEY="$(ykksm-gen-keys ${NEXTID} | grep -v ^#)"
IFS=',' read -r -a ARR <<< "$KEY"
SQL="INSERT INTO ykksm.yubikeys VALUES (${ARR[0]}, '${ARR[1]}', '${ARR[5]}', '${ARR[2]}', '${ARR[3]}', '${ARR[4]}', 'bash', 1, 1);"
echo $SQL | $MYSQL
echo "Set Yubikey:"
echo "ykpersonalize -1 -y -a${ARR[3]} -o fixed=${ARR[1]} -o uid=${ARR[2]}"
yubikey_val
Der Yubikey Validation Service macht die eigentliche Validierung der One-Time Passwörtern (OTP). Es werden folgende Punkte verifiziert und verarbeitet:
- Client: Der anfragende Client muss sich verifizieren, jeder Client hat eine ID und ein dazugehöriges Passwort. Dies verhindert, dass nicht jeder Client eine Anfrage stellen kann. Als Client wird in diesem Fall z.B. ein ssh Daemon oder eine Webseite verstanden, nicht der User davor.
- Yubikey: Das OTP wird an den Service yubikey_ksm weitergeleitet. Ist das OTP gültig, wird durch den Service yubikey_val getestet, ob es sich um eine Replay Attacke handelt.
- Sync: Die anderen Valdiation Server werden über den aktuellen Counter des Yubikeys benachrichtigt, damit keine Replay Attacke an einem anderen Validation Server getätigt werden kann.
Auf einem Debian System ist die Installation mit apt install yubikey-val
gemacht. Die entsprechenden Konfigurationsdateien befinden sich im Verzeichnis /etc/yubico/val/
.
Danach ist Apache auch schon wieder global konfiguriert. Bei mehreren VirtualHosts sollte die Konfiguration wieder spezifisch für nur einen VirtualHost eingerichtet werden. Folgende Aliase sollten dabei konfiguriert sein:
/wsapi/2.0/verify
als/usr/share/yubikey-val/ykval-verify.php
/wsapi/verify
als/usr/share/yubikey-val/ykval-verify.php
/wsapi/2.0/sync
als/usr/share/yubikey-val/ykval-sync.php
/wsapi/2.0/resync
als/usr/share/yubikey-val/ykval-resync.php
/wsapi/revoke
als/usr/share/yubikey-val/ykval-revoke.php
Datenbank
Die Datenbank beinhaltet drei Tabellen:
- clients
Hier werden die Clients (z.B. ein PAM oder Mediawiki) erfasst, welche den Validation Server anfragen dürfen.
CREATE TABLE `clients` (
`id` int(11) NOT NULL,
`active` tinyint(1) DEFAULT '1',
`created` int(11) NOT NULL,
`secret` varchar(60) NOT NULL DEFAULT '',
`email` varchar(255) DEFAULT NULL,
`notes` varchar(100) DEFAULT '',
`otp` varchar(100) DEFAULT '',
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
- queue
In der queue sind die Einträge, welche noch mit anderen Validation Servern abgeglichen werden müssen. Die Einträge werden vom System Service ykval-queue bearbeitet.
CREATE TABLE `queue` (
`queued` int(11) DEFAULT NULL,
`modified` int(11) DEFAULT NULL,
`server_nonce` varchar(32) NOT NULL,
`otp` varchar(100) NOT NULL,
`server` varchar(100) NOT NULL,
`info` varchar(256) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
- yubikeys
In dieser Tabelle sind die Yubikeys mit ihren entsprechenden Countern eingetragen. Diese Tabelle wird durch yubikey_val selber mit den anderen Validation Server synchronisiert.
CREATE TABLE `yubikeys` (
`active` tinyint(1) DEFAULT '1',
`created` int(11) NOT NULL,
`modified` int(11) NOT NULL,
`yk_publicname` varchar(16) NOT NULL,
`yk_counter` int(11) NOT NULL,
`yk_use` int(11) NOT NULL,
`yk_low` int(11) NOT NULL,
`yk_high` int(11) NOT NULL,
`nonce` varchar(40) DEFAULT '',
`notes` varchar(100) DEFAULT '',
PRIMARY KEY (`yk_publicname`),
UNIQUE KEY `yk_publicname` (`yk_publicname`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Synchronisation
Der Service kennt einen eigenen Mechanismus zur Synchronisation. Da jeweils der höchste Counter (der OTP) jedes Yubikeys auf allen Servern bekannt sein sollte, wird dies nicht über eine MySQL Replication gelöst. Dies hätte zur Folge, dass auch tiefere Counter synchronisiert werden.
Damit die Server synchronisieren dürfen, muss zuerst noch die Konfiguration angepasst werden. Als Beispiel werden die beiden Hosts srv-tfvalid-01 (IP 128.66.1.1) und srv-tfvalid-02 (IP 128.66.1.2) genutzt. Folgende Konfigurationsparameter müssen angepasst werden:
- __YKVAL_SYNC_POOL__
Hier werden die Server eingetragen, mit welchen synchronisiert werden soll.
$baseParams['__YKVAL_SYNC_POOL__'] = array(
"https://srv-tfvalid-01/wsapi/2.0/sync",
"https://srv-tfvalid-02/wsapi/2.0/sync"
);
- __YKVAL_ALLOWED_SYNC_POOL__
Hier werden alle IP Adressen aller Validation Server eingetragen, damit diese synchronisieren dürfen.
$baseParams['__YKVAL_ALLOWED_SYNC_POOL__'] = array(
"127.0.0.1",
"128.66.1.1",
"128.66.1.2"
);
- __YKVAL_RESYNC_IPS__
Dieser Wert wird auf den Wert von __YKVAL_ALLOWED_SYNC_POOL__ gesetzt.
$baseParams['__YKRESYNC_IPS__'] = $baseParams['__YKVAL_ALLOWED_SYNC_POOL__'];
- __YKVAL_SYNC_DEFAULT_LEVEL__
Dieser Wert definiert den mindest Level in Prozent, wie viele Validation Server erfolgreich synchronisiert werden müssen, bevor das OTP als gültig deklariert wird. Sind Server nicht erreichbar, kann dies zur Folge haben, dass das OTP, aufgrund zu wenigen Antworten bei der Synchronisation, als ungültig deklariert wird.
Werte zwischen 0 und 100 sind möglich. Sind im gesamten Sync Pool zwei Server, und wird Server 1 angefragt, hat dieser folgende Sync Level:- Server 2 online: 100
- Server 2 offline: 0
Sind im gesamten Sync Pool drei Server und wird Server 1 angefragt, hat er folgende Sync Level:
- Beide Server online: 100
- Ein Server online, anderer offline: 50
- Beide Server offline: 0
Damit bei einem Setup mit zwei Servern einer offline sein darf, muss der Wert also folgendermassen auf 0 gesetzt werden:
$baseParams['__YKVAL_SYNC_DEFAULT_LEVEL__'] = 0;
Services für die Synchronisation
Der System Service ykval-queue kann bei systemd mit folgendem Service File gestartet werden:
[unit]
Description=Yubikey Validation Server Sync Queue
After=network.target
[Service]
ExecStart=/usr/sbin/ykval-queue
Restart=on-failure
[Install]
WantedBy=multi-user.target
Zusätzlich muss noch der Cronjob, welcher die Synchronisation auslöst, erstellt werden. Der Cronjob muss pro Kombination Validation Server – Validation Server erstellt werden und sieht in etwa wie folgt aus:
* * * * * /usr/sbin/ykval-synchronize validation-server-2 all
Neue Validation Clients erstellen
Neue Clients können mit dem Tool ykval-gen-clients erstellt werden. Mit folgendem Bash Script können Clients automatisch erstellt und in die Datenbank gespeichert werden:
#!/bin/bash
MYSQL='mysql'
ERRORMSG='Failed to insert new client with query '
CLIENT="$(ykval-gen-clients 1 2>&1)"
echo "USE ykval; ${CLIENT#$ERRORMSG}" | $MYSQL
echo "Client configuration:"
echo ${CLIENT#$ERRORMSG}
Validation Server nutzen
Die Validation Server sollten vor der Nutzung noch getestet werden. Zum Beispiel sollte getestet werden, ob eine Replay-Attacke an den zweiten Server nicht möglich ist, nachdem am ersten Server die Validierung schon gemacht wurde. Ein weiterer Test ist, ob die MySQL Datenbanken sich synchronisieren und die Einträge in der Tabelle ykval.queue
abarbeiten.
SSHd
Soll ein SSH Server mit TwoFactor abgesichert werden, wird dies am einfachsten im PAM (Pluggable Authentication Modules for Linux) gemacht. Es gibt ein extra PAM Modul (pam_yubico), welches die Yubikey Validation Server anfragt.
PAM ist in diesem Beispiel ein Client vom Validation Server, also muss für PAM eine ID und ein Key mit ykval-gen-clients
generiert werden. Es sollen nur User in der POSIX Gruppe Users
eine TwoFactor Validierung machen müssen, bei den anderen reicht ein Login ohne. Die ID der Yubikeys wird im LDAP mit dem User verknüpft, sprich die User, welche eine TwoFactor Validierung machen müssen, haben im LDAP ein Attribut (im Beispiel: yubikey
), welches dem publicname ihres Yubikeys entspricht (Beispiel: cccccccccccb
).
Die folgende Konfiguration wird zusätzlich in /etc/pam.d/sshd
eingefügt. Am besten nach der Zeile, welche die Passwort Authentifizierung macht, also beispielsweise nach pam_unix.so
oder pam_ldap.so
in der Chain auth
. Diese können auch mit einem @include
aus z.B. der common-auth
eingebunden werden, daher kann hier nicht eine fertige Konfiguration angegeben werden.
auth [success=2 default=ignore] pam_succeed_if.so user notingroup Users
auth [success=1 default=ignore] pam_yubico.so id=1 \
key=bjMN3jRHquwHr5NqNKN+LEFZUjY= \
urllist=https://srv-tfvalid-01/wsapi/2.0/verify;https://srv-tfvalid-02/wsapi/2.0/verify \
ldap_uri=ldap://ldap1.example.com:389/;ldap://ldap2.example.com:389/ \
ldapdn=cn=users,dc=example,dc=com \
user_attr=uid \
yubi_attr=yubikey \
verbose_otp
auth requisite
pam_deny.so
Danach sollte das Login auf den Server getestet werden (Achtung: Dabei immer ein root Login offen halten, da wenn etwas nicht funktioniert, gegebenenfalls kein Login mehr möglich ist).
Damit wir im Monitoring-Tool sehen können, ob und wann ein SSL-Zertifikat abläuft, wurde ein Script zur Ermittlung des Ablaufdatums geschrieben. Im Vergleich zu anderen Checks, kann dieses Script nicht nur Zertifikate via HTTPS prüfen.
Hier findest du eine Beschreibung, wie das Ablaufdatum eines SSL Zertifikats geholt wird.
openssl s_client -servername "${HOST}" -connect "${HOST}":"${PORT}" 2>&- | openssl x509 -enddate -noout
Damit überhaupt eine Verbindung zu einem SSL Host gemacht werden kann, braucht man zuerst einen SSL client. Hier wird der s_client von OpenSSL verwendet, welcher auch TLS beherrscht. Der s_client dient allgemein zum Diagnostizieren und Debuggen von SSL/TLS Zertifikaten.
servername
Über den Parameter “servername” kann man verifizieren, dass das richtige Zertifikat benützt wird, falls ein Server über VHosts mehrere SSL Zertifikate hat.
Dies geschieht über SNI (Server Name Indication).
connect
Hier geschieht die Verbindung zum Host über den Hostname und Port.
openssl x509 -enddate -noout
Nun wird das x509 Zertifikat ausgelesen und durch die Parameter “enddate” und “noout” wird das Ablaufdatum ausgegeben respektive dass das Zertifikat nicht nach Datum XY gültig ist. Durch “noout” wird der restliche Output verhindert.
Alarm, Alarm!
Das Ziel war es selbst bestimmen zu können, wie und wann Nagios / Icinga alarmiert. Damit Nagios / Icinga alarmiert braucht es den Error Status Code 2. Error Codes:
- 1 – Warning
- 2 – Critical
0 ist natürlich OK. Es werden Parameter zum Einstellen der Warning- und Critical-Werte vergeben. Standartwerte sind:
- Warning=30 (Tage)
- Critical=5 (Tage)
Das Ablaufdatum wird mit dem aktuellem Datum verglichen, so ist erkennbar, wie viele Tage man noch hat bis das Zertifikat abläuft.
Das Monitoring Script ist auf GitHub verfügbar.
Integration ins Monitoring
Das Script wird bei uns als Icinga Plugin ausgeführt.
Commands sind im configfile “/etc/icinga/icinga.cfg” definiert bzw. es ist beschrieben wo diese definiert sind.
Untenstehend der Auszug aus der Icinga-Konfiguration:
define command {
command_name check _ssl
command_line /bin/bash $USER1$/check_ssl.sh -H $ARG1$ -p $ARG2$ -P $ARG3$ -w $ARG4$ -c $ARG5$
}
Die $ARG$ Variablen werden dann durch eine Service Definition gegeben, welche sich standartmässig in /etc/icinga/objects/services_icinga.cfg befindet.
So wird der SSL Check Service für einen Host definiert:
define service {
use template-service
host_name Hostname (e.g. adfinis.com)
service_description check_ssl
max_check_attempts 5
check_interval 360
retry_interval 1
check_command check _ssl!'adfinis.com'!'443'!'no_tls'!'30'!'5'
}
Bei der check_command Zeile werden die $ARG$ Variablen durch Ausrufezeichen getrennt und werden danach auch in dieser Reihenfolge vergeben. Das heisst:
- adfinis.com = $ARG1
- 443 = $ARG2$
- no_tls = $ARG3$
- 30 = $ARG4$
- 5 = $ARG5$
Links
Es gibt (immer) noch diverse Server im Internet, die keine oder nur eine unzureichende SSL/TLS Konfiguration haben. Es handelt sich dabei nicht nur um Webserver (wie nginx oder Apache), sondern auch z.B. um XMPP/Jabber Server und Mailserver. Als Grundlage jeder SSL/TLS Konfiguration werden Keys und Zertifikate sowie allfällig auch noch Diffie-Hellman-Parameter benötigt. Dieser Artikel soll die wichtigsten Kommandos von OpenSSL zusammenfassen und kurz erklären.
Keys und Zertifikate erstellen
Um private Schlüssel und Zertifikate von Hand zu erstellen, kommen nachfolgend diverse nützliche Kommandos und deren Erklärungen.
Formate
Es gibt verschiedene Formate, wie Zertifikate und Keys gespeichert werden können. Nachfolgend wird immer das PEM-Format genutzt, dieses wird von den meisten Tools am besten unterstützt, die Dateien sind jedoch grösser als z.B. das DER-Format, da PEM aus ASCII Zeichen besteht und DER binär ist. Typische Endungen für PEM Zertifikate sind .pem
oder .crt
. Zertifikate im DER-Format sollten jeweils die Endung .der
haben.
Das PEM-Format ist einfach zu erkennen, da der Inhalt der Dateien mit -----BEGIN CERTIFICATE-----
anfängt und mit -----END CERTIFICATE-----
endet. Ein guter Überblick der Formate und deren Umwandlung in jeweils andere Formate ist auf ssl.com erklärt.
Eine Liste der gängigsten Formate ist folgende:
- PEM: Endung
.pem
,.crt
,.cer
- DER: Endung
.der
- PKCS#7: Endung
.p7b
,.p7c
- PKCS#12: Endung
.p12
- PFX: Endung
.pfx
Certificate Signing Request erstellen
Certificate Signing Requests (CSR) sind Anträge für neue Zertifikate. Diese müssen anschliessend entweder von einer Certificate Authority (CA) oder Self-Signed unterschrieben werden. Damit ein CSR erstellt werden kann, braucht es zuerst einen privaten Schlüssel. Normalerweise muss jedes mal wenn ein Zertifikat beantragt wird, ein neuer Certificate Signing Request erstellt werden.
Im ersten Schritt wird ein RSA Key mit 4096 Bit erstellt. Dies kann nach heutigen Standards als sicher angeschaut werden. Im zweiten Schritt wird der CSR erstellt, welcher mit SHA256 signiert wird (viele default Werte sind noch SHA1, deshalb sollte zwingend SHA256 explizit angegeben werden). Weitere Informationen zum Erstellen von RSA Keys kann in der Manpage von genrsa
bzw. req
für Certificate Signing Requests nachgelesen werden.
$ openssl genrsa -out example.com.key 4096
$ openssl req -new -sha256 -key example.com.key -out example.com.csr
Dies ist auch in einem Schritt möglich. Hier wird direkt ein CSR erstellt und dazu OpenSSL noch aufgefordert, den entsprechenden privaten Schlüssel zu erstellen.
$ openssl req -new -sha256 -nodes -newkey rsa:4096 -keyout example.com.key -out example.com.csr
Self-signed Certificate erstellen
Um schnell SSL Konfigurationen zu testen oder auf Servern, auf welchen nie geprüft wird, ob ein Zertifikat auch korrekt von einer Certificate Authority signiert wurde, können self-signed Zertifikate verwendet werden. Diese zu erstellen ist mit folgendem Kommando möglich. Es erstellt einen privaten Schlüssel, generiert daraus eine Certificate Signing Request und signiert diese mit dem privaten Schlüssel. Daraus folgt das Zertifikat, welches in example.com.pem
abgelegt wird.
$ openssl req -x509 -sha256 -nodes -newkey rsa:4096 -keyout example.com.key -days 730 -out example.com.pem
Eigene CA erstellen und damit die Zertifikate signieren
Normale Zertifikate sollten die Berechtigung zum Signieren anderer Zertifikate nicht haben, dafür sollten spezielle Zertifikate zum Einsatz kommen, sogenannte Certificate Authorities (CA).
Ist die Anzahl der Clients überschaubar oder in anderen speziellen Fällen, kann eine eigene Certificate Authority (CA) erstellt werden. Dies ist zum Beispiel bei vielen Virtual Private Networks (VPN) nötig, da dort das Zertifikat des Servers und aller Clients signiert werden müssen.
Zuerst erstellen wir eine Datei (Dateiname z.B. x509.ext
), in welcher die x509 Extensions definiert sind. Es gibt dafür zwei Abschnitte, den für die CA und den für Server Zertifikate.
[ ca ]
# X509 extensions for a ca
keyUsage = critical, cRLSign, keyCertSign
basicConstraints = CA:TRUE, pathlen:0
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
[ server ]
# X509 extensions for a server
keyUsage = critical,digitalSignature,keyEncipherment
extendedKeyUsage = serverAuth,clientAuth
basicConstraints = critical,CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
Danach erstellen wir die CA und die Server Zertifikate.
Im ersten Schritt wird ein neuer privater Schlüssel und ein Zertifikat erstellt, welches danach als Certificate Authority dient. Das Zertifikat der Certificate Authority hat in diesem Beispiel ein Ablaufdatum von 3 Jahren. Dieses Zertifikat darf nur zum Signieren weiterer Zertifikate genutzt werden (dies ist im Extension File im Abschnitt ca
definiert).
Im zweiten Schritt wird das Server Zertifikat erstellt und von der CA signiert. Dem Zertifikat des Servers wird ein Ablaufdatum von 2 Jahren gesetzt. Weiter wird ein CA serial number File erstellt, wenn es nicht schon vorhanden ist. Dieses wird von der CA benötigt, damit die CA die aktuelle Seriennummer kennt. Das Server Zertifikat wird beim Signieren darauf eingeschränkt, dass es nur als Server oder Client agieren und keine weiteren Zertifikate signieren darf. Weitere Informationen sind in der Manpage von x509
und x509v3_config
enthalten.
$ openssl req -new -sha256 -nodes -newkey rsa:4096 -keyout CA.key -out CA.csr
$ openssl x509 -req -sha256 -extfile x509.ext -extensions ca -in CA.csr -signkey CA.key -days 1095 -out CA.pem
$ openssl req -new -sha256 -nodes -newkey rsa:4096 -keyout www.example.com.key -out www.example.com.csr
$ openssl x509 -req -sha256 -CA CA.pem -CAkey CA.key -days 730 -CAcreateserial -CAserial CA.srl -extfile x509.ext -extensions server -in www.example.com.csr -out www.example.com.pem
Certificate und Certificate Signing Requests betrachten
Der Inhalt von Zertifikaten und Certificate Signing Requests kann am besten mit OpenSSL dargestellt werden. Nebst dem gesamten Inhalt (Option -text
) können auch nur Teile davon dargestellt werden, so kann zum Beispiel das Erstell- und Ablaufdatum mit -dates
dargestellt werden. Die entsprechende Liste ist in der Manpage (man 1 x509
) unter dem Punkt Display options
zu finden.
- Certificate
$ openssl x509 -in example.com.pem -noout -text
- Certificate Signing Request
$ openssl req -in example.com.csr -noout -text
Diffie-Hellman Parameter erstellen
Diffie-Hellman Parameter werden für Forward-Secrecy benötigt. Folgendes Kommando erstellt Diffie-Hellman Parameter mit 4096 Bit. Es ist nicht nötig so grosse Parameter zu erstellen, 2048 sollten auch reichen. Das Erstellen kann je nach Maschine extrem lange dauern. Es kann sich evtl. lohnen diese auf einer Hardware Maschine zu erstellen (da mehr Entropie vorhanden ist) und danach auf die virtuelle Maschine zu transferieren.
$ openssl dhparam -out dh4096.pem 4096
Konvertieren
Zertifikate können mit OpenSSL in andere Formate umgewandelt werden. Teilweise ist ein Zwischenschritt notwendig. Die gängigsten Umwandlungen, von DER zu PEM und umgekehrt, kann mit folgenden Kommandos gemacht werden:
$ openssl x509 -in cert.pem -outform der -out cert.der
und
$ openssl x509 -in cert.der -inform der -outform pem -out cert.pem
Das PKCS#12 und PFX Format kann mit folgenden Kommandos umgewandelt werden.
PFX (privater Schlüssel und Zertifikat) nach PEM (privater Schlüssel und Zertifikat):
$ openssl pkcs12 -in keyStore.pfx -out keyStore.pem -nodes
PEM (privater Schlüssel und Zertifikat) nach PFX (privater Schlüssel und Zertifikat):
$ openssl pkcs12 -export -out certificate.pfx -inkey privateKey.key -in certificate.crt -certfile CACert.crt
Weitere Kommandos zur Umwandlung finden sich auf bereits oben erwähnter Seite (ssl.com).
Sandro Köchli, Mitgründer und Verwaltungsratsmitglied der Adfinis SyGroup, erklärt wie es dazu kam, dass aus der Rivalität zwischen Microsoft und Linux eine Symbiose wurde.
Im Artikel der Netzwoche erfahren Sie mehr über die Geschichte hinter unserer Partnerschaft mit Microsoft und der damit zusammenhängenden Relevanz der Azure Cloud Services.