Conntrack konnte seine eigenen TCP-Pakete nicht von einem anderen VRF NATen

Conntrack konnte seine eigenen TCP-Pakete nicht von einem anderen VRF NATen

Ich bin auf ein kniffliges Problem mit Source-NAT gestoßen, als ich mehrere VRF auf einem Debian-basierten Router verwendet habe. Es ist ein bisschen kompliziert zu erklären, also werde ich versuchen, es klar auszudrücken, aber es wird nicht kurz sein, das tut mir leid. Das Problem sollte jedoch leicht zu reproduzieren sein.

Um den „Verwaltungs“-Teil des Routers (SSH und andere Dienste) von seinem Router-Job (Routing und NATing von Paketen) zu isolieren, habe ich versucht, das „MGMT“-VRF im Standard-VRF (einfachere Handhabung mit Service-Sockets) und das Routing-VRF in einem VRF namens „Firewall“ einzurichten.

Das Diagramm kann wie folgt zusammengefasst werden:

Netzwerkdiagramm

Das „Management“-Netzwerk ist 192.168.100.0/24 und wird von einem L3-Switch geroutet, der einen L3 mit der „Firewall“-VRF des Routers über das Netzwerk 10.254.5.0/24 hat. Die dritte Router-Schnittstelle ist die „Internet“-Schnittstelle und Pakete, die durch sie gehen, werden per Source-NAT verarbeitet. Dieses Setup funktioniert für alles im Management-Subnetz recht gut, außer für die eigenen Pakete des Routers, aufgrund von Conntrack.

Über iptables-Regeln:

# Table filter

# chain INPUT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
(some INPUT rules, for ssh, snmp, etc)
-A INPUT -j DROP

# chain FORWARD
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -m conntrack --ctstate INVALID -j DROP
-A FORWARD -o eth2 -j ACCEPT
-A FORWARD -j DROP

# Table nat

# chain POSTROUTING
-A POSTROUTING -o eth2 -j SNAT --to-source 192.168.122.100

Über die Routing-Tabelle:

# default VRF
default via 192.168.100.1 dev eth0 proto static metric 20 
192.168.100.0/24 dev eth0 proto kernel scope link src 192.168.100.90

# firewall VRF
default via 192.168.122.1 dev eth2 proto static metric 20
10.254.5.0/24 dev eth1 proto kernel scope link src 10.254.5.2
192.168.100.0/24 proto bgp metric 20 nexthop via 10.254.5.10 dev eth1 weight 1 
192.168.122.0/24 dev eth2 proto kernel scope link src 192.168.122.100 

Wenn also ein Paket vom Standard-VRF versucht, auf das Internet zuzugreifen, verlässt es eth0, wird vom L3-Switch weitergeleitet, gelangt über eth1 in das Firewall-VRF und wird über eth2 weitergeleitet und per NAT verarbeitet. Da ich die INPUT- und FORWARD-Verbindungen verfolge, ist conntrack etwas verwirrt, wenn das Paket zurückkommt, und weiß nicht, was es mit dem Paket tun soll.

Ich konnte dies für ICMP und UDP beheben, indem ich die Conntrack-Zone in der Rohtabelle verwendete

# Table raw
# chain PREROUTING
-A PREROUTING -i eth0 -j CT --zone 5
# chain OUTPUT
-A OUTPUT -o eth0 -j CT --zone 5

Mit diesen Regeln werden Pakete, die vom Router stammen und durchgehen, eth0markiert zone 5, und wenn Pakete eingehen, eth0werden sie ebenfalls markiert zone 5.

Bei einem Ping auf 8.8.8.8 sieht das dann (mit dem Befehl ) so aus conntrack -E:

    [NEW] icmp     1 30 src=192.168.100.90 dst=8.8.8.8 type=8 code=0 id=1999 [UNREPLIED] src=8.8.8.8 dst=192.168.100.90 type=0 code=0 id=1999 zone=5
    [NEW] icmp     1 30 src=192.168.100.90 dst=8.8.8.8 type=8 code=0 id=1999 [UNREPLIED] src=8.8.8.8 dst=192.168.122.100 type=0 code=0 id=1999
 [UPDATE] icmp     1 30 src=192.168.100.90 dst=8.8.8.8 type=8 code=0 id=1999 src=8.8.8.8 dst=192.168.122.100 type=0 code=0 id=1999
 [UPDATE] icmp     1 30 src=192.168.100.90 dst=8.8.8.8 type=8 code=0 id=1999 src=8.8.8.8 dst=192.168.100.90 type=0 code=0 id=1999 zone=5

Wir können hier sehen, dass die erste Verbindung erstellt wird, wenn das Paket mit dem Tag NEWdurchgeht , und dann eine neue, wenn es ohne Tag durch die Firewall-VRF gelangt. Wenn die Antwort kommt, wird zuerst die zweite Verbindung aktualisiert (da sie zum Internet zeigt) und dann die erste.eth0zone=5eth1

