Nftables Netze absichern: Unterschied zwischen den Versionen

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen
Linkai.zhang (Diskussion | Beiträge)
 
(164 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
<span id="einleitung"></span>
= Einleitung =
= Einleitung =


* Nachdem wir ein Hostsystem abgesichert haben, kommen wir nun zum Absichern von Netzen.
* Nachdem wir ein Hostsystem abgesichert haben, kommen wir nun zum Absichern von Netzen.
* Die Firewall agiert als Vermittler zwischen verschiedenen Netzen.
* Die Firewall agiert als Vermittler zwischen verschiedenen Netzen.
* In unserem Beispiel haben wir 3 Netzbereiche.
* In unserem Beispiel haben wir 4 Netzbereiche.


<!----->
<span id="wan"></span>
= WAN =
= WAN =


* Wide Area Net steht für alles was nicht die anderen beiden Netze betrifft
* Wide Area Net steht für alles was nicht die anderen Netze betrifft


<!----->
<span id="lan"></span>
= LAN =
= LAN =


Zeile 19: Zeile 14:
* Meist ist es über Network Address Translation (NAT) angebunden.
* Meist ist es über Network Address Translation (NAT) angebunden.


<!----->
<span id="dmz"></span>
= DMZ =
= DMZ =


* Demilitarized Zone ist ein Netz welches von aussen erreichbar ist.
* Demilitarized Zone ist ein Netz welches von außen erreichbar ist.
* Die Zugriffe werden aber durch die Firewall abgesichert.
* Die Zugriffe werden aber durch die Firewall abgesichert.
* Dort werden meistens Dienste wie Mail oder Web gehostet. Teilweise auch Proxy Server.
* Dort werden meistens Dienste wie Mail oder Web gehostet. Teilweise auch Proxy Server.


<!----->
=SERVER=
<span id="der-plan"></span>
* Hier stehen die internen SERVER
* Fileserver oder LDAP Server
 
= Der Plan =
= Der Plan =


{{#drawio:netzplan-nftables-1}}
{{#drawio:netzplan-nftables-1}}


<span id="das-grundgerüst"></span>
= Das Grundgerüst =
= Das Grundgerüst =


Zeile 39: Zeile 33:
* Wir wollen aber von vorneherein verstärkt mit Variablen arbeiten.
* Wir wollen aber von vorneherein verstärkt mit Variablen arbeiten.
* Dies macht die Skripte universeller.
* Dies macht die Skripte universeller.
* '''vim /etc/nftables.conf'''
===vim /etc/nftables-vars.conf===
 
{{vorlage:nftables-vars.conf}}
===vim /etc/nftables.conf===
  #!/usr/sbin/nft -f
  #!/usr/sbin/nft -f
  define remote_tcp_ports = { 22,25,53,80,465,443 }
  include "/etc/nftables-vars.conf"
define remote_udp_ports = { 53 }
define local_tcp_ports = { 22,80,443 }
define wandev = ens18
define dmzdev = ens19
define landev = ens20
define lan = 192.168.4.0/24
  flush ruleset
  flush ruleset
  table inet filter {
  table inet filter {
    chain input {
{{vorlage:input.conf}}
        type filter hook input priority filter; policy drop;
<span style="color:#FF0000">chain forward {</span>
        ct state established,related accept
                <span style="color:#FF0000">type filter hook forward priority filter; policy drop;</span>
        ct state new tcp dport $local_tcp_ports accept
                <span style="color:#FF0000">ct state established,related accept</span>
        iif "lo" accept
                <span style="color:#FF0000">log prefix "--nftables-drop-forward--"</span>
        log prefix "--nftables-drop-input--"
      <span style="color:#FF0000">}</span>
    }
    chain forward {
        type filter hook forward priority filter; policy drop;
        ct state established,related accept
        log prefix "--nftables-drop-forward--"
    }
   
   
    chain output {
{{vorlage:output.conf}}
        type filter hook output priority filter; policy drop;
        ct state established,related accept
        ct state new oif "lo" accept
        ct state new tcp dport $remote_tcp_ports accept
        ct state new udp dport $remote_udp_ports accept
        log prefix "--nftables-drop-output--"
    }
  }
  }
{{vorlage:nat2}}


= Forwarding =
== Weitere Tabellen ==
 
* Damit Pakete weitergeleitet werden können, muss als erstes FORWARDING im Kernel aktiviert werden.
* Aktivierung
* '''echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf'''
* '''sysctl -p'''
 
= Weitere Tabellen =


* Eine Skizze über die Reihenfolge der Hooks.
* Eine Skizze über die Reihenfolge der Hooks.
* Als erstes greift der Prerouting-Hook
* Als erstes greift der Prerouting-Hook
* Je nachdem wie geroutet wird greift dann entweder Input- oder Fowrward-Hook
* Je nachdem wie geroutet wird greift dann entweder Input- oder Forward-Hook
* Falls ein lokaler Prozess ein Paket sendet, dann greift der Output-Hook
* Falls ein lokaler Prozess ein Paket sendet, dann greift der Output-Hook
* Als letztes kann man das Paket mit dem Postrouting-Hook beeinflußen
* Als letztes kann man das Paket mit dem Postrouting-Hook beeinflußen


<!----->
{{#drawio:nft-inet1}}
{{#drawio:nft-inet1}}


<span id="snat"></span>
== Checken der forward Kette ==
== SNAT ==
*nft list chain inet filter forward
 
* 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.
 
#!/usr/sbin/nft -f
flush ruleset
define remote_tcp_ports = { 22,25,53,80,465,443 }
define remote_udp_ports = { 53 }
define local_tcp_ports = { 22,80,443 }
define wandev = ens18
define dmzdev = ens19
define landev = ens20
define wanip = 10.82.232.11
define lan = 192.168.4.0/24
  table inet filter {
  table inet filter {
    chain input {
chain forward {
        type filter hook input priority filter; policy drop;
type filter hook forward priority filter; policy drop;
        ct state established,related accept
ct state established,related accept
        iif "lo" ct state new accept
log prefix "--nftables-drop-forward--"
        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,new accept
        log prefix "--nftables-drop-output--"
    }
    chain forward {
        type filter hook forward priority filter; policy drop;
        ct state established,related accept
        log prefix "--nftables-drop-forward--"
    }
  }
  }
'''table inet nat {'''
    '''chain prerouting {'''
        '''type nat hook prerouting priority dstnat; policy accept;'''
    '''}'''
    '''chain postrouting {'''
        '''type nat hook postrouting priority srcnat; policy accept;'''
        '''oif $wandev ip saddr $lan snat ip to $wanip'''
    '''}'''
'''}'''
Neu verwendete Syntax:
* Definieren einer Variable
define ''variable_name'' = ''value''
* Interface des herausgehenden Paketes:
oif ''device_name''
* matche IPv4-Adresse des Ursprungpaketes
ip saddr ''<source address>''
* Die Ursprungs-IP auf eine andere Adresse natten
snat ip to ''<new_source_ip>''
== Portforwarding ==
* Um auf bestimmte Funktionen eines Rechners hinter einer Firewall zugreifen zu können, müssen die dazugehörenden Ports entsprechend weitergeleitet werden.
* Hierbei kann es ein anderer, nicht-standard Port der Firewall sein.


=Forward von innen nach aussen=
*Wir wollen das unsere Clients und die Server vorerst nach aussen alles dürfen.
===vim /etc/nftables-vars.conf===
{{vorlage:nftables-vars.conf}}
===vim /etc/nftables.conf===
  #!/usr/sbin/nft -f
  #!/usr/sbin/nft -f
   
  include "/etc/nftables-vars.conf"
  flush ruleset
  flush ruleset
flush ruleset
define remote_tcp_ports = { 22,25,53,80,465,443 }
define remote_udp_ports = { 53 }
define local_tcp_ports = { 22,80,443 }
define wandev = ens18
define dmzdev = ens19
define landev = ens20
define wanip = 10.82.232.11
define lan = 192.168.4.0/24
'''define webserver = 192.168.4.12'''
  table inet filter {
  table inet filter {
    chain input {
{{vorlage:input.conf}}
        type filter hook input priority filter; policy drop;
      chain forward {
        ct state established,related accept
            type filter hook forward priority filter; policy drop;
        iif "lo" ct state new accept
            ct state established,related accept
        ct state new tcp dport 22 accept
            <span style="color:#FF0000">ct state new ip saddr $LOCALNETS accept</span>
        ct state new icmp type echo-request accept
            log prefix "--nftables-drop-forward--"
        log prefix "--nftables-drop-input--"
        }
    }
{{vorlage:output.conf}}
    chain output {
        type filter hook output priority filter; policy drop;
        ct state established,related,new accept
        log prefix "--nftables-drop-output--"
    }
    chain forward {
        type filter hook forward priority filter; policy drop;
        ct state established,related accept
        '''iif $wandev ip daddr $webserver tcp dport 22 accept'''
        '''iif $wandev ip daddr $webserver tcp dport 80 accept'''
        log prefix "--nftables-drop-forward--"
    }
}
table inet nat {
    chain prerouting {
        type nat hook prerouting priority dstnat; policy accept;
        '''ip daddr $wanip tcp dport 9922 dnat ip to $webserver:22'''
        '''ip daddr $wanip tcp dport 80 dnat ip to $webserver:80'''
    }
    chain postrouting {
        type nat hook postrouting priority srcnat; policy accept;
        oif $wandev ip saddr $lan snat ip to $wanip
    }
  }
  }
{{vorlage:nat2}}


* Nun kann man per SSH auf den Rechner hinter der Firewall über Port 9922 der Firewall zugreifen...
=Regeln von aussen nach innen=
* '''ssh ''user@WEBSERVER'' -p 9922'''
* Die Regel die eingefügt wird bedeuten folgendes:
*  ... und HTTP-Requests an den Rechner hinter der Firewall schicken
* Ein Paket welches in die Schnittstelle enp0s3 reingeht und den Rechner über enp0s8 verlässt,
* '''curl ''WEBSERVER'''''
* Sowie an die Zieladresse des Nameservers und an den UDP Zielport 53 gerichtet ist,
 
* wird durchgelassen und in der Conntrack-Tabelle aufgenommen.
= Absichern von Netzen =
===vim /etc/nftables-vars.conf===
 
{{vorlage:nftables-vars.conf}}
Momentan wird nichts vom LAN zum WAN weitergeleitet. Um nur bestimmte Anwendungen zu erlauben kann man die für diese designierten Ports freischalten.
<span style="color:#FF0000">define NS = 10.88.2XX.21</span>


===vim /etc/nftables.conf===
  #!/usr/sbin/nft -f
  #!/usr/sbin/nft -f
   
  include "/etc/nftables-vars.conf"
  flush ruleset
  flush ruleset
define remote_tcp_ports = { 22,25,53,80,465,443 }
define remote_udp_ports = { 53 }
define local_tcp_ports = { 22,80,443 }
define wandev = ens18
define dmzdev = ens19
define landev = ens20
define lan = 192.168.4.0/24
define wanip = 10.82.232.11
define webserver = 192.168.4.12
  table inet filter {
  table inet filter {
    chain input {
{{vorlage:input.conf}}
        type filter hook input priority filter; policy drop;
        ct state established,related accept
        iif "lo" ct state new 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,new accept
        log prefix "--nftables-drop-output--"
    }
   
    chain forward {
        type filter hook forward priority filter; policy drop;
        ct state established,related accept
        iif $wandev ip daddr $webserver tcp dport 22 accept
        iif $wandev ip daddr $webserver tcp dport 80 accept
        '''ct state new iif $landev oif $wandev ip saddr $lan icmp type echo-request accept'''
        '''ct state new iif $landev oif $wandev ip saddr $lan udp dport 53 accept'''
        '''ct state new iif $landev oif $wandev ip saddr $lan tcp dport { 25, 53, 80, 143, 443, 465, 993 } accept'''
        log prefix "--nftables-drop-forward--"
    }
}
table inet nat {
    chain prerouting {
        type nat hook prerouting priority dstnat; policy accept;
        ip daddr $wanip tcp dport 9922 dnat ip to $webserver:22
        ip daddr $wanip tcp dport 80 dnat ip to $webserver:80
    }
    chain postrouting {
        type nat hook postrouting priority srcnat; policy accept;
        oif $wandev ip saddr $lan snat ip to $wanip
    }
}


Neu verwendete Syntax:
  chain forward {
 
            type filter hook forward priority filter; policy drop;
Bestimmte Ziel-Ports angeben
            ct state established,related accept
 
            <span style="color:#FF0000">ct state new iif $WANDEV oif $DMZDEV ip daddr $NS udp dport 53 accept</span>
''transport_protocol'' dport { ''port_number_1,port_number_2,...'' }
            ct state new ip saddr $LOCALNETS accept
 
              log prefix "--nftables-drop-forward--"
= Eigene Ketten =
         }
 
Man kann auch Ketten ohne Default Policy oder Hooks erstellen, die mehrere Regeln zusammenfassen. In diese Ketten gelangt man durch die Basisketten.
 
#!/usr/sbin/nft -f
flush ruleset
define wandev = ens18
define dmzdev = ens19
define landev = ens20
define wanip = 10.82.232.11
define lan = 192.168.4.0/24
define webserver = 192.168.4.12
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,new accept
        log prefix "--nftables-drop-output--"
    }
   
    chain forward {
        type filter hook forward priority filter; policy drop;
        ct state established,related accept
        ct state new iif $wandev ip daddr $webserver tcp dport 22 accept
        ct state new iif $wandev ip daddr $webserver tcp dport 80 accept
        ct state new icmp type echo-request '''jump lan2wan'''
        udp dport 53 '''jump lan2wan'''
        tcp dport { 25, 53, 80, 143, 443, 465, 993 } '''jump lan2wan'''
        log prefix "--nftables-drop-forward--"
    }
    '''chain lan2wan {'''
        '''ct state new iif $landev oifname $wandev ip saddr $lan accept'''
    '''}'''
}
table inet nat {
    chain prerouting {
        type nat hook prerouting priority dstnat; policy accept;
        ip daddr $wanip tcp dport 9922 dnat ip to $webserver:22
        ip daddr $wanip tcp dport 80 dnat ip to $webserver:80
    }
   
    chain postrouting {
        type nat hook postrouting priority srcnat; policy accept;
        oif $wandev ip saddr $lan snat ip to $wanip
    }
}
Neu verwendete Syntax:
 
Springe in eine andere Kette
 
jump ''target''
 
= Limits setzten =
 
* 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:
 
<!----->
#!/usr/sbin/nft -f
flush ruleset
define remote_tcp_ports = { 22,25,53,80,465,443 }
define remote_udp_ports = { 53 }
define local_tcp_ports = { 22,80,443 }
define wandev = ens18
define dmzdev = ens19
define landev = ens20
define lan = 192.168.4.0/24
define wanip = 10.82.232.11
define webserver = 192.168.4.12
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
        ct state new icmp type echo-request accept
        '''limit rate 5/minute''' log prefix "--nftables-drop-input--"
    }
   
    chain output {
        type filter hook output priority filter; policy drop;
        ct state established,related,new accept
        '''limit rate 5/minute''' log prefix "--nftables-drop-output--"
    }
   
    chain forward {
        type filter hook forward priority filter; policy drop;
        ct state established,related accept
        iifname $wandev meta nfproto ipv4 ip daddr $webserver tcp dport 22 accept
        iifname $wandev meta nfproto ipv4 ip daddr $webserver tcp dport 80 accept
        icmp type echo-request jump lan2wan
        udp dport 53 jump lan2wan
        tcp dport { 25, 53, 80, 143, 443, 465, 993 } jump lan2wan
        '''limit rate 5/minute''' log prefix "--nftables-drop-forward--"
    }
   
    chain lan2wan {
        ct state new iifname $landev oifname $wandev ip saddr $lan accept
    }
}
table inet nat {
    chain prerouting {
        type nat hook prerouting priority dstnat; policy accept;
        meta nfproto ipv4 ip daddr $wanip tcp dport 9922 dnat ip to $webserver:22
        meta nfproto ipv4 ip daddr $wanip tcp dport 80 dnat ip to $webserver:80
    }
    chain postrouting {
        type nat hook postrouting priority srcnat; policy accept;
        oifname $wandev ip saddr $lan snat ip to $wanip
    }
}
<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.
* vim fw.nft
 
<!----->
#!/usr/sbin/nft -f
flush ruleset
define wandev = ens18
define landev = ens19
define wanip = 10.82.232.11
define lan = 192.168.4.0/24
'''define vpn = 192.168.178.0/24'''
define webserver = 192.168.4.12
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
        ct state new icmp type echo-request accept
        '''iifname $wandev ct state new udp dport 500 jump ipsec'''
        '''iifname $wandev ct state new udp dport 4500 jump ipsec'''
        '''iifname $wandev ct state new meta l4proto esp jump ipsec'''
        limit rate 5/minute log prefix "--nftables-drop-input--"
    }
   
    chain output {
        type filter hook output priority filter; policy drop;
        ct state established,related,new accept
        limit rate 5/minute log prefix "--nftables-drop-output--"
    }
    chain forward {
        type filter hook forward priority filter; policy drop;
        ct state established,related accept
        iifname $wandev meta nfproto ipv4 ip daddr $webserver tcp dport 22 accept
        iifname $wandev meta nfproto ipv4 ip daddr $webserver tcp dport 80 accept
        icmp type echo-request jump lan2wan
        udp dport 53 jump lan2wan
        tcp dport { 25, 53, 80, 143, 443, 465, 993 } jump lan2wan
        '''iifname $wandev ip saddr $vpn ct state new jump ipsec'''
        limit rate 5/minute log prefix "--nftables-drop-forward--"
    }
    chain lan2wan {
        ct state new iifname $landev oifname $wandev ip saddr $lan accept
    }
    '''chain ipsec {'''
        '''accept'''
    '''}'''
}
table inet nat {
    chain prerouting {
        type nat hook prerouting priority dstnat; policy accept;
        meta nfproto ipv4 ip daddr $wanip tcp dport 9922 dnat ip to $webserver:22
        meta nfproto ipv4 ip daddr $wanip tcp dport 80 dnat ip to $webserver:80
    }
    chain postrouting {
        type nat hook postrouting priority srcnat; policy accept;
         oifname $wandev ip saddr $lan snat ip to $wanip
    }
}
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, …
 
* ip route show table 220
 
<!----->
192.168.178.0/24 via 10.82.229.1 dev ens18 proto static src 192.168.4.1
 
… dass nur Pakete mit einer Ursprungs-IP von 192.168.4.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
   
   
flush ruleset
{{vorlage:output.conf}}
define wandev = ens18
define landev = ens19
define wanip = 10.82.232.11
define lan = 192.168.4.0/24
define vpn = 192.168.178.0/24
define webserver = 192.168.4.12
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
        ct state new icmp type echo-request accept
        iifname $wandev ct state new udp dport 500 jump ipsec
        iifname $wandev ct state new udp dport 4500 jump ipsec
        iifname $wandev ct state new meta l4proto esp jump ipsec
        limit rate 5/minute log prefix "--nftables-drop-input--"
    }
   
    chain output {
        type filter hook output priority filter; policy drop;
        ct state established,related,new accept
        limit rate 5/minute log prefix "--nftables-drop-output--"
    }
   
    chain forward {
        type filter hook forward priority filter; policy drop;
        ct state established,related accept
        iifname $wandev meta nfproto ipv4 ip daddr $webserver tcp dport 22 accept
        iifname $wandev meta nfproto ipv4 ip daddr $webserver tcp dport 80 accept
        icmp type echo-request jump lan2wan
        udp dport 53 jump lan2wan
        tcp dport { 25, 53, 80, 143, 443, 465, 993 } jump lan2wan
        iifname $wandev ip saddr $vpn ct state new jump ipsec
        limit rate 5/minute log prefix "--nftables-drop-forward--"
    }
   
    chain lan2wan {
        ct state new iifname $landev oifname $wandev ip saddr $lan accept
    }
   
    chain ipsec {
        accept
    }
  }
  }
table inet nat {
{{vorlage:nat2}}
    chain prerouting {
=Erklärungen=
        type nat hook prerouting priority dstnat; policy accept;
ct state new iif $WANDEV oif $DMZDEV ip saddr $HOST ip daddr $WWW tcp dport 80 accept
        meta nfproto ipv4 ip daddr $wanip tcp dport 9922 dnat ip to $webserver:22
{| class="wikitable"
        meta nfproto ipv4 ip daddr $wanip tcp dport 80 dnat ip to $webserver:80
! Schlüsselwort / Variable !! Typ !! Erklärung
    }
|-
    chain postrouting {
| <code>ct state new</code> || nftables-Ausdruck || Paket-Tracking via Connection Tracking: Trifft auf neue Verbindungen zu (kein bestehendes ct-Entry)
        type nat hook postrouting priority srcnat; policy accept;
|-
        oifname $wandev ip saddr $lan '''ip daddr != $vpn''' snat ip to $wanip
| <code>iif</code> || Schlüsselwort || Eingehendes Interface (Input Interface Flag)
    }
|-
}
| <code>$WANDEV</code> || Variable || Enthält den Namen des WAN-Interfaces (z. B. <code>eth0</code>), über das das Paket eingeht
Zum Vergleich die ‘’tcpdump’’-Analysen bei einem Ping auf einen der Rechner im VPN…
|-
 
| <code>oif</code> || Schlüsselwort || Ausgehendes Interface (Output Interface Flag)
* …ohne die Ziel-IPs auszuschließen: tcpdump -i ens18 icmp or esp
|-
 
| <code>$DMZDEV</code> || Variable || Enthält den Namen des DMZ-Interfaces (z. B. <code>eth2</code>), über das das Paket weitergeleitet wird
<!----->
|-
15:30:07.481373 IP fw-linkai > 192.168.178.2: ICMP echo request, id 2845, seq 1, length 64
| <code>ip saddr</code> || Schlüsselwort || Quelladresse auf IPv4-Ebene (Source Address)
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
| <code>$HOST</code> || Variable || Enthält die IPv4-Adresse des erlaubten Quell-Hosts
* …wenn die Ziel-IPs auszuschließen werden: tcpdump -i ens18 icmp or esp
|-
| <code>ip daddr</code> || Schlüsselwort || Zieladresse auf IPv4-Ebene (Destination Address)
|-
| <code>$WWW</code> || Variable || Enthält die IPv4-Adresse des Ziel-Webservers
|-
| <code>tcp dport 80</code> || Ausdruck || Protokoll TCP, Zielport 80 (HTTP)
|-
| <code>accept</code> || Aktion || Paket wird akzeptiert und passiert die Regel
|}


<!----->
=old stuff=
15:27:31.091907 IP fw-linkai > 10.82.228.2: ESP(spi=0xc668795e,seq=0x4), length 136
*[[nftables-net-oldstuff]]
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 > 192.168.4.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 > 192.168.4.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 > 192.168.4.1: ICMP echo reply, id 32171, seq 3, length 64

Aktuelle Version vom 28. September 2026, 08:28 Uhr

Einleitung

  • Nachdem wir ein Hostsystem abgesichert haben, kommen wir nun zum Absichern von Netzen.
  • Die Firewall agiert als Vermittler zwischen verschiedenen Netzen.
  • In unserem Beispiel haben wir 4 Netzbereiche.

WAN

  • Wide Area Net steht für alles was nicht die anderen Netze betrifft

LAN

  • Local Area Net steht in der Regel für ein Netz das von aussen nicht erreichbar ist.
  • Meist ist es über Network Address Translation (NAT) angebunden.

DMZ

  • Demilitarized Zone ist ein Netz welches von außen erreichbar ist.
  • Die Zugriffe werden aber durch die Firewall abgesichert.
  • Dort werden meistens Dienste wie Mail oder Web gehostet. Teilweise auch Proxy Server.

SERVER

  • Hier stehen die internen SERVER
  • Fileserver oder LDAP Server

Der Plan

netzplan-nftables-1

Das Grundgerüst

  • Wir nutzen unsere Host Firewall als Ausgangsskript
  • Wir wollen aber von vorneherein verstärkt mit Variablen arbeiten.
  • Dies macht die Skripte universeller.

vim /etc/nftables-vars.conf

define WANDEV = enp0s3
define DMZDEV = enp0s8
define LANDEV = enp0s9
define SERVERDEV = enp0s10
define WANIP = <WANIP der Firewall>
define LAN = 172.26.2XX.0/24
define SERVER = 10.2XX.1.0/24
define MGMT = 172.27.2XX.0/24
define DMZ = 10.88.2XX.0/24
define KIT = <SCHULUNGS NETZ>
define HOST = <EUER HOST>
define LOCALNETS = { $DMZ, $LAN, $SERVER, $MGMT }

vim /etc/nftables.conf

#!/usr/sbin/nft -f
include "/etc/nftables-vars.conf"
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 iif $DMZDEV ip saddr $DMZ tcp dport 22 accept
 	     	 ct state new iif $LANDEV ip saddr $LAN tcp dport 22 accept
 	  	 ct state new iif $SERVERDEV ip saddr $SERVER tcp dport 22 accept
 	 	 ct state new iif $WANDEV ip saddr $HOST 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 forward {
                type filter hook forward priority filter; policy drop;
                ct state established,related accept
                log prefix "--nftables-drop-forward--"
      }

chain output {
                 type filter hook output priority filter; policy drop;
                 ct state established,related 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
     }
  }

Weitere Tabellen

  • Eine Skizze über die Reihenfolge der Hooks.
  • Als erstes greift der Prerouting-Hook
  • Je nachdem wie geroutet wird greift dann entweder Input- oder Forward-Hook
  • Falls ein lokaler Prozess ein Paket sendet, dann greift der Output-Hook
  • Als letztes kann man das Paket mit dem Postrouting-Hook beeinflußen
nft-inet1

Checken der forward Kette

  • nft list chain inet filter forward
table inet filter {
	chain forward {
		type filter hook forward priority filter; policy drop;
		ct state established,related accept
		log prefix "--nftables-drop-forward--"
	}
}

Forward von innen nach aussen

  • Wir wollen das unsere Clients und die Server vorerst nach aussen alles dürfen.

vim /etc/nftables-vars.conf

define WANDEV = enp0s3
define DMZDEV = enp0s8
define LANDEV = enp0s9
define SERVERDEV = enp0s10
define WANIP = <WANIP der Firewall>
define LAN = 172.26.2XX.0/24
define SERVER = 10.2XX.1.0/24
define MGMT = 172.27.2XX.0/24
define DMZ = 10.88.2XX.0/24
define KIT = <SCHULUNGS NETZ>
define HOST = <EUER HOST>
define LOCALNETS = { $DMZ, $LAN, $SERVER, $MGMT }

vim /etc/nftables.conf

#!/usr/sbin/nft -f
include "/etc/nftables-vars.conf"
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 iif $DMZDEV ip saddr $DMZ tcp dport 22 accept
 	     	 ct state new iif $LANDEV ip saddr $LAN tcp dport 22 accept
 	  	 ct state new iif $SERVERDEV ip saddr $SERVER tcp dport 22 accept
 	 	 ct state new iif $WANDEV ip saddr $HOST 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 forward {
            type filter hook forward priority filter; policy drop;
            ct state established,related accept
            ct state new ip saddr $LOCALNETS accept
           log prefix "--nftables-drop-forward--"
        }
chain output {
                 type filter hook output priority filter; policy drop;
                 ct state established,related 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
     }
  }

