FHEM mit HTTPS SSL-Zertifikat und eine eigene Zertifizierungsstelle: Unterschied zwischen den Versionen
(Die Seite wurde neu angelegt: „= Vorwort = === Dein Anliegen === Du möchtest FHEM mit HTTPS betreiben, hasst es aber ständig von Deinem Browser darauf aufmerksam gemacht zu werden das dies…“) |
Drhirn (Diskussion | Beiträge) K (Liste aus den Möglichkeiten gemacht) |
||
(14 dazwischenliegende Versionen von 7 Benutzern werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
= Vorwort = | == Vorwort == | ||
=== Dein Anliegen === | === Dein Anliegen === | ||
Du möchtest FHEM mit HTTPS betreiben, hasst es aber ständig von Deinem Browser darauf aufmerksam gemacht zu werden | Du möchtest FHEM mit HTTPS betreiben, hasst es aber, ständig von Deinem Browser darauf aufmerksam gemacht zu werden, dass dies "keine sichere Verbindung" ist. | ||
Oder Du möchtest einen weiteren Serverdienst aufsetzen, welcher verschlüsselte SSL oder TLS-Verbindungen anbietet (z.B. HTTPS, POP3S, IMAPS, LDAPS, SMTP mit TLS). | Oder Du möchtest einen weiteren Serverdienst aufsetzen, welcher verschlüsselte SSL oder TLS-Verbindungen anbietet (z.B. HTTPS, POP3S, IMAPS, LDAPS, SMTP mit TLS). | ||
=== Die Schwierigkeit dabei === | === Die Schwierigkeit dabei === | ||
Um eine mit SSL/TLS abgesicherte Verbindung anzubieten, benötigst Du ein Serverzertifikat. Dieses muss von einer Zertifizierungsstelle (Certification Authority oder kurz CA) signiert sein. | Um eine mit SSL/TLS abgesicherte Verbindung anzubieten, benötigst Du ein Serverzertifikat. Dieses muss von einer Zertifizierungsstelle (Certification Authority oder kurz CA) signiert sein. | ||
Ein offizielles Serverzertifikat, welches von einer offiziellen Stelle signiert ist, ist leider nicht kostenlos. Meist werden jährliche Gebühren in Höhe von mehreren hundert Euro fällig. | Ein offizielles Serverzertifikat, welches von einer offiziellen Stelle signiert ist, ist leider nicht kostenlos. Meist werden jährliche Gebühren in Höhe von mehreren hundert Euro fällig. Ausnahme ist die CA [https://letsencrypt.org/ Let's Encrypt], die seit 2015 kostenlose Zertifikate anbietet. | ||
=== | === Mögliche Lösungen === | ||
Unter Linux kann man mit Bordmitteln eine eigene CA aufsetzen und ein | *Unter Linux kann man mit Bordmitteln eine eigene CA aufsetzen und selbst ein Zertifikate erstellen und signieren. Das ist ein Vorgang von wenigen Minuten. Alle Einzelheiten beschreibt dieser Artikel. Der einzige Unterschied zu einem von einer anerkannten Stelle signierten Zertifikat ist, dass der Client (Emailprogramm, Browser, etc.) einmalig das root CA importieren muß. | ||
Der einzige Unterschied zu einem von einer anerkannten Stelle signierten Zertifikat ist, dass der Client (Emailprogramm, Browser, etc.) einmalig das root CA importieren muß. | |||
*Eine weitere Lösung ist die Verwendung der Let's Encrypt CA und des Tools Certbot. Damit werden Zertifikate erstellt, die von allen gängigen Browsern als gültig anerkannt werden. Eine Anleitung zur Einrichtung ist in diesem Wiki-Beitrag: [[FHEMWEB_mit_Let's_Encrypt_Zertifikaten]]. | |||
= Genaues Vorgehen = | == Genaues Vorgehen == | ||
== | === OpenSSL installieren === | ||
Für die Verwaltung der Zertifikate und im übrigen auch für die Verschlüsselung der Verbindungen mit SSL und TLS kommt unter Linux fast immer OpenSSL zum Einsatz. Wahrscheinlich ist das auf Deinem Sytem deshalb bereits installiert | Für die Verwaltung der Zertifikate und im übrigen auch für die Verschlüsselung der Verbindungen mit SSL und TLS kommt unter Linux fast immer OpenSSL zum Einsatz. Wahrscheinlich ist das auf Deinem Sytem deshalb bereits installiert, wenn nicht, musst Du das Paket openssl nachinstallieren. Du benötigst aus diesem Paket den Kommandozeilenbefehl openssl. | ||
== | === Erstellen der CA === | ||
Lege zunächst ein Verzeichnis an, in dem Du das Zertifikat ablegen willst. Wir nehmen in unserem Beispiel /root/ca: | Lege zunächst ein Verzeichnis an, in dem Du das Zertifikat ablegen willst. Wir nehmen in unserem Beispiel /root/ca: | ||
<syntaxhighlight lang="bash"> | |||
root@linux# mkdir /root/ca | root@linux# mkdir /root/ca | ||
root@linux# cd /root/ca</ | root@linux# cd /root/ca</syntaxhighlight> | ||
Die Gültigkeit setzen wir mit 10 Jahren bewusst sehr hoch an. Läuft die CA aus, so werden nämlich auch alle damit signierten Serverzertifikate ungültig. Die CA enthält einen geheimen Schlüssel, welcher automatisch erzeugt und in der Datei cakey.pem abgelegt wird. Das CA-Zertifikat wird nach cacert.pem geschrieben. Der folgende Befehl erzeugt das einen Schlüssel für das Zertifikat mit einer Länge von 2048 Bit: | Die Gültigkeit setzen wir mit 10 Jahren bewusst sehr hoch an. Läuft die CA aus, so werden nämlich auch alle damit signierten Serverzertifikate ungültig. Die CA enthält einen geheimen Schlüssel, welcher automatisch erzeugt und in der Datei cakey.pem abgelegt wird. Das CA-Zertifikat wird nach cacert.pem geschrieben. Der folgende Befehl erzeugt das einen Schlüssel für das Zertifikat mit einer Länge von 2048 Bit: | ||
<syntaxhighlight lang="bash"> | |||
root@linux# openssl req -new -x509 -newkey rsa:2048 -keyout cakey.pem -out cacert.pem -days 3650 | root@linux# openssl req -new -x509 -newkey rsa:2048 -keyout cakey.pem -out cacert.pem -days 3650 | ||
Generating a 2048 bit RSA private key | Generating a 2048 bit RSA private key | ||
Zeile 30: | Zeile 30: | ||
.........................................+++ | .........................................+++ | ||
......................................+++ | ......................................+++ | ||
writing new private key to 'cakey.pem'</ | writing new private key to 'cakey.pem'</syntaxhighlight> | ||
Wer den geheimen Schlüssel der CA kennt, kann damit beliebige Serverzertifikate signieren. Deshalb wird diese Schlüsseldatei nicht im Klartext auf der Festplatte abgelegt, sondern mit einer Passphrase verschlüsselt. Diese Passphrase benötigst Du immer dann, wenn Du mit der CA neue Zertifikate ausstellen willst: | Wer den geheimen Schlüssel der CA kennt, kann damit beliebige Serverzertifikate signieren. Deshalb wird diese Schlüsseldatei nicht im Klartext auf der Festplatte abgelegt, sondern mit einer Passphrase verschlüsselt. Diese Passphrase benötigst Du immer dann, wenn Du mit der CA neue Zertifikate ausstellen willst: | ||
<nowiki> | <nowiki> | ||
Enter PEM pass phrase: sehrlangesgeheimespasswort | Enter PEM pass phrase: sehrlangesgeheimespasswort | ||
Verifying - Enter PEM pass phrase: sehrlangesgeheimespasswort</nowiki> | Verifying - Enter PEM pass phrase: sehrlangesgeheimespasswort</nowiki> | ||
Nun werden wir gebeten, Daten einzugeben, welche die CA identifizieren. Diese werden dem Client angezeigt, wenn er aufgefordert wird, das Zertifikat zu akzeptieren oder abzulehnen. Der Code für Deutschland ist DE. Wenn Du ein Feld leer lassen möchtest, so gib einen Punkt ein. Ansonsten wird der in eckigen Klammern stehende Defaultwert eingetragen: | Nun werden wir gebeten, Daten einzugeben, welche die CA identifizieren. Diese werden dem Client angezeigt, wenn er aufgefordert wird, das Zertifikat zu akzeptieren oder abzulehnen. Der Code für Deutschland ist DE. Wenn Du ein Feld leer lassen möchtest, so gib einen Punkt ein. Ansonsten wird der in eckigen Klammern stehende Defaultwert eingetragen: | ||
<nowiki> | <nowiki> | ||
----- | ----- | ||
You are about to be asked to enter information that will be incorporated | You are about to be asked to enter information that will be incorporated | ||
into your certificate request. | into your certificate request. | ||
What you are about to enter is what is called a Distinguished Name or a DN. | What you are about to enter is what is called a Distinguished Name or a DN. | ||
There are quite a few fields but you can leave some blank | There are quite a few fields but you can leave some blank | ||
For some fields there will be a default value, | For some fields there will be a default value, | ||
If you enter '.', the field will be left blank. | If you enter '.', the field will be left blank. | ||
----- | ----- | ||
Country Name (2 letter code) [AU]: DE | Country Name (2 letter code) [AU]: DE | ||
State or Province Name (full name) [Some-State]:Brandenburg | State or Province Name (full name) [Some-State]:Brandenburg | ||
Locality Name (eg, city) []:Potsdam | Locality Name (eg, city) []:Potsdam | ||
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Familie AG | Organization Name (eg, company) [Internet Widgits Pty Ltd]:Familie AG | ||
Organizational Unit Name (eg, section) []:EDV</nowiki> | Organizational Unit Name (eg, section) []:EDV</nowiki> | ||
Das Feld Common Name (CN) ist hier der offizielle Name der Zertifizierungsstelle. Für Dein eigenes CA kannst Du einfach Deinen eigenen Namen eintragen: | Das Feld Common Name (CN) ist hier der offizielle Name der Zertifizierungsstelle. Für Dein eigenes CA kannst Du einfach Deinen eigenen Namen eintragen: | ||
<nowiki> | <nowiki> | ||
Common Name (eg, YOUR name) []: Cool Tux | Common Name (eg, YOUR name) []: Cool Tux | ||
Email Address []: cooltux@gmail.tada</nowiki> | Email Address []: cooltux@gmail.tada</nowiki> | ||
Fertig. Folgende zwei Dateien sind entstanden: | Fertig. Folgende zwei Dateien sind entstanden: | ||
<nowiki> | <nowiki> | ||
root@linux# ll | root@linux# ll | ||
insgesamt 9 | insgesamt 9 | ||
drwxr-xr-x 2 root root 112 2006-04-30 12:08 . | drwxr-xr-x 2 root root 112 2006-04-30 12:08 . | ||
drwx------ 12 root root 600 2006-04-30 11:54 .. | drwx------ 12 root root 600 2006-04-30 11:54 .. | ||
-rw-r--r-- 1 root root 1212 2006-04-30 12:08 cacert.pem | -rw-r--r-- 1 root root 1212 2006-04-30 12:08 cacert.pem | ||
-rw-r--r-- 1 root root 963 2006-04-30 12:08 cakey.pem</nowiki> | -rw-r--r-- 1 root root 963 2006-04-30 12:08 cakey.pem</nowiki> | ||
Vorsichtshalber solltest Du die Rechte so setzen, dass die Schlüsseldatei nur für root lesbar ist: | Vorsichtshalber solltest Du die Rechte so setzen, dass die Schlüsseldatei nur für root lesbar ist: | ||
<nowiki> | <nowiki> | ||
root@linux# chmod 600 cakey.pem</nowiki> | root@linux# chmod 600 cakey.pem</nowiki> | ||
Du kannst nun ausprobieren, ob Du den Schlüssel mit der Passphrase wieder öffnen kannst: | Du kannst nun ausprobieren, ob Du den Schlüssel mit der Passphrase wieder öffnen kannst: | ||
<nowiki> | <nowiki> | ||
root@linux# openssl rsa -in cakey.pem -noout -text | root@linux# openssl rsa -in cakey.pem -noout -text | ||
Enter pass phrase for cakey.pem: wrzlprmpft | Enter pass phrase for cakey.pem: wrzlprmpft | ||
Private-Key: (1024 bit) | Private-Key: (1024 bit) | ||
modulus: | modulus: | ||
00:d5:a5:37:51:e9:d9:fa:e3:97:e7:46:b2:88:1a: | |||
b5:46:80:47:76:14:ae:2b:8b:3e:35:5c:ab:15:84: | |||
53:d9:63:2e:7f:08:4b:ec:77:db:02:45:f8:c7:46: | |||
58:cd:2d:f9:29:4d:96:3d:d8:6c:5d:9f:79:8a:04: | |||
cf:b7:3a:89:da:a9:63:9f:44:b3:83:cf:0d:70:7d:</nowiki> | |||
usw... | usw... | ||
== | === Schlüssel für das Serverzertifikat erzeugen === | ||
Nachdem wir nun eine eigene CA haben, kann diese nun endlich für unseren Server ein Zertifikat herausgeben. Dazu erzeugen wir zunächst einen 2048 Bit langen RSA Schlüssel, der mit AES 128 verschlüsselt auf der Platte abgelegt wird (ja wirklich, auch hier wieder ein verschlüsselter Schlüssel). Die Passphrase muss diesmal nicht sonderlich geheim sein, da wir sie ohnehin im Anschluss wieder entfernen werden. OpenSSL lässt allerdings keine leere Phrase zu: | Nachdem wir nun eine eigene CA haben, kann diese nun endlich für unseren Server ein Zertifikat herausgeben. Dazu erzeugen wir zunächst einen 2048 Bit langen RSA Schlüssel, der mit AES 128 verschlüsselt auf der Platte abgelegt wird (ja wirklich, auch hier wieder ein verschlüsselter Schlüssel). Die Passphrase muss diesmal nicht sonderlich geheim sein, da wir sie ohnehin im Anschluss wieder entfernen werden. OpenSSL lässt allerdings keine leere Phrase zu: | ||
<syntaxhighlight lang="bash"> | |||
root@linux# openssl genrsa -out | root@linux# openssl genrsa -out server-key.pem -aes128 2048 | ||
Generating RSA private key, 2048 bit long modulus | Generating RSA private key, 2048 bit long modulus | ||
....+++ | ....+++ | ||
.......................................+++ | .......................................+++ | ||
e is 65537 (0x10001) | e is 65537 (0x10001) | ||
Enter pass phrase for | Enter pass phrase for server-key.pem: test | ||
Verifying - Enter pass phrase for | Verifying - Enter pass phrase for server-key.pem: test</syntaxhighlight> | ||
So. Nun entfernen wir die Passphrase wieder. Warum? Der Serverdienst (Apache, Cyrus, etc.) muss schließlich in der Lage sein, den Schlüssel ohne Dein Zutun zu lesen. Oder möchtest Du bei jedem Booten des Servers ein Passwort eingeben müssen? | So. Nun entfernen wir die Passphrase wieder. Warum? Der Serverdienst (Apache, Cyrus, etc.) muss schließlich in der Lage sein, den Schlüssel ohne Dein Zutun zu lesen. Oder möchtest Du bei jedem Booten des Servers ein Passwort eingeben müssen? | ||
<syntaxhighlight lang="bash"> | |||
root@linux# openssl rsa -in | root@linux# openssl rsa -in server-key.pem -out server-key.pem | ||
Enter pass phrase for | Enter pass phrase for server-key.pem: jaja | ||
writing RSA key</ | writing RSA key</syntaxhighlight> | ||
== | === Certificate Signing Request erzeugen === | ||
Der nächste Schritt zum eigenen Zertifikat ist ein CSR. Dies muss dann nur noch von der CA signiert werden. Hier sind wieder Angaben analog zum Erstellen der CA nötig, was oft Verwirrung stiftet. Die allgemeinen Daten kann man ggfl. gleich wie oben eingeben: | Der nächste Schritt zum eigenen Zertifikat ist ein CSR. Dies muss dann nur noch von der CA signiert werden. Hier sind wieder Angaben analog zum Erstellen der CA nötig, was oft Verwirrung stiftet. Die allgemeinen Daten kann man ggfl. gleich wie oben eingeben: | ||
<syntaxhighlight lang="bash"> | |||
root@linux# openssl req -new -key | root@linux# openssl req -new -key server-key.pem -out req.pem -nodes | ||
You are about to be asked to enter information that will be incorporated | You are about to be asked to enter information that will be incorporated | ||
into your certificate request. | into your certificate request. | ||
Zeile 109: | Zeile 110: | ||
Locality Name (eg, city) []:Potsdam | Locality Name (eg, city) []:Potsdam | ||
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Familie AG | Organization Name (eg, company) [Internet Widgits Pty Ltd]:Familie AG | ||
Organizational Unit Name (eg, section) []:EDV</ | Organizational Unit Name (eg, section) []:EDV</syntaxhighlight> | ||
ACHTUNG, jetzt kommt das Wichtige: Beim Serverzertifikat ist der Common Name von entscheidender Bedeutung. Hier muss der DNS-Name stehen, unter dem der Client den Server anspricht! Wird das Zertifikat für eine HTTPS-Verbindung zu fhem.local verwendet, so muss der Common Name eben genau fhem.local heißen. Anderfalls wird der Browser das Zertifikat nicht akzeptieren, da er davon ausgehen muss, auf dem falschen Server gelandet zu sein. | ACHTUNG, jetzt kommt das Wichtige: Beim Serverzertifikat ist der Common Name von entscheidender Bedeutung. Hier muss der DNS-Name stehen, unter dem der Client den Server anspricht! Wird das Zertifikat für eine HTTPS-Verbindung zu fhem.local verwendet, so muss der Common Name eben genau fhem.local heißen. Anderfalls wird der Browser das Zertifikat nicht akzeptieren, da er davon ausgehen muss, auf dem falschen Server gelandet zu sein. | ||
<nowiki> | <nowiki> | ||
Common Name (eg, YOUR name) []: fhem.local | Common Name (eg, YOUR name) []: fhem.local | ||
Email Address []: admin.fhem.local</nowiki> | Email Address []: admin.fhem.local</nowiki> | ||
Weitere Optionen kann man einfach leer lassen: | Weitere Optionen kann man einfach leer lassen: | ||
<nowiki> | <nowiki> | ||
A challenge password []: | A challenge password []: | ||
An optional company name []:</nowiki> | An optional company name []:</nowiki> | ||
Mittlerweile tummeln sich schon vier Dateien in unserem Verzeichnis: | Mittlerweile tummeln sich schon vier Dateien in unserem Verzeichnis: | ||
<syntaxhighlight lang="bash"> | |||
root@linux# ll | root@linux# ll | ||
insgesamt 17 | insgesamt 17 | ||
Zeile 127: | Zeile 128: | ||
-rw------- 1 root root 963 2006-04-30 12:08 cakey.pem | -rw------- 1 root root 963 2006-04-30 12:08 cakey.pem | ||
-rw-r--r-- 1 root root 1017 2006-04-30 12:29 req.pem | -rw-r--r-- 1 root root 1017 2006-04-30 12:29 req.pem | ||
-rw-r--r-- 1 root root 1679 2006-04-30 12:21 | -rw-r--r-- 1 root root 1679 2006-04-30 12:21 server-key.pem</syntaxhighlight> | ||
== | === OpenSSL-Konfiguration anpassen === | ||
Leider kann man bei OpenSSL nicht alle Daten als Kommandozeilenargumente übergeben. Einige Einstellungen muss man lästigerweise in der Datei /etc/ssl/openssl.cnf ändern, bevor man signieren kann. Öffne diese Datei und passe folgende Zeilen in der Sektion [ CA_default ] an: | Leider kann man bei OpenSSL nicht alle Daten als Kommandozeilenargumente übergeben. Einige Einstellungen muss man lästigerweise in der Datei /etc/ssl/openssl.cnf ändern, bevor man signieren kann. Öffne diese Datei und passe folgende Zeilen in der Sektion [ CA_default ] an: | ||
<syntaxhighlight lang="bash"> | |||
/etc/ssl/openssl.cnf: | /etc/ssl/openssl.cnf: | ||
dir = . # Where everything is kept | dir = . # Where everything is kept | ||
Zeile 137: | Zeile 138: | ||
private_key = $dir/cakey.pem # The private key | private_key = $dir/cakey.pem # The private key | ||
RANDFILE = $dir/.rand # private random number file | RANDFILE = $dir/.rand # private random number file | ||
default_days = 3650 # how long to certify for</ | default_days = 3650 # how long to certify for</syntaxhighlight> | ||
Das Feld default_days ist auf 365 Tage voreingestellt und gibt die Gültigkeit des Zertifikates an. Abgelaufene Zertifikate sind im Übrigen ein sehr häufiges Problem. Wenn es soweit ist, kennt sich damit nämlich schon lange keiner mehr aus. Deswegen kannst Du wie im Beispiel angegeben die Lebensdauer z.B. auf 10 Jahre heraufsetzen. | Das Feld default_days ist auf 365 Tage voreingestellt und gibt die Gültigkeit des Zertifikates an. Abgelaufene Zertifikate sind im Übrigen ein sehr häufiges Problem. Wenn es soweit ist, kennt sich damit nämlich schon lange keiner mehr aus. Deswegen kannst Du wie im Beispiel angegeben die Lebensdauer z.B. auf 10 Jahre heraufsetzen. | ||
Nun muss man noch einige Dateien anlegen: | Nun muss man noch einige Dateien anlegen: | ||
<syntaxhighlight lang="bash"> | |||
root@linux# echo 01 > serial | root@linux# echo 01 > serial | ||
root@linux# touch index.txt</ | root@linux# touch index.txt</syntaxhighlight> | ||
== | === Serverzertifikat signieren === | ||
Kommen wir zum feierlichen Abschluss: Unsere CA signiert nun das Zertifikat: | Kommen wir zum feierlichen Abschluss: Unsere CA signiert nun das Zertifikat: | ||
root@linux# openssl ca -in req.pem -notext -out | ''(Hinweis: Vor Ausführung das Kapitel "Bekannte Probleme" beachten)'' | ||
<syntaxhighlight lang="bash"> | |||
root@linux# openssl ca -in req.pem -notext -out server-cert.pem | |||
Enter pass phrase for ./cakey.pem: langesgeheimespasswort | Enter pass phrase for ./cakey.pem: langesgeheimespasswort | ||
Zeile 160: | Zeile 162: | ||
1 out of 1 certificate requests certified, commit? [y/n] y | 1 out of 1 certificate requests certified, commit? [y/n] y | ||
Write out database with 1 new entries | Write out database with 1 new entries | ||
Data Base Updated</ | Data Base Updated</syntaxhighlight> | ||
== | === Zertifikate installieren === | ||
Wie Du das Zertifikat in FHEM installierst findest Du [[Raspberry_Pi_%26_HTTPS|hier]] und wenn Du ein Server Zertifikat für NGINX installieren möchtest findest Du Infos dazu [[HTTPS-Absicherung_%26_Authentifizierung_via_nginx_Webserver|hier]] | Wie Du das Zertifikat in FHEM installierst, findest Du [[Raspberry_Pi_%26_HTTPS|hier]] und wenn Du ein Server Zertifikat für NGINX installieren möchtest, findest Du Infos dazu [[HTTPS-Absicherung_%26_Authentifizierung_via_nginx_Webserver|hier]] | ||
=== Schlüsselcontainer erstellen === | |||
Für externe Applikationen wie "owntracks" müssen die erstellten Zertifikate und Keys in einen .p12 - Schlüsselcontainer verpackt werden | |||
<syntaxhighlight lang="bash"> | |||
root@linux# openssl pkcs12 -export -out server.p12 -in server-cert.pem -inkey server-key.pem | |||
= Nachwort = | Enter Export Password: | ||
== Einbinden der root CA in die Zertifizierungsstelle des Browsers == | Verifying - Enter Export Password: | ||
Beim Firefox importieren wir unsere | </syntaxhighlight> | ||
Das dort vergebene Passwort unbedingt sichern! | |||
Die Dateien server.p12 sowie die cacert.pem zusammen mit dem vergebenen Passwort für die .p12 Datei , können nun auf der externen Applikation verwendet werden um von extern auf den Server per SSL zugreifen zu können. | |||
Bitte hierbei unbedingt auch den Punkt unter "Bekannte Probleme" beachten! | |||
== Nachwort == | |||
=== Einbinden der root CA in die Zertifizierungsstelle des Browsers === | |||
Beim Firefox importieren wir unsere cacert.pem unter Einstellungen -> Erweitert -> Zertifikate -> Zertifikate anzeigen -> Zertifizierungsstellen ein. | |||
Unter Chrome/Chromium finden wir die Zertifikatsverwaltung unter Einstellungen -> Erweitert -> Zertifikate verwalten HTTPS/SSL-Zertifikate und -Einstellungen verwalten -> Zertifizierungsstellen | Unter Chrome/Chromium finden wir die Zertifikatsverwaltung unter Einstellungen -> Erweitert -> Zertifikate verwalten HTTPS/SSL-Zertifikate und -Einstellungen verwalten -> Zertifizierungsstellen | ||
== Bekannte Probleme == | === Bekannte Probleme === | ||
Für den Chrome/Chromium müssen wir zusätzlich "Subject Alternative Names (SAN)" in unser Zertifikat eintragen. Dies geschieht beim Serverzertifikat signieren. Dazu müssen wir uns eine weitere Datei anlegen: | Für den Chrome/Chromium und externen Applikationen wie "owntracks" müssen wir zusätzlich "Subject Alternative Names (SAN)" in unser Zertifikat eintragen. Dies geschieht beim Serverzertifikat signieren. Dazu müssen wir uns eine weitere Datei anlegen: | ||
<syntaxhighlight lang="bash"> | |||
root@linux# vim oats.extensions.cnf | root@linux# vim oats.extensions.cnf | ||
Zeile 181: | Zeile 196: | ||
[ my_subject_alt_names ] | [ my_subject_alt_names ] | ||
DNS.1 = | DNS.1 = localhost | ||
DNS. | DNS.2 = localhost.local | ||
DNS. | DNS.3 = localhost.fritz.box | ||
Die | |||
DNS.4 = HomeServer | |||
openssl ca -in req.pem -notext -extfile oats.extensions.cnf -out | DNS.5 = HomeServer.local | ||
DNS.6 = HomeServer.fritz.box | |||
# [Optional] Address of your dynamic DNS subdomain | |||
DNS.7 = homeserver.domain.de | |||
# IPv4 local host | |||
IP.1 = 127.0.0.1 | |||
# your local IPv4 address of your fhem Server | |||
IP.2 = 192.168.178.200 | |||
# [Optional] IPv6 Link local address of your fhem Server if available | |||
IP.3 = fe80::dea1:dea2:dea3:dead | |||
# [Optional] local IPv6 address of your fhem Server without network prefix if available | |||
# The difference to the above address is the missing "fe80" reference | |||
IP.4 = ::dea1:dea2:dea3:dead</syntaxhighlight> | |||
Dabei die DNS.x Namen durch die DNS Namen (bzw. IP Addressen) ersetzen, womit man Fhem aufruft. | |||
Die Signierung unseres Serverzertifikates erfolgt dann mit folgendem Befehl: | |||
<syntaxhighlight lang="bash"> | |||
openssl ca -in req.pem -notext -extfile oats.extensions.cnf -out server-cert.pem</syntaxhighlight> | |||
=== Prüfen von Zertifikaten === | |||
Zertifikate kann man im übrigen auf dieser [https://tools.keycdn.com/ssl| Seite] prüfen lassen. | |||
Dazu kopiert man den Inhalt der server-cert.pem in das Eingabefeld der Seite und klickt dann auf Check. | |||
[[Kategorie:HOWTOS]] |
Aktuelle Version vom 9. November 2023, 12:18 Uhr
Vorwort
Dein Anliegen
Du möchtest FHEM mit HTTPS betreiben, hasst es aber, ständig von Deinem Browser darauf aufmerksam gemacht zu werden, dass dies "keine sichere Verbindung" ist. Oder Du möchtest einen weiteren Serverdienst aufsetzen, welcher verschlüsselte SSL oder TLS-Verbindungen anbietet (z.B. HTTPS, POP3S, IMAPS, LDAPS, SMTP mit TLS).
Die Schwierigkeit dabei
Um eine mit SSL/TLS abgesicherte Verbindung anzubieten, benötigst Du ein Serverzertifikat. Dieses muss von einer Zertifizierungsstelle (Certification Authority oder kurz CA) signiert sein. Ein offizielles Serverzertifikat, welches von einer offiziellen Stelle signiert ist, ist leider nicht kostenlos. Meist werden jährliche Gebühren in Höhe von mehreren hundert Euro fällig. Ausnahme ist die CA Let's Encrypt, die seit 2015 kostenlose Zertifikate anbietet.
Mögliche Lösungen
- Unter Linux kann man mit Bordmitteln eine eigene CA aufsetzen und selbst ein Zertifikate erstellen und signieren. Das ist ein Vorgang von wenigen Minuten. Alle Einzelheiten beschreibt dieser Artikel. Der einzige Unterschied zu einem von einer anerkannten Stelle signierten Zertifikat ist, dass der Client (Emailprogramm, Browser, etc.) einmalig das root CA importieren muß.
- Eine weitere Lösung ist die Verwendung der Let's Encrypt CA und des Tools Certbot. Damit werden Zertifikate erstellt, die von allen gängigen Browsern als gültig anerkannt werden. Eine Anleitung zur Einrichtung ist in diesem Wiki-Beitrag: FHEMWEB_mit_Let's_Encrypt_Zertifikaten.
Genaues Vorgehen
OpenSSL installieren
Für die Verwaltung der Zertifikate und im übrigen auch für die Verschlüsselung der Verbindungen mit SSL und TLS kommt unter Linux fast immer OpenSSL zum Einsatz. Wahrscheinlich ist das auf Deinem Sytem deshalb bereits installiert, wenn nicht, musst Du das Paket openssl nachinstallieren. Du benötigst aus diesem Paket den Kommandozeilenbefehl openssl.
Erstellen der CA
Lege zunächst ein Verzeichnis an, in dem Du das Zertifikat ablegen willst. Wir nehmen in unserem Beispiel /root/ca:
root@linux# mkdir /root/ca
root@linux# cd /root/ca
Die Gültigkeit setzen wir mit 10 Jahren bewusst sehr hoch an. Läuft die CA aus, so werden nämlich auch alle damit signierten Serverzertifikate ungültig. Die CA enthält einen geheimen Schlüssel, welcher automatisch erzeugt und in der Datei cakey.pem abgelegt wird. Das CA-Zertifikat wird nach cacert.pem geschrieben. Der folgende Befehl erzeugt das einen Schlüssel für das Zertifikat mit einer Länge von 2048 Bit:
root@linux# openssl req -new -x509 -newkey rsa:2048 -keyout cakey.pem -out cacert.pem -days 3650
Generating a 2048 bit RSA private key
..............................................................
..............................................................
.........................................+++
......................................+++
writing new private key to 'cakey.pem'
Wer den geheimen Schlüssel der CA kennt, kann damit beliebige Serverzertifikate signieren. Deshalb wird diese Schlüsseldatei nicht im Klartext auf der Festplatte abgelegt, sondern mit einer Passphrase verschlüsselt. Diese Passphrase benötigst Du immer dann, wenn Du mit der CA neue Zertifikate ausstellen willst:
Enter PEM pass phrase: sehrlangesgeheimespasswort Verifying - Enter PEM pass phrase: sehrlangesgeheimespasswort
Nun werden wir gebeten, Daten einzugeben, welche die CA identifizieren. Diese werden dem Client angezeigt, wenn er aufgefordert wird, das Zertifikat zu akzeptieren oder abzulehnen. Der Code für Deutschland ist DE. Wenn Du ein Feld leer lassen möchtest, so gib einen Punkt ein. Ansonsten wird der in eckigen Klammern stehende Defaultwert eingetragen:
----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]: DE State or Province Name (full name) [Some-State]:Brandenburg Locality Name (eg, city) []:Potsdam Organization Name (eg, company) [Internet Widgits Pty Ltd]:Familie AG Organizational Unit Name (eg, section) []:EDV
Das Feld Common Name (CN) ist hier der offizielle Name der Zertifizierungsstelle. Für Dein eigenes CA kannst Du einfach Deinen eigenen Namen eintragen:
Common Name (eg, YOUR name) []: Cool Tux Email Address []: cooltux@gmail.tada
Fertig. Folgende zwei Dateien sind entstanden:
root@linux# ll insgesamt 9 drwxr-xr-x 2 root root 112 2006-04-30 12:08 . drwx------ 12 root root 600 2006-04-30 11:54 .. -rw-r--r-- 1 root root 1212 2006-04-30 12:08 cacert.pem -rw-r--r-- 1 root root 963 2006-04-30 12:08 cakey.pem
Vorsichtshalber solltest Du die Rechte so setzen, dass die Schlüsseldatei nur für root lesbar ist:
root@linux# chmod 600 cakey.pem
Du kannst nun ausprobieren, ob Du den Schlüssel mit der Passphrase wieder öffnen kannst:
root@linux# openssl rsa -in cakey.pem -noout -text Enter pass phrase for cakey.pem: wrzlprmpft Private-Key: (1024 bit) modulus: 00:d5:a5:37:51:e9:d9:fa:e3:97:e7:46:b2:88:1a: b5:46:80:47:76:14:ae:2b:8b:3e:35:5c:ab:15:84: 53:d9:63:2e:7f:08:4b:ec:77:db:02:45:f8:c7:46: 58:cd:2d:f9:29:4d:96:3d:d8:6c:5d:9f:79:8a:04: cf:b7:3a:89:da:a9:63:9f:44:b3:83:cf:0d:70:7d:
usw...
Schlüssel für das Serverzertifikat erzeugen
Nachdem wir nun eine eigene CA haben, kann diese nun endlich für unseren Server ein Zertifikat herausgeben. Dazu erzeugen wir zunächst einen 2048 Bit langen RSA Schlüssel, der mit AES 128 verschlüsselt auf der Platte abgelegt wird (ja wirklich, auch hier wieder ein verschlüsselter Schlüssel). Die Passphrase muss diesmal nicht sonderlich geheim sein, da wir sie ohnehin im Anschluss wieder entfernen werden. OpenSSL lässt allerdings keine leere Phrase zu:
root@linux# openssl genrsa -out server-key.pem -aes128 2048
Generating RSA private key, 2048 bit long modulus
....+++
.......................................+++
e is 65537 (0x10001)
Enter pass phrase for server-key.pem: test
Verifying - Enter pass phrase for server-key.pem: test
So. Nun entfernen wir die Passphrase wieder. Warum? Der Serverdienst (Apache, Cyrus, etc.) muss schließlich in der Lage sein, den Schlüssel ohne Dein Zutun zu lesen. Oder möchtest Du bei jedem Booten des Servers ein Passwort eingeben müssen?
root@linux# openssl rsa -in server-key.pem -out server-key.pem
Enter pass phrase for server-key.pem: jaja
writing RSA key
Certificate Signing Request erzeugen
Der nächste Schritt zum eigenen Zertifikat ist ein CSR. Dies muss dann nur noch von der CA signiert werden. Hier sind wieder Angaben analog zum Erstellen der CA nötig, was oft Verwirrung stiftet. Die allgemeinen Daten kann man ggfl. gleich wie oben eingeben:
root@linux# openssl req -new -key server-key.pem -out req.pem -nodes
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]: DE
State or Province Name (full name) [Some-State]:Brandenburg
Locality Name (eg, city) []:Potsdam
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Familie AG
Organizational Unit Name (eg, section) []:EDV
ACHTUNG, jetzt kommt das Wichtige: Beim Serverzertifikat ist der Common Name von entscheidender Bedeutung. Hier muss der DNS-Name stehen, unter dem der Client den Server anspricht! Wird das Zertifikat für eine HTTPS-Verbindung zu fhem.local verwendet, so muss der Common Name eben genau fhem.local heißen. Anderfalls wird der Browser das Zertifikat nicht akzeptieren, da er davon ausgehen muss, auf dem falschen Server gelandet zu sein.
Common Name (eg, YOUR name) []: fhem.local Email Address []: admin.fhem.local
Weitere Optionen kann man einfach leer lassen:
A challenge password []: An optional company name []:
Mittlerweile tummeln sich schon vier Dateien in unserem Verzeichnis:
root@linux# ll
insgesamt 17
drwxr-xr-x 2 root root 168 2006-04-30 12:29 .
drwx------ 12 root root 600 2006-04-30 11:54 ..
-rw-r--r-- 1 root root 1212 2006-04-30 12:08 cacert.pem
-rw------- 1 root root 963 2006-04-30 12:08 cakey.pem
-rw-r--r-- 1 root root 1017 2006-04-30 12:29 req.pem
-rw-r--r-- 1 root root 1679 2006-04-30 12:21 server-key.pem
OpenSSL-Konfiguration anpassen
Leider kann man bei OpenSSL nicht alle Daten als Kommandozeilenargumente übergeben. Einige Einstellungen muss man lästigerweise in der Datei /etc/ssl/openssl.cnf ändern, bevor man signieren kann. Öffne diese Datei und passe folgende Zeilen in der Sektion [ CA_default ] an:
/etc/ssl/openssl.cnf:
dir = . # Where everything is kept
new_certs_dir = $dir # default place for new certs
private_key = $dir/cakey.pem # The private key
RANDFILE = $dir/.rand # private random number file
default_days = 3650 # how long to certify for
Das Feld default_days ist auf 365 Tage voreingestellt und gibt die Gültigkeit des Zertifikates an. Abgelaufene Zertifikate sind im Übrigen ein sehr häufiges Problem. Wenn es soweit ist, kennt sich damit nämlich schon lange keiner mehr aus. Deswegen kannst Du wie im Beispiel angegeben die Lebensdauer z.B. auf 10 Jahre heraufsetzen.
Nun muss man noch einige Dateien anlegen:
root@linux# echo 01 > serial
root@linux# touch index.txt
Serverzertifikat signieren
Kommen wir zum feierlichen Abschluss: Unsere CA signiert nun das Zertifikat:
(Hinweis: Vor Ausführung das Kapitel "Bekannte Probleme" beachten)
root@linux# openssl ca -in req.pem -notext -out server-cert.pem
Enter pass phrase for ./cakey.pem: langesgeheimespasswort
...
Certificate is to be certified until Apr 27 10:45:36 2016 GMT (3650 days)
Sign the certificate? [y/n]: y
1 out of 1 certificate requests certified, commit? [y/n] y
Write out database with 1 new entries
Data Base Updated
Zertifikate installieren
Wie Du das Zertifikat in FHEM installierst, findest Du hier und wenn Du ein Server Zertifikat für NGINX installieren möchtest, findest Du Infos dazu hier
Schlüsselcontainer erstellen
Für externe Applikationen wie "owntracks" müssen die erstellten Zertifikate und Keys in einen .p12 - Schlüsselcontainer verpackt werden
root@linux# openssl pkcs12 -export -out server.p12 -in server-cert.pem -inkey server-key.pem
Enter Export Password:
Verifying - Enter Export Password:
Das dort vergebene Passwort unbedingt sichern!
Die Dateien server.p12 sowie die cacert.pem zusammen mit dem vergebenen Passwort für die .p12 Datei , können nun auf der externen Applikation verwendet werden um von extern auf den Server per SSL zugreifen zu können.
Bitte hierbei unbedingt auch den Punkt unter "Bekannte Probleme" beachten!
Nachwort
Einbinden der root CA in die Zertifizierungsstelle des Browsers
Beim Firefox importieren wir unsere cacert.pem unter Einstellungen -> Erweitert -> Zertifikate -> Zertifikate anzeigen -> Zertifizierungsstellen ein. Unter Chrome/Chromium finden wir die Zertifikatsverwaltung unter Einstellungen -> Erweitert -> Zertifikate verwalten HTTPS/SSL-Zertifikate und -Einstellungen verwalten -> Zertifizierungsstellen
Bekannte Probleme
Für den Chrome/Chromium und externen Applikationen wie "owntracks" müssen wir zusätzlich "Subject Alternative Names (SAN)" in unser Zertifikat eintragen. Dies geschieht beim Serverzertifikat signieren. Dazu müssen wir uns eine weitere Datei anlegen:
root@linux# vim oats.extensions.cnf
basicConstraints=CA:FALSE
subjectAltName=@my_subject_alt_names
subjectKeyIdentifier = hash
[ my_subject_alt_names ]
DNS.1 = localhost
DNS.2 = localhost.local
DNS.3 = localhost.fritz.box
DNS.4 = HomeServer
DNS.5 = HomeServer.local
DNS.6 = HomeServer.fritz.box
# [Optional] Address of your dynamic DNS subdomain
DNS.7 = homeserver.domain.de
# IPv4 local host
IP.1 = 127.0.0.1
# your local IPv4 address of your fhem Server
IP.2 = 192.168.178.200
# [Optional] IPv6 Link local address of your fhem Server if available
IP.3 = fe80::dea1:dea2:dea3:dead
# [Optional] local IPv6 address of your fhem Server without network prefix if available
# The difference to the above address is the missing "fe80" reference
IP.4 = ::dea1:dea2:dea3:dead
Dabei die DNS.x Namen durch die DNS Namen (bzw. IP Addressen) ersetzen, womit man Fhem aufruft.
Die Signierung unseres Serverzertifikates erfolgt dann mit folgendem Befehl:
openssl ca -in req.pem -notext -extfile oats.extensions.cnf -out server-cert.pem
Prüfen von Zertifikaten
Zertifikate kann man im übrigen auf dieser Seite prüfen lassen. Dazu kopiert man den Inhalt der server-cert.pem in das Eingabefeld der Seite und klickt dann auf Check.