Nftables Host absichern: Unterschied zwischen den Versionen

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen
 
(150 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
=Standard=
 
*Bei einem frisch installierten Debian oder Ubuntu System sieht die Konfiguration so aus
 
*Diese stellt ein Zustand da, der an iptables erinnert.
 
*Wir haben die filter Tabelle und 3 Ketten: INPUT OUTPUT und FORWARD.
 
*Wenn wir die Konfiguration laden wird impliziet die Default Policy accept gesetzt.
 
  
=Datei=
+
=Die ersten wirklichen Regeln die etwas bewirken=
*cat /etc/nftables.conf
+
*Momentan wollen wir nur den Host absichern.
<pre>
+
*Darum können wir die '''forward''' Kette erstmal aussen vor lassen.
#!/usr/sbin/nft -f
+
*Wir beziehen uns also nur auf den Host selbst.
 +
*Wir wollen nun folgendes tun:
 +
*<span style="color:#202FF0">Der Rechner soll mit sich selbst über das Loopback Interface kommunizieren können.</span>
 +
*<span style="color:#004334">Vom Rechner selbst nach aussen soll alles zugelassen werden </span>
 +
*<span style="color:#8a2be2">Auf den Rechner soll per "ssh" zugegriffen werden können.</span>
  
flush ruleset
+
=Die erste sinnvolle Konfiguration=
 +
{{nftabels-var1
 +
| kit = 172.22.0.0/16
 +
}}
 +
# Alte Regeln löschen (flush)
 +
flush ruleset
  
table inet filter {
+
  table inet filter {
        chain input {
+
        chain input {
                type filter hook input priority 0;
+
                type filter hook input priority filter; policy drop;
        }
+
                ct state established,related accept
        chain forward {
+
                <span style="color:#8a2be2">ct state new iif "lo" accept</span>
                type filter hook forward priority 0;
+
                <span style="color:#8a2be2">ct state new tcp dport 22 accept</span>  
        }
+
   
        chain output {
+
        }
                type filter hook output priority 0;
+
     
        }
 
}
 
 
 
</pre>
 
 
 
=Laden der Konfigurationsdatei=
 
*nft -f /etc/nftables.conf
 
 
 
= Syntax Allgemein =
 
 
 
Die momentan in der '''inet''' Familie vorhandenen Tabellen sieht man mit:
 
 
 
  nft list tables '''inet'''
 
Die momentan in der '''filter''' Tabelle aus der '''inet''' Familie gestetzen Ketten und Regeln sieht man mit:
 
 
 
nft list table '''inet''' '''filter'''
 
Der einzige Defaultwert hier ist die Familie '''ip''', was nur IPv4 Verkehr sieht. Im Gegensatz dazu sieht '''inet''' sowohl IPv4 als auch IPv6.
 
 
 
<span id="firewall-skripte"></span>
 
 
 
=Setzen der Default Policy=
 
<span style="color:#000FF0">table inet filter</span> {  
 
<span style="color:#F00FF0">chain INPUT</span> {
 
type <span style="color:#F00F0F">filter</span> hook <span style="color:#FF5F9F">input</span>  priority filter; policy drop;
 
}
 
        <span style="color:#F00FF0">chain OUTPUT</span> {
 
type <span style="color:#F00F0F">filter</span>  hook <span style="color:#FF5F9F">output</span>  priority filter; policy drop;
 
}
 
        <span style="color:#F00FF0">chain FORWARD</span>{
 
type <span style="color:#F00F0F">filter</span>  hook <span style="color:#FF5F9F">forward</span>  priority filter; policy drop;
 
}
 
}
 
 
 
=Firewall-Skripte=
 
*Bei Nftables wird empfohlen die keine eigenen Bashskripte für die Firewall zu schreiben.
 
*Stattdessen sollte man Konfigurationsdateien nutzen.
 
*Diese sind übersichtlicher und man kann eine laufende Konfiguration direkt dumpen.
 
==Eklärung==
 
;<span style="color:#000FF0">table inet filter</span> - Es handelt sich um eine Tabelle mit dem Namen filter, dies ist von Typ inet was ipv4 und ipv6 einschliesst.
 
;<span style="color:#F00FF0">chain INPUT</span> - Die Kette INPUT ist vom Type filter und hängt an der input hook und hat die Standard Priorität filter
 
;<span style="color:#F00FF0">chain OUTPUT</span> - Die Kette INPUT ist vom Type filter und hängt an der input hook und hat die Standard Priorität filter
 
;<span style="color:#F00FF0">chain FORWARD</span> - Die Kette INPUT ist vom Type filter und hängt an der input hook und hat die Standard Priorität filter
 
*Diese Zeilten stellen den Zustand her der bei iptables normal ist.
 
*Es wird mit den Tabellen input,output und forward gearbeitet.
 
;type filter hook input priority filter;
 
;type filter hook output  priority filter;
 
;type filter hook forward  priority filter;
 
*Wir lehnen alle Pakete die nicht matchen ab.
 
;policy drop - Die Default policy drop bedeutet ablehnen
 
 
 
= '''established''' und '''related''' Pakekte (Connection Tracking) =
 
*Eine Verbindungen den Status '''established''', nachdem das erste Paket erlaubt wird.
 
*Dafür schaut es, ob ein Paket mit Status '''new''', die Bedingungen für die Annahme erfüllt.
 
*'''related''' Pakete stehen in Beziehung zu einer '''established''' Verbindung, beispielsweise ICMP Nachrichten.
 
*Die Idee ist nun alle '''established''' und '''related''' Pakekte freizuschalten und nur zu entscheiden.
 
*Wir schalten nur frei ob eine Verbindung überhaupt aufgebaut werden darf.
 
=Hinzufügen der established und related Regeln=
 
<span style="color:#000FF0">table inet filter</span> {
 
<span style="color:#F00FF0">chain INPUT</span> {
 
type <span style="color:#F00F0F">filter</span> hook <span style="color:#FF5F9F">input</span>  priority filter; policy drop;
 
<span style="color:#F00F00">ct state established,related accept</span>
 
}
 
                <span style="color:#F00FF0">chain OUTPUT</span> {
 
type <span style="color:#F00F0F">filter</span>  hook <span style="color:#FF5F9F">output</span>  priority filter; policy drop;
 
<span style="color:#F00F00">ct state established,related accept</span>
 
}
 
                <span style="color:#F00FF0">chain FORWARD</span>{
 
type <span style="color:#F00F0F">filter</span>  hook <span style="color:#FF5F9F">forward</span>  priority filter; policy drop;
 
<span style="color:#F00F00">ct state established,related accept</span>
 
        }
 
}
 
 
 
=Minimal Skript einer Firwall=
 
<span style="color:#000FF0">table inet filter</span> {
 
<span style="color:#F00FF0">chain INPUT</span> {
 
type <span style="color:#F00F0F">filter</span> hook <span style="color:#FF5F9F">input</span>  priority filter; policy drop;
 
<span style="color:#F00F00">ct state established,related accept</span>
 
iifname "lo" ct state accept
 
tcp dport 22 ct state accept
 
}
 
 
 
<span style="color:#F00FF0">chain OUTPUT</span> {
 
type <span style="color:#F00F0F">filter</span> hook <span style="color:#FF5F9F">output</span>  priority filter; policy drop;
 
<span style="color:#F00F00">ct state established,related accept</span>
 
ct state new accept
 
}
 
 
   
 
   
<span style="color:#F00FF0">chain FORWARD</span>{
+
        chain output {
type <span style="color:#F00F0F">filter</span>  hook <span style="color:#FF5F9F">forward</span>  priority filter; policy drop;
+
                type filter hook output priority filter; policy drop;
<span style="color:#F00F00">ct state established,related accept</span>
+
                ct state established,related accept
}
+
                <span style="color:#004334">ct state new accept</span>
 +
          }
 
  }
 
  }
 +
{{vorlage:nat2}}
 +
==Aktivieren und Kontrolliere==
 +
;Aktivieren
 +
*nft -f /etc/nftables.conf
 +
;Kontrollieren
 +
*nft list ruleset
  
Dies wird folgendermaßen umgesetzt:
+
=Wir schalten ping frei=
 
+
{{nftabels-var1
$ vi '''fw.nft'''
+
| kit = 172.22.0.0/16
+
}}
---
+
  # Alte Regeln löschen (flush)
+
  flush ruleset
#!/usr/sbin/nft -f
 
add table inet filter
 
add chain inet filter INPUT { type filter hook input priority filter; policy drop; }
 
add chain inet filter OUTPUT { type filter hook output priority filter; policy drop; }
 
add chain inet filter FORWARD { type filter hook forward priority filter; policy drop; }
 
 
  # Basic rules for communication with established connections
 
'''add rule inet filter INPUT ct state established,related accept'''
 
'''add rule inet filter FORWARD ct state established,related accept'''
 
'''add rule inet filter OUTPUT ct state established,related accept'''
 
Neu verwendete Syntax:
 
 
 
* Hänge Regeln an die Kette an
 
add rule ''familiy'' ''table'' ''chain_name'' ''<conditions>'' ''target''
 
* Interface des einkommenden Paketes
 
 
 
iifname ''device name''
 
* Überprüfen auf bestimmte Zustände des Paketes
 
 
 
  ct state ''<states>''
 
== Erste zutreffende Regeln ==
 
 
 
Im jetztigen Zustand wird das erste Paket immer abgelehnt und das Gerät könnte nichtmal mit sich selbst kommunizieren. Auch nach und von außen wird jede Verbindung abgelehnt, was auch eine bestehende SSH-Verbindung bei Aktivierung der Firewall unterbrechen würde. Damit das nicht passiert müssen folgende Regeln hinzugefügt werden:
 
  
$ vi '''fw.nft'''
 
 
---
 
 
#!/usr/sbin/nft -f
 
add table inet filter
 
add chain inet filter INPUT { type filter hook input priority filter; policy drop; }
 
add chain inet filter OUTPUT { type filter hook output priority filter; policy drop; }
 
add chain inet filter FORWARD { type filter hook forward priority filter; policy drop; }
 
 
# Basic rules for communication with itself and established connections
 
add rule inet filter INPUT ct state established,related accept
 
add rule inet filter FORWARD ct state established,related,'''new''' accept
 
add rule inet filter OUTPUT ct state established,related accept
 
'''add rule inet filter INPUT iifname lo ct state new accept'''
 
 
# Enable SSH to firewall
 
'''add rule inet filter INPUT ct state new tcp dport 22 accept'''
 
<span id="status-nach-firewall-start-1"></span>
 
== Status nach '''firewall start''' ==
 
 
$ firewall start
 
 
---
 
 
 
  table inet filter {
 
  table inet filter {
    chain INPUT {
+
        chain input {
        type filter hook input priority filter; policy drop;
+
                type filter hook input priority filter; policy drop;
        ct state established,related accept
+
                ct state established,related accept
        iifname "lo" ct state new accept
+
                ct state new iif "lo" accept
        ct state new tcp dport 22 accept
+
                ct state new tcp dport 22 accept
+
                <span style="color:#8a2be2">ct state new icmp type echo-request accept</span>
    }
+
        }
   
+
     
    chain OUTPUT {
 
        type filter hook output priority filter; policy drop;
 
        ct state established,related,new accept
 
    }
 
 
   
 
   
    chain FORWARD {
+
        chain output {
        type filter hook forward priority filter; policy drop;
+
                type filter hook output priority filter; policy drop;
        ct state established,related accept
+
                ct state established,related accept
    }
+
                <span style="color:#004334">ct state new accept</span>
 +
          }
 
  }
 
  }
<span id="das-logging"></span>
+
{{vorlage:nat2}}
  
= Das Logging =
+
==Aktivieren und Kontrolliere==
 +
;Aktivieren
 +
*nft -f /etc/nftables.conf
 +
;Kontrollieren
 +
*nft list ruleset
  
''nftables'' kann in das Systemlogbuch, was normalerweise '''/var/log/syslog''' ist, schreiben. Es sollen nun alle abgelehnten Pakete geloggt werden, d.h. eine Regel vor der Anwendung der Default Policy. Im Gegensatz zu den anderen Zielen bricht ''log'' nicht die weitere Verarbeitung in der Kette ab.
+
=Wir loggen=
 +
*Wir wollen die abgelehnten Pakete loggen.
 +
*Die Idee dahinter ist, wir schreiben eine Regel kurz bevor die Default Policy greift.
 +
*<span style="color:#FF0000">Neu: Wir fügen in jeder Kette eine log-Regel ein, um verworfene Pakete zu protokollieren</span>
  
$ vi '''fw.nft'''
+
{{nftabels-var1
+
| kit = 172.22.0.0/16
  ---
+
}}
   
+
  # Alte Regeln löschen (flush)
  #!/usr/sbin/nft -f
+
  flush ruleset
add table inet filter
+
  table inet filter {
add chain inet filter INPUT { type filter hook input priority filter; policy drop; }
+
        chain input {
add chain inet filter OUTPUT { type filter hook output priority filter; policy drop; }
+
                type filter hook input priority filter; policy drop;
add chain inet filter FORWARD { type filter hook forward priority filter; policy drop; }
+
                ct state established,related accept
+
                ct state new iif "lo" accept
# Basic rules for communication with itself and established connections
+
                ct state new tcp dport 22 accept
add rule inet filter INPUT ct state established,related accept
+
                ct state new icmp type echo-request accept  
add rule inet filter FORWARD ct state established,related,new accept
+
                  <span style="color:#8a2be2">log prefix " --nftables-drop-input-- "</span>
add rule inet filter OUTPUT ct state established,related accept
+
        }
add rule inet filter INPUT iifname lo ct state new accept
+
   
 
# Enable SSH to firewall
 
add rule inet filter INPUT ct state new tcp dport 22 accept
 
 
# Log dropped packets.
 
'''add rule inet filter INPUT limit rate 5/minute log prefix "--nftables-drop-input--"'''
 
'''add rule inet filter OUTPUT limit rate 5/minute log prefix "--nftables-drop-output--"'''
 
'''add rule inet filter FORWARD limit rate 5/minute log prefix "--nftables-drop-forward--"'''
 
Neu verwendete Syntax: Logge das Pakete mit diesem Präfix:
 
  
log prefix ''<prefix string>''
+
        chain output {
Man kann sich anschauen, was aktuell geloggt wird:
+
                type filter hook output priority filter; policy drop;
 +
                ct state established,related accept
 +
                ct state new oif "lo" accept
 +
                ct state new accept
 +
                  <span style="color:#8a2be2">log prefix " --nftables-drop-output-- "</span>
 +
        }
 +
}
  
tail -f /var/log/syslog | grep nftables
+
{{vorlage:nat2}}
 
---
 
 
Sep 15 14:58:21 fw-linkai kernel: [93778.514323] --nftables-drop-forward--IN=ens19 OUT=ens18 MAC=f2:8c:80:a8:c0:cc:12:05:0c:18:11:6b:08:00 SRC=10.82.244.8 DST=78.46.102.180 LEN=76 TOS=0x10 PREC=0x00 TTL=63 ID=25389 DF PROTO=UDP SPT=34193 DPT=123 LEN=56
 
Sep 15 14:58:31 fw-linkai kernel: [93788.764377] --nftables-drop-forward--IN=ens19 OUT=ens18 MAC=f2:8c:80:a8:c0:cc:12:05:0c:18:11:6b:08:00 SRC=10.82.244.8 DST=172.104.134.72 LEN=76 TOS=0x10 PREC=0x00 TTL=63 ID=40828 DF PROTO=UDP SPT=58350 DPT=123 LEN=56
 
Sep 15 14:58:42 fw-linkai kernel: [93799.014461] --nftables-drop-forward--IN=ens19 OUT=ens18 MAC=f2:8c:80:a8:c0:cc:12:05:0c:18:11:6b:08:00 SRC=10.82.244.8 DST=65.21.184.1 LEN=76 TOS=0x10 PREC=0x00 TTL=63 ID=32369 DF PROTO=UDP SPT=54458 DPT=123 LEN=56
 
<span id="icmp-freischalten"></span>
 
= ICMP freischalten =
 
  
$ vi '''firewall'''
+
=DHCP für das Lan freischalten=
+
*<span style="color:#FF0000">Neu: Wir schlaten für das LAN UDP Port 67 frei</span>
---
 
 
...
 
add rule inet filter INPUT ct state new meta l4proto icmp icmp type echo-request accept
 
 
# Log dropped packets.
 
...
 
Neu verwendete Syntax:
 
  
* IPv4 und IPv6 Layer 4 Protokoll
+
{{nftabels-var1
 
+
| kit = 172.22.0.0/16
<!----->
+
}}
  meta l4proto ''protocol''
+
  define LANDEV=enp0s9
* Nur Echo-Anfragen freischalten
+
# Alte Regeln löschen (flush)
 
+
flush ruleset
<!----->
+
  table inet filter {
  icmp type '''echo-request'''
+
        chain input {
<span id="forwarding"></span>
+
                type filter hook input priority filter; policy drop;
= Forwarding =
+
                ct state established,related accept
 
+
                ct state new iif "lo" accept
Damit Pakete weitergeleitet werden können, muss als erstes FORWARDING im Kernel aktiviert werden.
+
                ct state new tcp dport 22 accept
 
+
                ct state new icmp type echo-request accept
<span id="aktivierung"></span>
+
                <span style="color:#8a2be2">ct state new iif $LANDEV udp dport 67 accept</span>
== Aktivierung ==
+
                log prefix " --nftables-drop-input-- "
 
+
        }
$ echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
+
   
$ sysctl -p
 
 
---
 
 
net.ipv4.ip_forward = 1
 
<span id="snat"></span>
 
== SNAT ==
 
 
 
Rechner in einem LAN können nicht ohne weiteres mit dem WAN kommunizieren, da an die lokale IP-Adresse der Rechner im LAN nicht von außen geroutet werden kann. Um eine Internetverbindung aufzubauen, muss die Adresse aus dem LAN in eine öffentliche umgeschrieben werden.
 
 
 
$ vi '''fw.nft'''
 
 
---
 
 
#!/usr/sbin/nft -f
 
'''define WANDEV = ens18'''
 
'''define WANIP = 10.82.229.11'''
 
'''define LAN = 10.82.244.0/24'''
 
...
 
'''add table inet nat'''
 
'''add chain inet nat PREROUTING { type nat hook prerouting priority dstnat; policy accept; }'''
 
'''add chain inet nat POSTROUTING { type nat hook postrouting priority srcnat; policy accept; }'''
 
...
 
'''add rule inet nat POSTROUTING oifname $WANDEV ip saddr $LAN snat to $WANIP'''
 
 
# Log dropped packets.
 
...
 
Neu verwendete Syntax:
 
  
* Definieren einer Variable
+
        chain output {
 
+
                type filter hook output priority filter; policy drop;
<!----->
+
                ct state established,related accept
define ''variable_name'' = ''value''
+
                ct state new oif "lo" accept
* Interface des herausgehenden Paketes:
+
                ct state new accept
 
+
                log prefix " --nftables-drop-output-- "
<!----->
+
         }
oifname ''device name''
 
* IPv4-Adresse des Ursprungpaketes
 
 
 
<!----->
 
ip saddr ''<source address>''
 
<span id="absichern-von-netzen"></span>
 
= Absichern von Netzen =
 
 
 
Momentan wird nichts vom LAN zum WAN weitergeleitet. Um nur bestimmte Anwendungen zu erlauben kann man die für diese designierten Ports freischalten.
 
 
 
$ vi '''fw.nft'''
 
 
---
 
 
#!/usr/sbin/nft -f
 
define WANDEV = ens18
 
'''define LANDEV = ens19'''
 
define WANIP = 10.82.229.11
 
define LAN = 10.82.244.0/24
 
...
 
# SNAT and open certain ports for internet access of client
 
add rule inet nat POSTROUTING oifname $WANDEV ip saddr $LAN snat to $WANIP
 
'''add rule inet filter FORWARD ct state new iifname $LANDEV oifname $WANDEV ip saddr $LAN meta l4proto icmp icmp type echo-request accept'''
 
'''add rule inet filter FORWARD ct state new iifname $LANDEV oifname $WANDEV ip saddr $LAN udp dport 53 accept'''
 
'''add rule inet filter FORWARD ct state new iifname $LANDEV oifname $WANDEV ip saddr $LAN tcp dport { 25, 53, 80, 143, 443, 465, 993 } accept'''
 
# Log dropped packets.
 
...
 
Neu verwendete Syntax:
 
 
 
Bestimmte Ziel-Ports angeben
 
 
 
''transport_protocol'' dport { ''port number'' }
 
<span id="status-nach-firewall-start-2"></span>
 
== Status nach '''firewall start''' ==
 
 
 
$ firewall start
 
 
---
 
 
table inet filter {
 
    chain INPUT {
 
        type filter hook input priority filter; policy drop;
 
        ct state established,related accept
 
        iifname "lo" ct state new accept
 
        ct state new tcp dport 22 accept
 
 
    }
 
   
 
    chain OUTPUT {
 
        type filter hook output priority filter; policy drop;
 
        ct state established,related,new accept
 
    }
 
 
    chain FORWARD {
 
        type filter hook forward priority filter; policy drop;
 
        ct state established,related accept
 
        ct state new iifname "ens19" oifname "ens18" ip saddr 10.82.244.0/24 icmp type echo-request jump LAN2WAN
 
        ct state new iifname "ens19" oifname "ens18" ip saddr 10.82.244.0/24 udp dport 53 jump LAN2WAN
 
         ct state new iifname "ens19" oifname "ens18" ip saddr 10.82.244.0/24 tcp dport { 25, 53, 80, 143, 443, 465, 993 } jump LAN2WAN
 
    }
 
 
  }
 
  }
table inet nat {
 
    chain PREROUTING {
 
        type nat hook prerouting priority dstnat; policy accept;
 
    }
 
 
    chain POSTROUTING {
 
        type nat hook postrouting priority srcnat; policy accept;
 
        oifname "ens18" ip saddr 10.82.244.0/24 snat ip to 10.82.229.11
 
    }
 
}
 
<span id="eigene-ketten"></span>
 
= Eigene Ketten =
 
  
Man kann auch Ketten ohne Default Policy oder Hooks erstellen, die mehrere Regeln zusammenfassen. In diese Ketten gelangt man durch die Basisketten.
+
{{vorlage:nat2}}
  
$ vi '''fw.nft'''
+
==nftables Logging über journalctl ==
+
;Erklärung
---
+
*journalctl -k -f -g nftables
+
;Nur Logtext ohne Metadaten
#!/usr/sbin/nft -f
+
*journalctl -k -f -g nftables -o cat
...
+
;Logausgabe mit ISO-Zeitformat
# Custom chain: Forward traffic from with the LAN
+
*journalctl -k -f -g nftables -o short-iso
'''add chain inet filter LAN2WAN'''
+
;Nur drop-input
'''add rule inet filter LAN2WAN ct state new iifname $LANDEV oifname $WANDEV ip saddr $LAN accept'''
+
*journalctl -k -f -g nftables-drop-input
...
 
add rule inet filter FORWARD meta l4proto icmp icmp type echo-request '''jump LAN2WAN'''
 
add rule inet filter FORWARD udp dport 53 '''jump LAN2WAN'''
 
add rule inet filter FORWARD tcp dport { 25, 53, 80, 143, 443, 465, 993 } '''jump LAN2WAN'''
 
Neu verwendete Syntax:
 
  
Springe in eine andere Kette
+
=Aktivieren der Firewall beim Systemstart=
 +
*systemctl enable nftables --now
  
jump ''target''
+
=Source oder Destination IP oder Netze=
<span id="limits-setzten"></span>
+
;Hinweis für die Aufgaben.
= Limits setzten =
+
Source Ips oder Netze werden mit einem '''ip saddr IP''' angeben
  
Man kann die Anzahl die eine Regel annimmt zeitlich begrenzen. Dafür fügt man ’‘’limit rate’’’ in die Regel ein. Falls nur 5 Pakete pro Minute geloggt werden sollen:
+
Destination Ips oder Netze werden mit einem '''ip daddr IP''' angeben
 +
;Beispiele
  
  $ vi '''fw.nft'''
+
  ct state new iif "enp0s9" ip saddr 172.26.213.0/24 tcp dport 22 accept
 
---
 
#!/usr/sbin/nft -f
 
...
 
# Log dropped packets. Max. 5/min
 
add rule inet filter INPUT '''limit rate 5/minute''' log prefix "--nftables-drop-input--"
 
add rule inet filter OUTPUT '''limit rate 5/minute''' log prefix "--nftables-drop-output--"
 
add rule inet filter FORWARD '''limit rate 5/minute''' log prefix "--nftables-drop-forward--"
 
<span id="vpns-ermöglichen"></span>
 
= VPNs ermöglichen =
 
  
Damit VPN-Verbindungen von außen aufgebaut werden können müssen die UDP-Ports 500 und 4500 für IPSec-Protokolle offen sein. Nachdem eine Secure Association hergestellt wurde, müssen ESP Pakete von der Firewall zugelassen und die entpackten Pakete weitergeleitet werden.
+
=Aufgabe=
 +
*Grenzt den Zugriff per ssh so ein das folgende Bereiche zugelassen:
 +
**DMZ
 +
**LAN
 +
**SERVER
 +
**HOST
 +
;Testet ob die Regel greifen positiv wie negativ <nowiki>:)</nowiki>
  
