Raspberry Pi hinter NAT ======================= .. highlight:: shell-session Letzte Aktualisierung: 24. Mai 2020 Ein im heimischen LAN hinter einem WLAN-Router ("behind NAT") aufgestellter Linux-Rechner soll Web Services fürs Internet (WAN) anbieten. Dafür kann z.B. ein stromsparender Single Board Computer (SBC) wie Raspberry Pi eingesetzt werden, auf dem Raspian (entspricht aktuell Debian 10/Buster) läuft. In diesem Szenario ergeben sich zwei besondere Problemstellungen: a) Behind NAT Da der dieser kleine Rechner hinter dem üblichen WLAN-Router steht (Fritzbox, Speedport, ...), der nur Verbindungen von innen nach außen zum clientseitigen "Surfen" zulässt (NAT), muss im WLAN-Router der fürs Internet freizugebende Port freigeschaltet werden (PAT). Damit wird eine Kommunikation in umgekehrter Richtung möglich. Aus Sicherheitsgründen öffnen wir den Port im WLAN-Router erst, nachdem wir den Server abgesichert haben. b) Dynamical IP Address Der WLAN-Router bekommt vom Internetprovider zumeist eine sich ändernde IP-Adresse dynamisch zugewiesen. Das ist natürlich ungünstig, wenn man draußen dauerhaft erreichbar sein möchte. Die Lösung hierfür ist DynDNS. Siehe dazu https://www.maketecheasier.com/best-dynamic-dns-providers/ Zu b) ist anzumerken, dass der Linux-Server nach dem Einrichten von Port-Forwarding auch direkt mit der öffentlichen IP-Adresse des WLAN-Routers angesprochen werden könnte, was wie beschrieben eher unpraktisch ist. Diese IP-Adresse kann z.B. auch per Kommandozeile ermittelt werden - und tatsächlich benötigen wir sie auch gleich bei der DynDNS-Registrierung: :: raspi:~$ curl -4 ifconfig.co 84.124.158.196 raspi:~$ raspi:~$ curl ifconfig.co 2003:f2:e729:c533:244:d6fa:fa2b:f728 raspi:~$ Nun bitte hier registrieren... => https://www.spdyn.de/register (die hinterlegte eMail-Adresse dient dann als Loginname) Im linken Navigationsbereich kann man sich via "Host", "Add" einen Domainnamen kostenlos registrieren: a) Verfügbaren Domainnamen aus der Drop/Down-Liste heraussuchen b) Einen eigenen Hostnamen eintragen (kann evl. schon vergeben sein) c) Update-Token für ddclient erstellen (= Passwort für automatische Aktualisierung) d) Status im "Dashboard" kontrollieren, ein grüner Punkt vor dem Hostnamen bedeutet dann später, dass die Host-IP erfolgreich aktualisiert wurde. Raspberry Pi als Server ----------------------- Hierfür sind zwei wichtige Komponenten erforderlich: - DynDNS-Client: ``ddclient`` (Account via https://securepoint.de anlegen, Konfiguration nach https://wiki.securepoint.de/SPDyn/Hostverwenden vornehmen) - Nginx als Webserver: Siehe https://www.raspifun.de/viewtopic.php?t=24 Software installieren ^^^^^^^^^^^^^^^^^^^^^ Wir installieren gleich zwei Pakete, neben dem DynDNS-Client auch einen schnellen, sparsamen Webserver. Während der Installation von 'ddclient' sind erste Einstellungen vorzunehmen, die aber im Anschluss sowieso angepasst werden müssen: :: raspi:~ # apt-get install ddclient nginx Reading package lists... Konfiguration ddclient ^^^^^^^^^^^^^^^^^^^^^^ Laut Beschreibung des Securepoint-Wikis konfigurieren wir weiter, in dem wir die Datei mittels ``nano /etc/ddclient.conf`` editieren und auf die hier gezeigten Werte anpassen: .. highlight:: bash :: # Configuration file for ddclient generated by debconf # # /etc/ddclient.conf # Protokoll angeben: protocol=dyndns2 # Falls der WLAN-Router eine eigene Konfiguration zulässt: #use=if, if=eth0 # Falls der im LAN laufende Raspi das Updaten auslöst: use=web, web=checkip.spdyn.de # Bei Verwendung des Update-Tokens: server=update.spdyn.de login=linuxia.my-gateway.de password='lgoo-rule-xvbb' linuxia.my-gateway.de Mit ``systemctl restart ddclient`` lesen wir die Änderung ein, wobei dann anhand ``systemctl status ddclient`` erkennbar wird, ob es geklappt hat ("SUCCESS: updating linuxia.my-gateway.de: good: IP address set to 84.184.188.196"). Testen können wir das Ganze vom selben DSL-Anschluss aus leider nicht, man nehme am besten sein Smartphone, deaktiviere WLAN und surfe dann via mobile Datenverbindung die neue URL an. Alternativen sind, Freunde zu bitten, die URL aufzurufen oder sich auf einen im Internet laufenden (Cloud-)Host einzuloggen, um von dort aus die Tests durchzuführen. Aber einen Blick in die DNS-Datenbanken kann man schon werfen: .. highlight:: shell-session :: raspi:~ # host linuxia.my-gateway.de linuxia.my-gateway.de has address 84.184.188.196 raspi:~ # **Für das neue IPv6** muss ein eben solcher Host mit "Add" hinzugefügt werden (mit selben Namen, allerdings mit AAAA-Record). Ebenso ist wieder ein Update-Token zu erstellen. Das automatische Updaten via ``ddclient`` kann mit der folgenden, separaten Konfiguration ``/etc/ddclient-v6.conf`` erfolgen (leider lässt sich der Dual-Stack nicht in einer einzigen Datei konfigurieren): .. highlight:: bash :: # Protokoll für dynmische Updates: protocol=dyndns2 # Hier wird die IP des Raspis und nicht wie bei v4 die des WLAN-Routers gesendet: usev6=if, if=eth0 # Udate-URL: server=update.spdyn.de # FQDN des Hosts für Login: login=linuxia.my-gateway.de # Separater Update-Token für AAAA-Record: password='ljfn-ufne-gfex' # FQDN des Hosts: linuxia.my-gateway.de Testweise können wir diese Konfiguration per Direktaufruf starten: .. highlight:: shell-session :: root@raspi:~ # ddclient -verbose -file /etc/ddclient-v6.conf INFO: setting IP address to 2003:f2:e729:c533:244:d6fa:fa2b:f728 for linuxia.my-gateway.de UPDATE: updating linuxia.my-gateway.de CONNECT: update.spdyn.de CONNECTED: using HTTP SENDING: GET /nic/update?system=dyndns&hostname=linuxia.my-gateway.de&myip=2003:f2:e729:c533:244:d6fa:fa2b:f728 HTTP/1.0 SENDING: Host: update.spdyn.de SENDING: Authorization: Basic dG9udXMuc3BkbHajKGU6bGlmbi11Zm58LWd2LXg= SENDING: User-Agent: ddclient/3.8.3 SENDING: Connection: close SENDING: RECEIVE: HTTP/1.1 200 OK RECEIVE: Server: openresty RECEIVE: Content-Type: text/plain; charset=UTF-8 RECEIVE: Connection: close RECEIVE: Vary: Accept-Encoding RECEIVE: Cache-Control: no-cache RECEIVE: Date: Fri, 22 May 2020 20:43:06 GMT RECEIVE: pragma: no-cache RECEIVE: expires: Tue, 21 Apr 2020 20:43:06 GMT RECEIVE: X-RateLimit-Limit: 60 RECEIVE: X-RateLimit-Remaining: 59 RECEIVE: X-Frame-Options: DENY RECEIVE: X-Content-Type-Options: nosniff RECEIVE: X-XSS-Protection: 1; mode=block RECEIVE: Content-Security-Policy: default-src 'self' ; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://apis.google.com https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/ https://stats.spdns.de; object-src 'none' ; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com/ ; img-src 'self' data: https://ssl.gstatic.com/ https://stats.spdns.de ; media-src 'none'; frame-src https://stats.spdns.de/ https://www.google.com/recaptcha/ https://www.youtube.com/embed/; connect-src 'self' wss://dev-av.securepoint.de; font-src 'self' https://fonts.gstatic.com RECEIVE: Referrer-Policy: no-referrer RECEIVE: Expect-CT: max-age=86400 RECEIVE: Feature-Policy: accelerometer 'none'; camera 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; payment 'none'; usb 'none' RECEIVE: RECEIVE: good 2003:f2:e729:c533:244:d6fa:fa2b:f728 SUCCESS: updating linuxia.my-gateway.de: good: IP address set to 2003:f2:e729:c533:244:d6fa:fa2b:f728 root@raspi:~ # root@raspi:~ # root@raspi:~ # host linuxia.my-gateway.de linuxia.my-gateway.de has address 84.124.158.196 linuxia.my-gateway.de has IPv6 address 2003:f2:e729:c533:244:d6fa:fa2b:f728 root@raspi:~ # Anstelle die Aktualisierung für IPv6 manuell mittels ``ddclient -verbose -file `` vorzunehmen, empfiehlt es sich dann, eine eigene Systemd-Serviceunit anzulegen, die einen automatischen Start ermöglicht. Die Nutzung dieser globalen IPv6-Unicast-Adresse ist allerdings nur dann im Internet möglich, wenn der WLAN-Router sie nach draußen durchgibt. Anders als bei IPv4, wo private Adressen in öffentliche übersetzt werden müssen, sind wir mit IPv6 normalerweise direkt im Internet erreichbar. Leider gestatten nicht alle Router das Freischalten via Firewall. Das betrifft z.B. die Speedport-Geräte der Telekom. Bereitstellung von Webdokumenten ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Konfigurieren müssen wir den Webserver 'nginx' vorerst nicht, interessant ist in der Datei ``/etc/nginx/sites-enabled/default`` nur, welcher Pfad als Ablageort für die Dokumente vorgesehen ist (Anweisung: ``root /var/www/html;``). Dort legen wir eine Datei namens ``index.html`` (also insgesamt ``/var/www/html/index.html``) mit folgendem Inhalt an: .. highlight:: html :: Testseite mit ein paar Links

