Nftables Netze absichern: Unterschied zwischen den Versionen

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen
Zeile 280: Zeile 280:
 
  define serverdev = enp0s8
 
  define serverdev = enp0s8
 
  define mgmtdev = enp0s10
 
  define mgmtdev = enp0s10
  define wanip = 192.168.5.113
+
  define wanip = 192.168.5.213
  define lan = 172.17.113.0/24
+
  define lan = 172.17.213.0/24
  define server = 172.16.113.0/24
+
  define server = 172.16.213.0/24
  define mgmt = 172.18.113.0/24
+
  define mgmt = 172.18.213.0/24
  define dmz = 10.88.113.0/24
+
  define dmz = 10.88.213.0/24
 
  define local_tcp_ports = { 22 }
 
  define local_tcp_ports = { 22 }
 
  define localnets = { $lan , $server , $dmz, $server }
 
  define localnets = { $lan , $server , $dmz, $server }

Version vom 23. Juni 2025, 13:34 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}
 
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 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 192.168.5.200 hat, sowie an die Zieladresse 102.88.113.21 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 }

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 "enp0s3" oif "enp0s9" ip saddr 192.168.5.200 ip daddr 10.88.113.21 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"

Aufgabe

kit Host

Der Kit Host soll Vollzugriff auf die Firewall haben.

mail.it1xx.int

22/tcp  open  ssh    (openssh)) (Wir verlegen den Port auf 6666) (Partnernetz und Host  freischalten, ansonsten vpn)
25/tcp  open  smtp  (postfix) (wird frei geschaltet)
80/tcp  open  http  (apache2)  (wird nicht frei geschaltet) 
443/tcp  open  http  (apache2)  (wird frei geschaltet) 
143/tcp open  imap (dovecot) (wird nicht frei geschaltet)  
465/tcp open  smtps (postfix) (wird frei geschaltet)
993/tcp open  imaps  (dovecot) (wird frei geschaltet)
3306 /tcp open mysqld (127.0.0.1)  (mariadb)

www.it1xx.int

22/tcp  open  ssh    (openssh)) (Wir verlegen den Port auf 6666) (Partnernetz und Host freischalten, ansonsten vpn)
80/tcp  open  http  (apache2)  (wird nicht frei geschaltet) 
443/tcp open  https  (apache2) (wird frei geschaltet)

ns.it1xx.int

22/tcp  open  ssh    (openssh)) (Wir verlegen den Port auf 6666) (Partnernetz und Host freischalten, ansonsten vpn)
53/tcp open  domain   (kan mann abschalten, eventuell freigeben für den secondary Nameserver)
53/udp open  domain  (wird frei geschaltet)

fw.itxx.int

22/tcp  open  ssh    (openssh)) (Wir verlegen den Port auf 6666) (Partnernetz und Host freischalten, ansonsten vpn)

Für den Anfang schalten wir allen anderen ausgehenden Verkehr frei Später gehen wir hin und werden nach und nach restriktiver.

DNAT zum client

Man soll über den port 9922 und der äusseren Ip der Firewall per ssh auf den Client auf Port 22 zugreifen
 define client = 172.17.113.49

table inet filter {
   ....
   chain forward {
   type filter hook forward priority filter; policy drop;
   ct state established,related accept
   ...
    ct state new iif $wandev oif $landev ip daddr $client tcp dport 22 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 $client:22
      }
Wir wollen auf die Server ns, mail und www über 6666 auf ssh zugreifen ohne das die Ports auf den Server geändert werden.
  • filter-forward-vor dem-loggen
ct state new iif $wandev oif $landev ip daddr { 10.88.113.21 ,10.88.113.34, 10.88.113.41 }  tcp dport 22 accept
  • nat-prerouting anhängen
ip daddr 10.88.113.21 tcp dport 6666 dnat ip to 10.88.113.21:22
ip daddr 10.88.113.34 tcp dport 6666 dnat ip to 10.88.113.34:22
ip daddr 10.88.113.41 tcp dport 6666 dnat ip to 10.88.113.41:22

old stuff