* vim fw.nft
+
=Handling=
 
+
;Regelsatz anzeigen
<!----->
+
*nft list ruleset
#!/usr/sbin/nft -f
+
;Regelsatz neuladen
...
+
*systemctl restart nftables
define VPN = 192.168.178.0/24
+
oder
...
+
*nft -f /etc/nftables.conf
# Establish rules for VPN connections but leave chains empty for toggling
+
;Regelsatz löschen
outside this script
+
*systemctl stop nftables
add chain inet filter IPSEC
+
oder
add rule inet filter IPSEC accept
+
*nft flush ruleset
add rule inet filter INPUT iifname $WANDEV ct state new udp dport 500 jump IPSEC
+
;Firewall für den System aktiveren
add rule inet filter INPUT iifname $WANDEV ct state new udp dport 4500 jump IPSEC
+
*systemctl enable nftables
add rule inet filter INPUT iifname $WANDEV ct state new meta l4proto esp jump IPSEC
+
;Ist die Firewall enabled?
add rule inet filter FORWARD iifname $WANDEV ip saddr $VPN ct state new jump IPSEC
+
*systemctl is-enabled nftables
...
+
;Firewall start
# Log dropped packets. Max. 5/min
+
*systemctl start nftables
...
+
;Firewall start und enabled
Der Weg nach außen muss in dem Fall nicht speziell freigeschaltet werden, da unsere Firewall sowieso alle neuen Pakete nach außen durchlässt. Damit aber ESP-Pakete korrekt generiert werden, muss die POSTROUTING-Regel für den Internetzugang der Clients angepasst werden. Ein Blick auf die Routing-Tabelle zeigt nämlich, …
+
*systemctl enable nftables --now
 