Regeln von aussen nach innen

  • Die Regel die eingefügt wird bedeuten folgendes:
  • Ein Paket welches in die Schnittstelle enp0s3 reingeht und den Rechner über enp0s8 verlässt,
  • Sowie an die Zieladresse des Nameservers und an den UDP Zielport 53 gerichtet ist,
  • wird durchgelassen und in der Conntrack-Tabelle aufgenommen.

vim /etc/nftables-vars.conf

define WANDEV = enp0s3
define DMZDEV = enp0s8
define LANDEV = enp0s9
define SERVERDEV = enp0s10
define WANIP = <WANIP der Firewall>
define LAN = 172.26.2XX.0/24
define SERVER = 10.2XX.1.0/24
define MGMT = 172.27.2XX.0/24
define DMZ = 10.88.2XX.0/24
define KIT = <SCHULUNGS NETZ>
define HOST = <EUER HOST>
define LOCALNETS = { $DMZ, $LAN, $SERVER, $MGMT }
define NS = 10.88.2XX.21

vim /etc/nftables.conf

#!/usr/sbin/nft -f
include "/etc/nftables-vars.conf"
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 iif $DMZDEV ip saddr $DMZ tcp dport 22 accept
 	     	 ct state new iif $LANDEV ip saddr $LAN tcp dport 22 accept
 	  	 ct state new iif $SERVERDEV ip saddr $SERVER tcp dport 22 accept
 	 	 ct state new iif $WANDEV ip saddr $HOST 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 forward {
            type filter hook forward priority filter; policy drop;
            ct state established,related accept
            ct state new iif $WANDEV oif $DMZDEV ip daddr $NS udp dport 53 accept
            ct state new ip saddr $LOCALNETS accept
             log prefix "--nftables-drop-forward--"
        }