Kleine Testseite

Ein paar Hyperlinks:

Sicherheit / Raspi härten ------------------------- TLS-Verschlüsselung ^^^^^^^^^^^^^^^^^^^ Heutzutage ist es üblich geworden, Webseiten verschlüsselt auszuliefern. Spätestens, wenn man einen mit Benutzername/Passwort gesicherten Zugang realisieren möchte, ist dies wichtig. Eine Voraussetzung dafür sind Zertifikate nach dem X.509-Standard, die dank der Let’s Encrypt Initiative kostenlos zur Verfügung stehen. Die beim DynDNS-Provider *Securepoint* erhältlichen Domainnamen eignen sich problemlos für eine Registrierung bei Let’s Encrypt. Unter `linuxize.com `_ ist sehr schön beschrieben, wie man das sicher und robust für Debian einrichten kann. Dazu gibt es `unter pemmann.de `_ einen Kurzabriss samt Konfigurationsdateien. Hinweis: Im WLAN-Router muss dann später der TCP-Port 443 freigeschaltet werden (siehe ganz unten). SSH-Server ^^^^^^^^^^ Am besten erzeugt man sich auf einer anderen Linux-Maschine, die als Workstation dient (über die normalerweise der Login auf den Raspi geschieht), ein eigenes, clientseitiges Schlüsselpaar. Damit kann der unsichere Login mit Benutzername/Passwort-Paar später deaktiviert werden. Im Prinzip sind dies nur diese beiden Zeilen: .. highlight:: shell-session :: user@linuxPC:~ $ ssh-keygen -b 4096 ... user@linuxPC:~ $ ssh-copy-id pi@RASPBERRY ... In letzterer Zeile bitte "RASPBERRY" durch die IP-Adresse des Geräts ersetzen. Bei dieser Aktion wird der Public-Key auf den Raspberry-Server transferiert, wobei er anhängend in die auf dem Server evl. schon vorhandene Datei ``/home/pi/.ssh/authorized_keys`` geschrieben wird. HINWEIS: Verschlüsselt wird stets mit dem öffentlichen Schlüssel des Partners, die Entschlüsselung erfolgt dann jeweils lokal mit dem eigenen, privaten Schlüssel. Er darf das System niemals verlassen! Nun können wir die Einstellungen des SSH-Servers ändern, indem wir die Datei ``/etc/ssh/sshd_config`` editieren. Vor allem ist hierbei die Direktive von Zeile 1 explizit auf 'no' zu setzen (``PermitRootLogin no``). Nach dem erfolgreichen Einbinden dieses nun erzeugten Client-Schlüsselpaares, ist es nun auch möglich, die Direktive in Zeile 2 auf 'no' zu schalten (``PasswordAuthentication no``) sowie die weiteren Einstellungen auf die hier gezeigten Werte zu setzen: :: raspi:~ # grep -v '^\s*#\|^$' /etc/ssh/sshd_config | nl 1 PermitRootLogin no 2 PasswordAuthentication no 3 ChallengeResponseAuthentication no 4 UsePAM no 5 X11Forwarding yes 6 PrintMotd no 7 AcceptEnv LANG LC_* 8 Subsystem sftp /usr/lib/openssh/sftp-server raspi:~ # Nach dem Editieren nicht vergessen, ``systemctl reload sshd`` auszuführen. Wenn wir einmal auf dem Server sind, wollen wir schließlich nicht vergessen, die Fingerprints für die Clients bereitszustellen, so dass sie beim Erstlogin in der Lage sind, die Echtheit der Serveridentität zu verifizieren und mit "yes" in ihrer ``~/.ssh/known_hosts`` dauerhaft zu beglaubigen: .. highlight:: bash :: ssh-keygen -l -f /etc/ssh/ssh_host_ecdsa_key.pub ssh-keygen -l -f /etc/ssh/ssh_host_ed25519_key.pub ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key.pub Einbruchsvorbeugung ^^^^^^^^^^^^^^^^^^^ Das Installieren eines Intrusion Prevention Systems (IPS) lohnt sich in jedem Falle, um unberechtigten, permanenten Loginversuchen Einhalt zu gebieten. In der Grundeinstellung ist das Jail für den SSH-Server bereits aktiv: .. highlight:: shell-session :: raspi:~ # apt-get install fail2ban ... raspi:~ # fail2ban-client status sshd Status for the jail: sshd |- Filter | |- Currently failed: 0 | |- Total failed: 21 | `- File list: /var/log/auth.log `- Actions |- Currently banned: 0 |- Total banned: 0 `- Banned IP list: raspi:~ # Weiterführendes siehe unter https://www.raspberrypi.org/documentation/configuration/security.md Port-Forwarding im WLAN-Router ------------------------------ Zum Einrichten der Portweiterleitung vom Internet hin zum internen Raspberry siehe z.B. den `Crashkurs Fernzugriff `_ von PCwelt. Im Speedport-Router schaut das so aus: .. image:: img/raspi-portweiterleitung.png Möchte man wie beschrieben TLS-Verschlüsselung anbieten, muss im WLAN-Router zusätzlich zu Port 80 auch eine Portweiterleitung für Port 443 angelegt werden.