%20mit%20NAT%20und%20Bridging%20f%C3%BCr%20VMs.png)
Mein Setup:
In diesem Setup gibt es nur eine physische Maschine, ein Hostsystem für virtuelle Maschinen (VMs) mit zwei Netzwerkadaptern.
Eine Netzwerkkarte (eth0) ist an ein internes Netzwerk (LAN-Subnetz, z. B. 10.xxx/24) angeschlossen und soll für den internen Datenverkehr verwendet werden.
Die andere Netzwerkkarte (eth1) ist mit dem öffentlichen Internet verbunden (sie hat eine öffentlich routbare IP konfiguriert). Diese Verbindung soll verwendet werden, um den öffentlichen Internetverkehr an die internen IPs der VMs weiterzuleiten (eingehender Verkehr) und den VMs den Zugriff auf das öffentliche Internet (ausgehender Verkehr) über NAT zu ermöglichen.
Virtuelle Maschinen verwenden IP-Adressen im LAN-Subnetz (10.xxx/24, dasselbe wie eth0)
Ich habe ein Bridge-Gerät (br0) für die virtuellen Netzwerkschnittstellen der VMs (vnet0, vnet1, ...) und der LAN-NIC (eth0) konfiguriert. Das bedeutet:
- br0 hat eine IP-Adresse im LAN-Subnetz (10.xxx/24)
- eth0 wird zur Brücke hinzugefügt
- vnet0, vnet1, ... (von den VMs verwendet) werden dynamisch zur Bridge hinzugefügt
Probleme
Die Kommunikation im LAN klappt einwandfrei. Auch der VM-Host ist über die öffentliche IP erreichbar und hat Internetzugang.
Mein Problem ist die NAT-Konfiguration, die den VMs auch den Zugriff auf das öffentliche Internet ermöglicht.
Ich habe versucht, eine einfache (S)NAT-Regel zu verwenden:
iptables -t nat -I POSTROUTING -s 10.x.x.x/24 ! -d 10.x.x.x/24 -j SNAT --to-source y.y.y.102
Wobei yyy102 die öffentliche, routbare IP der zweiten Netzwerkkarte (eth1) ist.
Ich habe herausgefunden, dass ich „ip_forward“ und „bridge-nf-call-iptables“ aktivieren muss:
echo 1 > /proc/sys/net/ipv4/ip_forward
echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables
Andernfalls werden die überbrückten Pakete nicht von iptables verarbeitet.
Jetzt scheinen die Pakete von den VMs die folgenden iptables-Ketten zu durchlaufen:
- „FORWARD“ (regulär) – ich akzeptiere sie dort (-j ACCEPT, Zähler geht hoch)
- „PREROUTING“ (nat) – ich akzeptiere sie dort (Richtlinie ACCEPT, Zähler geht hoch)
- "POSTROUTING" (nat) - Sie entsprechen der SNAT-Regel
Aber aus einem Grund, den ich bisher nicht herausfinden konnte, scheinen nicht alle Pakete bei PRE/POSTROUTING anzukommen.
Interessanter ist jedoch, tcpdump -i eth0
dass tcpdump -i eth1
die Pakete (ich habe versucht, eine externe IP aus einer VM heraus anzupingen) anscheinend über die falsche Schnittstelle eth0 (=LAN-NIC) gesendet werden. Sogar die NAT-Regel wurde angewendet, sodass die Quelladresse auf die IP der anderen NIC (eth1) geändert wurde.
Fragen:
Wie kann ich das System so konfigurieren, dass die NAT-Pakete mit der öffentlichen IP als Quelladresse ausgegeben werden, damit sie über die richtige Netzwerkkarte (eth1) gesendet werden?
Muss ich eth1 irgendwie zur Bridge (br0) hinzufügen? Wenn ja, wie weise ich die öffentliche IP-Adresse richtig zu? Normalerweise muss die IP auf dem Bridge-Gerät konfiguriert werden. Muss ich der Bridge eine Alias-Adresse zuweisen (öffentliche IP auf br0:0)?
Konfigurationsdetails
Die Routing-Konfiguration auf dem Hostsystem:
# ip r
default via y.y.y.126 dev eth1
10.x.x.0/24 dev br0 proto kernel scope link src 10.x.x.11
y.y.y.96/27 dev eth1 proto kernel scope link src y.y.y.102
- IP: yyy126 ist unser Router für das öffentliche Internet.
- IP: yyy102 ist die öffentliche IP des Hostcomputers
- IP: 10.xx11 ist die LAN-IP des Host-Rechners
- SUBNET: 10.xx0/24 ist das LAN
- SUBNET: yyy96/27 ist das öffentliche IP-Subnetz
NIC-Konfiguration:
# ifconfig
br0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.x.x.11 netmask 255.255.255.0 broadcast 10.x.x.255
inet6 ####::###:####:####:#### prefixlen 64 scopeid 0x20<link>
ether ##:##:##:##:##:## txqueuelen 0 (Ethernet)
RX packets 2139490 bytes 243693436 (232.4 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 29085 bytes 2398024 (2.2 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 ####::###:####:####:#### prefixlen 64 scopeid 0x20<link>
ether ##:##:##:##:##:## txqueuelen 1000 (Ethernet)
RX packets 2521995 bytes 290600491 (277.1 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 383089 bytes 48876399 (46.6 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
device memory 0xdfa60000-dfa7ffff
eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet y.y.y.102 netmask 255.255.255.224 broadcast y.y.y.127
inet6 ####::###:####:####:#### prefixlen 64 scopeid 0x20<link>
ether ##:##:##:##:##:## txqueuelen 1000 (Ethernet)
RX packets 2681476 bytes 597532550 (569.8 MiB)
RX errors 0 dropped 130 overruns 0 frame 0
TX packets 187755 bytes 21894113 (20.8 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
device memory 0xdfa00000-dfa1ffff
Brückenkonfiguration:
# brctl show
bridge name bridge id STP enabled interfaces
br0 8000.002590eb1900 no eth0
vnet0
Und iptables-Regeln:
# iptables -vnL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
723 106K DROP udp -- * * y.y.y.0/24 0.0.0.0/0 udp spt:5404
586 40052 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
5 420 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22
2 458 LOG all -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
2 458 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
1343 173K ACCEPT tcp -- * * 10.x.x.2 0.0.0.0/0 tcp spt:3389
1648 127K ACCEPT tcp -- * * 0.0.0.0/0 10.x.x.2 tcp dpt:3389
18 1040 LOG all -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
18 1040 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0
Chain OUTPUT (policy ACCEPT 525 packets, 84016 bytes)
pkts bytes target prot opt in out source destination
# iptables -vnL -t nat
Chain PREROUTING (policy ACCEPT 13 packets, 1218 bytes)
pkts bytes target prot opt in out source destination
Chain INPUT (policy ACCEPT 5 packets, 420 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 13 packets, 880 bytes)
pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 14 packets, 920 bytes)
pkts bytes target prot opt in out source destination
5 300 SNAT all -- * * 10.x.x.0/24 !10.x.x.0/24 to:y.y.y.102
Und hier ein erfasstes NAT-Paket (Ping von VM) auf der LAN-Schnittstellenkarte:
# tcpdump -i eth0
12:53:55.243350 IP y.y.y.102 > y.y.y.110: ICMP echo request, id 2, seq 5, length 40
Ausgabe von „ip rule“:
# ip rule
0: from all lookup local
32766: from all lookup main
32767: from all lookup default
Antwort1
Überprüfen Sie, ob Ihre VMs IP-Adressen auf 10.xxx/24 (Netzmaske 255.255.255.0) haben.
Legen Sie 10.xx11 (br0 IP-Adresse) als Standard-Gateway Ihrer VMs fest
Aktivieren Sie die IP-Weiterleitung auf dem physischen Host
Aktivieren Sie SNAT mit:
iptables -t nat -A POSTROUTING -s 10.x.x.x/24 -o eth1 -j SNAT --to y.y.y.102
Antwort2
iptables -t nat -I POSTROUTING -s 10.xxx/24 ! -d 10.xxx/24 -j SNAT --to-source yyy102
Dies muss geändert werden in
iptables -t nat -I POSTROUTING --out-interface eth1 -j SNAT --to-source y.y.y.102
Gemäß Ihrer ersten Regel dürfen nur Pakete mit dem Ziel 10.xxx verarbeitet werden. Wie sieht es also mit dem Datenverkehr von außerhalb Ihres Netzwerks aus? (Quelle – aus aller Welt, Ziel ist Ihre öffentliche IP :)
Wie kann ich das System so konfigurieren, dass die NAT-Pakete mit der öffentlichen IP als Quelladresse ausgegeben werden, damit sie über die richtige Netzwerkkarte (eth1) gesendet werden?
Lesen Sie oben. Ändern Sie einfach die NAT-Regel.
Muss ich eth1 irgendwie zur Bridge (br0) hinzufügen? Wenn ja, wie weise ich die öffentliche IP-Adresse richtig zu? Normalerweise muss die IP auf dem Bridge-Gerät konfiguriert werden. Muss ich der Bridge eine Alias-Adresse zuweisen (öffentliche IP auf br0:0)?
Auf keinen Fall, es sei denn, Sie wissen, was und warum Sie das tun. Halten Sie interne und externe Schnittstellen getrennt. Erlauben Sie nur Routing.
Ich habe die von Ihnen beschriebene Konfiguration seit mehr als 5 Jahren live (Produktion). Funktioniert reibungslos für 3 Hostserver und 25 VMs, einschließlich Bridge-Links über OpenVPN-Tunnel.
Antwort3
Silvios Beitrag hat mir geholfen, eine ähnliche Konfiguration zum Laufen zu bringen. Zusätzlich zu seinem Beitrag sind hier noch ein paar Dinge, die ich ebenfalls tun musste.
In neueren Versionen des Linux-Kernels (z. B. Redhat 7) müssen Sie das Bridge-Kernelmodul aktivieren:
modprobe br_netfilter
und um diese Änderung auch nach einem Neustart des Servers dauerhaft zu machen, fügen Sie die gleiche Zeile zu einer Datei mit dem Namen /etc/modules-load.d/.conf hinzu.
Nachdem ich br_netfilter aktiviert hatte, musste ich auch iptable-Weiterleitungsregeln für die VM(s) aktivieren, z. B.:
iptables -I FORWARD -d 10.x.x.x/24 -j ACCEPT iptables -I FORWARD -s 10.x.x.x/24 -j ACCEPT
Anstelle von SNAT habe ich eine Maskerade-Regel verwendet, da ich innerhalb einer Server-Hosting-Einrichtung nur eine einzige Route benötigte.
iptables -t nat -A POSTROUTING -s <single-local-vm-ip>/32 -d <my-destination-subnet>/24 -p tcp -j MASQUERADE --to-ports 1024-65535