+
;Logging
* ip route show table 220
+
*journalctl -fkg nftables
 
 
<!----->
 
192.168.178.0/24 via 10.82.229.1 dev ens18 proto static src 10.82.244.1
 
… dass nur Pakete mit einer Ursprungs-IP von 10.82.244.1 an das lokale Netz der VPN-Verbindung geleitet wird. Die bisherige SNAT-Regel schreibt jedoch alle Pakete auf die IP des WAN-Interfaces um. Also müssen wir die Ziel-IPs der VPN ausschließen:
 
 
 
#!/usr/sbin/nft -f
 
...
 
define VPN = 192.168.178.0/24
 
...
 
# SNAT and open certain ports for internet access of client
 
add rule inet nat POSTROUTING oifname $WANDEV ip saddr $LAN '''ip daddr != $VPN''' snat to $WANIP
 
...
 
Zum Vergleich die ''tcpdump''-Analysen bei einem Ping auf einen der Rechner im VPN…
 
 
 
* …ohne die Ziel-IPs auszuschließen: tcpdump -i ens18 icmp or esp
 
 
 
<!----->
 
15:30:07.481373 IP fw-linkai > 192.168.178.2: ICMP echo request, id 2845, seq 1, length 64
 
15:30:08.493319 IP fw-linkai > 192.168.178.2: ICMP echo request, id 2845, seq 2, length 64
 