chain output {
                 type filter hook output priority filter; policy drop;
                 ct state established,related 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
     }
  }

Erklärungen

ct state new iif $WANDEV oif $DMZDEV ip saddr $HOST ip daddr $WWW tcp dport 80 accept
Schlüsselwort / Variable Typ Erklärung
ct state new nftables-Ausdruck Paket-Tracking via Connection Tracking: Trifft auf neue Verbindungen zu (kein bestehendes ct-Entry)
iif Schlüsselwort Eingehendes Interface (Input Interface Flag)
$WANDEV Variable Enthält den Namen des WAN-Interfaces (z. B. eth0), über das das Paket eingeht
oif Schlüsselwort Ausgehendes Interface (Output Interface Flag)
$DMZDEV Variable Enthält den Namen des DMZ-Interfaces (z. B. eth2), über das das Paket weitergeleitet wird
ip saddr Schlüsselwort Quelladresse auf IPv4-Ebene (Source Address)
$HOST Variable Enthält die IPv4-Adresse des erlaubten Quell-Hosts
ip daddr Schlüsselwort Zieladresse auf IPv4-Ebene (Destination Address)
$WWW Variable Enthält die IPv4-Adresse des Ziel-Webservers
tcp dport 80 Ausdruck Protokoll TCP, Zielport 80 (HTTP)
accept Aktion Paket wird akzeptiert und passiert die Regel

old stuff