Der FeM DHCP Server läuft in zwei virtuellen Maschinen, wobei sich corosync+pacemaker um das Failover kümmern. Im Fehlerfall wird also zunächst die IP und dann der dhcpd auf die andere VM umgezogen. Es wird also für den DHCP-Server nur eine IP je VLAN benötigt.
Die beiden virtuellen Maschinen haben dafür je zwei Netzwerkkarten. Die erste Netzwerkkarte bekommt alle VLANs und wird nur für DHCP genutzt, auf der zweiten Netzwerkkarte liegen die für die Verwaltung genutzen VLANs an, damit die beiden VMs einzeln und unabhängig vom Failover-Status erreichbar sind. Dabei liegt ein VLAN auf beiden Netzwerkkarten an - in diesem VLAN gibt es je eine IP für die beiden VMs sowie die DHCP-Server-IP.
Dem DHCP Server wurde beim Start als Kommandozeilenoption mitgegeben, dass er nur VLAN-Interfaces der ersten Netzwerkkarte DHCP bereit stellen soll. Das funktionierte auch prima, nur einige Clienten in dem auf beiden Netzwerkkarten verfügbaren VLAN hatten Probleme, ihr Lease zu verlängern.
Es stellte sich heraus, dass bei der Verlängerung eines Leases im dafür gesendeten DHCP-Request das Feld Client-IP gesetzt ist. Dies bewirkt, dass der DHCP Server das Paket nicht über ein SOCK_PACKET Interface direkt auf eine Netzwerkkarte schreibt, sondern das Paket durch den IP Stack des Linux Kernels sendet. Dabei entscheidet jedoch der Kernel selbstständig über die Quell-IP und Quell-MAC des ausgehenden Paketes. Die Antwort kam also mit der MAC und IP der zweiten Netzwerkkarte an. Dies führte dazu, dass die neueren Switche in der FeM diese Pakete gefiltert haben, der Client also keine Antwort bekam. Mit Ablauf der Lease-Zeit gibt dann der Client auf und versucht, ein neues Lease zu beantragen - was dann auch klappt, da das Feld Client-IP dabei nicht gesetzt ist.
Die beiden VMs waren mittels Policy-Routing bereits so eingestellt, dass je nach Quell-IP automatisch das passende Interface gewählt wird.
Außerdem war das Server-ID Feld in der DHCP Antwort immer auf die (korrekte) IP der ersten Netzwerkkarte gesetzt. Eine Lösung hätte also vermutlich darin bestanden, dass der ISC DHCP Server das Socket vor dem Versenden an die richtige IP bindet und Linux dann automatisch die richtige Netzwerkkarte auswählt.
Definitiv funktionieren und hier eingesetzt wird jedoch eine andere Variante.
Zunächst wird eine zusätzliche Routingtabelle "dhcp" in /etc/iproute2/rt_tables eingetragen. Dann werden alle ausgehenden DHCP Pakete mittels iptables -A OUTPUT -t mangle -p udp --sport 67 -j MARK --set-mark 1
markiert und dann mit ip rule add fwmark 1 table dhcp
entsprechend der neuen Routing-Tabelle versandt.
In die DHCP Routing-Tabelle wird nun für alle Netze, in denen DHCP bereit gestellt wird, die passende Regel eingefügt: ip route add $Subnetz dev $Netzwerkkarte table dhcp
Dies stellt sicher, dass die Pakete auf der passenden Netzwerkkarte versandt werden.
Allerdings sind die Pakete immernoch mit der falschen Quell-IP unterwegs.
Dies lässt sich mit einem beherztem iptables -A POSTROUTING -t nat -o $Netzwerkkarte -s $Subnetz -j SNAT --to-source $Richtige-DHCP-Server-IP
korrigieren.
Et voilà, schon kommen die Antworten mit passender MAC und IP beim Client an.
Trackbacks