![Nftables DNAT scheint nicht zu funktionieren](https://rvso.com/image/1615273/Nftables%20DNAT%20scheint%20nicht%20zu%20funktionieren.png)
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“)
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 -E
es 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 nat
Tabelle:
# 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_mark
Es 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
}
:
}