HOWTO: Apache Proxy mit Zweifaktor-Authentisierung TOTP 2FA

Begonnen von Peedy, 28 Januar 2019, 20:15:46

Vorheriges Thema - Nächstes Thema

Peedy

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?

CoolTux

Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

Peedy