DHCP-Failover mit PXE

DHCP-Failover mit PXE

Ich versuche, DHCP-Failover mit PXE-Booten von einem der DHCP-Server einzurichten. Wie in der DHCP-Spezifikation gefordert, habe ich separate Pools für „normales“ DHCP und für PXE-Booten eingerichtet. Meine Failover-Konfiguration funktioniert einwandfrei, aber die DHCP-Konfiguration, die auf PXE-Anfragen reagieren soll, funktioniert nicht mehr.

Hintergrund: Ich habe vor Kurzem ein Upgrade auf AlmaLinux 9 (von CentOS 7) durchgeführt, auf dem ISC DHCP 4.4 läuft. In der älteren Konfiguration hatte ich kein DHCP-Failover und habe PXE-Booten aus dem gesamten Pool zugelassen. Aufgrund einiger Hardwarefehler an unserem Standort möchte ich ein DHCP-Failover einrichten.

Für die Zwecke dieser Konfiguration nennen wir das System, das auf PXE-Anfragen antworten soll, den „primären“ DHCP-Server. Hier ist ein Ausschnitt von /etc/dhcp/dhcpd/confdiesem Server. Beachten Sie, dass ich einen separaten Pool eingerichtet habe, nur um die PXE/BOOTP-Anfragen zu verarbeiten. (Bitte entschuldigen Sie den didaktischen Ton der Kommentare. Sie sind für mich gedacht, da ich meine Sysadmin-Aufgaben erledige.)

authoritative; # Send out acknowledgements to DHCP client queries.

failover peer "dhcp-failover" {
  primary; # declare this to be the primary server
  address 10.4.7.9;
  port 647;
  peer address 10.4.7.210;
  peer port 647;
  # How many seconds to wait before we assume that the other has failed.
  max-response-delay 30;
  # How many BNDUPD messages to send before receiving BNDACK.
  max-unacked-updates 10;
  # How many seconds to wait before disabling load balancing.
  load balance max seconds 3;
  # Maximum Client Lead Time = How long a lease may be renewed
  # without contacting the other DHCP peer.
  mclt 1800;
  # The split between primary and secondary. 128 means a
  # 50% split between peers; 255 means the primary handles
  # everything until it fails. 
  split 128;
}

# This is the primary DHCP server. Respond to BOOTP requests.
allow booting;
allow bootp;

option domain-name "company.example.com";
option time-offset -18000; # Eastern Standard Time

# Is this a DHCP query (as opposed to a BOOTP query)?
class "dhcp" {
      match if exists dhcp-message-type;
}
class "pxe" {
      match if substring (option vendor-class-identifier, 0, 9) = "PXEClient";
}

subnet 10.4.0.0 netmask 255.255.0.0 {
    default-lease-time 86400; # one day (in seconds)
    option subnet-mask 255.255.0.0;
    option broadcast-address 10.4.255.255;
    option routers 10.4.0.1;
    option domain-name-servers 10.4.7.7, 10.4.7.29; 
    option domain-name "company.example.com";
    option time-offset -18000; # Eastern Standard Time
    option ntp-servers 10.4.7.105, 10.4.7.7, 10.4.7.29;

    pool {
         failover peer "dhcp-failover";
         deny dynamic bootp clients;
         deny members of "pxe";
         range 10.4.45.1 10.4.45.250; # DHCP pool on private network
    }
    # A separate pool for BOOTP services.
    pool {
         range dynamic-bootp 10.4.45.251 10.4.45.255; # DHCP pool on private network
         allow dynamic bootp clients;
         deny members of "dhcp";
         allow members of "pxe";
         next-server 10.4.7.9;    # On which system the bootp filename is located.

         if substring (option vendor-class-identifier, 0, 9) = "PXEClient" {

            if substring(option vendor-class-identifier,15,5) = "00007" {
               log(info,"UEFI PXE Boot - private network");
               filename "pxelinux/grubx64.efi"; # The file to load for EFI systems.
               }
            else {
                log(info,"BIOS PXE Boot - private network");
                filename "pxelinux.0"; # The file to load via bootp for BIOS systems.
                }
        }
    }
}

Dies stammt /etc/dhcp/dhcpd.confvom Failover-/Sekundär-/Nicht-PXE-Server:

authoritative; # Send out acknowledgements to DHCP client queries. 

failover peer "dhcp-failover" {
  secondary; # declare this to be the secondary server
  address 10.4.7.210;
  port 647;
  peer address 10.4.7.9;
  peer port 647;
  # How many seconds to wait before we assume that the other has failed.
  max-response-delay 30;
  # How many BNDUPD messages to send before receiving BNDACK.
  max-unacked-updates 10;
  # How many seconds to wait before disabling load balancing.
  load balance max seconds 3;
}

