Für eine erweiterte Redundanz möchte man einen zweiten DHCP-Server installieren und diese im failover Modus betreiben.
Ich werde hier einen sauberen Weg für ein solches Setup unter Ubuntu beschreiben; es kann aber praktisch unverändert auch für andere Linux wie CentOS verwendet werden.
Alternativ könnte man dieses Setup auch zum loadbalancing verwenden, auch wenn dies wohl selten „nötig“ sein wird.
Inhalt
Installation
Zunächst mal wird auf beiden Servern der ISC DHCP Server installiert:
apt install isc-dhcp-server |
Als nächstes muss man einen der Server zum „primären“ machen und der andere zum „sekundären“, da die Konfiguration sich nicht automatisch synchronisiert.
Jeder Server besitzt zwei Dateien, eine /etc/dhcp/dhcpd.conf in der die spezifischen Angaben des jeweiligen Nodes stehen und eine inkludierte /etc/dhcp/dhcpd.example.net.conf, welche für beide Nodes gleich ist und die allgemeine DHCP-Konfiguration enthält.
Diese Datei wird dann auch per cronjob vom primären auf den sekundären Host synchronisiert.
Zu den Servernamen die hier verwendet werden, heissen die beiden DHCPs dhcp01.example.net (192.168.1.10) und dhcp01.example.net (192.168.1.20).
Primärer DHCP node
/etc/dhcp/dhcpd.conf
authoritative; log-facility local1; failover peer "dhcp.example.net" { primary; address dhcp01.example.net; port 647; peer address dhcp02.example.net; peer port 847; max-response-delay 60; max-unacked-updates 10; mclt 3600; # Nur Failover split 255; # Failover und Loadbalancing #split 128; load balance max seconds 3; } omapi-port 7911; omapi-key omapi_key; key omapi_key { algorithm hmac-md5; secret Ofakekeyfakekeyfakekey==; } include "/etc/dhcp/dhcpd.example.net.conf"; |
- Der Name bei
failover peer
ist egal, er muss einfach bei beiden DHCP Servern gleich sein. Möglich wäre z.B. auch „failover-partner“ oder etwas in der Art - Bei
address
muss entweder der Hostname oder IP Adresse des ersten- und beipeer address
des zweiten DHCP-Servers stehen. - Der „
Split
„-Wert legt fest wie sich die Server die herausgabe der Adresse aufteilen. 255 bedeutet, dass der primäre DHCP Server 100% des IP Pools verwaltet, d.h. so lange beide laufen gibt nur der primäre IP addressen heraus (reines failover).
Bei einem Wert von 128 würden beide DHCP Server je die Hälfte des IP Pools verwalten (failover + loadbalancing).
Sofern man nicht seeeehr viele DHCP clients hat, ist es übersichtlicher, wenn ein Server die „obehrand“ hat und der zweite nur beim Ausfall des ersten übernimmt. - Der key
omapi_key
kann beispielsweise mit dem Programm dnssec-keygen aus dem bind-Paket generiert werden:dnssec-keygen ‐a HMAC‐MD5 ‐b 512 ‐n USER DHCP_OMAPI
In diesem Setup ist der primäre Server grundsätzlich zuständig für alle IP-Adressen. Sollte dieser ausfallen übernimmt der sekundäre alle leases und den IP-Pool, so lange bis der Primäre wieder online ist; danach erfolgt eine „Rückgabe“ an den primären Server.
/etc/dhcp/dhcpd.example.net.conf
subnet 192.168.1.0 netmask 255.255.255.0 { # Global options default-lease-time 3600; # 1 hour # DHCP options option subnet-mask 255.255.255.0; option routers 192.168.1.1; option domain-name-servers 192.168.1.10, 192.168.1.20; option netbios-name-servers 192.168.1.10, 192.168.1.20; option netbios-node-type 8; option domain-name "ad.example.net"; option domain-search "ad.example.net", "lan.example.net"; # DHCP Pool pool { failover peer "dhcp.example.net"; range 192.168.1.100 192.168.1.200; } } # Static IPs host fixed-client01 { hardware ethernet 00:00:00:00:00:00; fixed-address 192.168.1.11; } |
Dies ist ein einfaches Beispiel einer DHCP-Konfiguration.
Hinweis: Wie man sieht müssen die statischen IP Adressen ausserhalb des Subnets sein.
Diese Datei wird dann initial auf den sekundären Server kopiert:
scp /etc/dhcp/dhcpd.example.net.conf dhcp02.example.net:/etc/dhcp/dhcpd.example.net.conf |
DHCP Replikation
Da dhcpd derzeit noch keine automatische Replikation unterstützt wird die DHCP-Konfigurationsdatei mittels rsync synchronisiert.
Dazu wird auf dem primären DHCP ein rsync-server eingerichtet:
/etc/xinetd.d/rsync
service rsync { disable = no only_from = 192.168.1.20 socket_type = stream wait = no user = root server = /usr/bin/rsync server_args = --daemon log_on_failure += USERID } |
Danach noch xinetd neu starten:
systemctl restart xinetd |
Dazu die rsync Konfiguationsdatei:
/etc/rsyncd.conf
[dhcpd] path = /etc/dhcp/ comment = dhcpd configuration uid = root gid = root read only = yes auth users = dhcpd-repl secrets file = /etc/rsync.secret |
Und das dazugehörige secrets file:
/etc/rsync.secret
dhcpd-repl:geheim |
Dieses noch absichern:
chmod -v 600 /etc/rsync.secret |
Sekundärer DHCP node
Zunächst wird das node-spezifische file erstellt:
/etc/dhcp/dhcpd.conf
authoritative; log-facility local1; failover peer "dhcp.example.net" { secondary; address dhcp02.example.net; port 847; peer address dhcp01.example.net; peer port 647; max-response-delay 60; max-unacked-updates 10; load balance max seconds 3; } omapi-port 7911; omapi-key omapi_key; key omapi_key { algorithm hmac-md5; secret Ofakekeyfakekeyfakekey==; } include "/etc/dhcp/dhcpd.example.net.conf"; |
Replikation konfigurieren
Nun wird der sekundäre Server so konfiguriert, dass er sich per Script die gemeinsame DHCP-Konfigurationsdatei vom primären Server holt, vergleicht und nur falls sich diese geändert hat den DHCP Server neu lädt.
rsync Konfigurieren
Zuerst die Datei mit dem rsync Passwort anlegen:
echo "geheim" > /etc/rsync.pass chmod -v 600 /etc/rsync.pass |
Synchronisationsscript anlegen
Nun wird das folgende Script hinzugefügt:
/usr/local/lib/dhcpd/sync-dhcpd-config.sh
#!/bin/bash # updates the dhcpd.conf file from the primary cluster node, # checks if it changed and restarts when neccessary SCRIPT_NAME=$(basename $0) FILE_CHECK=/etc/dhcp/dhcpd.example.net.conf.md5 MD5_CURRENT=$(cat "$FILE_CHECK") MD5_NEW="" /usr/bin/rsync -XAavz --delete-after --password-file=/etc/rsync.pass rsync://dhcpd-repl@zh-v-dc01/dhcpd/dhcpd.example.net.conf /etc/dhcp/dhcpd.example.net.conf > /dev/null 2>&1 MD5_NEW=$(/usr/bin/md5sum /etc/dhcp/dhcpd.example.net.conf | awk '{print $1}') if [ "$MD5_NEW" != "$MD5_CURRENT" ]; then logger -p local1.notice -t $SCRIPT_NAME -i "dhcpd configuration on master changed, restarting dhcpd (Current md5sum: $MD5_CURRENT / New md5sum: $MD5_NEW)" # Check config before reloading /usr/sbin/dhcpd -t > /dev/null 2>&1 RC=$? if [ "$RC" -eq 0 ]; then systemctl restart isc-dhcp-server /usr/bin/md5sum /etc/dhcp/dhcpd.example.net.conf | awk '{print $1}' > $FILE_CHECK else logger -p local1.warning -t $SCRIPT_NAME -i "WARNING: configuration check failed, will NOT restart dhcpd!" fi fi # Can be turned on, optionally, but fills the logs with "OK" messages #else # echo "Nothing changed, no restart required" #fi |
cronjob für die Replikation erstellen
*/5 * * * * /usr/local/lib/dhcpd/sync-dhcpd-config.sh |
Danach noch auf beiden Servern den DHCP-Server starten und fertig ist das faiover-setup. 🙂
Sehr hilfreicher Artikel. Bei der Konfiguration auf unseren DHCP-Servern gelang es nicht die im „failover peer“ Abschnitt angegebenen „address“ Zeilen als FQDN auszuführen. Der dhcpd startet dann nicht und meldet als Fehler „failover peer failover-partner: invalid argument“
Diesen „Bug ?“ findet man auch in anderen Publikationen
Noch ein Verbesserungsvorschlag: Wenn die dhcp-Konfiguration in mehrere Files modularisiert ist ist ein
"cat /etc/dhcp/dhcpd.example.net.conf weitereconfig.conf | md5sum | awk '{print $1}'" zu verwenden und natürlich per rsync auch entsprechende Files zu kopieren.
Danke für deinen Artikel. Damit hat der Failover endlich geklappt – nach einem vergeblichen Versuch letzten Sommer.
Nun möchte ich noch die automatische Replikation in Angriff nehmen. Ich setze rsync bereits oft für Backups ein, allerdings gehe ich immer über SSH. So spare ich mir den Betrieb des zusätzlichen rsync-servers.
Wie müsste man das Skript anpassen, um rsync via ssh statt über den rsync-Server laufen zu lassen?
Einfach die Zeile:
/usr/bin/rsync -XAavz --delete-after --password-file=/etc/rsync.pass rsync://dhcpd-repl@zh-v-dc01/dhcpd/dhcpd.example.net.conf /etc/dhcp/dhcpd.example.net.conf > /dev/null 2>&1
ändern in:/usr/bin/rsync -XAavz --delete-after zh-v-dc01:/dhcpd/dhcpd.example.net.conf /etc/dhcp/dhcpd.example.net.conf > /dev/null 2>&1
Danke für deine Antwort.
Ich habe jetzt übrigens doch deine rsync-Server-Lösung übernommen.
Denn bei SSH müsste ich im Prinzip ja „root“ Zugriff erlauben, und mit rsync gibt es doch eine Schranke mehr.