Nftables Netze absichern: Unterschied zwischen den Versionen

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen
Linkai.zhang (Diskussion | Beiträge)
 
(179 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 oifname "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
        iifname "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;'''
        '''oifname $wandev ip saddr $lan snat ip to $wanip'''
    '''}'''
'''}'''
Neu verwendete Syntax:


* Definieren einer Variable
=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 ''variable_name'' = ''value''
{{vorlage:nftables-vars.conf}}
* Interface des herausgehenden Paketes:
===vim /etc/nftables.conf===
 
<!----->
oifname ''device name''
<ul>
<li><p>IPv4-Adresse des Ursprungpaketes</p>
<p>ip saddr ’‘<source address>’’</p></li></ul>
 
<span id="portforwarding"></span>
== 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.
 
<!----->
  #!/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;
        iifname "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
        '''iifname $wandev meta nfproto ipv4 ip daddr $webserver tcp dport 22 accept'''
        '''iifname $wandev meta nfproto ipv4 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;
        '''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
    }
  }
  }
Nun kann man mit:
{{vorlage:nat2}}
 
* ssh ''user@WEBSERVER'' -p 9922 auf den Rechner hinter der Firewall zugreifen
* curl ''WEBSERVER'' HTTP-Requests an den Rechner hinter der Firewall schicken


<!----->
=Regeln von aussen nach innen=
<span id="absichern-von-netzen"></span>
* Die Regel die eingefügt wird bedeuten folgendes:
= Absichern von Netzen =
* 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,
Momentan wird nichts vom LAN zum WAN weitergeleitet. Um nur bestimmte Anwendungen zu erlauben kann man die für diese designierten Ports freischalten.
* wird durchgelassen und in der Conntrack-Tabelle aufgenommen.
===vim /etc/nftables-vars.conf===
{{vorlage:nftables-vars.conf}}
<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
        iifname "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
        iifname $wandev meta nfproto ipv4 ip daddr $webserver tcp dport 22 accept
        iifname $wandev meta nfproto ipv4 ip daddr $webserver tcp dport 80 accept
        '''ct state new iifname $landev oifname $wandev ip saddr $lan icmp type echo-request accept'''
        '''ct state new iifname $landev oifname $wandev ip saddr $lan udp dport 53 accept'''
        '''ct state new iifname $landev oifname $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;
        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
    }
}
Neu verwendete Syntax:


Bestimmte Ziel-Ports angeben
  chain forward {
 
            type filter hook forward priority filter; policy drop;
''transport_protocol'' dport { ''port number'' }
            ct state established,related accept
<span id="eigene-ketten"></span>
            <span style="color:#FF0000">ct state new iif $WANDEV oif $DMZDEV ip daddr $NS udp dport 53 accept</span>
= Eigene Ketten =
            ct state new ip saddr $LOCALNETS accept
 
              log prefix "--nftables-drop-forward--"
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 iifname "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 iifname $wandev ip daddr $webserver tcp dport 22 accept
        ct state new iifname $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 iifname $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;
        oifname $wandev ip saddr $lan snat ip to $wanip
    }
}
Neu verwendete Syntax:
 
Springe in eine andere Kette
 
jump ''target''
<span id="limits-setzten"></span>
= 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
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 {
{{vorlage:output.conf}}
    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