15:30:09.517369 IP fw-linkai > 192.168.178.2: ICMP echo request, id 2845, seq 3, length 64
 
* …wenn die Ziel-IPs auszuschließen werden: tcpdump -i ens18 icmp or esp
 
 
 
<!----->
 
15:27:31.091907 IP fw-linkai > 10.82.228.2: ESP(spi=0xc668795e,seq=0x4), length 136
 
15:27:31.093913 IP 10.82.228.2 > fw-linkai: ESP(spi=0xccf83bd8,seq=0x4), length 136
 
15:27:31.093913 IP 192.168.178.2 > 10.82.244.1: ICMP echo reply, id 32171, seq 1, length 64
 
15:27:32.093502 IP fw-linkai > 10.82.228.2: ESP(spi=0xc668795e,seq=0x5), length 136
 
15:27:32.095404 IP 10.82.228.2 > fw-linkai: ESP(spi=0xccf83bd8,seq=0x5), length 136
 
15:27:32.095404 IP 192.168.178.2 > 10.82.244.1: ICMP echo reply, id 32171, seq 2, length 64
 
15:27:33.095023 IP fw-linkai > 10.82.228.2: ESP(spi=0xc668795e,seq=0x6), length 136
 
15:27:33.096880 IP 10.82.228.2 > fw-linkai: ESP(spi=0xccf83bd8,seq=0x6), length 136
 
