Senior Admin

Published by senioradmin on

Internetserver im eigenen Heim Teil 2

senioradmin

Internetserver im eigenen Heim Teil 2

Einleitung

Im 1. Teil habe ich grundlegende Überlegungen für den Betrieb eines Internet-Servers im eigenen Heim angestellt. tl;dr:

In diesem zweiten Teil geht es um die konkrete Umsetzung. Dabei stelle ich die Lösung vor, die mir am praktikabelsten erschien. Es gibt viele andere Wege. Es ist eine Frage der verfügbaren Ressourcen, der persönlichen Kenntnisse und Angewohnheiten und auch des Geschmacks, welche Lösungen man bevorzugt. Insofern erhebt die hier vorgestellte Lösung nicht den Anspruch, der Weisheit letzter Schluss zu sein.

Umfang

Aufgesetzt wird ein Mailserver “mail” (SMTP + IMAP) und ein Webserver “web”.

Grafische Übersichten

Hier nochmal eine (unvollständige) grafische Darstellung der Realisierung.


                      .--.
                  _ -(    )- _
             .--,(   INTERNET  ),--.
         _.-(  .----------.         )-._     VPN-Tunnel
        (      | IPv4-VPS |<.......................
         '-._( '----------'        )_..'          .
              '__,(            ),__' |            .
                   - ._(__)_. -      |            .
                                     |            .
       _________                _____|___         .
      [_...__...]------------- [_..._'...]        .
  Servernetz   .       Internet-Router.           .
  Router       |                      |           .
               |                      '           .
               |                 .-,(  ),-.       .
               |              .-(          )-.    .
               |             (    Heimnetz     )  .
               |              '-(          ).-'   .
               |                  '-.( ).-'       .
              .'-.                                .
          _ -(    )- _                            .
     .--,(  Servernetz ),--.                      .
 _.-(        .--------.     )-._                  .
(            | Server |<..........................'
 '-._(       '--------'    )_.-'         VPN-Tunnel
      '__,(            ),__'
           - ._(__)_. -

Und hier detaillierter Ausschnitt über das Servernetz

                                                                  ____
                                              VServer vps 1.2.3.4|====|
                                                                 |    |
               _________                                         |    |
              [_...._...] Servernetz-Router      vpn 172.16.0.1  |____|
                   |                                             ^    ^
                   |                 ____                        |    |
                ___'____            |====|vpn 172.16.0.3---------'    |
               |==|=====|-----------|    |                            |
               |  |     |           |    |                            |
               |  |     |           |____|                            |
               |  |     |  Container mail 192.168.2.7                 |
               |  |     |            ____                             |
               |  |==== |           |====|vpn 172.16.0.2--------------'
               |__|_____|-----------|    |
       Server srv 192.168.2.5       |    |
                                    |____|
                             Container web 192.168.2.6

              Servernetz 192.168.2.0/24

Servernetz-Router

Der Servernetz-Router wird “hinter” dem Internet-Router angeschlossen. Hier wird ein eigenes, privates Netz konfiguriert. Auf dem Router selbst muss konfiguriert werden, dass keine keine Pakete aus dem Servernetz in das Heimnetz gelangen. Lediglich das NAT-Forwarding an den Heimnetz-Router wird erlaubt.

Server

Dies ist unser Host für die VMs/Container. Ich nutze hier ein ausgemustertes Mini-ITX-Board mit einem Intel Atom D510 Prozessor. Dieser ist relativ verbrauchsarm und hat den Vorteil, nicht von Spectre/Meltdown betroffen zu sein - ist aber 64bit-fähig. Der größte Nachteil ist, dass diese CPU keine Hardware-Virtualisierung beherrscht. Daher nutze ich unprivilegierte LXC-Container.

Als OS verwende ich Alpine Linux in der Version 3.13 und einem LTS-Kernel. Die Installation erfolgt mit der Extended-Variante als System-Installation (“sys”).

Nach der Installation muss das System vorbereitet werden, LXC-Container zu hosten. Die Container sollen im selben Netz sein wie der Host, also benötigen wir eine Netzwerk-Brücke (bridge). Zunächst werden die benötigten Pakete installiert:

apk add lxc bridge lxcfs lxc-download lxc-openrc lxc-templates bridge-utils 

Dann wird die Bridge konfiguriert

# /etc/network/interfaces
auto lo
iface lo inet loopback

auto br0
iface br0 inet static
        bridge-ports eth0
        bridge-stp 0
        address 192.168.2.5
        netmask 255.255.255.0
        gateway 192.168.2.1

Unprivilegierte Container

Zwecks Separation sollten die Systeme voneinander getrennt sein. Container laufen im selben Kernelspace ab wie der Host und somit wäre es relativ einfach aus einem Container auszubrechen, der mit Root-Rechten läuft. Daher wären eigentlich “echte” virtuelle Maschinen zu bevorzugen. Da dies hier keine Option ist, verwende ich unprivilegierte Container. Dies sind - grob gesagt - Container ohne Root-Rechte auf dem Host-System. Dies wird erreicht durch ein User-ID-Mapping und den Einsatz von User-Namespaces innerhalb des Kernels. Der Root-User innerhalb des Containers ist also nicht identisch mit dem Host-Root-User. Außerdem sorgt der Kernel dafür, dass alle Prozesse des Containers in ihrem eigenen Namensraum “eingesperrt” werden.

Zunächst wird das Usermapping vorbereitet:

echo root:1000000:65536 | tee -a /etc/subuid 
echo root:1000000:65536 | tee -a /etc/subgid

In die Datei /etc/lxc/default.conf wird eingetragen

lxc.idmap = u 0 1000000 65536
lxc.idmap = g 0 1000000 65536

Nun können die Container erstellt werden:

lxc-create -n web -t download
lxc-create -n mail -t download

Mit “-t download” kann man komfortabel vorhandene Images verschiedener Linux-Distributionen auswählen. Ich entschied mich hier erneut in beiden Fällen für Alpine 3.13.

Die Config-Datei des Containers liegt anschließend unter /var/lib/lxc/[Containername]/config. Diese sollte überprüft werden und etwa so aussehen (hier für den Container “web”):

lxc.include = /usr/share/lxc/config/common.conf
lxc.include = /usr/share/lxc/config/userns.conf
lxc.arch = linux64
lxc.idmap = u 0 1000000 65536
lxc.idmap = g 0 1000000 65536
lxc.rootfs.path = dir:/var/lib/lxc/web/rootfs
lxc.uts.name = web
lxc.net.0.type = veth
lxc.net.0.flags = up
lxc.net.0.link = br0

Gestartet werden die Container mit

lxc-start <Containername>

Der Zugriff auf die Container kann vom Host aus mit dem Befehl “lxc-attach” geschehen. Dies erspart dann auch die Installation eines SSH-Servers innerhalb des Containers - und vermeidet so einen weiteren Angriffsvektor.

Umgekehrt sollte auf dem Host jedoch der Zugriff per SSH aus dem Container heraus auf dem Host unterbunden werden. Man kann dies über die Konfiguration des SSH-Dienstes regeln oder aber auch einfach per iptables:

iptables -A INPUT -p tcp --dport 22 --source 192.168.2.6  -j DROP
iptables -A INPUT -p tcp --dport 22 --source 192.168.2.7  -j DROP

Externer vServer

Auf dem VPS läuft ebenfalls Alpine Linux. Hier müssen nun Maßnahmen getroffen werden, um dem VPN-Tunnel vorzubereiten. Aufgrund der Einfachheit habe ich mich für die moderne VPN-Lösung Wireguard entschieden

apk add wireguard-tools wireguard-virt 
cd /etc/wireguard
umask 077; wg genkey | tee privatekey | wg pubkey > publickey

Nun wird noch die Konfiguration /etc/wireguard/wg0.conf für das Wireguard-Interface und zwei Peers (Web und Mailserver) erstellt.

[Interface]
ListenPort = 43210
Address = 172.16.0.1/24
PrivateKey = <private key des Hosts>
PostUp = iptables -A INPUT -i wg0 -j ACCEPT; iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; iptables -F -t nat

[Peer]
PublicKey = <public key web>
AllowedIPs = 172.16.0.2/32
PersistentKeepalive = 25


[Peer]
PublicKey = <public key mail>
AllowedIPs = 172.16.0.3/32
PersistentKeepalive = 25

Die iptables-Regeln in “PostUp” erlauben Forwarding per NAT über wg0, damit die Peers anschließend über den VPS auch ins Internet kommen. PersistentKeepalive ist hier nötig, um den Tunnel offen zu halten.

Web und Mail Container

An dieser Stelle muss der Wireguard-Tunnel auf den beiden Containern eingerichtet werden. Die Installation und die Generierung der Keys läuft exakt so wie auf dem externen vServer. Die Konfigurationsdatei /etc/wireguard/wg0.conf sieht wie folgt aus

[Interface]
PrivateKey =  <private key des Containers>
Address = 172.16.0.2/24               #bzw. 172.16.0.3/24  für "mail"
Table = off
PostUp = ip rule add to 1.2.3.4 lookup main pref 30; ip rule add to 192.168.2.0/24 lookup main pref 31; ip rule add to all lookup 80 pref 40; ip route add default dev wg0 table 80
PostDown = ip rule del to 1.2.3.4 lookup main pref 30; ip rule del to all lookup 80 pref 40; ip rule del to 192.168.2.0/24 lookup main pref 31

[Peer]
PublicKey = <public key des VPS>
Endpoint = 1.2.3.4:43210
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25

Es soll anschließend das Tool wg-quick benutzt werden, welches standardmäßig default-Routen setzt. Da diese Default-Routing-Tabellen nicht ganz passten, habe ich sie deaktiviert (Table=off) und stattdessen mit PostUp eigene Routing-Tabellen angelegt.

Nun muss auf allen Seiten, d.h. auf dem VPS und in den beiden Containern, nur noch Wireguard gestartet werden:

wg-quick up wg0

Damit steht schon mal der Tunnel. Überprüft werden kann dies mit dem Befehl “wg show” und ping auf die IP des jeweiligen Peers.

Services betreiben

Der Tunnel steht, wie kommt bekommt man nun Verbindungen, die zum VPS konnektieren auf die beiden Container? Hier gibt es mehrere Möglichkeiten

In der folgenden Lösung verwende ich Apache als Reverse Proxy für “web” und Port Forwarding für “mail”.

web

Zunächst müssen wir Apache auf dem VPS einrichten. Die Grundkonfiguration inklusive SSL-Zertifikat (von Let’s Encrypt) würde den Rahmen sprengen, daher hier nur der VHost-Abschitt für die im Container gehostete Webseite

<VirtualHost *:443>
        ServerAdmin meine@email.mail
        ServerName meine.coole.site
        SSLEngine On
        SSLProxyEngine On
        SSLCertificateFile /etc/ssl/meine.coole.site.fullchain.pem
        SSLCertificateKeyFile /etc/ssl/private/meine.coole.site.key

        ProxyPass / http://172.16.0.2/
        ProxyPassReverse / http://172.16.0.2/
        
    CustomLog logs/meine.coole.site.log combined
        ErrorLog logs/meine.coole.site-error.log

</VirtualHost>

Apache leitet damit alle ankommenden Pakete, die an https: // meine.coole.site gerichtet sind, an den Webserver im Container “web” mit der URL http: // 172.16.0.2/ weiter. Zwar könnte man auch hier https verwenden, aber der Wireguard-Tunnel sorgt ja bereits für Verschlüsselung, daher habe ich an dieser Stelle darauf verzichtet.

Auf “web” muss dann nur noch ein Webdienst eingerichtet werden, der auf Port 80 hört.

Mail

Für den Mailserver werden auf dem VPS entsprechende Forwarding-Regeln per iptables eingerichtet

# SMTP
iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 25 -j DNAT --to 172.16.0.3:25
# IMAP
iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 143 -j DNAT --to 172.16.0.3:143
# IMAPS
iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 993 -j DNAT --to 172.16.0.3:993 

Wenn weitere Dienste genutzt werden sollen (z.B. POP3) müssen natürlich auch entsprechende Weiterleitungen eingerichtet werden. In dem Container “mail” müssen sodann Dienste für SMTP und IMAP eingerichtet werden, deren Installation und Konfiguration aber hier nicht besprochen wird - das folgt dann in einem späteren Beitrag.

Tags: InternetServer.