ein Blog

Guest-WiFi AirPlay

Man möchte ja in der heutigen Zeit seinen Gästen WiFi anbieten. Man möchte sie aber nicht unbedingt ins eigene Netzwerk lassen. Da bietet sich ja ein Gast-Netz an.

Die meisten Accesspoints können das inzwischen. Wir haben uns vor einer Weile für die UniFi Accesspoints entschieden. Die kann man im UniFi Controller ganz leicht eine eigene SSID in ein VLAN stecken lassen:

Jetzt hat man aber vielleicht das ein oder andere AirPlay Gerät das man seinen Gästen doch zur verfügung stellen möchte. Und genau das habe ich die letzten Tage zusammengebastelt.

Wenn man einen Linux-Basierten Router hat auf dem man sachen Installieren möchte, lässt sich das etwas leichter lösen aber wir wollten die ganze Magie in einer kleinen VM haben.

Teil 1 ist relativ einfach. Man installiert das Paket avahi-daemon und aktiviert die "Reflector" Option in /etc/avahi/avahi-daemon.conf:

[reflector]
enable-reflector=yes
reflect-ipv=no

reflect-ipv ist standardmäßig aus und so wie ich die Dokumentation verstanden habe, will man das normalerweise auch aus lassen. Das spiegelt sonst Bonjour-Announcements zwischen IPv4 und IPv6 hin und her. Wenn man jetzt ein IPv6-only Netz hat, ist das vielleicht nochmal ne andere sache, aber wenn du das hast, brauchst du vermutlich diese Anleitung nicht ;)

Teil 2 ist etwas fummeliger. Wir müssen natürlich die kommunikation aus dem Gast-Netzwerk zu den AirPlay Geräten erlauben, gleichzeitig soll aber natürlich anderer kram nicht erlaubt sein. Weil wir eigentlich alle Geräte mit DHCP adressieren und sich die Adressen auch mal ändern können, ist es unsinnig dafür IP-Basierte Firewall-Regeln zu verwenden.

Lösung ist das Tool ebtables. Das arbeitet schon auf Layer 2 und kann (besser) mit MAC-Adressen umgehen (als iptables). Damit ebtables funktioniert braucht es allerdings eine Bridge. In unserem aktuellen Setup reicht eine bridge an der nur das Interface in unser Netz hängt. Mehr dazu später.

Wir können jetzt mit ebtables den Traffic der die bridge verlassen möchte und

wir möchten ja weiterhin aus unserem netz z. B. per SSH auf die VM kommen.

APDEVICES="b8:27:eb:**:**:** b8:27:eb:**:**:** b8:27:eb:**:**:**"
INTDEV="ens3"
GUESTNET="10.0.6.0/24"

# (1)
for dev in $APDEVICES; do
    ebtables -A OUTPUT -o $INTDEV -d $dev -j ACCEPT
done

#(2)
ebtables -A OUTPUT -o $INTDEV -p IPv4 --ip-src $GUESTNET -j DROP

Jetzt noch etwas iptables Spaß:

INTBR="br0"
GUESTDEV="ens10"

iptables -P INPUT DROP
iptables -P FORWARD DROP

# das übliche
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

# Multicast nur von erlaubten geräten zulassen (damit nicht noch die restlichen bonjour-announcements von anderen geräten gespiegelt werden)
# INPUT und nicht FORWARD weil die sachen ja von avahi-daemon empfangen und dann auf dem anderen interface gespiegelt werden
for dev in $APDEVICES; do
    iptables -A INPUT -d 224.0.0.0/8 -i $INTBR -m mac --mac-source $dev -j ACCEPT
done
iptables -A INPUT -d 224.0.0.0/8 -i $INTBR -j DROP

# DHCP und DNS Requests erlauben ist vielleicht eine ganz gute Idee
iptables -A INPUT -i $GUESTDEV -p udp --dport 67:68 --sport 67:68 -j ACCEPT
iptables -A INPUT -i $GUESTDEV -p udp --dport 53 -j ACCEPT
iptables -A INPUT -i $GUESTDEV -d 224.0.0.0/8 -j ACCEPT

# pakete aus dem internen netz sollen ja auch wieder zurück dürfen
iptables -A FORWARD -i $INTBR -o $GUESTDEV -m state --state RELATED,ESTABLISHED -j ACCEPT

# AirPrint
iptables -A FORWARD -i $GUESTDEV -o $INTBR -m tcp -p tcp --dport 631 -j ACCEPT
# AirPlay
iptables -A FORWARD -i $GUESTDEV -o $INTBR -m tcp -p tcp --dport 5000:5100 -j ACCEPT
iptables -A FORWARD -i $GUESTDEV -o $INTBR -m udp -p udp --dport 6000:6100 -j ACCEPT
iptables -A FORWARD -i $GUESTDEV -o $INTBR -m tcp -p tcp --dport 7000:7100 -j ACCEPT
# AppleTV Status Magic
iptables -A FORWARD -i $GUESTDEV -o $INTBR -m tcp -p tcp --dport 49152:65535 -j ACCEPT

jetzt noch eine Route ins Gast-netz auf dem Standard-Gateway hinterlegen und fertig:

route add -net $GUESTNET gw 10.0.0.42

und das wars dann eigentlich auch schon. Ich möchte nämlich eigentlich die pakete in beide Richtungen filtern. Das geht aber momentan noch nicht weil die Quell-MAC nicht die der AirPlay Geräte sind sondern natürlich die des Routers ist.

Dafür lasse ich im DHCP Server für unser internes Netz die statische route ins Gast-Netz verteilen:

option rfc3442-classless-static-routes code 121 = array of integer 8;
option ms-classless-static-routes code 249 = array of integer 8;

subnet 10.0.0.0 netmask 255.255.255.0 {
    ...
    option rfc3442-classless-static-routes 24, 10,0,6, 10,0,0,42, 0, 10,97,0,1;
    option ms-classless-static-routes      24, 10,0,6, 10,0,0,42, 0, 10,97,0,1;
}

Jetzt kann ich auch mit ebtables die quell-MAC prüfen:

for dev in $APDEVICES; do
        ebtables -A OUTPUT -o $INTDEV -d $dev -j ACCEPT
        ebtables -A INPUT  -i $INTDEV -s $dev -j ACCEPT
done

ebtables -A OUTPUT -o $INTDEV -p IPv4 --ip-src $GUESTNET -j DROP
ebtables -A INPUT -i $INTDEV -p IPv4 --ip-dst $GUESTNET -j DROP

...und natürlich die statische route aus dem router wieder entfernen.

das komplette Firewall-script gibts hier.

(ich habe es als shell script geschrieben damit ich schleifen und variablen benutzen kann. beim systemstart wird es natürlich mit netfilter-persistent geladen.) (ich habe dafür auch ein netfilter-persistent plugin geschrieben. hier)