Nftables DNAT scheint nicht zu funktionieren

Nftables DNAT scheint nicht zu funktionieren

Ich versuche, mithilfe von nftables ein DNAT auf meinem neuen CentOS 8 einzurichten. Dieses Dienstprogramm (und CentOS 8) ist neu für mich, ich verwende seit Ewigkeiten iptables (CentOS bis 6).

Ich gehe davon aus, dass ich etwas nicht richtig eingerichtet habe, damit DNAT greift. Es kann aber auch sein, dass ich die Tools einfach nicht richtig verwende. Oder beides.

Falls es von Bedeutung ist, hier ist eine meiner früheren Fragen zu einigen Routing-Problemen auf derselben Box:Mehrere Internetverbindungen, eingehende Pakete am falschen NIC-Port (Problem beim eingehenden Routing?)(Problem war ein ARP-Fluss, gelöst).

Hier unten ist eine Skizze meines aktuellen Setups und die blaue Linie markiert, was passieren soll (der erwartete „Pfad“)

Bildbeschreibung hier eingeben

Grundsätzlich kommen Pakete aus dem Internet, gehen über Schnittstelle 2 (ens2) und werden über die lokale Schnittstelle (ens5, lokale IP 192.168.1.10) an 192.168.1.2 weitergeleitet. (Sobald dies funktioniert, wird dasselbe für ens 3 und 4 eingerichtet und geht an ein paar verschiedene VMs im selben LAN.)

Ich habe überprüft, dass die Pakete über die richtige Schnittstelle eingehen (die erwarteten NFT-Protokollauslöser), conntrack -Ees wird jedoch nichts angezeigt.

Außerdem zeigt die iptables-Protokollierung auf der CentOS 6-Box (dem eigentlichen Ziel, 192.168.1.2) nichts an (dieselbe Protokollierung, die vor langer Zeit eingerichtet wurde, zeigte bei meiner letzten Überprüfung vor ein paar Monaten die erwartete Ausgabe, also sollte diese Box theoretisch in Ordnung sein).

Hier ist mein Nftables-Skript in seinem aktuellen Zustand, mit entsprechend der Skizze übersetzten IPs/IFs.

table ip nat {
    chain PREROUTING {
            type nat hook prerouting priority -100; policy accept;
            iif "ens2" goto PREROUTING_RDS2
            iif "ens3" goto PREROUTING_RDS3
    }

    chain PREROUTING_RDS2 {
            tcp dport { http, https } log prefix "RDS2_dnat-3 "
            tcp dport { http, https } dnat to IP_6
    }

    chain PREROUTING_RDS3 {
            tcp dport { http, https } log prefix "RDS3_dnat-3 "
            tcp dport { http, https } dnat to IP_6
    }
}

table inet filter {
    chain INPUT {
            type filter hook input priority 0; policy drop;
            #
            iif "lo" accept
            #
            # allow ping
            ip protocol icmp icmp type echo-request limit rate 1/second log prefix "PING "
            ip protocol icmp icmp type echo-request limit rate 1/second accept
            # following is required and must be BEFORE the ct state established otherwise the ping flooding will not be stopped
            ip protocol icmp drop
            #
            ct state established,related accept
            ct status dnat accept
            #
            iifname "ens5" goto INPUT_LOCAL
            #
            # now we drop the rest
            ct state invalid log prefix "INPUT_STATE_INVALID_DROP: "
            ct state invalid drop
            log prefix "INPUT_FINAL_REJECT: "
            reject with icmpx type admin-prohibited
    }

    chain FILTER {
            type filter hook forward priority 50; policy drop;
            iif "ens2" goto FILTER_RDS2
            iif "ens3" goto FILTER_RDS3
    }

    chain INPUT_LOCAL {
            tcp dport ssh goto INPUT_LOCAL_ssh
    }

    chain INPUT_LOCAL_ssh {
            ip saddr IP_MY_PC accept
    }

    chain FILTER_RDS2 {
            oifname "ens5" ip daddr IP_6 tcp dport { http, https } accept
    }

    chain FILTER_RDS3 {
            oifname "ens5" ip daddr IP_6 tcp dport { http, https } accept
    }
}

