Proxmox VE: Martian Packets beseitigen

Seit einiger Zeit nutze ich die Open-Source-Virtualisierungsplattform Proxmox VE. Nachdem sich bereits einige virtuelle Maschinen bzw. Container auf dem Host angesammelt haben, ist mir aufgefallen, dass die auf den Systemen konfigurierten Dienste zwar dauerhaft aus dem Internet heraus per IPv4 erreichbar sind, aber die Verbindung von den Systemen in das Internet zumindest per IPv4 zeitweise nicht möglich ist. Das führt beispielsweise dazu, dass die Monitoringmails teilweise mit deutlicher Verzögerung versendet werden. Das Problem trat interessanterweise ausschließlich für IPv4 Verbindungen auf.

Bei einem genaueren Blick ins Syslog musste ich feststellen, dass der Linux-Kernel regelmäßig sogenannte Martian Packets herausfiltert:

May 19 16:41:58 proxmox kernel: [62251.236437] IPv4: martian source 10.x.x.x from 10.y.y.y, on dev fwbr100i0
May 19 16:41:58 proxmox kernel: [62251.236442] ll header: 00000000: ff ff ff ff ff ff aa bb cc dd ee ff 08 06

Leider geben die Log-Einträge keinen Anhaltspunkt, was genau mit den herausgefilterten Paketen nicht stimmt. Bei der Fehleranalyse habe ich festgestellt, dass die virtuellen Container teilweise falsche MAC-Adressen für das Default-Gateway beziehen. Dies hat beispielsweise zu einem seltsamen Verhalten des Netzwerks in den Container geführt: Wenn noch kein ARP-Eintrag für das Default-Gateway in der ARP-Tabelle hinterlegt war, konnten vom Container aus keine Systeme erreicht werden. Sobald aber ein Ping vom Default-Gateway (Proxomox VE Host) an den Container gesendet wurde, konnte eine Verbindung aufgebaut werden.

Das virtuelle Netzwerk auf dem Proxmox-Host

Um zu verstehen wie es zu dem Problem kommt, muss man zunächst verstehen wie das virtuelle Netzwerk  auf dem Proxmox Host  aufgebaut ist.

Bei der Installation habe ich die Bridge vmbr0 angelegt, der aktuell bisher lediglich das physische Netzwerkinterface enp4s0 zugeordnet ist. Diesem Interface  ist auch die öffentliche IPv4-Adresse des Providers zugeordnet.

Der zweite Bridge (vmbr1) ist pro virtuellem Container mindestens ein Interface zugeordnet. Da ich in Proxmox die Firewall aktiviert habe sind das die Interfaces fwpr+. Außerdem habe ich für die virtualisierten Systeme auf die Proxmox-Firewall aktiviert. Dadurch wird für jeden virtuellen Container eine weitere Bridge automatisch angelegt (fwbr+). Diese Bridges fassen dann jeweils das Interface fwln+- und das zugehörige veth+-Device zusammen.  Die eigentliche Paket-Filterung für den jeweiligen Container wird am Interface fwln+ (also z.B.: fwln100i0 für den Container mit der ID 100) vorgenommen, während das zugehörige veth-Device dem Netzwerk-Device innerhalb des Containers entspricht (z.B. eth0).

Zusammengefasst sieht das Netzwerk also ungefähr so aus:

 
                +-------------------------------------------------------------------------------------+
                |  Proxmox Host                                                                       |
                |                                                                                     |