15:27:33.096880 IP 192.168.178.2 > 10.82.244.1: ICMP echo reply, id 32171, seq 3, length 64
 

Aktuelle Version vom 22. Mai 2026, 09:14 Uhr

Die ersten wirklichen Regeln die etwas bewirken

  • Momentan wollen wir nur den Host absichern.
  • Darum können wir die forward Kette erstmal aussen vor lassen.
  • Wir beziehen uns also nur auf den Host selbst.
  • Wir wollen nun folgendes tun:
  • Der Rechner soll mit sich selbst über das Loopback Interface kommunizieren können.
  • Vom Rechner selbst nach aussen soll alles zugelassen werden
  • Auf den Rechner soll per "ssh" zugegriffen werden können.

Die erste sinnvolle Konfiguration

  • cat /etc/nftables.conf
#!/usr/sbin/nft -f

# Variablen
define WANIP = <WANIP der Firewall>
define LAN = 172.26.2XX.0/24
define MGMT = 172.27.2XX.0/24
define SERVER = 10.2XX.1.0/24
define DMZ = 10.88.2XX.0/24
define KIT = 172.22.0.0/16
define WANDEV = enp0s3
# Alte Regeln löschen (flush)
flush ruleset
table inet filter {
        chain input {
                type filter hook input priority filter; policy drop;
                ct state established,related accept
                ct state new iif "lo" accept
                ct state new tcp dport 22 accept 

        }
     

        chain output {
                type filter hook output priority filter; policy drop;
                ct state established,related accept
                ct state new accept
          }
}
 table inet nat {
  chain postrouting {
   type nat hook postrouting priority 100; policy accept;
        ip saddr $DMZ ip daddr $KIT return
        ip saddr $DMZ ip daddr 10.88.0.0/16 return
        ip saddr $DMZ oif $WANDEV snat to $WANIP
        ip saddr $LAN oif $WANDEV snat to $WANIP
        ip saddr $SERVER oif $WANDEV snat to $WANIP
        ip saddr $MGMT oif $WANDEV snat to $WANIP
     }
  }

