<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Reverse Proxy &#8211; SmartHomeNG | smarthome knx homematic mqtt hue 1wire home automation</title>
	<atom:link href="https://www.smarthomeng.de/tag/reverse-proxy/feed" rel="self" type="application/rss+xml" />
	<link>https://www.smarthomeng.de</link>
	<description>Die Device Integrations-Plattform für Dein Smart Home</description>
	<lastBuildDate>Sun, 11 Apr 2021 20:48:05 +0000</lastBuildDate>
	<language>de</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.5.5</generator>

<image>
	<url>https://www.smarthomeng.de/wp-content/uploads/global/logo_small_152x152-150x150.png</url>
	<title>Reverse Proxy &#8211; SmartHomeNG | smarthome knx homematic mqtt hue 1wire home automation</title>
	<link>https://www.smarthomeng.de</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Reverse Proxy für Websocket der VISU mit Apache</title>
		<link>https://www.smarthomeng.de/reverse-proxy-fuer-websocket-der-visu-mit-apache</link>
					<comments>https://www.smarthomeng.de/reverse-proxy-fuer-websocket-der-visu-mit-apache#respond</comments>
		
		<dc:creator><![CDATA[Thomas Creutz]]></dc:creator>
		<pubDate>Tue, 18 Sep 2018 06:36:52 +0000</pubDate>
				<category><![CDATA[Tipps & Tricks]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[Reverse Proxy]]></category>
		<category><![CDATA[smartVISU]]></category>
		<guid isPermaLink="false">https://www.smarthomeng.de/?p=2095</guid>

					<description><![CDATA[Hallo Zusammen, ich wurde vor längerer Zeit gefragt, ob ich den Weg meiner Implementierung mit Apache hier niederschreiben könnte, was ich hiermit erledigen möchte. Warum man das macht und wie das ganze mit NGINX funktioniert hat psilo sehr gut auf dieser Seite erklärt! Deswegen möchte ich auch hier nur auf die<a class="moretag" href="https://www.smarthomeng.de/reverse-proxy-fuer-websocket-der-visu-mit-apache"> Weiterlesen&#8230;</a>]]></description>
										<content:encoded><![CDATA[<p>Hallo Zusammen,</p>
<p>ich wurde vor längerer Zeit gefragt, ob ich den Weg meiner Implementierung mit Apache hier niederschreiben könnte, was ich hiermit erledigen möchte.</p>
<p>Warum man das macht und wie das ganze mit NGINX funktioniert hat <a href="https://www.smarthomeng.de/author/psilo">psilo</a> sehr gut auf <a href="https://www.smarthomeng.de/nginx-als-reverseproxy">dieser Seite</a> erklärt!</p>
<p>Deswegen möchte ich auch hier nur auf die Änderungen zu Apache eingehen und setzte also Voraus, dass man weiß was man erreichen will und auch über die genannte Seite von psilo geschaut hat!</p>
<p>Als kleine Änderung will ich hier gleich anmerken, dass ich keine extra Maschine als Reverse Proxy einsetzte, da ich bei mir soweit alles abgesichert habe und darin einige Erfahrung habe <img src="https://s.w.org/images/core/emoji/15.0.3/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>Damit gehe ich also auch davon aus, dass ihr Apache auch für eure smartVISU einsetzt, wie ich es mache. Falls nicht müsst ihr natürlich apache nachinstallieren.</p>
<p>Unter Debian/Ubuntu/Raspbian funktioniert das mit:</p>
<pre><code class="language-bash">sudo apt-get update
sudo apt-get install apache2</code></pre>
<p>Unter Ubuntu 18.04 habe ich auch keine weiteren Module (wie libapache2-mod-XXX) für Apache benötigt. Ob dies bei allen Debian-basierenden Distributionen der Fall ist müsste man im Einzelfall prüfen. Man wird es auf jeden Fall merken, wenn sich die kommenden Befehle zum aktivieren der Module nicht durchführen lassen.</p>
<p>Nun müssen wir die folgenden Module aktivieren:</p>
<pre><code class="language-bash">sudo a2enmod proxy_wstunnel
sudo a2enmod rewrite
sudo a2enmod setenvif</code></pre>
<p>Bei Apache arbeite ich gerne nach dem modularen Prinzip, weswegen ich mir für die Einstellungen die ich brauche, einer eigene Konfigurationsdatei mit dem Namen <code>/etc/apache2/smartvisu.conf</code> angelegt habe, die ich hier entsprechend erläutern möchte.</p>
<pre><code class="language-apacheconf">
&lt;IfModule mod_rewrite.c&gt;
   RewriteEngine on

   # Eine Umleitung vom Ordner zur index.php (es gab da mal einen Bug,
   # in der alten VISU, keine Ahnung ob das noch aktuell ist, schaden
   # tut es aber nicht, man kann es aber gerne auch weglassen)
   RewriteCond %{REQUEST_URI} ^/smartVISU$ [NC,OR]
   RewriteCond %{REQUEST_URI} ^/smartVISU/$ [NC]
   RewriteRule .* /smartVISU/index.php [R=302,L]

   # Mit dieser Definition wird der Reverse Proxy für Websocket aktiviert
   # Da wie oben schon erwähnt, die VISU und SH bei mir auf dem lokalen Host
   # läuft, verwende ich hier als Ziel auch localhost. Das kann man aber
   # natürlich Anpassen und soll auch nur als Beispiel dienen.
   &lt;IfModule mod_proxy.c&gt;

      ProxyPreserveHost On
      ProxyVia On

      # socket.io 1.0+ starts all connections with an HTTP polling request
      RewriteCond %{QUERY_STRING} transport=polling [NC]
      RewriteRule /(.*) http://localhost:2424/$1 [P]

      # When socket.io wants to initiate a WebSocket connection, it sends an
      # "upgrade: websocket" request that should be transferred to ws://
      RewriteCond %{HTTP:Upgrade} websocket [NC]
      RewriteRule /(.*) ws://localhost:2424/$1 [P]
   &lt;/IfModule&gt;

   # Hier ist Platz für spezielle Ausnahmen (die wie unten mit SetEnvIf
   # gezeigt nicht abgebildet werden können), z.B. für eine Manifest-Datei die
   # ich mir in die VISU rein Programmiert habe. Hier wird beim Auffinden
   # des entsprechenden Query-Strings die Umgebungsvariable
   # no_auth_required auf 1 gesetzt, was dann weiter unten ausgewertet wird
   # und dann dazu führt, dass keine Anmeldung erforderlich ist
   RewriteCond %{QUERY_STRING} page=manifest
   RewriteRule ^/smartVISU/index.php - [E=no_auth_required:1]
   # !! Das ist natürlich nur ein Beispiel und wäre bei euch nicht erforderlich !!

&lt;/IfModule&gt;

# Hier definiere ich wann man sich anmelden muss und wann nicht und
# das gilt dabei für den kompletten Webserver Stamm also ab der Wurzel.
# Das ist !Wichtig!, da so auch automatisch die Websocket-Verbindung
# per Basic Auth geschützt wird!
&lt;Location /&gt;
   # Hier kann ich dann wieder Dinge freigeben, die ohne Anmeldung funktionieren sollen
   # (wie auch weiter oben im Beispiel, nur das es mit SetEnvIf etwas einfacher geht)
   # z.B. kann sich jeder meine Temperatur Statistik im Unterordner /mytemplogger ohne
   # Anmeldung ansehen, dazu setzte ich wieder die Umgebungsvariable no_auth_required auf 1
   SetEnvIf Request_URI ^/mytemplogger no_auth_required=1

   # Dann definiere ich die Basic Auth Parameter
   AuthName "Private"
   AuthType Basic
   AuthUserFile /etc/apache2/htpasswd
   Require valid-user

   # Hier gebe ich an, dass man sich über die lokalen Netze nicht anmelden muss,
   # dass muss also jeder für sich Anpassen. Wer kein IPv6 hat kann die /64 Adressen
   # natürlich auch weg lassen
   Require ip 192.168.XX.0/24 2a02:810c:XXX:XXX::/64 fd00:XXXX:XXXX:XXXX::/64 fe80::/64
   # Und hier wird die Ausnahme mit der Umgebungsvariable definiert, so kann man einfacher
   # Seiten oder Aufrufe als Ausnahme definieren
   Require env no_auth_required

&lt;/Location&gt;</code></pre>
<p>Dann müssen wir uns natürlich die zuvor verwendete <code>/etc/apache2/htpasswd</code> anlegen:</p>
<pre><code class="language-bash">htpasswd -cB /etc/apache2/htpasswd BENUTZER
New password: MEINSUPERPASSWORD
Re-type new password: MEINSUPERPASSWORD
Adding password for user visu

# Und dann die Rechte anpassen:
chmod 660 /etc/apache2/htpasswd</code></pre>
<p>Wobei BENUTZER der Benutzername ist den man anlegen möchte. Es können natürlich mehrere Benutzer angelegt werden. Man sollte aber hier wirklich ein sicheres Passwort verwenden, da dies nicht vor Brute-Force Angriffen geschützt ist. Wobei man ganz klar die Webseite nochmal in mehreren wegen etwas weiter Schützen kann. Aber dazu später mehr.</p>
<p>Nun kann man auf jeden fall schon seine Konfiguration für den virtuellen Host anpassen. Im Standardfall wäre dass die <code>/etc/apache2/sites-enabled/000-default.conf</code> oder eben die von euch genutzte Datei. Da ich bei mir mehrere virtuelle Hosts habe, die jewels ein eigenes Zertifikat (Stichwort SSL) haben (für internen Host &#8211; ohne SSL, für externen Host &#8211; mit SSL, für den vom Internet und Intern aus erreichbaren IPv6 Host &#8211; mit SSL), kann ich jetzt die <code>smartvisu.conf</code> überall einbinden und hab eine zentrale Stelle für die Anpassungen.</p>
<p>Die nötige Anpassung zum Einbinden der Konfiguration sieht wie folgt aus:</p>
<p>Innerhalb des <code>&lt;VirtualHost&gt;&lt;/VirtualHost&gt;</code> Blocks muss nur noch folgende Zeile eingefügt werden:</p>
<p><code class="language-apacheconf">Include /etc/apache2/smartvisu.conf</code></p>
<p>Jetzt könnte man den Apache2 neustarten und testen.</p>
<p><code class="language-bash">service apache2 restart</code></p>
<h2>Nützliche Tipps zur Absicherung</h2>
<p>Zum Absichern gibt es mehrere Faktoren &#8211; vieles hier setzt zwar auf Verschleierung/Tarnung (was eine gute Methode ist, Angriffe gar nicht erst aufkommen zu lassen), aber natürlich nicht ausschließlich:</p>
<ul style="list-style-type: lower-alpha">
<li>) Die Webseite auf <strong>jeden</strong> Fall mit SSL absichern!! Auch ich verwende für die externen Zugriffe den kostenfreien Service von Let’s Encrypt. Möglich wäre aber auch ein self-signed Zertifikat (Anleitungen gibt es dazu wie Sand am Meer) aber eben nicht so schön und nicht ganz so sicher, oder wer von euch prüft schon den Fingerabdruck den Zertifikats?!</li>
<li>) die Brute-Force Angriffe auf die Basic-Anmeldung kann man ganz einfach mit fail2ban Abfangen/-mildern (Abmildern deswegen, da es möglich wäre auch ein Angriff von mehreren IPs zu koordinieren, was fail2ban nicht abfangen könnte), was ich trotzdem nur jeden empfehlen kann, weswegen ich es auch kurz erklären möchte:<br />
Zuerst installiert man das Paket mit <code class="language-bash">sudo apt-get install fail2ban</code><br />
dann erstellen wir uns eine local.conf, in dem wir das definieren was nicht in der Standardkonfiguration erfasst ist. Man könnte zwar auch die Standardkonfiguration unter <code>/etc/fail2ban/jail.conf</code> bearbeiten, aber übersichtlicher wird es mit meiner vorgeschlagenen Variante. Dazu öffnen wir mit dem Editor unserer Wahl die Datei <code>/etc/fail2ban/jail.d/local.conf</code> und aktivieren die Jail für die Definition von <code>apache-auth</code> wie folgt:</p>
<pre><code>[apache-auth]
enabled = true
</code></pre>
<p>und danach können wir fail2ban neu laden mit <code class="language-bash">sudo fail2ban-client reload</code> und den Status prüfen mit <code class="language-bash">sudo fail2ban-client status</code>.<br />
<strong><br />
Wichtig</strong>: Hat man den Protokollpfad seines Apache Vhosts modifiziert, muss man den Pfad für die Jail nochmals prüfen und ggf. in unserer local.conf überschreiben. Prüfen kann man das nochmal in der Datei <code>/etc/fail2ban/jail.conf</code> bzw. <code>/etc/fail2ban/paths-arch.conf</code> (dort steht bei meinem Ubuntu die Variable apache_error_log).</li>
<li>) Keine Standard-Ports für den Zugriff auf den Webserver von Extern verwenden. Das hält die ganzen Scanner davon ab die Seite zufällig zu finden. Natürlich wird ein gezielter Angriff (mit Port-Scan) die Seite trotzdem aufdecken, egal welcher Port verwendet wird. Dies wiederum könnte man mit Port Knocking (<a href="http://www.cipherdyne.org/fwknop/" target="_blank" rel="noopener">fwknop</a>/<a href="http://www.zeroflux.org/projects/knock" target="_blank" rel="noopener">knockd</a>) ausschalten, finde ich aber überflüssig, da es das ganze wieder unnötig verkompliziert.</li>
<li>) zusätzlichen Schutz würde auch noch eine zwei-Faktor Anmeldung bringen, z.B. über den Google Authenticator, der den offener Standard OATH (Initiative for Open Authentication) umsetzt und leicht verwendet werden kann. Dazu verweise ich aber z.B. auf <a href="https://www.linuxjournal.com/content/two-factor-authentication-system-apache-and-ssh" target="_blank" rel="noopener">diese Anleitung</a>.</li>
<li>) Client Zertifikate wären natürlich auch möglich, halte ich aber auch für Übertrieben/zu kompliziert und diese können genau so gut über einen Trojaner geklaut werden &#8211; dann lieber 2-Faktor <img src="https://s.w.org/images/core/emoji/15.0.3/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></li>
<li>) den Webserver vor Zugriffen aus dem Ausland schützen wäre natürlich auch unter Apache möglich, alternativ mit iptables. Aber mal ehrlich, wenn ich im Urlaub bin will ich auch darauf zugreifen und nicht extra dran denken müssen es frei zu schalten.</li>
<li>) die Seite nicht öffentlich im Web verlinken, da b) sonnst auch keinen Sinn macht. Nicht dass wir was zu verbergen haben &#8211; aber wie heist es so schön: Schlafende Hunde soll man nicht wecken</li>
<li>) dafür sorgen dass das System aktuell gehalten wird &#8211; Stichpunkt <a href="https://www.google.de/search?q=unattended-upgrades" target="_blank" rel="noopener">UnattendedUpgrades</a>, was es sowohl unter Debian und Ubuntu gibt. Auch sollte nur eine Distribution eingesetzt werden, welche auch noch vom Anbieter unterstützt wird.</li>
<li>) Keine öffentliche (also ohne Anmeldung zugängliche) Index Seite auf dem internen Webserver anlegen, wo mögliche öffentliche Inhalte &#8222;sichtbar&#8220; verlinkt sind. Auch sollten die öffentlichen Inhalte (wenn überhaupt unbedingt benötigt &#8211; man kann diese ja auch nur Intern erreichbar machen) nicht über Standard-Ordner laufen, wie z.B. wp (WordPress), Joomla, phpmyadmin, Webmail usw&#8230;<br />
Die Gefahr dabei besteht, dass in den gehosteten Inhalten, eine Sicherheitslücke dafür sorgt, dass jemand sich Zugriffsrechte auf den Webserver erschleichen kann, was dann wieder durch Intensivierung des Angriffs über eine Rechteausweitung zu ROOT-Rechte führen kann!!</li>
</ul>
<p><strong>TODO</strong>: Konfiguration LetsEncrypt</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.smarthomeng.de/reverse-proxy-fuer-websocket-der-visu-mit-apache/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>NGINX als ReverseProxy</title>
		<link>https://www.smarthomeng.de/nginx-als-reverseproxy</link>
					<comments>https://www.smarthomeng.de/nginx-als-reverseproxy#comments</comments>
		
		<dc:creator><![CDATA[Marc René Frieß]]></dc:creator>
		<pubDate>Mon, 30 Oct 2017 23:44:14 +0000</pubDate>
				<category><![CDATA[Tipps & Tricks]]></category>
		<category><![CDATA[NGINX]]></category>
		<category><![CDATA[Reverse Proxy]]></category>
		<category><![CDATA[smartVISU]]></category>
		<category><![CDATA[Zusatzsoftware]]></category>
		<guid isPermaLink="false">https://www.smarthomeng.de/?p=349</guid>

					<description><![CDATA[Um einen sicheren Zugriff auf SmartHomeNG und die smartVISU von außen (ohne VPN) zu ermöglichen, empfiehlt es sich, die Software NGINX als ReverseProxy mit Basic Authentication oder Clientzertifikaten zu nutzen. Die Idee hinter einem ReverseProxy ist, dass man einen einzigen sicheren Eintrittspunkt in das Heimnetzwerk hat, ohne ein VPN nutzen<a class="moretag" href="https://www.smarthomeng.de/nginx-als-reverseproxy"> Weiterlesen&#8230;</a>]]></description>
										<content:encoded><![CDATA[<div class="markdown-body">
<p>Um einen sicheren Zugriff auf SmartHomeNG und die smartVISU von außen (ohne VPN) zu ermöglichen, empfiehlt es sich, die Software <a href="https://www.nginx.com/" target="_blank" rel="noopener">NGINX</a> als ReverseProxy mit Basic Authentication oder Clientzertifikaten zu nutzen.</p>
<p>Die Idee hinter einem ReverseProxy ist, dass man einen einzigen sicheren Eintrittspunkt in das Heimnetzwerk hat, ohne ein VPN nutzen zu müssen. Der ReverseProxy hängt direkt hinter dem Router und wird von dort via Portforwarding angesprochen. Üblicherweise wird der HTTPS Port 443 vom Router auf den ReverseProxy umgeleitet. Für die Installation ist temporär auch der HTTP Port 80 notwendig, damit ein SSL Serverzertfikat, bspw. von <a href="https://letsencrypt.org/" target="_blank" rel="noopener">Let&#8217;s Encrypt</a>, für die hinterlegte DynDNS URL installiert werden kann.</p>
<p>Im ReverseProxy kann ein Zugriffsschutz implementiert werden, der via Basic Authentication oder Clientzertifikate realisiert wird. Beides wird in diesem Artikel erklärt. Es wird zudem auf weitere Sicherheitsmaßnahmen, wie das Blockieren von Requests aus nicht vertrauenswürdigen Ländern, eingegangen.</p>
<p>Je nach angesprungenem Kontextpfad (also bspw. <code>/smartVISU</code> oder <code>/alexa</code>) wird dann in Richtung des Hauptservers und des jeweiligen Ports weitergeleitet. Das folgende Bild illustriert das schematisch:<br />
<img fetchpriority="high" decoding="async" src="https://www.smarthomeng.de/wp-content/uploads/beitraege/Architecture-2.png" alt="" class="alignnone size-full wp-image-507" width="700" height="430" srcset="https://www.smarthomeng.de/wp-content/uploads/beitraege/Architecture-2.png 700w, https://www.smarthomeng.de/wp-content/uploads/beitraege/Architecture-2-300x184.png 300w" sizes="(max-width: 700px) 100vw, 700px" /></p>
<p>Die folgende Dokumentation beschreibt eine Installation von NGINX als ReverseProxy auf eigenständiger Hardware unter Raspbian Stretch Lite. Dieser ReverseProxy ist bspw. auch für das Alexa Plugin oder die Nutzung von SmartHomeNG mit &#8222;EgiGeoZone&#8220; / &#8222;Geofency&#8220; notwendig, damit ein sicherer Zugriff aus dem Internet auf die SmartHomeNG Instanz erfolgen kann.</p>
<h2>Annahmen</h2>
<p>Diese Anleitung beruht auf folgenden Annahmen</p>
<ul>
<li>NGINX wird auf einem frisch aufgesetzten RaspberryPi mit &#8222;Raspbian Stretch Lite&#8220; installiert.</li>
<li>Der RaspberryPi dient ausschliesslich der Funktion als ReverseProxy</li>
<li>Der Standarduser heißt weiterhin &#8222;pi&#8220;</li>
<li>Eine DynDNS (o.ä.) Domain ist vorhanden und leitet auf die aktuelle Internet IP</li>
<li>SmartHomeNG und smartVISU sind auf einem separaten Rechner im gleichen LAN installiert.</li>
</ul>
<h2>Basiskonfiguration</h2>
<ul>
<li>Deutsches Keyboard festlegen: <code>/etc/default/keyboard</code> editieren und in der Zeile <code>XKBLAYOUT="..."</code> ein &#8222;de&#8220; eintragen. Danach <code>sudo reboot now</code> eingeben, um neu zu starten.</li>
<li>Aus Sicherheitsgründen das Standard-Passwort für &#8222;pi&#8220; ändern: Als User &#8222;pi&#8220; mit Standard-Passwort einloggen und mit <code>passwd</code> ein neues Passwort setzen.</li>
</ul>
<h2>NGINX installieren:</h2>
<pre><code class="language-bash">sudo apt-get update
sudo apt-get install nginx-full
</code></pre>
<h2>GeoIP installieren:</h2>
<p>Über GeoIP kann mittels der anfragenden IP herausgefunden werden, aus welchem Land eine Anfrage kommt. Darüber lassen sich bspw. Requests aus Risikoländern blockieren.</p>
<pre><code class="language-bash">sudo apt-get install geoip-database libgeoip1
cd /usr/share/GeoIP/
sudo wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
sudo gunzip GeoIP.dat.gz
</code></pre>
<h2>Let&#8217;s Encrypt Server-Zertifikate</h2>
<p>(nach <a href="https://goneuland.de/debian-9-stretch-lets-encrypt-zertifikate-mit-certbot-erstellen/" rel="nofollow" title="https://goneuland.de/debian-9-stretch-lets-encrypt-zertifikate-mit-certbot-erstellen/">https://goneuland.de/debian-9-stretch-lets-encrypt-zertifikate-mit-certbot-erstellen/</a>)</p>
<p>Über Let&#8217;s Encrypt lassen sich kostenlos SSL Zertifikate, bspw. für dyndns-Domains, ausstellen.</p>
<p>Certbot installieren:</p>
<pre><code class="language-bash">sudo apt-get install certbot
</code></pre>
<p>Nun die Datei <code>/etc/nginx/snippets/letsencrypt.conf</code> bearbeiten:</p>
<pre><code class="language-bash">sudo nano /etc/nginx/snippets/letsencrypt.conf
</code></pre>
<p>Dort folgenden Inhalt einfügen, damit certbot die Identität überprüfen kann.:</p>
<pre><code class="language-bash">location ^~ /.well-known/acme-challenge/ {
 default_type "text/plain";
 root /var/www/letsencrypt;
}
</code></pre>
<pre><code class="language-bash">sudo mkdir -p /var/www/letsencrypt/.well-known/acme-challenge
</code></pre>
<pre><code class="language-bash">sudo nano /etc/nginx/sites-available/default
</code></pre>
<p>Dort unterhalb von <code>listen [::]:80 default_server;</code> die Zeile <code>include /etc/nginx/snippets/letsencrypt.conf;</code> einhängen:</p>
<pre><code class="language-json">server {
        listen 80 default_server;
        listen [::]:80 default_server;
        include /etc/nginx/snippets/letsencrypt.conf;
[...]
</code></pre>
<pre><code class="language-bash">sudo service nginx restart
</code></pre>
<p>Temporär Port 80 im Router auf den RaspberryPi weiterleiten !</p>
<pre><code class="language-bash">sudo certbot certonly --rsa-key-size 4096 --webroot -w /var/www/letsencrypt -d &lt;mydomain&gt;.&lt;myds&gt;.&lt;me&gt; 
</code></pre>
<p>Nachdem man seine E-Mail eingegeben hat, sollte die Generierung erfolgreich durch laufen und mit</p>
<pre><code class="language-text">Generating key (4096 bits): /etc/letsencrypt/keys/0000_key-certbot.pem
Creating CSR: /etc/letsencrypt/csr/0000_csr-certbot.pem
</code></pre>
<p>enden.</p>
<p>Port 80 im Browser wieder schließen, dafür Port 443 (https) entsprechend auf den ReverseProxy-RaspberryPi weiterleiten!</p>
<h2>NGINX Konfiguration</h2>
<p>/etc/nginx/nginx.conf bearbeiten und direkt im &#8222;http&#8220; Block die GeoIP Einstellungen hinzufügen. Unter der Konfiguration der &#8222;virtual hosts&#8220; noch einen Block als Schutz gegen Denial of Service Angriffe ergänzen:</p>
<pre><code class="language-nginx">http {
    ##
    # GeoIP Settings
    # Nur Länder aus erlaubten IP Bereichen dürfen den ReverseProxy
    # passieren!
    # https://www.howtoforge.de/anleitung/nginx-besucher-mit-dem-geoip-modul-nach-landern-blocken-debianubuntu/
    ##
    geoip_country /usr/share/GeoIP/GeoIP.dat;
    map $geoip_country_code $allowed_country {
        default yes;
        BY no;
        BR no;
        KP no;
        KR no;
        RS no;
        RO no;
        RU no;
        CN no;
        CD no;
        NE no;
        GH no;
        IQ no;
        IR no;
        SY no;
        UA no;
    }
[...]
    ##
    # Virtual Host Configs
    ##

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;

    ##
    # Harden nginx against DDOS
    ##

    client_header_timeout 10;
    client_body_timeout   10;
}
</code></pre>
<p>NGINX mit <code>sudo service nginx restart</code> neu starten.</p>
<h3>/etc/nginx/conf.d/&lt;mydomain&gt;.&lt;myds&gt;.&lt;me&gt;.conf erstellen</h3>
<pre><code class="language-nginx">server {
    server_tokens off;
    
    ## Blocken, wenn Zugriff aus einem nicht erlaubten Land erfolgt ##
    if ($allowed_country = no) {
        return 403;
    }    
    
    # https://www.cyberciti.biz/tips/linux-unix-bsd-nginx-webserver-security.html
    ## Block download agents ##
    if ($http_user_agent ~* LWP::Simple|BBBike|wget) {
        return 403;
    }

    ## Block some robots ##
    if ($http_user_agent ~* msnbot|scrapbot) {
        return 403;
    }

    ## Deny certain Referers ##
    if ( $http_referer ~* (babes|forsale|girl|jewelry|love|nudit|organic|poker|porn|sex|teen) )
    {
        return 403;
    }

    listen 443 ssl default_server;
    server_name &lt;mydomain&gt;.&lt;myds&gt;.&lt;me&gt;;

    ##
    # SSL
    ##
    
    ## Activate SSL, setze SERVER Zertifikat Informationen ## 
    # Generiert via Let's Encrypt! 
    ssl on;
    ssl_certificate /etc/letsencrypt/live/&lt;mydomain&gt;.&lt;myds&gt;.&lt;me&gt;/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/&lt;mydomain&gt;.&lt;myds&gt;.&lt;me&gt;/privkey.pem;
    ssl_session_cache builtin:1000 shared:SSL:10m;
    ssl_prefer_server_ciphers on;
    # unsichere SSL Ciphers deaktivieren!
    ssl_ciphers    HIGH:!aNULL:!eNULL:!LOW:!3DES:!MD5:!RC4;
    
    ##
    # HSTS
    ##

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    ##
    # global
    ##

    root /var/www/&lt;mydomain&gt;.&lt;myds&gt;.&lt;me&gt;;
    index index.php index.htm index.html;
    
    # Weiterleitung zu SmartHomeNG (Websocket Schnittstelle) mit Basic Auth
    # Nur Verbindungen gegen "/" durchlassen! Also weder auf Dateien noch Verzeichnisse (= nur Websocket Connects)
    location = / {
        auth_basic "Restricted Area: smartVISU";
        auth_basic_user_file /etc/nginx/.smartvisu;      
        proxy_pass http://&lt;SmartHomeNG LAN IP&gt;:&lt;Websocket Port&gt;;        
    }

    # Zugriff auf die smartVISU mit Basic Auth
    location /smartVISU {      
        auth_basic "Restricted Area: smartVISU";
        auth_basic_user_file /etc/nginx/.smartvisu;
        proxy_pass http://&lt;smartVISU Server LAN IP&gt;/smartVISU;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
    
    # Alexa Plugin Weiterleitung
    location /alexa {
        auth_basic "Restricted Area: Alexa";
        auth_basic_user_file /etc/nginx/.alexa;
        proxy_pass http://&lt;SmartHomeNG LAN IP&gt;:&lt;Alexa Plugin Port&gt;/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # Network Plugin Weiterleitung
    location /shng {
        auth_basic "Restricted Area: SmartHomeNG";
        auth_basic_user_file /etc/nginx/.shng;
        proxy_pass http://&lt;SmartHomeNG LAN IP&gt;:&lt;Network Plugin Port&gt;/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
</code></pre>
<h3>NGINX reloaden:</h3>
<pre><code class="language-bash">/etc/init.d/nginx reload
</code></pre>
<h3>Passwort-Files für unterschiedliche User für smartVISU, Alexa, Network Plugin erstellen</h3>
<pre><code class="language-bash">sudo apt-get install apache2-utils

sudo htpasswd -c /etc/nginx/.smartvisu &lt;username&gt;
sudo htpasswd -c /etc/nginx/.alexa &lt;username&gt;
sudo htpasswd -c /etc/nginx/.shng &lt;username&gt;
</code></pre>
<p>Dann ein Passwort vergeben.</p>
<p>Der Zugriff auf https://../smartVISU sollte nun klappen.</p>
<h3>Nacharbeiten: Port 80 in NGINX deaktivieren</h3>
<p>Da NGINX im LAN aktuell noch auf Port 80 konfiguriert ist, sollte man in der /etc/nginx/sites-available/default noch ein <code>return 403</code> ergänzen und NGINX neu starten:</p>
<pre><code class="language-nginx">server {
        listen 80 default_server;
        listen [::]:80 default_server;

        return 403;

        include /etc/nginx/snippets/letsencrypt.conf;
</code></pre>
<pre><code class="language-bash">/etc/init.d/nginx reload
</code></pre>
<h2>Client Zertifikate erstellen (optional)</h2>
<h3>openssl.cnf editieren</h3>
<pre><code class="language-bash">sudo nano /etc/ssl/openssl.cnf
</code></pre>
<p>Folgende Zeilen anpassen:</p>
<pre><code class="language-ini">dir = /etc/ssl/ca                       # Directory where everything is kept
[...]
new_certs_dir = $dir/certs               # default place for new certs.
[...]
certificate = $dir/ca.crt               # The CA certificate
[...]
crl = $dir/crl.pem                      # The current CRL
private_key = $dir/private/ca.key       # The private key
[...]
default_md = sha1 # use public key default MD
</code></pre>
<p>Drei neue Verzeichnisse und drei Dateien anlegen:</p>
<pre><code class="language-bash">sudo mkdir -p /etc/ssl/ca/certs/users
sudo mkdir -p /etc/ssl/ca/crl
sudo mkdir -p /etc/ssl/ca/private

sudo touch /etc/ssl/ca/index.txt
sudo touch /etc/ssl/ca/index.txt.attr
</code></pre>
<p>In der Datei crlnumber den Wert &#8222;01&#8220; eintragen und speichern.</p>
<pre><code class="language-bash">sudo nano /etc/ssl/ca/crlnumber
</code></pre>
<p>Zertifikat für Certification Authority (CA) erstellen, Passwort für die CA wählen und eigene Daten eingeben:</p>
<pre><code class="language-bash">sudo openssl genrsa -des3 -out /etc/ssl/ca/private/ca.key 4096
sudo openssl req -new -x509 -days 1095 -key /etc/ssl/ca/private/ca.key -out /etc/ssl/ca/certs/ca.crt
sudo openssl ca -name CA_default -gencrl -keyfile /etc/ssl/ca/private/ca.key -cert /etc/ssl/ca/certs/ca.crt -out /etc/ssl/ca/private/ca.crl -crldays 1095
</code></pre>
<p>Client Zertifikat für einen User erstellen und ein Passwort für das Client Zertifikat vergeben:</p>
<pre><code class="language-bash">sudo openssl genrsa -des3 -out /etc/ssl/ca/certs/users/&lt;USERNAME&gt;.key 1024
sudo openssl req -new -key /etc/ssl/ca/certs/users/&lt;USERNAME&gt;.key -out /etc/ssl/ca/certs/users/&lt;USERNAME&gt;.csr
</code></pre>
<p>Bei folgendem Schritt das Passwort für die CA eingeben:</p>
<pre><code class="language-bash">sudo openssl x509 -req -days 1095 -in /etc/ssl/ca/certs/users/&lt;USERNAME&gt;.csr -CA /etc/ssl/ca/certs/ca.crt -CAkey /etc/ssl/ca/private/ca.key -CAserial /etc/ssl/ca/serial -CAcreateserial -out /etc/ssl/ca/certs/users/&lt;USERNAME&gt;.crt
</code></pre>
<p>Bei folgendem Schritt mit dem Passwort für das Client Zertifikat bestätigen und ein Export Passwort wählen:</p>
<pre><code class="language-bash">sudo openssl pkcs12 -export -clcerts -in /etc/ssl/ca/certs/users/&lt;USERNAME&gt;.crt -inkey /etc/ssl/ca/certs/users/&lt;USERNAME&gt;.key -out /etc/ssl/ca/certs/users/&lt;USERNAME&gt;.p12 
</code></pre>
<p>&lt;USERNAME&gt;.p12 File herunterladen:</p>
<pre><code class="language-bash">sudo cp /etc/ssl/ca/certs/users/&lt;USERNAME&gt;.p12 /home/pi
cd /home/pi/
sudo chown pi &lt;USERNAME&gt;.p12
</code></pre>
<p>Bspw. nun via SFTP ziehen und aufs Datei aufs Android Handy übertragen und ausführen oder im Browser unter Zertifikate&#8220; importieren. Dabei muss es mit Export Passwort bestätigt werden.</p>
<h2>Client Zertifikate in NGINX nutzen (optional)</h2>
<p>Anleitung nach <a href="https://arcweb.co/securing-websites-nginx-and-client-side-certificate-authentication-linux/" rel="nofollow" title="https://arcweb.co/securing-websites-nginx-and-client-side-certificate-authentication-linux/">https://arcweb.co/securing-websites-nginx-and-client-side-certificate-authentication-linux/</a></p>
<p>/etc/nginx/conf.d/&lt;mydomain&gt;.&lt;myds&gt;.&lt;me&gt;.conf bearbeiten und die Zeilen im SSL Block ergänzen (&#8222;ab Client Zertifikat spezifisch&#8220;)</p>
<pre><code class="language-nginx">    ##
    # SSL
    ##

    ## Activate SSL, setze SERVER Zertifikat Informationen ##
    # Generiert via Let's Encrypt!    
    ssl on;
    ssl_certificate /etc/letsencrypt/live/&lt;mydomain&gt;.&lt;myds&gt;.&lt;me&gt;/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/&lt;mydomain&gt;.&lt;myds&gt;.&lt;me&gt;/privkey.pem;
    ssl_session_cache builtin:1000 shared:SSL:10m;
    ssl_prefer_server_ciphers on;
    # unsichere SSL Ciphers deaktivieren!
    ssl_ciphers    HIGH:!aNULL:!eNULL:!LOW:!3DES:!MD5:!RC4;

    # Client Zertifikat spezifisch
    ssl_client_certificate /etc/ssl/ca/certs/ca.crt;
    ssl_crl /etc/ssl/ca/private/ca.crl;
    ssl_verify_client optional;
    ssl_session_timeout 5m;
</code></pre>
<p>Die smartVISU relevanten Teile könnten jetzt folgendermaßen über Clientzertifikate geschützt werden:</p>
<pre><code class="language-json">    # Weiterleitung zu SmartHomeNG (Websocket Schnittstelle) mit Clientzertifikat
    location = / {
        # Clientzertifikat gültig?
        if ($ssl_client_verify != SUCCESS) {
                return 403;
        }
        proxy_pass http://&lt;SmartHomeNG LAN IP&gt;:&lt;Websocket Port&gt;;      
    }

    # Zugriff auf die smartVISU mit Clientzertifikat
    location /smartVISU {  
        # Clientzertifikat gültig?    
        if ($ssl_client_verify != SUCCESS) {
                return 403;
        }
        proxy_pass http://&lt;smartVISU Server LAN IP&gt;/smartVISU;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
</code></pre>
<p>Wer es doppelt sicher haben möchte, kann die Basic Auth in den jew. Blöcken auch beibehalten.</p>
<p>Testbar ist das Ganze, wenn es im Browser ohne Zertifikat einen 403er Fehler gibt und mit Zertifikat die smartVISU aufbaut.</p>
<h2>Erweiterung: Stärkere Diffie-Hellman-Parameter</h2>
<p>Damit die Sicherheit &#8222;perfekt&#8220; wird, sollten stärkere Diffie-Hellman-Schlüssel verwendet werden. Dazu muss ein neues .pem File generiert werden. Es empfiehlt sich, die Erzeugung dieses Files nicht direkt auf den Raspi, sondern auf einem PC mit stärkerer CPU durchzuführen. Ein Test auf einem Raspi3 dauerte 24 Stunden (!). Ein Intel 4790k brauchte hingegen nur 30 Minuten.</p>
<p>Folgendes ist zu tun:</p>
<pre><code class="language-bash">cd /etc/ssl/certs
sudo openssl dhparam -out dhparam.pem 4096
</code></pre>
<p>Alternativ kann die Datei auch einfach in <code>/etc/ssl/certs</code> kopiert werden.</p>
<p>Danach ist in der SSL Konfiguration von NGINX folgende Zeile zu ergänzen und NGINX neu zu starten:</p>
<pre><code class="language-bash"># Konfiguration editieren
sudo nano /etc/nginx/conf.d/\&lt;mydomain\&gt;.\&lt;myds\&gt;.\&lt;me\&gt;.conf 
</code></pre>
<pre><code class="language-bash">## Dort folgende Zeile im Block SSL einfügen:

##
# SSL
##
[...]
ssl_dhparam /etc/ssl/certs/dhparam.pem;
[...]
</code></pre>
<pre><code class="language-bash">## NGINX neu starten
sudo service nginx restart
</code></pre>
<p>Die Sicherheit der eigenen https-Domain kann nun unter <a href="https://www.ssllabs.com/ssltest/" rel="nofollow" title="https://www.ssllabs.com/ssltest/">https://www.ssllabs.com/ssltest/</a> getestet werden. Mit den oben genannten Maßnahmen sollte ein A+ erreicht werden.</p>
<p>Der versiertere Nutzer kann sich unter <a href="https://mozilla.github.io/server-side-tls/ssl-config-generator/" rel="nofollow" title="https://mozilla.github.io/server-side-tls/ssl-config-generator/">https://mozilla.github.io/server-side-tls/ssl-config-generator/</a> auch gleich eine eigene Konfiguration generieren lassen.</p>
</div>
<h2>Wartung: Zertifikat nach 3 Monaten erneuern</h2>
<p>Nach 3 Monaten muss das Let&#8217;s Encrypt Serverzertifikat erneuert werden. Damit das Erneuerungs-Skript funktioniert, muss Port 80 im <span class="highlighted">NGINX</span> freigegeben, bzw. über einen separaten <code>server</code> Block auf HTTPS umgeleitet werden:</p>
<pre><code class="language-bash">
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;
    return 301 https://$host$request_uri;
}
</code></pre>
<p>Die Erneuerung geht dann wie folgendermaßen:<br />
<code>sudo certbot certonly --rsa-key-size 4096 --webroot -w /var/www/letsencrypt -d &lt;mydomain&gt;.&lt;myds&gt;.&lt;me&gt;</code></p>
<p>Im nun folgenden Dialog Option 2 (2: Renew &amp; replace the cert (limit ~5 per 7 days)) auswählen. Danach <span class="highlighted">NGINX</span> neu starten:<br />
<code>sudo service nginx restart</code><code></code></p>
<p>Der Test über <a href="https://www.ssllabs.com/ssltest/">https://www.ssllabs.com/ssltest/</a> oder der Aufruf im Browser gibt nun Aufschluß über die Laufzeit des verlängerten Zertifikats.</p>
<p><strong>Tipp: </strong>Endet die Erneuerung mit einem Timeout, kann dies ggf. an einer fälschlicherweise an den DNS Server propagierten IPV6 Addresse liegen. In diesem Fall testweise bei den DynDNS Einstellungen diese deaktivieren.</p>
<p><em>(Die in diesem Artikel verwendeten Screenshots und Grafiken wurden selber erstellt. Verwendete Symbole und Icons stammen von https://openclipart.org. Das Titelbild ist unter der Creative Commons Zero (CC0) Lizenz veröffentlicht und wurde von www.pexels.com bezogen.)</em></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.smarthomeng.de/nginx-als-reverseproxy/feed</wfw:commentRss>
			<slash:comments>23</slash:comments>
		
		
			</item>
	</channel>
</rss>
