Nftables Netze absichern: Unterschied zwischen den Versionen

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen
 
(79 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
<span id="einleitung"></span>
 
 
= Einleitung =
 
= Einleitung =
  
Zeile 6: Zeile 5:
 
* In unserem Beispiel haben wir 3 Netzbereiche.
 
* In unserem Beispiel haben wir 3 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 beiden 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.
  
<!----->
 
<span id="der-plan"></span>
 
 
= 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 42: Zeile 32:
  
 
  #!/usr/sbin/nft -f
 
  #!/usr/sbin/nft -f
  define remote_tcp_ports = { 22,25,53,80,465,443 }
+
  define wandev = enp0s3
  define remote_udp_ports = { 53 }
+
  define wanip = 192.168.5.213
  define local_tcp_ports = { 22,80,443 }
+
  define lan = 172.17.213.0/24
  define wandev = ens18
+
  define server = 172.16.213.0/24
  define dmzdev = ens19
+
  define mgmt = 172.18.213.0/24
define landev = ens20
+
  define dmz = 10.88.213.0/24
  define lan = 192.168.4.0/24
+
 +
define local_tcp_ports = { 22 }
 
   
 
   
 
  flush ruleset
 
  flush ruleset
 
  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
        ct state new tcp dport $local_tcp_ports accept
+
                ct state new iifname "lo" accept
        iif "lo" accept
+
                ct state new tcp dport $local_tcp_ports accept
        log prefix "--nftables-drop-input--"
+
                ct state new icmp type echo-request accept
    }
+
                log prefix "--nftables-drop-input--"
    chain forward {
+
        }
        type filter hook forward 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>
        log prefix "--nftables-drop-forward--"
+
                <span style="color:#FF0000">ct state established,related accept</span>
    }
+
                <span style="color:#FF0000">log prefix "--nftables-drop-forward--"</span>
 +
      <span style="color:#FF0000">}</span>
 
   
 
   
    chain output {
+
        chain output {
        type filter hook output priority filter; policy drop;
+
                type filter hook output priority filter; policy drop;
        ct state established,related accept
+
                ct state established,related accept
        ct state new oif "lo" accept
+
                ct state new oifname "lo" accept
        ct state new tcp dport $remote_tcp_ports accept
+
                ct state new accept
        ct state new udp dport $remote_udp_ports accept
+
                log prefix "--nftables-drop-output--"
        log prefix "--nftables-drop-output--"
+
        }
    }
 
 
  }
 
  }
 +
 
 +
table inet nat {
 +
    chain postrouting {
 +
        type nat hook postrouting priority 100; policy accept;
 +
 +
        oif $wandev ip saddr $lan snat to $wanip
 +
        oif $wandev ip saddr $server snat to $wanip
 +
        oif $wandev ip saddr $mgmt snat to $wanip
 +
        # DMZ wird genattet, außer zu 10.88.0.0/16 und 10.82.89.0/24
 +
        oif $wandev ip saddr $dmz ip daddr != { 10.88.0.0/16, 10.82.89.0/24 } snat to $wanip
 +
    }
  
 
= Forwarding =
 
= Forwarding =
  
* Damit Pakete weitergeleitet werden können, muss als erstes FORWARDING im Kernel aktiviert werden.
+
Damit Pakete weitergeleitet werden können, muss als erstes FORWARDING im Kernel aktiviert werden.
* Aktivierung
+
 
 +
== Aktivierung ==
 +
 
 
* '''echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf'''
 
* '''echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf'''
 
* '''sysctl -p'''
 
* '''sysctl -p'''
  
= Weitere Tabellen =
+
== Weitere Tabellen ==
  
 
* Eine Skizze über die Reihenfolge der Hooks.
 
* Eine Skizze über die Reihenfolge der Hooks.
Zeile 90: Zeile 94:
 
* 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>
 
 
== SNAT ==
 
== SNAT ==
  
Zeile 100: Zeile 102:
  
 
  #!/usr/sbin/nft -f
 
  #!/usr/sbin/nft -f
 +
define wandev = enp0s3
 +
define wanip = 192.168.5.213
 +
define lan = 172.17.213.0/24
 +
define server = 172.16.213.0/24
 +
define mgmt = 172.18.213.0/24
 +
define dmz = 10.88.213.0/24
 +
define local_tcp_ports = { 22 }
 
   
 
   
 
  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
 
 
 
  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
        iif "lo" ct state new accept
+
  ct state new iifname "lo" accept
        ct state new tcp dport 22 accept
+
  ct state new tcp dport $local_tcp_ports accept
        ct state new icmp type echo-request accept
+
  ct state new icmp type echo-request accept
        log prefix "--nftables-drop-input--"
+
  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 {
+
  chain forward {
        type filter hook forward priority filter; policy drop;
+
  type filter hook forward priority filter; policy drop;
        ct state established,related accept
+
  log prefix "--nftables-drop-forward--"
        log prefix "--nftables-drop-forward--"
+
  }
    }
 
 
   
 
   
 +
  chain output {
 +
  type filter hook output priority filter; policy drop;
 +
  ct state established,related accept
 +
  ct state new oifname "lo" accept
 +
  ct state new accept
 +
  log prefix "--nftables-drop-output--"
 +
  }
 
  }
 
  }
 
   
 
   
  '''table inet nat {'''
