Claus Strasburger

Jetty TLS mit mehreren Domains

Knowledge Base | Ops

Einleitung

Hast du dich schon einmal gefragt, wie du einem Jetty-Server mehrere, verschiedene HTTPS-Zertifikate geben kannst? Einfaches Beispiel: Ein Raspberry-Pi, der von zwei Domains erreichbar sein soll?

Möglicherweise hast du auch schon etwas in den Jetty-Dokumentationen zu SSL oder Virtual Hosts umgesehen, bist aber nicht daraus schlau geworden.

Die Antwort ist ganz einfach! Du musst nichts konfigurieren. Du musst lediglich all deine Zertifikate in denselben Keystore legen. Alles andere funktioniert ganz von selbst.

Jetty wird bei jedem Verbindungsaufbau den per Server Name Indication (SNI) gesendeten Hostnamen nehmen und mit dem Common Name (CN) und Subject Alternative Names (SAN) abgleichen. Falls ein passendes existiert, wird dieses genommen. Falls keines passt, wird das erste (mit Alias “1”) genommen.

Beispiel

Hier ist ein Beispiel-Skript, mit dem du einem bestehenden Keystore ein weiteres Zertifikat hinzufügen kannst. In diesem werden wir ein Selbst-Signiertes Zertifikat erstellen, du kannst aber auch bei Schritt zwei anfangen, wenn du bereits ein existierendes Zertifikat hast (z.B. von Let’s Encrypt).

Schritt 0: Variablen

# Hostname für neues Zertifikat
HOSTNAME=meine-domain.de

# Bestehender Keystore
KEYSTORE=mein_keystore

# Keystore-Passwort
PASS=geheimes_keystore_passwort

# Der Alias; fängt mit 1 an und muss für jedes neue Zertifikat hochgezählt werden.
# Wenn du also in deinem Keystore vorher ein Zertifikat hattest, stelle hier 2 ein.
# Um das dritte hinzuzufügen, dann 3, usw.
ALIAS=2

# Namen für temporäre Dateien
KEY=key.pem
CSR=cert.csr
CA=ca.pem
CAKEY=ca.key
CERT=cert.pem
KEYPAIR=cert.pkcs12

rm -f $KEY $CERT $KEYPAIR $CSR $CAKEY $CA

Schritt 1

Wir erstellen ein Selbstsigniertes Zertifikat mit SubjectAlternateName (SAN).

openssl genrsa -out $CAKEY 2048
openssl req -new -x509 -days 365 -key $CAKEY \
    -subj "/C=CN/ST=GD/L=SZ/O=Self-Signed/CN=Self-Signed" \
    -out $CA
openssl req -newkey rsa:2048 -nodes -keyout $KEY \
    -subj "/CN=$HOSTNAME" -out $CSR
openssl x509 -req -extfile <(printf "subjectAltName=DNS:$HOSTNAME,DNS:www.$HOSTNAME") -days 365 -in $CSR -CA $CA -CAkey $CAKEY -CAcreateserial -out $CERT

## Wenn du ein "Intermediate" hast, kannst du es vorne an das bestehende dranhängen
#cat $CERT $INTERMEDIATE > $CERT.new
#mv $CERT.new $CERT

Schritt 2

Wir bauen Zertifikat und Private-Key so zusammen, dass keytool sie verwenden kann.

openssl pkcs12 -inkey $KEY -in $CERT -export -out $KEYPAIR -passout pass:$PASS

Schritt 3

Wir hängen das neue Zertifikat an den bestehenden Keystore an.

keytool -importkeystore \
    -srckeystore $KEYPAIR -srcstoretype PKCS12 -srcstorepass $PASS \
    -destkeystore $KEYSTORE -deststorepass $PASS \
    -srcalias 1 -destalias $ALIAS

Ausgabe

Hiermit kannst du dir den Inhalt deines Keystores ausgeben lassen:

keytool -list -keystore $KEYSTORE -storepass $PASS -v

Test

Und hiermit kannst du das Ergebnis testen.

Es wird angenommen, dass dein Jetty-Server auf 127.0.0.1:443 läuft.

echo | openssl s_client \
    -showcerts -debug -connect 127.0.0.1:443 \
    -servername $HOSTNAME \
    2>/dev/null \
    | grep -e "subject=" -e "issuer=" || :

## Ausgabe:
# subject=/CN=meine-domain.de
# issuer=/CN=meine-domain.de

Wenn du im obigen Kommando $HOSTNAME durch etwas anderes ersetzt, wirst du wieder das alte Zertifikat aus dem Keystore sehen.

Viel Erfolg!

7 Jan 2020 #Jetty #Java #TLS #SSL