Rocky fw firewalld
Version vom 7. Juli 2026, 03:42 Uhr von Thomas.will (Diskussion | Beiträge) (→Rich Rule wieder raus)
Die Firewall
Ziel
Die Firewall trennt drei Netzbereiche voneinander: das Schulungsnetz (WAN), die DMZ und das interne LAN. Sie übernimmt gleichzeitig die Aufgaben eines Routers, eines DHCP-Servers für das LAN und kontrolliert den gesamten Netzverkehr zwischen den Zonen.
Die firewalld-Zonen heißen in diesem Setup bewusst genauso wie ihre Aufgabe: wan, dmz und lan. Das macht die Konfiguration selbsterklärend – jede Policy und jede Regel lässt sich direkt einer Netzzone zuordnen.
Plan
| Interface | Zone | Wert | Erläuterung |
|---|---|---|---|
| enp0s3 | wan | 192.168.HS.2XX/24 | Bridge Adapter: br0 |
| GW | 10.88.2XX.1 | GATEWAY | |
| NS | 192.168.HS.88 | Resolver | |
| enp0s8 | dmz | 10.88.2XX.1/24 | Internal Network: DMZ |
| enp0s9 | lan | 172.26.2XX.1/24 | Internal Network: LAN |
| GW | 192.168.HS.254 | GATEWAY | |
| FQDN | fw.it2XX.int | Fully Qualified Domain Name | |
| SHORT | fw | Short Name | |
| DOM | it2XX.int | Domain Name | |
| ROUTE | 10.88.0.0/16 | 192.168.HS.88 |
Dienste auf der Firewall
- firewalld
- Zonenverwaltung, Paketfilterung, Masquerading
- Kea DHCP4
- IP-Vergabe für das LAN (172.26.2XX.0/24)
Regelwerk
| Von | Nach | Erlaubt | Gesperrt |
|---|---|---|---|
| lan | wan | alles | — |
| lan | dmz | alles (SSH für Ansible, DNS, HTTP ...) | — |
| dmz | wan | alles | — |
| wan | dmz | UDP+TCP/53 nur auf ns, TCP/80+443 nur auf http | alles andere |
| wan | lan | — | alles |
| dmz | lan | — | alles |
- lan ist vertrauenswürdig
- Aus dem internen Netz darf alles raus – sowohl ins WAN als auch in die DMZ. So kann Ansible von client.it2XX.int per SSH alle DMZ-Maschinen erreichen.
- wan → dmz gezielt
- Aus dem Internet kommen nur die Dienste rein, die wirklich öffentlich sein sollen – und nur auf die jeweilige Ziel-IP. Dafür werden Rich Rules verwendet.
- dmz → lan gesperrt
- LDAP liegt jetzt in der DMZ – kein Grund mehr für Verbindungen aus der DMZ ins LAN.
Umsetzung
Netzwerkkonfiguration
Hostname setzen
- hostnamectl set-hostname fw.it2XX.int
enp0s3 (WAN)
- Die WAN-Verbindung bekommt eine feste IP. Da die Connection bereits existiert, wird sie per mod angepasst.
- nmcli con mod enp0s3 ipv4.method manual ipv4.addresses 192.168.HS.2XX/24 ipv4.gateway 192.168.HS.254 ipv4.dns 192.168.HS.88
- nmcli con mod enp0s3 +ipv4.routes "10.88.0.0/16 192.168.HS.88"
- nmcli con up enp0s3
Tabula Rasa
- Rocky legt für neue Interfaces automatisch Connections mit generischen Namen an – diese werden gelöscht
- nmcli con delete "Wired connection 1"
- nmcli con delete "Wired connection 2"
enp0s8 (DMZ)
- Neue Connection mit explizitem Namen – kein Gateway, kein DNS nötig
- nmcli con add type ethernet ifname enp0s8 con-name enp0s8 ipv4.method manual ipv4.addresses 10.88.2XX.1/24
- nmcli con up enp0s8
enp0s9 (LAN)
- Das LAN-Interface wird Gateway für alle internen Clients
- nmcli con add type ethernet ifname enp0s9 con-name enp0s9 ipv4.method manual ipv4.addresses 172.26.2XX.1/24
- nmcli con up enp0s9
IP-Forwarding aktivieren
- Ohne IP-Forwarding leitet der Kernel keine Pakete zwischen den Interfaces weiter – die Firewall wäre kein Router
- echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/99-forwarding.conf
- sysctl -p /etc/sysctl.d/99-forwarding.conf
firewalld
Installation und Start
- firewalld ist auf Rocky meist vorinstalliert, zur Sicherheit
- dnf install -y firewalld
- systemctl enable --now firewalld
Eigene Zonen anlegen
- Wir wollen sprechende Zonennamen, die zu den Interfaces passen. dmz bringt firewalld bereits mit – wan und lan gibt es nicht von Haus aus und werden neu angelegt.
- firewall-cmd --permanent --new-zone=wan
- firewall-cmd --permanent --new-zone=lan
- firewall-cmd --reload
- Warum nicht external/internal? firewalld liefert fertige Zonen mit, die schon Vorbelegungen mitbringen
-
- external – Masquerading bereits eingebaut, ssh eingehend erlaubt
- internal – ssh, mdns, samba-client und dhcpv6-client erlaubt
- dmz – ssh erlaubt
- Selbstgebaute Zonen starten dagegen komplett leer (Target default, keine Dienste). Das ist hier sogar sauberer
-
- Das Masquerading machen wir ohnehin in den Policies (siehe unten), nicht über die Zone – das funktioniert mit wan genauso.
- Leer heißt: nichts ist implizit erlaubt. Jede Freigabe steht explizit in diesem Artikel. Das passt zur Tabula-rasa-Philosophie.
- Ein Punkt ist wichtig
- Weil lan leer startet, ist SSH zur Firewall selbst aus dem LAN zunächst gesperrt (bei internal wäre es offen gewesen). Da wir die Firewall übers LAN administrieren, schalten wir SSH dort gleich gezielt frei (siehe nächster Abschnitt). Auf wan bleibt SSH bewusst zu.
Interfaces den Zonen zuweisen
- Die Zonenzuordnung wird im NetworkManager-Connection-Profil gespeichert und nach jeder Aktivierung an firewalld gemeldet – so bleibt sie nach einem Reboot erhalten. Prüfen mit
- nmcli -f connection.zone con show enp0s9
- nmcli con mod enp0s3 connection.zone wan
- nmcli con mod enp0s8 connection.zone dmz
- nmcli con mod enp0s9 connection.zone lan
- nmcli con up enp0s3
- nmcli con up enp0s8
- nmcli con up enp0s9
SSH zur Firewall aus dem LAN erlauben
- Die lan-Zone ist leer, deshalb muss der administrative SSH-Zugang zur Firewall explizit freigegeben werden – sonst sperrt man sich beim nächsten Reboot selbst aus
- firewall-cmd --permanent --zone=lan --add-service=ssh
- firewall-cmd --reload
SSH zur Firewall aus dem WAN für unseren Host erlauben
- Wir wollen den administrative SSH-Zugang zur Firewall explizit vom Host freigegeben
- firewall-cmd --permanent --zone=wan --add-rich-rule='rule family="ipv4" source address="192.168.HS.TN" service name="ssh" accept'
- firewall-cmd --reload
Policies für inter-zone Forwarding
- In modernem firewalld regeln Policies den Verkehr zwischen Zonen – nicht die Zonen selbst. Ohne Policy wird Forwarding zwischen Zonen standardmäßig geblockt.
- lan → wan
- Clients kommen ins Internet, Masquerading ersetzt die private Quell-IP
- firewall-cmd --permanent --new-policy lan-to-wan
- firewall-cmd --permanent --policy lan-to-wan --add-ingress-zone lan
- firewall-cmd --permanent --policy lan-to-wan --add-egress-zone wan
- firewall-cmd --permanent --policy lan-to-wan --set-target ACCEPT
- firewall-cmd --permanent --policy lan-to-wan --add-masquerade
- dmz → wan
- DMZ-Server kommen ins Internet, ebenfalls mit Masquerading
- firewall-cmd --permanent --new-policy dmz-to-wan
- firewall-cmd --permanent --policy dmz-to-wan --add-ingress-zone dmz
- firewall-cmd --permanent --policy dmz-to-wan --add-egress-zone wan
- firewall-cmd --permanent --policy dmz-to-wan --set-target ACCEPT
- firewall-cmd --permanent --policy dmz-to-wan --add-masquerade
- lan → dmz
- Ansible und andere interne Zugriffe auf DMZ-Server
- firewall-cmd --permanent --new-policy lan-to-dmz
- firewall-cmd --permanent --policy lan-to-dmz --add-ingress-zone lan
- firewall-cmd --permanent --policy lan-to-dmz --add-egress-zone dmz
- firewall-cmd --permanent --policy lan-to-dmz --set-target ACCEPT
- wan → dmz
- Default DROP, nur explizite Rich-Rules lassen Verkehr durch
- firewall-cmd --permanent --new-policy wan-to-dmz
- firewall-cmd --permanent --policy wan-to-dmz --add-ingress-zone wan
- firewall-cmd --permanent --policy wan-to-dmz --add-egress-zone dmz
- firewall-cmd --permanent --policy wan-to-dmz --set-target DROP
- DNS auf ns.it2XX.int (10.88.2XX.21)
- firewall-cmd --permanent --policy wan-to-dmz --add-rich-rule='rule family="ipv4" destination address="10.88.2XX.21" service name="dns" accept'
- HTTP und HTTPS auf www.it2XX.int (10.88.2XX.11)
- firewall-cmd --permanent --policy wan-to-dmz --add-rich-rule='rule family="ipv4" destination address="10.88.2XX.11" service name="http" accept'
- firewall-cmd --permanent --policy wan-to-dmz --add-rich-rule='rule family="ipv4" destination address="10.88.2XX.11" service name="https" accept'
- HTTP und HTTPS auf container.it2XX.int (10.88.2XX.39)
- firewall-cmd --permanent --policy wan-to-dmz --add-rich-rule='rule family="ipv4" destination address="10.88.2XX.39" service name="http" accept'
- firewall-cmd --permanent --policy wan-to-dmz --add-rich-rule='rule family="ipv4" destination address="10.88.2XX.39" service name="https" accept'
ICMP überall erlauben
- Ping wird in allen Zonen und Policies freigeschaltet – erleichtert die Fehlersuche im Labor
- firewall-cmd --permanent --zone=wan --add-protocol=icmp
- firewall-cmd --permanent --zone=dmz --add-protocol=icmp
- firewall-cmd --permanent --zone=lan --add-protocol=icmp
- firewall-cmd --permanent --policy lan-to-wan --add-protocol=icmp
- firewall-cmd --permanent --policy dmz-to-wan --add-protocol=icmp
- firewall-cmd --permanent --policy lan-to-dmz --add-protocol=icmp
- firewall-cmd --permanent --policy wan-to-dmz --add-protocol=icmp
Konfiguration laden
- firewall-cmd --reload
Kontrolle
- firewall-cmd --get-zones
block dmz drop external home internal lan nm-shared public trusted wan work
- firewall-cmd --get-active-zones
dmz interfaces: enp0s8 lan interfaces: enp0s9 wan interfaces: enp0s3
- firewall-cmd --list-all --zone=wan
wan (active) target: default icmp-block-inversion: no interfaces: enp0s3 sources: services: ports: protocols: icmp forward: no masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: rule family="ipv4" source address="192.168.16.13" service name="ssh" accept
- firewall-cmd --list-all --zone=dmz
dmz (active) target: default icmp-block-inversion: no interfaces: enp0s8 sources: services: ssh ports: protocols: icmp forward: yes masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:
- firewall-cmd --list-all --zone=lan
lan (active) target: default icmp-block-inversion: no interfaces: enp0s9 sources: services: ssh ports: protocols: icmp forward: no masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:
- firewall-cmd --info-policy lan-to-wan
lan-to-wan (active) priority: -1 target: ACCEPT ingress-zones: lan egress-zones: wan services: ports: protocols: icmp masquerade: yes forward-ports: source-ports: icmp-blocks: rich rules:
- firewall-cmd --info-policy dmz-to-wan
dmz-to-wan (active) priority: -1 target: ACCEPT ingress-zones: dmz egress-zones: wan services: ports: protocols: icmp masquerade: yes forward-ports: source-ports: icmp-blocks: rich rules:
- firewall-cmd --info-policy lan-to-dmz
lan-to-dmz (active) priority: -1 target: ACCEPT ingress-zones: lan egress-zones: dmz services: ports: protocols: icmp masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:
Rich Rule wieder raus (Beispiel)
- firewall-cmd --permanent --zone=dmz --remove-rich-rule='rule family="ipv4" destination address="10.88.2XX.39" service name="https" accept'
Kea DHCP4 für das LAN
Installation
- dnf install -y kea
Konfiguration
- Kea lauscht nur auf enp0s9 (LAN) und verteilt IPs im Bereich .100–.200.
- vim /etc/kea/kea-dhcp4.conf
{
"Dhcp4": {
"interfaces-config": {
"interfaces": [ "enp0s9" ]
},
"lease-database": {
"type": "memfile",
"persist": true,
"name": "/var/lib/kea/kea-leases4.csv"
},
"valid-lifetime": 3600,
"subnet4": [
{
"id": 1,
"subnet": "172.26.2XX.0/24",
"pools": [ { "pool": "172.26.2XX.100 - 172.26.2XX.200" } ],
"option-data": [
{ "name": "routers", "data": "172.26.2XX.1" },
{ "name": "domain-name-servers", "data": "10.88.2XX.21" },
{ "name": "domain-name", "data": "it2XX.int" }
]
}
]
}
}
Start
- systemctl enable --now kea-dhcp4
Kontrolle
- ss -lnup | grep 67
- systemctl status kea-dhcp4
- journalctl -fu kea-dhcp4
- cat /var/lib/kea/kea-leases4.csv