UDM Pro: Netzwerktrennung - Teil 2

Hinweis vorab: Alle Aussagen in diesem Artikel beziehen sich auf die UnifiOS Version 1.10.0 für die UDM Pro und die Unifi Network in Version 6.2.26. Mit jedem Update sowohl von UnifiOS als auch der Network App kann sich das Netzwerk-Setup und die Firewall-Einstellungen grundlegend ändern.

Da die einzelnen LAN- und Guest-Netzwerke von der Unifi Dream Machine Pro leider nicht konsequent voneinander getrennt werden (siehe Artikel UDM Pro: Netzwerktrennung - Teil 1) muss das Firewall-Regelwerk wohl oder übel etwas angepasst werden, wenn eine Trennung zwischen den einzelnen VLANs umgesetzt werden soll. 

01| Voraussetzungen

Da eine Filterung für IPv6 bei dynamischen Prefix über die GUI aktuell nicht zu realisieren ist (siehe UDM Pro: Netzwerktrennung - Teil 1), muss das Firewall-Regelwerk per Script aktualisiert werden. Es muss also sichergestellt werden, dass das Script beim Boot der Unifi Dream Machine automatisch ausgeführt wird. Dies lässt sich mit dem dem UDM / UDMPro Boot Script von boostchicken realisieren. Daher muss dieses Tool zunächst installiert werden. Die Installationsanleitung findet sich auf der Github-Seite oder in meinem Artikel UDM Pro: NAT auf dem WAN Interface deaktivieren

Aber die Ausführung beim Boot alleine ist nicht ausreichend, da mit jeder Änderung am Firewall-Regelwerk per GUI die alten Regeln gelöscht werden. Daher erzeugt das Script zusätzlich einen Cron-Job, der alle zwei Minuten das Script erneut ausführt, so dass die Regeln wieder eingefügt werden, wenn sie fehlen. 

02| Script installieren und ausführen

Ist sichergestellt, dass das UDM / UDMPro Boot Script von boostchicken korrekt installiert ist und un funktioniert, so muss nur noch das Script 21-separate-vlans.sh von https://github.com/nerdiges/udmp-seperate-vlans im on_boot-Verzeichnis abgelegt und initial ausgeführt werden. Die Installation des SCriptes ist daher mit wenigen Befehlen umgesetzt: 

# 1. download file to directory /mnt/data/on_boot.d
curl -o /mnt/data/on_boot.d/21-separate-vlans.sh https://raw.githubusercontent.com/nerdiges/udmp-seperate-vlans/main/21-separate-vlans.sh

# 2. make script executable
chmod +x /mnt/data/on_boot.d/21-separate-vlans.sh

# 3. run script to add missing firewall rules and to create cron job
/mnt/data/on_boot.d/21-separate-vlans.sh

03| Hinweise zum Script

Das Script 21-separate-vlans.sh enthält einige Kommentare, die die Funktionsweise grundsätzlich erklären. Ergänzend dazu hier noch ein paar Hinweise zum Aufbau des Scriptes:

03.1| Erzeugte iptables Chains

Damit die Firewall-Regeln des Scripts sauber von den internen Regeln getrennt werden legt das Script zwei neue iptables-Chains an:

ChainBeschreibung
lan_separationIn dieser Chain werden die REJECT-Regeln zur Separierung der guest-Netzwerke hinterlegt.
guest_separationIn dieser Chain werden die REJECT-Regeln zur Separierung der guest-Netzwerke hinterlegt.

03.2| Erzeugte Firewall-Regeln

Das Script erzeugt insgesamt fünf unterschiedliche Typen von Firewall-Regeln:

03.1.1| Allow Established & Related

Damit später gezielte Verbindungen zwischen den einzelnen VLANs freigegeben werden können, sollten alle eingehenden Pakete zugelassen werden, die einer bestehenden Verbindung zugeordnet werden können.  Daher sollten alle Pakete mit dem Status Established oder Related an den LAN und Guest Interfaces zugelassen werden. Dies kann entweder manuell in der GUI eingetragen werden oder automatisch vom Script eingefügt werden. Da in der Regel die meisten Pakete einer bereits bestehenden Verbindung zugeordnet werden können, sollten die entsprechenden Regeln möglichst weit vorne im iptables Regelwerk eingetragen werden, um die Firewall-Performance zu verbessern. Mit dem folgenden Code wird daher im Script sichergestellt, dass die Regeln für die LAN-Interfaces in der Standard-Chain UBIOS_LAN_IN_USER an erster Stelle eingetragen werden:

# add allow related/established to UBIOS_LAN_IN_USER if requested
if [ $allow_related_lan == "true" ]; then
    rule="-A UBIOS_LAN_IN_USER -m conntrack --ctstate RELATED,ESTABLISHED.*-j RETURN"
    iptables --list-rules | grep -e "$rule" &> /dev/null ||
        iptables -I UBIOS_LAN_IN_USER 1 -m conntrack --ctstate RELATED,ESTABLISHED -j RETURN
    ip6tables --list-rules | grep -e "$rule" &> /dev/null ||
        ip6tables -I UBIOS_LAN_IN_USER 1 -m conntrack --ctstate RELATED,ESTABLISHED -j RETURN