Aktivieren und Kontrolliere

Aktivieren
  • nft -f /etc/nftables.conf
Kontrollieren
  • nft list ruleset

Wir schalten ping frei

  • cat /etc/nftables.conf
#!/usr/sbin/nft -f

# Variablen
define WANIP = <WANIP der Firewall>
define LAN = 172.26.2XX.0/24
define MGMT = 172.27.2XX.0/24
define SERVER = 10.2XX.1.0/24
define DMZ = 10.88.2XX.0/24
define KIT = 172.22.0.0/16
define WANDEV = enp0s3
# Alte Regeln löschen (flush)
flush ruleset
table inet filter {
        chain input {
                type filter hook input priority filter; policy drop;
                ct state established,related accept
                ct state new iif "lo" accept
                ct state new tcp dport 22 accept
                ct state new icmp type echo-request accept 
        }
     

        chain output {
                type filter hook output priority filter; policy drop;
                ct state established,related accept
                ct state new accept
          }
}
 table inet nat {
  chain postrouting {
   type nat hook postrouting priority 100; policy accept;
        ip saddr $DMZ ip daddr $KIT return
        ip saddr $DMZ ip daddr 10.88.0.0/16 return
        ip saddr $DMZ oif $WANDEV snat to $WANIP
        ip saddr $LAN oif $WANDEV snat to $WANIP
        ip saddr $SERVER oif $WANDEV snat to $WANIP
        ip saddr $MGMT oif $WANDEV snat to $WANIP
     }
  }