Vielen Dank im Voraus.

Antwort1

Tatsächlich ist diese Frage schwer zu beantworten, ohne einen genauen Blick auf dievorherige Frage/AntwortLösen der anfänglichen Einrichtung fürcentos8. Die Lösung wird sehr komplex. Angesichts der Art der Konfiguration, die dafür eingerichtet werden muss, lohnt es sich wahrscheinlich nicht, eine IP pro Schnittstelle zu haben, wenn mehrere Schnittstellen im selben LAN sind, anstatt alle IPs auf derselben Schnittstelle zu haben, insbesondere wenn man bedenkt, dass es sich um eine virtuelle Umgebung handelt: Es wird keine Beschleunigung geben. Jede Änderung an der Konfiguration muss sich in allen folgenden Befehlen widerspiegeln, daher wird es schwierig sein, dies richtig zu verwalten.


centos8Router

Da zur Lösung des Problems mehrerer Schnittstellen im selben LAN zusätzliche Routingtabellen vorhanden sind,centos8als Router fungiert, müssen weitere Routeneinträge aus der Haupttabelle in die zusätzlichen Routingtabellen dupliziert werden:

# ip route add 192.168.1.0/24 dev ens5 table 1001 src 192.168.1.10 
# ip route add 192.168.1.0/24 dev ens5 table 1002 src 192.168.1.10 
# ip route add 192.168.1.0/24 dev ens5 table 1003 src 192.168.1.10 
# ip route add 192.168.1.0/24 dev ens5 table 1004 src 192.168.1.10 

Andernfalls wird jedes Paket empfangen aufens1,ens2,ens3oderens4Unddnatdurchens5wird versagenRückwärtspfadfilterda es keinen Weg durch gibtens5auf diesen Tischen.

Natürlich ist das nicht genug: Es gibt keine Informationen in den Antwortpaketen (z.B.: zurückkommen voncentos6) darüber, welche Schnittstelle verwendet wurde und umgekehrt wiederverwendet werden sollte. Daher muss diese Information pro Flow mithilfe von Netfilters Conntrack gespeichert werden. Löschen Sie in den Nftables-Regeln die gesamte ip natTabelle:

# nft delete table ip nat

und ersetzen Sie es durch diese neue Tabelle ip markandnat:

# nft -f - << 'EOF'
table ip markandnat {
        map iif2mark {
                type iface_index : mark;
                elements = {
                        ens1 : 101,
                        ens2 : 102,
                        ens3 : 103,
                        ens4 : 104
                }
        }

        map mark2daddr {
                type mark : ipv4_addr;
                elements = {
                        102 : 192.168.1.2,
                        103 : 192.168.1.2, # same IP, as per OP's config
                        104 : 192.168.1.4  # some other VM
                }
        }
        chain premark {
                type filter hook prerouting priority -150; policy accept;
                meta mark set ct mark meta mark != 0 return
                meta mark set iif map @iif2mark meta mark != 0 ct mark set meta mark
        }

        chain prenat {
                type nat hook prerouting priority -100; policy accept;
                tcp dport { http, https } dnat to meta mark map @mark2daddr
        }
}
EOF

Dies wird Schnittstelle => Markierung => dnat Ziel zuordnen, während die Markierung als Markierung von conntrack gespeichert wird (siehe den Link am Ende überconnmarkVerwendung). Jetzt ist diese Markierung verfügbar und wird vom Routing-Stack verwendet, indem die folgenden Regeln hinzugefügt werden, um auf dieselben zusätzlichen Routing-Tabellen zu verweisen:

# ip rule add pref 11001 fwmark 101 table 1001
# ip rule add pref 11002 fwmark 102 table 1002
# ip rule add pref 11003 fwmark 103 table 1003
# ip rule add pref 11004 fwmark 104 table 1004