fi

Hinweis: Ob die Established & Related-Regeln vom Script automatisch erzeugt werden, kann über die Variablen allow_related_lan und allow_related_guest festgelegt werden. Per Default sind diese aktiviert, so dass das Script sicherstellt, dass entsprechende Regeln vorhanden sind. Um doppelte Regeln zu vermeiden, fügt das Script nur dann eine entsprechende Regel ein, wenn nicht bereits über die GUI eine Regel hinzugefügt wurde.

03.1.2| LAN > LAN Reject

Für jedes LAN-Interface werden Regeln erzeugt, die eine Kommunikation zu anderen LAN-Interfaces unterbinden (REJECT-Regeln). Ausgenommen werden allerdings die Interfaces, die in der Variable $exclude aufgelistet sind. Zusammen mit der Regel Allow Established & Related (s.o.) führt das dazu, dass aus diesen Netzwerk-Segmenten auf alle anderen LAN-Netzwerke ungefiltert zugegriffen werden kann. Die entsprechenden Regeln werden in einer For-Schleife automatisch erzeugt:

    # Add rules to separate LAN-VLANs to chain lan_separation
    for i in $lan_if; do
        case "$exclude " in
            *"$i "*)
                logger "$me: Excluding $i from VLAN separation as requested in config."
                ;;

            *)
                for o in $lan_if; do
                    if ! [ "$i" == "$o" ]; then
                        rule="-A lan_separation -i $i -o $o -j REJECT"
                        iptables --list-rules | grep -e "$rule" &> /dev/null || iptables $rule
                        ip6tables --list-rules | grep -e "$rule" &> /dev/null || ip6tables $rule
                    fi
                done
                ;;
        esac
    done

Existieren beispielsweise vier Corporate-Networks mit den VLANs 0-3 und soll die Kommunikation aus VLAN 1 in alle anderen Netzwerke ermöglicht werden, so muss lediglich das zugehörige Interface br1 in der Exclude-Variablen aufgenommen werden (exclude="br1"). Die erzeugten VLAN-Regeln sollten danach so aussehen:

-A lan_separation -i br0 -o br1 -j REJECT --reject-with icmp-port-unreachable
-A lan_separation -i br0 -o br2 -j REJECT --reject-with icmp-port-unreachable
-A lan_separation -i br0 -o br3 -j REJECT --reject-with icmp-port-unreachable
-A lan_separation -i br2 -o br0 -j REJECT --reject-with icmp-port-unreachable
-A lan_separation -i br2 -o br1 -j REJECT --reject-with icmp-port-unreachable
-A lan_separation -i br2 -o br3 -j REJECT --reject-with icmp-port-unreachable
-A lan_separation -i br3 -o br0 -j REJECT --reject-with icmp-port-unreachable
-A lan_separation -i br3 -o br1 -j REJECT --reject-with icmp-port-unreachable
-A lan_separation -i br3 -o br2 -j REJECT --reject-with icmp-port-unreachable

03.1.3| Guest > Guest Reject

Vergleichbar zur Trennung der LAN-Segmente, werden auch die Guest-Netzwerke voneinander getrennt. Diese Regeln werden allerdings in der Chain guest_separation eingetragen. Auch für die Guest-Netzwerke gilt: Wird ein Guest-Interface in die Exclude Liste aufgenommen, so wird es von der Filterung ausgenommen. 

03.1.4| LAN > Guest Reject

Bei der Analyse der Firewall-Regeln im ersten Teil der Artikelserie habe ich festgestellt, dass einzelne Pakete aus dem LAN-Netzwerk in das Guest-Netzwerk gelangen können, da die Standard Firewall-Regeln zwar den Datenverkehr aus dem Guest-Netzwerk in Richtung LAN-Netzwerk blockieren, aber eben nicht umgekehrt. TCP-SYN, UDP oder ICMP-Pakete die aus dem LAN-Netzwerk in Richtung Guest gesendet werden, kommen jedoch durch. Um das zu verhindern werden entsprechende REJECT-Regeln in der Chain lan_separation hinterlegt: 

# add rules to fix packet leakage from LAN > guest
for i in $lan_if; do
    for o in $guest_if; do
        rule="-A lan_separation -i $i -o $o -j REJECT"
        iptables --list-rules | grep -e "$rule" &> /dev/null || iptables $rule
        ip6tables --list-rules | grep -e "$rule" &> /dev/null || ip6tables $rule
    done
done

03.1.5| Regeln zur Einbindung der Custom-Chains