Aktivieren und Kontrolliere

Aktivieren
  • nft -f /etc/nftables.conf
Kontrollieren
  • nft list ruleset

Wir loggen

  • Wir wollen die abgelehnten Pakete loggen.
  • Die Idee dahinter ist, wir schreiben eine Regel kurz bevor die Default Policy greift.
  • Neu: Wir fügen in jeder Kette eine log-Regel ein, um verworfene Pakete zu protokollieren
  • cat /etc/nftables.conf
#!/usr/sbin/nft -f

# Variablen
define WANIP = <WANIP der Firewall>
define LAN = 172.26.2XX.0/24
define MGMT = 172.27.2XX.0/24
define SERVER = 10.2XX.1.0/24
define DMZ = 10.88.2XX.0/24
define KIT = 172.22.0.0/16
define WANDEV = enp0s3
# Alte Regeln löschen (flush)
flush ruleset
table inet filter {
        chain input {
                type filter hook input priority filter; policy drop;
                ct state established,related accept
                ct state new iif "lo" accept
                ct state new tcp dport 22 accept
                ct state new icmp type echo-request accept 
                 log prefix " --nftables-drop-input-- "
        }
   
        chain output {
                type filter hook output priority filter; policy drop;
                ct state established,related accept
                ct state new oif "lo" accept
                ct state new accept
                 log prefix " --nftables-drop-output-- "
        }
}
 table inet nat {
  chain postrouting {
   type nat hook postrouting priority 100; policy accept;
        ip saddr $DMZ ip daddr $KIT return
        ip saddr $DMZ ip daddr 10.88.0.0/16 return
        ip saddr $DMZ oif $WANDEV snat to $WANIP
        ip saddr $LAN oif $WANDEV snat to $WANIP
        ip saddr $SERVER oif $WANDEV snat to $WANIP
        ip saddr $MGMT oif $WANDEV snat to $WANIP
     }
  }