aber es fehlt noch ein Teil: nochmal zum Reverse Path Filter. Wenn Markierungen verwendet werden, führt der Reverse Path Filter keine erneute Prüfung anhand der durch die Markierungen geänderten neuen Routen durch und schlägt normalerweise fehl. Tatsächlich gibt es einenundokumentierte Funktion, hinzugefügt im Kernel 2.6.33/2.6.32.8 in 2009/2010, das dieses Problem zufällig löst, ohne dass der lose Reverse-Path-Modus verwendet werden muss: src_valid_mark.

# sysctl -w net.ipv4.conf.ens1.src_valid_mark=1
# sysctl -w net.ipv4.conf.ens2.src_valid_mark=1
# sysctl -w net.ipv4.conf.ens3.src_valid_mark=1
# sysctl -w net.ipv4.conf.ens4.src_valid_mark=1

centos6Server

Wenn Sie vorübergehend ein alternatives Gateway verwenden möchten, ist dies möglich, auch wenn dies die Komplexität erhöht und möglicherweise unvorhergesehene subtile Nebenwirkungen verursacht. Dies geschieht wiederum durch die Verwendung von Markierungen. Da es sich um CentOS 6 handelt,Nftablesist nicht verfügbar, alsoiptablesverwendet wird.

Ich werde das berücksichtigencentos6VM hat IP 192.168.1.2/24 auf (eindeutiger) Schnittstelleeth0und Standard-GW 192.168.1.1. Fügen wir eine neue Routing-Tabelle und Regel für das alternative Gateway 192.168.1.10 hinzu:

# ip route add table 10 default via 192.168.1.10
# ip rule add fwmark 10 lookup 10

Lege dasiptablesRegeln (hier nur dieMangelTabelle wird benötigt):

# iptables-restore << 'EOF'
*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A PREROUTING -j CONNMARK --restore-mark
-A PREROUTING -m mark ! --mark 0 -j RETURN
-A PREROUTING -i eth0 -p tcp -m tcp --dport 80 -j MARK --set-mark 10
-A PREROUTING -i eth0 -p tcp -m tcp --dport 443 -j MARK --set-mark 10
-A PREROUTING -m mark ! --mark 0 -j CONNMARK --save-mark
-A OUTPUT -m connmark ! --mark 0 -j CONNMARK --restore-mark
COMMIT
EOF

Jetzt markiert jeder Datenfluss, der über die Ports 80 oder 443 empfangen wird, die eingehenden Pakete und ihre Antworten. Diese Markierung wird vom Routing-Stack verwendet, um das Gateway für eingehende Pakete und Antworten auf 192.168.1.10 zu ändern (mangle/AUSGABElöst eine Umleitungsprüfung aus, siehe 2. Link unten).

src_valid_markEs scheint, dass es in diesem Fall nicht notwendig ist, es zu verwenden , aber setzen Sie es einfach oder setzen Sie es rp_filter=2, wenn es nicht funktioniert. Diese Einstellung erlaubt nicht auch den Empfangdnatgeleiteter Verkehr über 192.168.1.1.


Einige Links:

Antwort2

Den Kommentaren zufolge ist das unmittelbarste und wichtigste Versäumnis, die IP-Weiterleitung zu deaktivieren. Einfach:

echo 1 > /proc/sys/net/ipv4/ip_forward

und prüfen Sie, ob die DNATted-Pakete jetzt bei IP6 ankommen.

Das zweite Problem ist das asymmetrische Routing. Die DNAT-Pakete gelangen über 192.168.1.10 (IP5) zu IP6, wo sie geändert werden (die Zieladresse wird geändert). Die Rückpakete gehen über das Standard-Gateway im LAN (182.168.1.1) und werden auf dem Weg zum Verbindungsursprung nicht geändert. Sie behalten wahrscheinlich ihre RFC1918-Adresse oder werden auf 192.168.1.1 per SNAT an eine andere Adresse weitergeleitet und passen nie zu einer Verbindung an ihrem Ziel und werden wahrscheinlich verworfen.

BEARBEITEN:

Um die FORWARD-Kette anzusprechen, würde ich sie wie folgt umschreiben (meiner Meinung nach viel einfacher):

table inet filter {
:
    chain FORWARD {
            type filter hook forward priority 0; policy drop;
            ct state established,related accept
            ct status dnat accept
    }
:
}

verwandte Informationen