Nachdem die Firewall-Regeln zur VLAN-Trennung in den Chains lan_spearation und guest_separation eingefügt wurden, werden entsprechende JUMP-Regeln in die Chains UBIOS_LAN_IN_USER und UBIOS_GUEST_IN_USER eingefügt. Dabei wird vom Script automatisch die richtige Position für die JUMP-Regeln ermittelt, so dass die Regeln direkt  vor den jeweiligen ALLOW-Regeln des Standard-Regelwerks eingefügt werden. Für die IPv4-Regeln zur LAN-Trennung sieht das im Script so aus:

    # add IPv4 rule to include rules in chain lan_separation
    if ! iptables --list-rules | grep -e "-A UBIOS_LAN_IN_USER -j lan_separation" &> /dev/null; then
        rules=$(iptables -L UBIOS_LAN_IN_USER --line-numbers | awk 'END { print $1 }')
        v4_idx=$(expr $rules - $lan_if_count)
        iptables -I UBIOS_LAN_IN_USER $v4_idx -j lan_separation
    fi

03.3| Keine Kommentare für Firewall-Regeln

Auf der UDM Pro werden die Kommentare der Firewall-Regeln für die Verwaltung genutzt und scheinbar mit einer internen Datenbank abgeglichen. Alle Regeln, die einen unbekannten Kommentar enthalten (iptablesParamter -m comment) werden in /var/log/messages im Sekundentakt Warnmeldungen ausgegeben:

Aug  1 00:19:41 udmp user.notice ubios-udapi-server: ubios-udapi-server: Found unexpected rule --comment '0815'
Aug  1 00:19:42 udmp user.notice ubios-udapi-server: ubios-udapi-server: Found unexpected rule --comment '0815'
Aug  1 00:19:43 udmp user.notice ubios-udapi-server: ubios-udapi-server: Found unexpected rule --comment '0815'
Aug  1 00:19:44 udmp user.notice ubios-udapi-server: ubios-udapi-server: Found unexpected rule --comment '0815'
Aug  1 00:19:46 udmp user.notice ubios-udapi-server: ubios-udapi-server: Found unexpected rule --comment '0815'
Aug  1 00:19:47 udmp user.notice ubios-udapi-server: ubios-udapi-server: Found unexpected rule --comment '0815'
Aug  1 00:19:47 udmp user.notice ubios-udapi-server: ubios-udapi-server: Found unexpected rule --comment '0815'
Aug  1 00:19:49 udmp user.notice ubios-udapi-server: ubios-udapi-server: Found unexpected rule --comment '0815'
Aug  1 00:19:50 udmp user.notice ubios-udapi-server: ubios-udapi-server: Found unexpected rule --comment '0815'

Das führt dazu, dass das Syslog sehr schnell sehr umfangreich wird. Um das zu vermeiden sollte sichergestellt werden, dass alle Firewall-Regeln, die per Script oder manuell per Kommandozeile manuell hinzugefügt werden keinen Kommentar beinhalten.

04| Separierung dauerhaft sicherstellen

Da das Script und der on_boot-Mechanismus von Unifi offiziell nicht unterstützt werden, besteht mit jedem Firmware-Update das Risiko, dass das Script nach einem Update nicht mehr korrekt funktioniert. Das kann dazu führen, dass nach einem Update die Regeln nicht mehr greifen. Im schlimmsten Falle wird die VLAN-Separierung dann unbemerkt wieder aufgehoben und es kann wieder frei zwischen den VLANs kommuniziert werden. Um das zu unterbinden, verschiedenen Maßnahmen ergriffen werden: 

04.1| Ergänzende Firewall-Regeln über die GUI

Die vom Script erzeugten Regeln sollten, so weit möglich, auch in der GUI konfiguriert werden. Zumindest für den IPv4-Datenverkehr kann dies beispielsweise einfach über die jeweiligen IP-Adressbereiche der unterschiedlichen VLANs erfolgen. Werden die Firewall-Regeln vom Script nach einem Update nicht mehr korrekt gesetzt, so wird wenigstens für IPv4 die Trennung weiterhin aufrecht erhalten. Wie aber bereits im ersten Teil beschrieben ist das bei dynamischen IPv6-Prefixen für den IPv6-basierten Datenverkehr leider aktuell nicht möglich.

04.2| Monitoring der Filterung

Ist eine Hausautomatisierung im Einsatz, so kann auch durch VLAN-übergreifende Netzwerktest z.B. per ping oder nmap (siehe [04]) regelmäßig überprüft werden, ob die VLAN-Trennung noch aktiv ist. Sind bei einem solchen Test interne Systeme erreichbar, obwohl die Kommunikationsbeziehung nicht explizit freigegeben ist, dann könnte beispielsweise eine Alarmierung per Mail erfolgen.

05| Quelle:

[01] UDM Pro: Netzwerktrennung - Teil 1
[02] https://github.com/nerdiges/udmp-seperate-vlans
[03] UDM / UDMPro Boot Script von boostchicken
[04] https://nmap.org/ 
[05] 

Kommentare

PostadresseE-MailadresseFestnetzMobiltelefonSMS/SignalThreemaTwitter DirektnachrichtFAXWeb Page