DHCP für das Lan freischalten

  • Neu: Wir schlaten für das LAN UDP Port 67 frei
  • cat /etc/nftables.conf
#!/usr/sbin/nft -f

# Variablen
define WANIP = <WANIP der Firewall>
define LAN = 172.26.2XX.0/24
define MGMT = 172.27.2XX.0/24
define SERVER = 10.2XX.1.0/24
define DMZ = 10.88.2XX.0/24
define KIT = 172.22.0.0/16
define WANDEV = enp0s3
define LANDEV=enp0s9
# Alte Regeln löschen (flush)
flush ruleset
table inet filter {
        chain input {
                type filter hook input priority filter; policy drop;
                ct state established,related accept
                ct state new iif "lo" accept
                ct state new tcp dport 22 accept
                ct state new icmp type echo-request accept 
                ct state new iif $LANDEV udp dport 67 accept
                log prefix " --nftables-drop-input-- "
        }
   
        chain output {
                type filter hook output priority filter; policy drop;
                ct state established,related accept
                ct state new oif "lo" accept
                ct state new accept
                log prefix " --nftables-drop-output-- "
        }
}
 table inet nat {
  chain postrouting {
   type nat hook postrouting priority 100; policy accept;
        ip saddr $DMZ ip daddr $KIT return
        ip saddr $DMZ ip daddr 10.88.0.0/16 return
        ip saddr $DMZ oif $WANDEV snat to $WANIP
        ip saddr $LAN oif $WANDEV snat to $WANIP
        ip saddr $SERVER oif $WANDEV snat to $WANIP
        ip saddr $MGMT oif $WANDEV snat to $WANIP
     }
  }

nftables Logging über journalctl

Erklärung
  • journalctl -k -f -g nftables
Nur Logtext ohne Metadaten
  • journalctl -k -f -g nftables -o cat
Logausgabe mit ISO-Zeitformat
  • journalctl -k -f -g nftables -o short-iso
Nur drop-input
  • journalctl -k -f -g nftables-drop-input

Aktivieren der Firewall beim Systemstart

  • systemctl enable nftables --now

Source oder Destination IP oder Netze

Hinweis für die Aufgaben.

Source Ips oder Netze werden mit einem ip saddr IP angeben

Destination Ips oder Netze werden mit einem ip daddr IP angeben

Beispiele
ct state new iif "enp0s9" ip saddr 172.26.213.0/24 tcp dport 22 accept

Aufgabe

  • Grenzt den Zugriff per ssh so ein das folgende Bereiche zugelassen:
    • DMZ
    • LAN
    • SERVER
    • HOST
Testet ob die Regel greifen positiv wie negativ :)

Handling

Regelsatz anzeigen
  • nft list ruleset
Regelsatz neuladen
  • systemctl restart nftables

oder

  • nft -f /etc/nftables.conf
Regelsatz löschen
  • systemctl stop nftables

oder

  • nft flush ruleset
Firewall für den System aktiveren
  • systemctl enable nftables
Ist die Firewall enabled?
  • systemctl is-enabled nftables
Firewall start
  • systemctl start nftables
Firewall start und enabled
  • systemctl enable nftables --now
Logging
  • journalctl -fkg nftables