# Make sure that this failover DHCP server does _not_
# respond to bootp.
deny bootp;

option domain-name "company.example.com";
option time-offset -18000; # Eastern Standard Time

# Is this a DHCP query (as opposed to a BOOTP query)?
class "dhcp" {
      match if exists dhcp-message-type;
}
class "pxe" {
      match if substring (option vendor-class-identifier, 0, 9) = "PXEClient";
}

subnet 10.4.0.0 netmask 255.255.0.0 {
    default-lease-time 86400; # one day (in seconds)
    option subnet-mask 255.255.0.0;
    option broadcast-address 10.4.255.255;
    option routers 10.4.0.1;
    option domain-name-servers 10.4.7.7, 10.4.7.29; 
    option domain-name "company.example.com";
    option time-offset -18000; # Eastern Standard Time
    option ntp-servers 10.4.7.105, 10.4.7.7, 10.4.7.29;

    # Note that there are a few IP addresses in the range of the primary
    # server that are not included here. This is for BOOTP, which is
    # not handled by the secondary server.
    pool {
         failover peer "dhcp-failover";
         deny dynamic bootp clients;     
         deny members of "pxe";
         range 10.4.45.1 10.4.45.250; # DHCP pool on private network
    }
}

Ich weiß, dass ich es mit den Klassen „dhcp“ und „pxe“ übertreibe. Ich habe sie hinzugefügt, um das Problem zu beheben. Sie hatten keine Wirkung, außer dass sie die peer holds all free leasesfolgenden Protokollmeldungen einführten.

Dies ist, was ich in den Protokollen des „primären“ Servers sehe. Beachten Sie, dass dies 52:54:00:31:f2:7fdie MAC-Adresse eines Testsystems ist, das ich so eingerichtet habe, dass es über PXE bootet, bevor es „aufgibt“ und stattdessen von der Festplatte bootet.

Sep  8 14:20:46 dhcpd dhcpd[17922]: DHCPDISCOVER from 52:54:00:31:f2:7f via enp7s0: peer holds all free leases
Sep  8 14:20:49 dhcpd dhcpd[17922]: DHCPDISCOVER from 52:54:00:31:f2:7f via enp7s0: peer holds all free leases
Sep  8 14:20:57 dhcpd dhcpd[17922]: DHCPDISCOVER from 52:54:00:31:f2:7f via enp7s0: peer holds all free leases
Sep  8 14:21:13 dhcpd dhcpd[17922]: DHCPDISCOVER from 52:54:00:31:f2:7f via enp7s0: peer holds all free leases

Dies stammt aus dem Protokoll des „sekundären“ Servers. Dies steht im Einklang mit der Verzögerung von etwa einer Minute zwischen dem ersten Booten des Clients, bei dem dieser versucht, einen PXE-Server zu finden, und dem Punkt, an dem er vom Booten vom Betriebssystem auf die übliche Weise umschaltet und eine DHCP-Adresse abruft.

Sep  8 14:20:46 dhcpdsec dhcpd[67768]: DHCPDISCOVER from 52:54:00:31:f2:7f via enp7s0: peer holds all free leases
Sep  8 14:20:46 dhcpdsec dhcpd[67768]: bind update on 10.4.45.183 from dhcp-failover rejected: incoming update is less critical than outgoing update
Sep  8 14:20:49 dhcpdsec dhcpd[67768]: DHCPDISCOVER from 52:54:00:31:f2:7f via enp7s0: peer holds all free leases
Sep  8 14:20:57 dhcpdsec dhcpd[67768]: DHCPDISCOVER from 52:54:00:31:f2:7f via enp7s0: peer holds all free leases
Sep  8 14:21:13 dhcpdsec dhcpd[67768]: DHCPDISCOVER from 52:54:00:31:f2:7f via enp7s0: peer holds all free leases
Sep  8 14:22:03 dhcpdsec dhcpd[67768]: DHCPREQUEST for 10.4.45.183 from 52:54:00:31:f2:7f via enp7s0
Sep  8 14:22:04 dhcpdsec dhcpd[67768]: DHCPACK on 10.4.45.183 to 52:54:00:31:f2:7f via enp7s0

Durch Herumschlagen in früheren Tests habe ich bestätigt, dass der Wert von substring (option vendor-class-identifier, 0, 9)tatsächlich ist PXEClient.

Ich habe bereits versucht, den DHCP-Daemon auf beiden Maschinen zu stoppen und die Einträge für 52:54:00:31:f2:7fin manuell zu löschen /var/lib/dhcpd/dhcpd.leases. Keine Änderung.

Irgendwelche Ideen?

Bearbeiten: Mir ist eingefallen, dass es hilfreich sein könnte, meine vorherige DHCP-Konfiguration ohne Failover zu posten. Das PXE-Booten hat einwandfrei funktioniert:

subnet 10.4.0.0 netmask 255.255.0.0 {
    range dynamic-bootp 10.4.45.1 10.4.45.254; # DCHP pool on private network
    default-lease-time 86400; # one day (in seconds)
    option subnet-mask 255.255.0.0;
    option broadcast-address 10.4.255.255;
    option routers 10.4.0.1;
    option domain-name-servers 10.4.7.7, 10.4.7.29; 
    option domain-name "nevis.columbia.edu";
    option time-offset -18000; # Eastern Standard Time
    option ntp-servers 10.4.7.105, 10.4.7.7, 10.4.7.29;
    next-server 10.4.7.9;    # On which system the bootp filename is located.

    if substring (option vendor-class-identifier, 0, 9) = "PXEClient" {

        if substring(option vendor-class-identifier,15,5) = "00007" {
            log(info,"UEFI PXE Boot - private network");
            filename "pxelinux/grubx64.efi"; # The file to load for EFI systems.
            }
        else {
            log(info,"BIOS PXE Boot - private network");
            filename "pxelinux.0"; # The file to load via bootp for BIOS systems.
        }
    }
}

Antwort1

Nach vielen Experimenten habe ich eine Antwort gefunden: Es stellt sich heraus, dass die Reihenfolge der Zugriffskontrollanweisungen innerhalb eines Pools von Bedeutung ist.

Hier ist eine Wiederholung der Klassendefinitionen in meinem Originalbeitrag:

class "dhcp" {
      match if exists dhcp-message-type;
}
class "pxe" {
      match if substring (option vendor-class-identifier, 0, 9) = "PXEClient";
}

Hier ist die subnetDefinition, die auf meinem primären DHCP-Server funktioniert. Der Hauptunterschied zwischen dieser und der Konfiguration in meinem ursprünglichen Beitrag ist die Reihenfolge der rangeAnweisungen im Vergleich zu beliebigen allowoder denyAnweisungen und dass ich "pxe"zuerst den Pool definiere. Die ursprünglichen Failover-Zeilen bleiben unverändert.

subnet 10.4.0.0 netmask 255.255.0.0 {
    default-lease-time 86400; # one day (in seconds)
    option subnet-mask 255.255.0.0;
    option broadcast-address 10.4.255.255;
    option routers 10.4.0.1;
    option domain-name-servers 10.4.7.7, 10.4.7.29; 
    option domain-name "company.example.com";
    option time-offset -18000; # Eastern Standard Time
    option ntp-servers 10.4.7.105, 10.4.7.7, 10.4.7.29;
    next-server 10.4.7.9;    # On which system the bootp filename is located.

    if substring (option vendor-class-identifier, 0, 9) = "PXEClient" {
        if option architecture-type =  00:07 {
           filename "uefi/grubx64.efi"; # The file to load for EFI systems.
        }
        else {
           filename "pxelinux/pxelinux.0"; # The file to load via bootp for BIOS systems.
        }
    }

    # A separate pool for PXE services.
    pool {
         range dynamic-bootp 10.4.45.251 10.4.45.255; # DHCP pool on private network
         allow dynamic bootp clients;
         allow members of "pxe";
    }

    # The "regular" DHCP pool.
    pool {
         failover peer "dhcp-failover";
         range 10.4.45.1 10.4.45.250; # DHCP pool on private network
         deny dynamic bootp clients;
         deny members of "pxe";
    }
}

Hier sind die überarbeiteten subnetZeilen in meiner sekundären DHCP-Serverkonfiguration, obwohl diese Änderungen wahrscheinlich keine Rolle spielen:

subnet 10.4.0.0 netmask 255.255.0.0 {
    default-lease-time 86400; # one day (in seconds)
    option subnet-mask 255.255.0.0;
    option broadcast-address 10.4.255.255;
    option routers 10.4.0.1;
    option domain-name-servers 10.4.7.7, 10.4.7.29; 
    option domain-name "company.example.com";
    option time-offset -18000; # Eastern Standard Time
    option ntp-servers 10.4.7.105, 10.4.7.7, 10.4.7.29;

    # Note that there are a few IP addresses in the range of the primary
    # server that are not included here. This is for PXE, which is
    # not handled by the secondary server.
    pool {
         failover peer "dhcp-failover";
         deny dynamic bootp clients;     
         range 10.4.45.1 10.4.45.250; # DCHP pool on private network
    }
}

Ich habe jetzt ein Setup mit DHCP-Failover und PXE-Booten zum Installieren/Reparieren eines Betriebssystems, das sowohl BIOS- als auch EFI-Systeme unterstützt. Ich hoffe, dass jemand anderes die obigen Zeilen nützlich findet!

verwandte Informationen