Einführung
Manche Dienste will man nur für bestimmte Geräte zugänglich machen. Befindet sich der Server und der Client im selben Layer 2 Netz, ist es einfach die Verbindungen nur für bestimmte MAC-Adressen zuzulassen. Kommt die Verbindung nicht von der konfigurierten MAC-Adresse, wird der Verbindungsaufbau nicht zugelassen und der Dienst ist für dieses Gerät somit nicht verfügbar.
Mein Anwendungsfall: Music Player Daemon (MPD)
Um Musik zu hören verwende ich den Music Player Daemon (MPD). Dieser kann man
über eine einfache TCP Verbindung steuern (im Notfall auch mit telnet
:)). Ich
mag es auch die Musik von meinem Telefon aus mit einem speziellen Client zu
steuern. Jedoch möchte ich nicht allen im Netzwerk Zugriff auf den MPD geben
(Port 6600
). Deshalb lasse ich nur Verbindungen von meinem Mobiltelefon zu,
was ich über die MAC-Adresse des Telefons steuere.
Da ich das conntrack
Modul verwende, ist eine bereits konfigurierte stateful
Firewall eine Voraussetzung.
MAC-Adresse eintragen
Als erstes speichert man die MAC-Adresse in eine Variable, denn diese wird mehrmals verwendet:
PHONE="5C:0A:5B:93:3B:CB"
Logging
Die erste Regel wird für das Logging verwendet, damit ich im Systemlog sehe,
wann sich mein Mobiltelefon verbunden hat. Pro Minute wird einmal geloggt und
dann wird jeweils nur ein Eintrag geschrieben. Das LOG
Target lässt das Paket
weiter durch die Firewall laufen.
iptables -A INPUT -p tcp --dport 6600 -m conntrack --ctstate NEW \
-m mac --mac-source $PHONE -m limit --limit 1/min --limit-burst 1 \
-j LOG --log-prefix "Accept_MPD_IN" -m comment --comment "MPD_Phone"
Der MAC-Adresse den Zugriff erteilen
Bei der zweiten Firewallregel wird das Paket nur akzeptiert, falls die MAC-Adresse dem Telefon entspricht. Ansonsten gilt die Default-Regel der Firewall.
iptables -A INPUT -p tcp --dport 6600 -m conntrack --ctstate NEW \
-m mac --mac-source $PHONE -j ACCEPT -m comment --comment "MPD_Phone"
Testen
So sehen die Einträge im Logfile aus, wenn man sich mit dem MPD verbinden will:
$ sudo journalctl -f
Mar 26 15:18:24 eris kernel: Accept_MPD_ININ=wlp2s0
OUT= MAC=58:94:6b:e9:fd:78:5C:0A:5B:93:3B:CB:08:00 SRC=152.96.234.131
DST=152.96.235.57 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=60908 DF PROTO=TCP
SPT=34662 DPT=6600 WINDOW=14600 RES=0x00 SYN URGP=0
Mar 26 15:22:23 eris kernel: DROP_ININ=wlp2s0
OUT= MAC=58:94:6b:e9:fd:78:5c:23:05:50:42:23:08:00 SRC=152.96.234.235
DST=152.96.235.57 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=16799 DF PROTO=TCP
SPT=47564 DPT=6600 WINDOW=14600 RES=0x00 SYN URGP=0 OPT
(020405B40402080A00E265920000000001030306)
[...]
Die erste Verbindung wurde zugelassen ( Accept_MPD_IN
) und die zweite wurde
zurückgewiesen ( Drop_IN
).
IPv6
Dasselbe funktioniert mit IPv6:
PHONE="5C:0A:5B:93:3B:CB"
ip6tables -A INPUT -p tcp --dport 6600 -m conntrack --ctstate NEW \
-m mac --mac-source $PHONE -m limit --limit 1/min --limit-burst 1 \
-j LOG --log-prefix "Accept_MPD_IN" -m comment --comment "MPD_Phone"
ip6tables -A INPUT -p tcp --dport 6600 -m conntrack --ctstate NEW \
-m mac --mac-source $PHONE -j ACCEPT -m comment --comment "MPD_Phone"
Fazit
Wie man sieht ist dieser Schutzmechanismus sehr schnell implementiert und nützlich, wenn man ein Service (der allenfalls keine Authentifizierung unterstützt) nur für ein bestimmtes Gerät zur Verfügung stellen will. Diese Dienste sind dann bei einem Portscan auch nicht sichtbar und man sieht den verweigerten Zugriff im Logfile.