+
  <span style="color:#FF0000">table inet nat {</span>
    '''chain prerouting {'''
+
  <span style="color:#FF0000"> chain postrouting {</span>
        '''type nat hook prerouting priority dstnat; policy accept;'''
+
<span style="color:#FF0000">  type nat hook postrouting priority 100; policy accept;</span>
    '''}'''
+
<span style="color:#FF0000">  oif $wandev ip saddr $lan snat to $wanip</span>
   
+
<span style="color:#FF0000">  oif $wandev ip saddr $server snat to $wanip</span>
    '''chain postrouting {'''
+
<span style="color:#FF0000">  oif $wandev ip saddr $mgmt snat to $wanip</span>
        '''type nat hook postrouting priority srcnat; policy accept;'''
+
<span style="color:#FF0000">  # DMZ wird genattet, außer zu 10.88.0.0/16 und 10.82.89.0/24</span>
        '''oif $wandev ip saddr $lan snat ip to $wanip'''
+
<span style="color:#FF0000">  oif $wandev ip saddr $dmz ip daddr != { 10.88.0.0/16, 10.82.89.0/24 } snat to $wanip</span>
    '''}'''
+
  <span style="color:#FF0000"> }</span>
   
+
  <span style="color:#FF0000">}</span>
  '''}'''
+
 
 
Neu verwendete Syntax:
 
Neu verwendete Syntax:
  
Zeile 156: Zeile 156:
 
  oif ''device_name''
 
  oif ''device_name''
  
* IPv4-Adresse des Ursprungpaketes
+
* matche IPv4-Adresse des Ursprungpaketes
  
  ip saddr ''<source address>''
+
  ip saddr ''<source_ip>''
  
 
* Die Ursprungs-IP auf eine andere Adresse natten
 
* Die Ursprungs-IP auf eine andere Adresse natten
Zeile 164: Zeile 164:
 
  snat ip to ''<new_source_ip>''
 
  snat ip to ''<new_source_ip>''
  
== Portforwarding ==
+
=Forward von innen nach aussen=
 
+
*Wir wollen das unsere Clients und die Server vorerst nach aussen alles dürfen.
* 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
   
+
  define wandev = enp0s3
  flush ruleset
+
  define wanip = 192.168.5.213
   
+
  define lan = 172.17.213.0/24
 +
define server = 172.16.213.0/24
 +
define mgmt = 172.18.213.0/24
 +
define dmz = 10.88.213.0/24
 +
define local_tcp_ports = { 22 }
 +
  <span style="color:#FF0000">define localnets = { $lan , $server , $dmz, $mgmt}</span>
 +
 
 
  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 {
+
  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
        iif "lo" ct state new accept
+
  ct state new iifname "lo" accept
        ct state new tcp dport 22 accept
+
  ct state new tcp dport $local_tcp_ports accept
        ct state new icmp type echo-request accept
+
  ct state new icmp type echo-request accept
        log prefix "--nftables-drop-input--"
+
  log prefix "--nftables-drop-input--"
    }
+
  }
 
   
 
   
    chain output {
+
  chain forward {
        type filter hook output priority filter; policy drop;
+
  type filter hook forward priority filter; policy drop;
        ct state established,related,new accept
+
  <span style="color:#FF0000">ct state established,related accept</span>
        log prefix "--nftables-drop-output--"
+
  <span style="color:#FF0000">ct state new ip saddr $localnets accept</span>
    }
+
  log prefix "--nftables-drop-forward--"
 +
  }
 
   
 
   
    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
        '''iif $wandev ip daddr $webserver tcp dport 22 accept'''