+----------+    |                                                                                     |
|          |    |  +---------------------+                                                            |
| Internet +<------+ vmbr0 +-+ enp4s0    |                                                            |
|          |    |  |       |             |                                                            |
+----------+    |  |       +-+ [...]     |                                    +- - - - - - - - - - +  |
                |  +---------------------+                                    |    LXC-Container   |  |
                |                                                                                     |
                |  +---------------------+      +-------------------------+   |     +---------+    |  |
                |  | vmbr1 +-+ fwpr100p0 +----->+ fwbr100i0 +-+ fwln100i0 |         | LXC-100 |       |
                |  |       |             |      |           |             |   |     |         |    |  |
                |  |       +-+ fwpr101p1 +--+   |           +-+ veth100i0 +-------->+ eth0    |       |
                |  |       |             |  |   +-------------------------+   |     +---------+    |  |
                |  |       +-+ [...]     |  |                                                         |
                |  +---------------------+  +-->+-------------------------+   |     +---------+    |  |
                |                               | fwbr101i0 +-+ fwln101i0 |         | LXC-101 |       |
                |                               |           |             |   |     |         |    |  |
                |                               |           +-+ veth101i0 +-------->+ eth0    |       |
                |                               +-------------------------+   |     +---------+    |  |
                |                                                             +- - - - - - - - - - +  |
                |                                                                                     |
                +-------------------------------------------------------------------------------------+

Problem

Für das Beispiel nehme ich folgende Werte an:

DeviceMAC-AdresseIPv4-Adresse
vmbr1aa:aa:aa:aa:aa:aa192.168.0.1
fwpr100p0bb:bb:bb:bb:bb:bb169.254.b.b
fwbr100i0cc:cc:cc:cc:cc:cc169.254.c.c
fwln100i0dd:dd:dd:dd:dd:dd169.254.d.d
veth100i0ee:ee:ee:ee:ee:ee169.254.d.d

Dem eth0-Interface im Container ist die IP 192.168.0.100 und das Defautl Gatway 192.168.0.1 zugeordnet. Wird in dem Container die ARP-Tabelle ausgelesen (arp -a), so war der IP-Adresse des Default Gateway die MAC-Adresse des Interfaces fwbr100i0 anstatt des Interfaces vmbr1 zugeordnet:

arp -a | grep 192.168.0.1
192.168.0.1 at cc:cc:cc:cc:cc:cc [ether] on eth0

Gleichzeitig tauchen in der ARP-Tabelle auf dem Host viele unterschiedliche ARP-Einträge zu ein und derselben IP-Adresse auf. Dadurch werden die IP-Pakete nicht an das richtige Interface gesendet und dem Kernel kommt  das ganze "marsianisch" vor, weil das Interface fwbr100i0 eigentlich nicht auf ARP-Requests für die IP-Adresse 192.168.0.1 antworten sollte.

Wird aber ein Datenpakte vom Host an den Container geschickt, so wird die ARP-Tabelle automatisch aktualisiert und danach funktioniert der Netzwerkzugriff einwandfrei. Zumindest so lange, die ARP-Tabelle nicht bereinigt wird.

Lösung

Ist das Problem erstmal identifiziert, so ist die Lösung ziemlich einfach. Per sysctl kann mit dem Parameter arp_ignore das Verhalten der ARP-Replies angepasst werden:

arp_ignore - INTEGER
	Define different modes for sending replies in response to
	received ARP requests that resolve local target IP addresses:

0 - (default): reply for any local target IP address, configured on any interface
1 - reply only if the target IP address is local address configured on the incoming interface
2 - reply only if the target IP address is local address configured on the incoming interface and both with the sender's IP address are part from same subnet on this interface
3 - do not reply for local addresses configured with scope host, only resolutions for global and link addresses are replied
4-7 - reserved
8 - do not reply for all local addresses The max value from conf/{all,interface}/arp_ignore is used when ARP request is received on the {interface}

Werden also in der Datei /etc/sysctl.conf folgende Zeilen hinzugefügt,


cat <<\EOF >>/etc/sysctl.conf
# avoid martian packets due to wrong MAC address distribution
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.default.arp_ignore = 1
EOF

so war das Problem bei mir nach einem sysctl -p und löschen des ARP-Caches (ip -s -s neigh flush all) gelöst. 

Quellen

[1] Proxmox: Network Configuration
[2] /proc/sys/net/ipv4/* Variables

Kommentare

PostadresseE-MailadresseFestnetzMobiltelefonSMS/SignalThreemaTwitter DirektnachrichtFAXWeb Page