Dies funktioniert auch mit UDP, zum Beispiel mit einer DNS-Abfrage an 8.8.8.8

    [NEW] udp      17 30 src=192.168.100.90 dst=8.8.8.8 sport=53369 dport=53 [UNREPLIED] src=8.8.8.8 dst=192.168.100.90 sport=53 dport=53369 zone=5
    [NEW] udp      17 30 src=192.168.100.90 dst=8.8.8.8 sport=53369 dport=53 [UNREPLIED] src=8.8.8.8 dst=192.168.122.100 sport=53 dport=53369
 [UPDATE] udp      17 30 src=192.168.100.90 dst=8.8.8.8 sport=53369 dport=53 src=8.8.8.8 dst=192.168.122.100 sport=53 dport=53369
 [UPDATE] udp      17 30 src=192.168.100.90 dst=8.8.8.8 sport=53369 dport=53 src=8.8.8.8 dst=192.168.100.90 sport=53 dport=53369 zone=5

Mit TCP klappt es allerdings nicht. Eine Telnet-Anfrage an 172.16.10.10 Port 80 sieht so aus:

    [NEW] tcp      6 120 SYN_SENT src=192.168.100.90 dst=172.16.10.10 sport=60234 dport=80 [UNREPLIED] src=172.16.10.10 dst=192.168.100.90 sport=80 dport=60234 zone=5
    [NEW] tcp      6 120 SYN_SENT src=192.168.100.90 dst=172.16.10.10 sport=60234 dport=80 [UNREPLIED] src=172.16.10.10 dst=192.168.122.100 sport=80 dport=60234
 [UPDATE] tcp      6 58 SYN_RECV src=192.168.100.90 dst=172.16.10.10 sport=60234 dport=80 src=172.16.10.10 dst=192.168.122.100 sport=80 dport=60234
 [UPDATE] tcp      6 57 SYN_RECV src=192.168.100.90 dst=172.16.10.10 sport=60234 dport=80 src=172.16.10.10 dst=192.168.122.100 sport=80 dport=60234
(The last line repeat multiple times)

Wenn ich eth2die Antwort per TCPdump ausgibt, ist sie dort:

IP 192.168.122.100.60236 > 172.16.10.10.80: Flags [S], seq 4203590660, win 62720, options [mss 1460,sackOK,TS val 1511828881 ecr 0,nop,wscale 7], length 0
IP 172.16.10.10.80 > 192.168.122.100.60236: Flags [S.], seq 3672808466, ack 4203590661, win 65535, options [mss 1430,sackOK,TS val 2474659117 ecr 1511828881,nop,wscale 8], length 0
IP 192.168.122.100.60236 > 172.16.10.10.80: Flags [S], seq 4203590660, win 62720, options [mss 1460,sackOK,TS val 1511829887 ecr 0,nop,wscale 7], length 0
IP 172.16.10.10.80 > 192.168.122.100.60236: Flags [S.], seq 3672808466, ack 4203590661, win 65535, options [mss 1430,sackOK,TS val 2474660123 ecr 1511828881,nop,wscale 8], length 0

Da die SIN-ACK jedoch nie bestätigt wird, sendet der Router weiterhin neue SIN.

Wenn ich jetzt tcpdump ausführe eth1:

IP 192.168.100.90.60238 > 172.16.10.10.80: Flags [S], seq 3124513394, win 62720, options [mss 1460,sackOK,TS val 1511928806 ecr 0,nop,wscale 7], length 0
IP 192.168.100.90.60238 > 172.16.10.10.80: Flags [S], seq 3124513394, win 62720, options [mss 1460,sackOK,TS val 1511929823 ecr 0,nop,wscale 7], length 0
IP 192.168.100.90.60238 > 172.16.10.10.80: Flags [S], seq 3124513394, win 62720, options [mss 1460,sackOK,TS val 1511931839 ecr 0,nop,wscale 7], length 0

Wir können sehen, dass die Antwort nie an 192.168.100.90 zurückgeleitet wird.

Wenn ich die Verbindungsverfolgung deaktiviere und alles in iptables zulasse, funktioniert es. Ich denke also, dass conntrack Probleme hat, TCP-Verbindungen von sich selbst zu einer anderen Zone zu verwalten, wenn sie NAT sind? Wenn etwas nicht klar ist, beantworte ich gerne alle Fragen dazu.

Antwort1

Das Problem trat unter Debian 10 mit einem Kernel 4.19.0-12-amd64 auf, aber nach einem Upgrade auf Debian 11 mit einem Kernel 5.10.0-11-amd64 funktioniert es wie erwartet, sogar für TCP-Flows.

verwandte Informationen