+
  ct state new oifname "lo" accept
        '''iif $wandev ip daddr $webserver tcp dport 80 accept'''
+
  ct state new accept
        log prefix "--nftables-drop-forward--"
+
  log prefix "--nftables-drop-output--"
    }
+
  }
 +
}
 
   
 
   
}
 
 
  table inet nat {
 
  table inet nat {
    chain prerouting {
+
  chain postrouting {
        type nat hook prerouting priority dstnat; policy accept;
+
  type nat hook postrouting priority 100; policy accept;
        '''ip daddr $wanip tcp dport 9922 dnat ip to $webserver:22'''
+
  oif $wandev ip saddr $lan snat to $wanip
        '''ip daddr $wanip tcp dport 80 dnat ip to $webserver:80'''
+
  oif $wandev ip saddr $server snat to $wanip
    }
+
  oif $wandev ip saddr $mgmt snat to $wanip
+
  # DMZ wird genattet, außer zu 10.88.0.0/16 und 10.82.89.0/24
    chain postrouting {
+
  oif $wandev ip saddr $dmz ip daddr != { 10.88.0.0/16, 10.82.89.0/24 } snat to $wanip
        type nat hook postrouting priority srcnat; policy accept;
+
  }
        oif $wandev ip saddr $lan snat ip to $wanip
 
    }
 
 
  }
 
  }
  
* Nun kann man per SSH auf den Rechner hinter der Firewall über Port 9922 der Firewall zugreifen...
+
=Unsere Netze dürfen auf die Firewall andere nicht=
* '''ssh ''user@WEBSERVER'' -p 9922'''
+
*Wir wollen das unsere Clients und die Server vorerst nach aussen alles dürfen.
* ... und HTTP-Requests an den Rechner hinter der Firewall schicken
 
* '''curl ''WEBSERVER'''''
 
 
 
= 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.
 
 
 
 
  #!/usr/sbin/nft -f
 
  #!/usr/sbin/nft -f
   
+
define wandev = enp0s3
 +
<span style="color:#FF0000">define dmzdev = enp0s9</span>
 +
<span style="color:#FF0000">define landev = enp0s8</span>
 +
<span style="color:#FF0000">define serverdev = enp0s10</span>
 +
define wanip = 192.168.5.213
 +
define lan = 172.17.213.0/24
 +
define server = 172.16.213.0/24
 +
define mgmt = 172.18.213.0/24
 +
define dmz = 10.88.213.0/24
 +
define local_tcp_ports = { 22 }
 +
define localnets = { $lan , $server , $dmz, $server}
 +
<span style="color:#FF0000">define host = 192.168.10.200</span>  
 
  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 {
+
  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
        iif "lo" ct state new accept
+
  ct state new iifname "lo" accept
        ct state new tcp dport 22 accept
+
  <span style="color:#FF0000">ct state new iif $landev ip saddr $lan tcp dport $local_tcp_ports accept</span>
        ct state new icmp type echo-request accept
+
  <span style="color:#FF0000">ct state new iif $dmzdev ip saddr $dmz tcp dport $local_tcp_ports accept</span>
        log prefix "--nftables-drop-input--"
+
  <span style="color:#FF0000">ct state new iif $serverdev ip saddr $server tcp dport $local_tcp_ports accept</span>
    }
+
  <span style="color:#FF0000">ct state new iif $wandev ip saddr $host tcp dport $local_tcp_ports accept</span>
 +
  ct state new icmp type echo-request accept
 +
  log prefix "--nftables-drop-input--"
 +
  }
 
   
 
   
    chain output {
+
  chain forward {
        type filter hook output priority filter; policy drop;
+
  type filter hook forward priority filter; policy drop;
        ct state established,related,new accept
+
  ct state established,related accept
        log prefix "--nftables-drop-output--"
+
  ct state new saddr $localnets accept
    }
+
  log prefix "--nftables-drop-forward--"
   
+
  }
    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 {
+
  chain output {
        type nat hook postrouting priority srcnat; policy accept;
+
  type filter hook output priority filter; policy drop;
        oif $wandev ip saddr $lan snat ip to $wanip
+
  ct state established,related accept
    }
+
  ct state new oifname "lo" accept
 +
  ct state new accept
 +
  log prefix "--nftables-drop-output--"
 +
  }
 
  }
 
  }
 
