Nach vielen Überlegungen und Versuchen zur Absicherung von fhem nach "aussen" bin ich zum Schuss gekommen, den Zugang mit einer Zweifaktor-Authentisierung abzusichern.
Hierzu bietet sich das Projekt apache_2fa von itemir auf GitHub an.
Nach einigen Stunden habe ich es auch für fhem unter Centos 7 zum laufen gebracht.
Hier will ich nun meine Erfahrungen mit der Gemeinde teilen ...
Benötigt wird noch onetimepass über pip installiert.
Bei mir hatte auch noch pip gefehlt ...
yum install python-pip python-devel
pip install onetimepass
Apache (hier httpd) benötigt hierfür folgende Module:
- proxy_html_module (shared)
- fcgid_module (shared)
- rewrite_module (shared)
- auth_digest_module (shared)
Bei mir haben nach der Grundinstallation noch proxy_html und fcgid gefehlt.
yum install mod_proxy_html mod_fcgid
Zur Kontrolle kann noch der Webserver neu gestartet werden
systemctl restart httpd
Auflisten geladener Module:
httpd -M
Nun holen wir den Projektinhalt nach /var/www/a2fa
git clone https://github.com/itemir/apache_2fa /var/www/a2fa
Das state-Verzeichnis für die Sessions fehlt noch
mkdir /var/www/a2fa/state
Nun noch die benötigten Berechtigungen vergeben
chown -R apache:apache /var/www/a2fa
chmod 750 /var/www/a2fa/state
chmod 755 /var/www/a2fa/auth
chmod 755 /var/www/a2fa/state_clean
chmod 640 /var/www/a2fa/tokens.json
Bei aktiviertem SELinux fehlen noch Freigaben für den Webserver zum ausführen des Projektes, wie auch zum schreiben im state-Verzeichnis.
semanage fcontext -a -t httpd_sys_script_exec_t '/var/www/a2fa(/.*)?'
restorecon -Rv '/var/www/a2fa/
semanage fcontext -a -t httpd_sys_rw_content_t '/var/www/a2fa/state(/.*)?'
restorecon -Rv '/var/www/a2fa/state/'
Nun wird die Konfiguration zur Webseite in /etc/httpd/conf.d/ erstellt.
Empfohlen ist eine Namenskonvention, wie z.B. meine.domaene.org_2FA.conf
Hier nun meine komplette Konfiguration (sanitarisiert)
<VirtualHost *:80>
DocumentRoot /var/www/html/sweethome
ServerName meine.domaene.org
ServerAlias meine.domaene.org
Redirect permanent / https://meine.domaene.org/
<Directory />
Require all granted
Options None
AllowOverride All
</Directory>
</VirtualHost>
<VirtualHost *:443>
ServerName meine.domaene.org
ServerAlias meine.domaene.org
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/auth/
RewriteCond %{HTTP_COOKIE} !^.*2FA_Auth=([a-zA-Z0-9]+)
RewriteRule ^(.*)$ /auth/auth?/fhem%{QUERY_STRING} [L,R=302]
RewriteCond %{REQUEST_URI} !^/auth/
RewriteCond %{HTTP_COOKIE} ^.*2FA_Auth=([a-zA-Z0-9]+)
RewriteCond /var/www/a2fa/state/%1 !-f
RewriteRule ^(.*)$ /auth/auth?/fhem%{QUERY_STRING} [L,R=302]
Header always set Feature-Policy "microphone 'none'; camera 'none'; geolocation 'none';payment 'none'; sync-xhr 'self' https://meine.domaene.org"
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/butzies.ddnss.org/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/butzies.ddnss.org/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/butzies.ddnss.org/chain.pem
# a2fa selbst
ScriptAlias /auth/ /var/www/a2fa/
<Directory /var/www/a2fa>
AllowOverride All
Options FollowSymLinks
AuthType Digest
AuthName "meine.domaene.org"
AuthDigestDomain /
AuthDigestProvider file
AuthUserFile /var/www/a2fa/apache_credentials
Require valid-user
</Directory>
# a2fa geschützer Pfad
<Directory /var/www/html/sweethome>
AllowOverride All
Options Indexes FollowSymLinks
AuthType Digest
AuthName "meine.domaene.org"
AuthDigestDomain /
AuthDigestProvider file
AuthUserFile /var/www/a2fa/apache_credentials
Require valid-user
</Directory>
ProxyRequests Off
ProxyVia Off
ProxyPreserveHost On
<Location /fhem>
ProxyPass http://localhost:8083/fhem
ProxyPassReverse http://localhost:8083/fhem
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /fhem(.*) ws://localhost:8083/fhem$1 [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteRule /fhem(.*) http://localhost:8083/fhem$1 [P,L]
</Location>
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
LogLevel warn
ErrorLog /var/log/httpd/meine.domaene.org.ERROR.log
CustomLog /var/log/httpd/meine.domaene.org.CUSTOM.log combined
</VirtualHost>
Dieses Beispiel beinhaltet auch eine letsencrypt-Konfiguration.
Weitere Informationen hierzu gibt es im Wiki.
Neustart des Webservers ...
systemctl restart httpd
Nun müssen noch Schlüssel generiert und angezeigt werden.
Hierfür werden oathtool und qrencode benötigt
yum install oathtool qrencode
Und los geht's ...
Hierfü habe ich mir ein Tool geschrieben und auf GitHub gestellt.
cd /var/www
git clone https://github.com/peedy2495/apache_2fa-newuser.git a2fa/newuser.sh
chmod +x a2fa/newuser.sh
Los geht's :-)
cd /var/www/a2fa
./newuser.sh
Bitte achtet darauf, dass der Shell-Benutzer die notwendigen Rechte zum bearbeiten der Dateien apache_credentials und tokens.json besitzt.
Nun muss nur noch regelmäßig im Verzeichnis state die Kehrwoche gemacht werden:
crontab -e
mit folgend anghängten Eintrag wird stündlich aufgeräumt
0 * * * * /var/www/a2fa/state_clean
Das soll es schon gewesen sein ... viel Spaß!
PS: Musste alles offline vorbereiten, da eine Stunde Loginzeit einfach zu mager ist ... >1Std?
Ohne Worte ....