Neu verwendete Syntax:
 
 
Bestimmte Ziel-Ports angeben
 
 
''transport_protocol'' dport { ''port_number_1,port_number_2,...'' }
 
 
= 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 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 {
 
  table inet nat {
    chain prerouting {
+
  chain postrouting {
        type nat hook prerouting priority dstnat; policy accept;
+
  type nat hook postrouting priority 100; policy accept;
        ip daddr $wanip tcp dport 9922 dnat ip to $webserver:22
+
  oif $wandev ip saddr $lan snat to $wanip
        ip daddr $wanip tcp dport 80 dnat ip to $webserver:80
+
  oif $wandev ip saddr $server snat to $wanip
    }
+
  oif $wandev ip saddr $mgmt snat to $wanip
   
+
  # DMZ wird genattet, außer zu 10.88.0.0/16 und 10.82.89.0/24
    chain postrouting {
+
  oif $wandev ip saddr $dmz ip daddr != { 10.88.0.0/16, 10.82.89.0/24 } snat to $wanip
        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.
+
=Regeln von aussen nach innen=
* Dafür fügt man ’‘’limit rate’’’ in die Regel ein.
+
*Die Regel die eingefügt wurde bedeutet folgendes:
* Falls nur 5 Pakete pro Minute geloggt werden sollen:
+
*Ein Paket welches in die Schnittstelle enp0s3 reingeht und den Rechner über enp0s9 verlässt.
 +
*und die Absendeadresse Host hat, sowie an die Zieladresse des Nameserver und an den Zielport 22 gerichtet ist.
 +
*wird durch gelassen und in den Conntrack Tabelle aufgenommen.
  
<!----->
 
 
  #!/usr/sbin/nft -f
 
  #!/usr/sbin/nft -f
 +
define wandev = enp0s3
 +
define landev = enp0s9
 +
define serverdev = enp0s8
 +
define mgmtdev = enp0s10
 +
define wanip = 192.168.5.213
 +
define lan = 172.17.213.0/24
 +
define server = 172.16.213.0/24
 +
define mgmt = 172.18.213.0/24
 +
define dmz = 10.88.213.0/24
 +
define local_tcp_ports = { 22 }
 +
define localnets = { $lan , $server , $dmz, $server }
 +
define host = 192.168.10.200
 +
define ns = 10.88.213.21
 
   
 
   
 
  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 {
+
  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 iifname "lo" accept
        ct state new tcp dport 22 accept
+
  ct state new iifname $landev ip saddr $lan tcp dport $local_tcp_ports accept
        ct state new icmp type echo-request accept
+
  ct state new iifname $dmzdev ip saddr $dmz tcp dport $local_tcp_ports accept
        '''limit rate 5/minute''' log prefix "--nftables-drop-input--"
+
  ct state new iifname $serverdev ip saddr $server tcp dport $local_tcp_ports 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
 
        '''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
+
  chain forward {
define wandev = ens18
+
  type filter hook forward priority filter; policy drop;
define landev = ens19
+
  ct state established,related accept
define wanip = 10.82.232.11
+
  <span style="color:#FF0000"> ct state new iif $wandev oif $dmzdev ip saddr $host ip daddr $ns tcp dport 22 accept
define lan = 192.168.4.0/24
+
</span>
'''define vpn = 192.168.178.0/24'''
+
 
define webserver = 192.168.4.12
+
  ct state new ip saddr $localnets accept
 +
  log prefix "--nftables-drop-forward--"
 +
  }
 
   
 
   
table inet filter {
+
  chain output {
    chain input {
+
  type filter hook output priority filter; policy drop;
        type filter hook input priority filter; policy drop;
+
  ct state established,related accept
        ct state established,related accept
+
  ct state new oifname "lo" accept
        iifname "lo" ct state new accept
+
  ct state new accept
        ct state new tcp dport 22 accept
+
  log prefix "--nftables-drop-output--"
        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 {
 
    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 {
 
  table inet nat {
    chain prerouting {
+
  chain postrouting {
        type nat hook prerouting priority dstnat; policy accept;
+
  type nat hook postrouting priority 100; policy accept;
        meta nfproto ipv4 ip daddr $wanip tcp dport 9922 dnat ip to $webserver:22
+
  oif $wandev ip saddr $lan snat to $wanip
        meta nfproto ipv4 ip daddr $wanip tcp dport 80 dnat ip to $webserver:80
+
  oif $wandev ip saddr $server snat to $wanip
    }
+
  oif $wandev ip saddr $mgmt snat to $wanip
    chain postrouting {
+
  # DMZ wird genattet, außer zu 10.88.0.0/16 und 10.82.89.0/24
        type nat hook postrouting priority srcnat; policy accept;
+
  oif $wandev ip saddr $dmz ip daddr != { 10.88.0.0/16, 10.82.89.0/24 } snat to $wanip
        oifname $wandev ip saddr $lan '''ip daddr != $vpn''' snat ip 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
 
  
<!----->
+
=Man kann die Variablen auch auslagern=
15:27:31.091907 IP fw-linkai > 10.82.228.2: ESP(spi=0xc668795e,seq=0x4), length 136
+
;Wichtig sind die Anführungszeichen
15:27:31.093913 IP 10.82.228.2 > fw-linkai: ESP(spi=0xccf83bd8,seq=0x4), length 136
+
  include "/etc/nftables.var"
15:27:31.093913 IP 192.168.178.2 > 192.168.4.1: ICMP echo reply, id 32171, seq 1, length 64
+
=old stuff=
  15:27:32.093502 IP fw-linkai > 10.82.228.2: ESP(spi=0xc668795e,seq=0x5), length 136
+
*[[nftables-net-oldstuff]]
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 25. Juli 2025, 12:11 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 3 Netzbereiche.

WAN

  • Wide Area Net steht für alles was nicht die anderen beiden 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.

Der Plan

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.conf
#!/usr/sbin/nft -f
define wandev = enp0s3
define wanip = 192.168.5.213
define lan = 172.17.213.0/24
define server = 172.16.213.0/24
define mgmt = 172.18.213.0/24
define dmz = 10.88.213.0/24

define local_tcp_ports = { 22 } 

flush ruleset
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 $local_tcp_ports accept
               ct state new icmp type echo-request 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 oifname "lo" accept
               ct state new accept
               log prefix "--nftables-drop-output--"
       }
}
 
table inet nat {
   chain postrouting {
       type nat hook postrouting priority 100; policy accept;

       oif $wandev ip saddr $lan snat to $wanip
       oif $wandev ip saddr $server snat to $wanip
       oif $wandev ip saddr $mgmt snat to $wanip
       # DMZ wird genattet, außer zu 10.88.0.0/16 und 10.82.89.0/24
       oif $wandev ip saddr $dmz ip daddr != { 10.88.0.0/16, 10.82.89.0/24 } snat to $wanip
   }

Forwarding

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.
  • Als erstes greift der Prerouting-Hook
  • Je nachdem wie geroutet wird greift dann entweder Input- oder Fowrward-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

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.
#!/usr/sbin/nft -f
define wandev = enp0s3
define wanip = 192.168.5.213
define lan = 172.17.213.0/24
define server = 172.16.213.0/24
define mgmt = 172.18.213.0/24
define dmz = 10.88.213.0/24
define local_tcp_ports = { 22 }

flush ruleset
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 $local_tcp_ports accept
  ct state new icmp type echo-request accept
  log prefix "--nftables-drop-input--"
 }

 chain forward {
  type filter hook forward priority filter; policy drop;
  log prefix "--nftables-drop-forward--"
 }

 chain output {
  type filter hook output priority filter; policy drop;
  ct state established,related accept
  ct state new oifname "lo" accept
  ct state new accept
  log prefix "--nftables-drop-output--"
 }
}

table inet nat {
 chain postrouting {
  type nat hook postrouting priority 100; policy accept;
  oif $wandev ip saddr $lan snat to $wanip
  oif $wandev ip saddr $server snat to $wanip
  oif $wandev ip saddr $mgmt snat to $wanip
  # DMZ wird genattet, außer zu 10.88.0.0/16 und 10.82.89.0/24
  oif $wandev ip saddr $dmz ip daddr != { 10.88.0.0/16, 10.82.89.0/24 } snat 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_ip>
  • Die Ursprungs-IP auf eine andere Adresse natten
snat ip to <new_source_ip>

Forward von innen nach aussen

  • Wir wollen das unsere Clients und die Server vorerst nach aussen alles dürfen.
#!/usr/sbin/nft -f
define wandev = enp0s3
define wanip = 192.168.5.213
define lan = 172.17.213.0/24
define server = 172.16.213.0/24
define mgmt = 172.18.213.0/24
define dmz = 10.88.213.0/24
define local_tcp_ports = { 22 }
 define localnets = { $lan , $server , $dmz, $mgmt}
 
flush ruleset
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 $local_tcp_ports accept
  ct state new icmp type echo-request 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 oifname "lo" accept
  ct state new accept
  log prefix "--nftables-drop-output--"
 }
}

table inet nat {
 chain postrouting {
  type nat hook postrouting priority 100; policy accept;
  oif $wandev ip saddr $lan snat to $wanip
  oif $wandev ip saddr $server snat to $wanip
  oif $wandev ip saddr $mgmt snat to $wanip
  # DMZ wird genattet, außer zu 10.88.0.0/16 und 10.82.89.0/24
  oif $wandev ip saddr $dmz ip daddr != { 10.88.0.0/16, 10.82.89.0/24 } snat to $wanip
 }
}

Unsere Netze dürfen auf die Firewall andere nicht

  • Wir wollen das unsere Clients und die Server vorerst nach aussen alles dürfen.
#!/usr/sbin/nft -f
define wandev = enp0s3
define dmzdev = enp0s9
define landev = enp0s8
define serverdev = enp0s10
define wanip = 192.168.5.213
define lan = 172.17.213.0/24
define server = 172.16.213.0/24
define mgmt = 172.18.213.0/24
define dmz = 10.88.213.0/24
define local_tcp_ports = { 22 }
define localnets = { $lan , $server , $dmz, $server}
define host = 192.168.10.200  
flush ruleset
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 iif $landev ip saddr $lan tcp dport $local_tcp_ports accept
  ct state new iif $dmzdev ip saddr $dmz tcp dport $local_tcp_ports accept
  ct state new iif $serverdev ip saddr $server tcp dport $local_tcp_ports accept
  ct state new iif $wandev ip saddr $host tcp dport $local_tcp_ports accept
  ct state new icmp type echo-request accept
  log prefix "--nftables-drop-input--"
 }

 chain forward {
  type filter hook forward priority filter; policy drop;
  ct state established,related accept
  ct state new 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 oifname "lo" accept
  ct state new accept
  log prefix "--nftables-drop-output--"
 }
}

table inet nat {
 chain postrouting {
  type nat hook postrouting priority 100; policy accept;
  oif $wandev ip saddr $lan snat to $wanip
  oif $wandev ip saddr $server snat to $wanip
  oif $wandev ip saddr $mgmt snat to $wanip
  # DMZ wird genattet, außer zu 10.88.0.0/16 und 10.82.89.0/24
  oif $wandev ip saddr $dmz ip daddr != { 10.88.0.0/16, 10.82.89.0/24 } snat to $wanip
 }
}

Regeln von aussen nach innen

  • Die Regel die eingefügt wurde bedeutet folgendes:
  • Ein Paket welches in die Schnittstelle enp0s3 reingeht und den Rechner über enp0s9 verlässt.
  • und die Absendeadresse Host hat, sowie an die Zieladresse des Nameserver und an den Zielport 22 gerichtet ist.
  • wird durch gelassen und in den Conntrack Tabelle aufgenommen.
#!/usr/sbin/nft -f
define wandev = enp0s3
define landev = enp0s9
define serverdev = enp0s8
define mgmtdev = enp0s10
define wanip = 192.168.5.213
define lan = 172.17.213.0/24
define server = 172.16.213.0/24
define mgmt = 172.18.213.0/24
define dmz = 10.88.213.0/24
define local_tcp_ports = { 22 }
define localnets = { $lan , $server , $dmz, $server }
define host = 192.168.10.200 
define ns = 10.88.213.21

flush ruleset
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 iifname $landev ip saddr $lan tcp dport $local_tcp_ports accept
  ct state new iifname $dmzdev ip saddr $dmz tcp dport $local_tcp_ports accept
  ct state new iifname $serverdev ip saddr $server tcp dport $local_tcp_ports accept
  ct state new icmp type echo-request 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 saddr $host ip daddr $ns tcp dport 22 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 oifname "lo" accept
  ct state new accept
  log prefix "--nftables-drop-output--"
 }
}

table inet nat {
 chain postrouting {
  type nat hook postrouting priority 100; policy accept;
  oif $wandev ip saddr $lan snat to $wanip
  oif $wandev ip saddr $server snat to $wanip
  oif $wandev ip saddr $mgmt snat to $wanip
  # DMZ wird genattet, außer zu 10.88.0.0/16 und 10.82.89.0/24
  oif $wandev ip saddr $dmz ip daddr != { 10.88.0.0/16, 10.82.89.0/24 } snat to $wanip
 }
}

Man kann die Variablen auch auslagern

Wichtig sind die Anführungszeichen
include "/etc/nftables.var"

old stuff