DHCPとPXEサーバーを構築(IPフォワーディング、NAT推奨)

ネットワーク管理を効率化し、手動でのIPアドレス設定の手間を省くために、DHCPサーバーの設定は非常に有用です。さらに、ネットワークブートを実現するためのPXEサーバー構築にも欠かせない要素です。この記事では、DHCPサーバーとPXEサーバーを設定し、シームレスなネットワーク環境を構築する方法について詳しく解説します。

DHCPとは?

DHCP(Dynamic Host Configuration Protocol)とは、ネットワーク内のデバイスに自動でIPアドレスを割り当てる仕組みです。手動でIPアドレスを設定する手間を省くことができます。

例:

例えば、あなたが自宅のWi-Fiにスマホを接続するとき、DHCPサーバーが自動的にスマホにIPアドレスを割り当てます。これにより、スマホはインターネットに接続できます。

なぜ重要か?

  • 簡単さ:ネットワークに新しいデバイスを追加する際、手動でIPアドレスを設定する必要がありません。
  • 効率性:IPアドレスの重複を防ぎ、ネットワーク管理が簡素化されます。
  • 柔軟性:デバイスがネットワークを離れて再接続する際に、異なるIPアドレスを割り当てることができます。

まず、DHCPサーバーをインストールして、IPアドレスを自動で割り当てる方法を説明します。こうすることで、ネットワーク内のデバイスが一元管理され、設定が簡素化されます。その後、PXEサーバーの設定方法に移り、ネットワークブートの仕組みを構築していきます。

作業を開始する前に、現在のネットワーク環境とIPアドレスの状況を確認しましょう。最初に確認しておけば、設定後の変化を明確に把握できるようになります。Dockerを使用して実現したいので、Docker関連の情報も表示されています。Ubuntu24.04にDockerをインストール済みです。

ip a

1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host noprefixroute
valid_lft forever preferred_lft forever
2: enp1s0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether f0:76:1c:88:14:76 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.1/24 brd 10.0.0.255 scope global enp1s0
valid_lft forever preferred_lft forever
inet6 fe80::f276:1cff:fe88:1476/64 scope link
valid_lft forever preferred_lft forever
3: wlp2s0: mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether ac:b5:7d:87:8e:90 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.107/24 brd 192.168.0.255 scope global wlp2s0
valid_lft forever preferred_lft forever
inet6 fe80::aeb5:7dff:fe87:8e90/64 scope link
valid_lft forever preferred_lft forever
4: docker0: mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:e2:46:ea:31 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever

DHCPサーバーのインストールと設定

DHCPサーバーのインストール方法と設定については後で詳しく説明しますが、ここでのポイントは、サーバーPCがDHCPサーバーとして機能することで、ネットワーク内のクライアントPCに自動的にIPアドレスを割り当て、ネットワーク設定を簡素化できることです。

また、サーバーPCがルーターとして機能し、クライアントPCがインターネットにアクセスできるようにする方法も紹介します。これは、ネットワークデバイスが2つあるPCでネットワークを分離する方法であり、二重のDHCPを避けるための構築例です。特にこちらの設定はしなくてもDHCPとPXEは実現可能です。 [参考URL: https://minokamo.tokyo/2024/07/31/7481/]

PXEサーバーの設定

次に、PXEサーバーとして機能するようにサーバーPCを設定します。PXE(Preboot Execution Environment)は、コンピュータがネットワーク経由で起動するための標準的な仕組みであり、OSのインストールをUSBやDVDから行う代わりにネットワーク経由で行うことができます。

NetBoot.XYZは、このPXEブート環境を提供するツールで、さまざまなOSやユーティリティをネットワーク経由で起動・インストールするためのメニューを提供します。NetBoot.XYZのサーバーをセットアップしておけば、ネットワークに接続されたどのPCからでもネットワーク経由でOSのインストールやその他のブートが可能になります。これにより、物理的なメディア(USBドライブやCD/DVD)を用意する手間が省け、管理が非常に楽になります。

PXE(Preboot Execution Environment)の概要

  1. DHCPリクエスト
    • コンピュータが起動すると、PXEブートが有効になっている場合、まずDHCPリクエストを送信してIPアドレスを取得します。
  2. DHCPサーバーからの応答
    • DHCPサーバーは、IPアドレスに加えて、次に接続すべきTFTPサーバーの情報(next-server)と、取得すべきブートローダーのファイル名(filename)をクライアントに提供します。
  3. TFTPサーバーからのブートローダー取得
    • クライアントはTFTPサーバーから指定されたブートローダー(例:netboot.xyz.kpxe)をダウンロードします。
  4. ブートローダーの実行
    • ダウンロードしたブートローダーが実行され、必要なOSイメージやインストールイメージをさらにネットワーク経由で取得して起動プロセスを続行します。

Client Computer

1. Send DHCP Request

2. Receive DHCP Response with IP, next-server, boot file name

3. Download boot file from TFTP server

4. Execute boot file, initiate OS install or network boot

DHCP Server

Provide IP, next-server, boot file name

TFTP Server

Provide boot file to client

以下の2つのGitHubのページを参考に、Dockerを使用してNetBoot.XYZのコンテナとDHCPサーバーのコンテナを立ち上げます。NetBoot.XYZコンテナはTFTPサーバーとして機能しますが、DHCPサーバーは別途設定する必要があります。

https://github.com/netbootxyz/docker-netbootxyz
https://github.com/wastrachan/docker-dhcpd

docker-compose.ymlファイルを使用して、これらを結合してみました(後述)。また、docker0のネットワークが再起動のたびに変わると、dhcpd.confファイルを毎回更新しなければならなくなるため、これは非効率です。dhcpd.confはコンテナを立ち上げた時、ホストにマウントしているファイルです(後述)。この問題を解決するために、固定ネットワークをDockerで作成し、それを使用するように設定します(後述)。

dhcpd.confファイルは、DHCPサーバーの設定ファイルです。このファイルには、DHCPサーバーがどのように動作するかを指定する設定が含まれています。以下は、dhcpd.confファイルの典型的な設定項目とその説明です。

dhcpd.confの典型的な設定項目

# Global configuration options
default-lease-time 600; # デフォルトのリース時間(秒)
max-lease-time 7200; # 最大リース時間(秒)

# DNSサーバーとゲートウェイの設定
option domain-name-servers 8.8.8.8, 8.8.4.4;
option domain-name "example.com";
option routers 192.168.1.1;

# サブネットごとの設定
subnet 192.168.1.0 netmask 255.255.255.0 {
range 192.168.1.100 192.168.1.200; # IPアドレスの割り当て範囲
option subnet-mask 255.255.255.0;
option broadcast-address 192.168.1.255;
}

# 特定のホストに対する固定IPアドレスの割り当て
host myclient {
hardware ethernet 00:11:22:33:44:55;
fixed-address 192.168.1.50;
}

設定項目の説明

  1. Global configuration options(グローバル設定オプション)
    • default-lease-time:クライアントがDHCPサーバーからIPアドレスをリースするデフォルトの時間(秒)。
    • max-lease-time:クライアントがDHCPサーバーからIPアドレスをリースする最大の時間(秒)。
  2. DNSサーバーとゲートウェイの設定
    • option domain-name-servers:クライアントに提供するDNSサーバーのアドレス。
    • option domain-name:クライアントに提供するドメイン名。
    • option routers:クライアントに提供するデフォルトゲートウェイのアドレス。
  3. サブネットごとの設定
    • subnet:DHCPサーバーがIPアドレスを割り当てるサブネットの範囲とネットマスク。
    • range:サブネット内でDHCPサーバーがクライアントに割り当てるIPアドレスの範囲。
    • option subnet-mask:クライアントに提供するサブネットマスク。
    • option broadcast-address:クライアントに提供するブロードキャストアドレス。
  4. 特定のホストに対する固定IPアドレスの割り当て
    • host:特定のホストの設定。
    • hardware ethernet:ホストのMACアドレス。
    • fixed-address:ホストに割り当てる固定IPアドレス。

dhcpd.confが何をしているか

dhcpd.confファイルは、DHCPサーバーがクライアントに対してどのようにIPアドレスを割り当てるか、どのDNSサーバーやデフォルトゲートウェイを提供するか、リース時間はどのくらいか、特定のホストに固定IPアドレスを割り当てるかなどの設定を行います。これで、ネットワーク内のクライアントが自動的にネットワーク設定を取得できるようになります。

Dockerコンテナ内でこの設定を使用してDHCPサーバーを動作させる場合、dhcpd.confファイルをホストにマウントしてコンテナ内で使用することで、DHCPサーバーの設定を簡単に管理し、変更することができます。

余談ですが、操作するPCにはVSコードでリモート接続しています。

VS Codeを使ってリモートサーバー上のファイルを編集するのは非常に便利です。いくつかの理由を挙げてみます。

VS Codeの利便性

  1. シームレスな操作
    • リモートサーバー上のファイルをローカルにあるかのように開いて編集できるため、操作感が非常に自然です。
  2. Remote – SSH拡張機能
    • VS CodeのRemote – SSH拡張機能を使うと、リモートサーバーに簡単に接続して作業できます。これにより、サーバー上のプロジェクトを直接操作できます。
  3. 豊富なプラグイン
    • VS Codeは多数のプラグインがあり、リモート開発に必要なツールも豊富に揃っています。例えば、Gitの操作やデバッグツールなどを統合して利用できます。
  4. 統合ターミナル
    • VS Codeには統合ターミナルがあり、エディタ内から直接リモートサーバー上でコマンドを実行できます。エディタとターミナルを行き来する手間が省けます。
  5. ファイルシステムへのアクセス
    • ファイルブラウザを使って、リモートサーバー上のディレクトリ構造を視覚的に操作できます。これにより、ファイルの移動や削除、作成が簡単に行えます。
  6. 同期とバージョン管理
    • ローカルでの作業と同様に、Gitを使ったバージョン管理が可能です。リモートリポジトリに対する操作もシームレスに行えます。
Network Diagram

ネットワーク図

+——————+ +——————+ +——————+
| Client Computer | | DHCP Server | | PXE Server |
| | | | | |
| (Client PC) | | | | |
+——–+———+ +——–+———+ +——–+———+
| | |
| DHCP Request | |
+————————> | |
| | |
| | |
| DHCP Response | |
| <------------------------+ |
| |
| PXE Request |
+—————————————————–>|
| |
| PXE Response |
| <-----------------------------------------------------+
| |
| Boot Image Download |
+—————————————————–>|
| |
| |

データフロー図

+——————-+
| Client Computer |
| |
| 1. DHCP Request |
| | |
| v |
| 2. DHCP Response |
| | |
| v |
| 3. PXE Request |
| | |
| v |
| 4. PXE Response |
| | |
| v |
| 5. Boot Image |
| |
+——————-+

ネットワーク図の説明

  1. クライアントPC
    • まず、ネットワークに接続されているクライアントPC(例:新しいパソコン)が存在します。このPCがネットワーク経由でブート(起動)しようとします。
  2. DHCPサーバー
    • ネットワーク内にはDHCPサーバーが配置されています。このサーバーはネットワーク内のデバイスに自動的にIPアドレスを割り当てる役割を持っています。
  3. PXEサーバー
    • また、PXE(Preboot Execution Environment)サーバーも配置されています。このサーバーはネットワーク経由でクライアントPCにブートイメージ(OSやユーティリティ)を提供する役割を持っています。
  4. DHCPリクエスト
    • クライアントPCが起動すると、最初にDHCPサーバーに対してIPアドレスのリクエストを送信します。これが「DHCP Request」です。
  5. DHCPレスポンス
    • DHCPサーバーはクライアントPCにIPアドレスを割り当て、レスポンスを返します。これが「DHCP Response」です。このレスポンスにはPXEサーバーの情報も含まれています。
  6. PXEリクエスト
    • クライアントPCはDHCPサーバーから受け取ったPXEサーバーの情報を基に、PXEサーバーに対してリクエストを送信します。これが「PXE Request」です。
  7. PXEレスポンス
    • PXEサーバーはクライアントPCにブートイメージの情報を返します。これが「PXE Response」です。
  8. ブートイメージのダウンロード
    • 最後に、クライアントPCはPXEサーバーからブートイメージをダウンロードし、そのイメージを使ってOSのインストールやネットワークブートを行います。

クライアントPCがネットワーク経由で起動する流れを説明。

  1. DHCPリクエスト
    • クライアントPCは、ネットワーク上のDHCPサーバーに対してIPアドレスをリクエストします。
  2. DHCPレスポンス
    • DHCPサーバーは、クライアントPCにIPアドレスを割り当てて、その情報を返します。
  3. PXEリクエスト
    • 次に、クライアントPCはPXEサーバーに対して、起動に必要なデータをリクエストします。
  4. PXEレスポンス
    • PXEサーバーは、クライアントPCに起動用のデータを返します。
  5. ブートイメージの取得
    • 最後に、クライアントPCはPXEサーバーからブートイメージをダウンロードし、それを使ってOSをインストールしたり、ネットワークから直接起動します。

固定ネットワークの作成

まず、Dockerで固定のカスタムネットワークを作成します。これで、ネットワークのIP範囲が一定になります。作成する理由は前述したとおりですが、再度理由を述べておくことにします。docker0のネットワークが再起動のたびに変わると、dhcpd.confファイルを毎回更新しなければならなくなるため、これは非効率だからです。

  1. 固定ネットワークの作成:以下のコマンドを実行して、固定のカスタムネットワークを作成します。
    docker network create --subnet=172.20.0.0/16 my_custom_network
    これで、my_custom_networkという名前の固定ネットワークが作成され、サブネットは 172.20.0.0/16 になります。

docker0のネットワーク(再掲)

  1. デフォルトブリッジネットワーク:
    • docker0は、Dockerが自動的に作成するデフォルトのブリッジネットワークです。
    • Dockerコンテナを起動すると、特に指定しない限り、このネットワークが使用されます。
  2. IPアドレスの自動割り当て:
    • docker0ネットワークは通常、172.17.0.0/16のアドレス範囲を使用しますが、これはシステムによって異なることがあります。
    • コンテナに対してIPアドレスが自動的に割り当てられます。

再起動時のIPアドレス

  1. コンテナの再起動:
    • コンテナを再起動するたびに、新しいIPアドレスが割り当てられる場合があります。Dockerのデフォルトの動作では、再起動ごとに新しいIPアドレスが割り当てられることが多いです。
  2. 固定IPアドレスの設定:
    • 必要に応じて、コンテナに固定のIPアドレスを割り当てることも可能です。これはカスタムネットワークを作成し、そのネットワークに対して固定IPを設定することで実現できます。

作成されたネットワークは以下のコマンドで確認できます。

docker network ls

作成した固定ネットワークを使用するように、docker-compose.ymlファイルを作成します。

version: "2"

services:
  docker-dhcpd:
    image: wastrachan/dhcpd
    container_name: docker-dhcpd
    environment:
      - PUID=1111
      - PGID=1112
    volumes:
      - /home/mamu/netboot/dhcpconfig:/config
    network_mode: "host"  # ホストネットワークモードを使用
    restart: unless-stopped

  netbootxyz:
    image: ghcr.io/netbootxyz/netbootxyz
    container_name: netbootxyz
    environment:
      - MENU_VERSION=2.0.47
      - NGINX_PORT=80
      - WEB_APP_PORT=3000
    volumes:
      - /home/mamu/netboot/config:/config
      - /home/mamu/netboot/assets:/assets
    networks:
      - my_custom_network
    ports:
      - 3000:3000
      - 69:69/udp
      - 8080:80
    restart: unless-stopped

networks:
  my_custom_network:
    external: true
docker compose up -d

IPアドレスを確認すると以下のようになっています。

ip a

1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host noprefixroute
valid_lft forever preferred_lft forever
2: enp1s0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether f0:76:1c:88:14:76 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.1/24 brd 10.0.0.255 scope global enp1s0
valid_lft forever preferred_lft forever
inet6 fe80::f276:1cff:fe88:1476/64 scope link
valid_lft forever preferred_lft forever
3: wlp2s0: mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether ac:b5:7d:87:8e:90 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.107/24 brd 192.168.0.255 scope global wlp2s0
valid_lft forever preferred_lft forever
inet6 fe80::aeb5:7dff:fe87:8e90/64 scope link
valid_lft forever preferred_lft forever
4: docker0: mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:e2:46:ea:31 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
5: br-a180cb5a6bfa: mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:6a:7c:7c:8f brd ff:ff:ff:ff:ff:ff
inet 172.20.0.1/16 brd 172.20.255.255 scope global br-a180cb5a6bfa
valid_lft forever preferred_lft forever
inet6 fe80::42:6aff:fe7c:7c8f/64 scope link
valid_lft forever preferred_lft forever
7: veth68ca453@if6: mtu 1500 qdisc noqueue master br-a180cb5a6bfa state UP group default
link/ether aa:4f:ef:fc:fb:ff brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::a84f:efff:fefc:fbff/64 scope link
valid_lft forever preferred_lft forever

コンテナを立ち上げたことでネットワークの状態が変わったことがわかります。特に、docker network createコマンドで作成されたカスタムネットワークが反映されています。以下に具体的な解説を示します。

ネットワーク状態の変化

docker network create --subnet=172.20.0.0/16 my_custom_networkコマンドによって作成されたカスタムネットワークmy_custom_networkが、インターフェースbr-a180cb5a6bfaとして反映されています。このネットワークの状態について説明します。

インターフェースの詳細

  1. br-a180cb5a6bfaインターフェース
    • IPアドレス172.20.0.1/16
      • サブネット172.20.0.0/16のゲートウェイアドレスです。
    • MACアドレス02:42:6a:7c:7c:8f
      • ブリッジインターフェースのMACアドレスです。
    • ブロードキャストアドレス172.20.255.255
      • サブネット内の全デバイスにパケットを送信するためのアドレスです。
    • IPv6アドレスfe80::42:6aff:fe7c:7c8f/64
      • リンクローカルアドレスです。
  2. veth68ca453@if6インターフェース
    • MACアドレスaa:4f:ef:fc:fb:ff
      • 仮想イーサネットペアの一方のインターフェースです。
    • IPv6アドレスfe80::a84f:efff:fefc:fbff/64
      • リンクローカルアドレスです。
    • このインターフェースはコンテナのネットワークインターフェースに接続されています。

2のインターフェースについてもう少し解説します。vethインターフェースの役割は以下になります。

vethインターフェースは、仮想イーサネットインターフェースの一種で、主にDockerコンテナのネットワークを接続するために使われます。具体的には、以下のような役割を果たします:

  1. 仮想ネットワークブリッジ
    • vethインターフェースはペアで動作し、一方の端がコンテナに接続され、もう一方の端がホストのネットワークブリッジに接続されます。そうすると、コンテナとホスト、または他のネットワークリソースとの通信が可能になります。
  2. ネットワークパケットの転送
    • vethインターフェースを通じて、コンテナ内とホスト上の他のネットワーク間でデータが送受信されます。これで、コンテナがインターネットやホスト内の他のサービスにアクセスできるようになります。

具体例での説明

「vethインターフェースを理解するために、次のように考えます。

  • コンテナは仮想マシンのようなもので、独自のネットワークインターフェースを持っています。
  • vethインターフェースはケーブルのようなもので、このケーブルは一方の端がコンテナに接続され、もう一方の端がホストのネットワークに接続されています。
  • このケーブルを通じて、コンテナはホストやインターネットと通信することができます。」

実際の役割

「具体的には、veth68ca453@if6というインターフェースは、以下の役割を果たしています。

通信:コンテナが外部のネットワークにアクセスするためのパケットは、このvethインターフェースを通過します。つまり、コンテナの内部ネットワークとホストのネットワークを接続するためのトンネルの役割を果たしています。」

接続:このインターフェースは、ホストのブリッジインターフェースbr-a180cb5a6bfaとペアになっています。このペアの一方がホスト側にあり、もう一方がコンテナ側にあります。

まだまだやることがあります。新しい固定ネットワークに対するサブネット宣言を追加します。IP情報を元にすると記述内容は以下になります。DHCPサーバーの設定ファイルである/home/mamu/netboot/dhcpconfig/dhcpd.confを編集します。コンテナのディレクトリをマウントしているのでホストのこのファイルを編集するわけです。仮にdocker0を使用すると、コンテナの再起動時に172.18.0.Xや172.19.0.Xになりこのファイルを編集する羽目になります。ですのでカスタムネットワークを作成したわけです。

default-lease-time 600;
max-lease-time 7200;

# Subnet declaration for 10.0.0.x (enp1s0)
subnet 10.0.0.0 netmask 255.255.255.0 {
  range 10.0.0.100 10.0.0.200;
  option routers 10.0.0.1;
  option broadcast-address 10.0.0.255;
  next-server 10.0.0.1;  # NetBoot.XYZコンテナのIPアドレス
  filename "netboot.xyz.kpxe";
}

# Subnet declaration for 172.20.0.x (my_custom_network)
subnet 172.20.0.0 netmask 255.255.0.0 {
  range 172.20.0.10 172.20.0.100;
  option routers 172.20.0.1;
  option broadcast-address 172.20.255.255;
  # next-server 172.20.0.2;  # 必要に応じて設定
  # filename "pxelinux.0";
}

VSコードで編集して上書き保存しようとすると以下のメッセージが表示されました。これはログインしているユーザーにファイルの書き込み権限がないためです。

‘dhcpd.conf’ を保存できませんでした。ファイル ‘vscode-remote://ssh-remote+ub2404dhcp/home/mamu/netboot/dhcpconfig/dhcpd.conf’ を書き込むことができません (NoPermissions (FileSystemError): Error: EACCES: permission denied, open ‘/home/mamu/netboot/dhcpconfig/dhcpd.conf’)

そこで、「Save as Root in Remote – SSH」というプラグインをインストールしました。このプラグインを使用すると、VS Code上で直接ルート権限を使ってファイルを保存することができます。ファイルの所有権やパーミッションを変更する手間を省くことができます。ファイルを編集したのでコンテナを再起動します。

docker compose down
docker compose up -d

これでDHCPサーバーとして機能するはずなので、WindowsPCをハブ経由で接続して確認します。DHCPサーバーがネットワーク上で動作している場合、クライアントはインターネットプロトコルバージョン4 (IPv4) を使用して自動的にIPアドレスを取得できます。クライアントはDHCPサーバーから自動的にIPアドレス取得するので、ネットワークの設定は特に何もしなくてもいいはずです。

WindowsPCには10.0.0.100というプライベートIPアドレスを取得したようです。

DHCPサーバーからIPを取得する手順

  1. DHCPクライアントの初期化
    • クライアントPCがネットワークに接続されると、DHCPクライアントが自動的に起動します。これは、ネットワークインターフェースが有効になると同時に行われます。
  2. DHCPディスカバリメッセージの送信
    • クライアントはブロードキャストメッセージ(DHCP Discover)をネットワークに送信し、利用可能なDHCPサーバーを探します。
  3. DHCPオファーメッセージの受信
    • ネットワーク内のDHCPサーバーは、このディスカバリメッセージを受信し、クライアントにIPアドレスのオファー(DHCP Offer)を返信します。
  4. DHCPリクエストメッセージの送信
    • クライアントは、受け取ったオファーの中から1つを選び、そのIPアドレスを要求するリクエストメッセージ(DHCP Request)を送信します。
  5. DHCPアクノリッジメッセージの受信
    • DHCPサーバーはリクエストを受け取り、指定されたIPアドレスのリースを確認するアクノリッジメントメッセージ(DHCP Acknowledge)を送信します。
  6. IPアドレスの設定
    • クライアントは受け取ったIPアドレス、サブネットマスク、デフォルトゲートウェイ、DNSサーバーなどの情報を使用してネットワーク設定を行います。

特に何もしなくてもIPを割り当てる理由

  • 自動設定
    • 多くのオペレーティングシステム(Windows、Linux、macOSなど)は、ネットワークインターフェースが有効になると自動的にDHCPクライアントを起動し、IPアドレスの取得プロセスを開始します。
  • デフォルト設定
    • 通常、ネットワークインターフェースの設定で「自動(DHCP)」がデフォルトのIPアドレス取得方法として設定されています。ですので、ユーザーが特別な設定を行わなくても、ネットワークに接続するだけでIPアドレスが自動的に割り当てられます。

Windowsでの確認方法

  1. ネットワーク設定の確認
    • [コントロールパネル] > [ネットワークとインターネット] > [ネットワークと共有センター] に移動します。
    • [アダプター設定の変更] をクリックし、使用しているネットワークアダプターを右クリックして [プロパティ] を選択します。
    • [インターネット プロトコル バージョン 4 (TCP/IPv4)] を選択し、[プロパティ] をクリックします。
    • 「IPアドレスを自動的に取得する」と「DNSサーバーのアドレスを自動的に取得する」にチェックが入っていることを確認します。
  2. IPアドレスのリリースと再取得
    • コマンドプロンプトを開き、以下のコマンドを実行します。
      ipconfig /release
      ipconfig /renew

Linuxでの確認方法

  1. ネットワークマネージャーの確認
    • 通常、NetworkManagerやsystemd-networkdなどのサービスが自動的にDHCPクライアントを管理します。
  2. 手動でのリリースと再取得
    • ターミナルを開き、以下のコマンドを実行します。
      sudo dhclient -r
      sudo dhclient

次にPXEサーバーとして正常に機能しているか確認します。クライアントPCはBIOS画面でブートの順番でネットワークブートを最優先に設定しておきます。

PXEブートを設定する際に、BIOSの設定でUEFIとレガシーサポートのオプションを選択する必要があります。以下に、各オプションについて簡単に説明します。

UEFIとレガシーサポート

  1. UEFI (Unified Extensible Firmware Interface)
    • UEFIは、従来のBIOSの後継として設計されたファームウェアインターフェースで、より高速なブート時間やセキュリティ機能の向上を提供します。UEFIは、GPT(GUID Partition Table)パーティションスタイルをサポートしています。
  2. レガシーサポート
    • レガシーサポートは、従来のBIOS(Basic Input/Output System)互換のブートモードを提供します。レガシーモードは、MBR(Master Boot Record)パーティションスタイルを使用します。

レガシーサポートの詳細オプション

  1. UEFIファースト
    • この設定では、システムはまずUEFIブートを試み、失敗した場合にレガシーブートを試みます。UEFIが優先されます。
  2. レガシーファースト
    • この設定では、システムはまずレガシーブートを試み、失敗した場合にUEFIブートを試みます。レガシーブートが優先されます。

どのオプションを選ぶべきか?

  • UEFI
    • 可能であればUEFIを使用することをお勧めします。UEFIはより新しく、セキュリティ機能が強化されており、GPTパーティションをサポートします。最新のハードウェアやソフトウェアとの互換性も高いです。
  • レガシーサポート
    • 古いハードウェアやUEFI非対応のシステムを使用している場合は、レガシーサポートを選択します。また、一部の古いOSやツールはレガシーモードでのみブート可能です。
  • UEFIファースト vs レガシーファースト
    • UEFIファースト:UEFI対応のブートメディアを優先し、互換性のある場合に推奨されます。新しいシステムやOSをインストールする場合に有効です。
    • レガシーファースト:古いハードウェアやレガシーブートのみサポートする場合に使用します。互換性が必要な場合に便利です。

実際の設定例

  1. UEFIモードでPXEブート
    • BIOS設定でUEFIを選択し、ネットワークブートオプションを有効にします。
    • PXEサーバーがUEFI PXEブートをサポートしていることを確認します。
  2. レガシーモードでPXEブート
    • BIOS設定でレガシーサポートを選択し、必要に応じてレガシーファーストを選びます。
    • PXEサーバーがレガシーPXEブートをサポートしていることを確認します。

ちなみに、上記のDHCP設定ファイルはレガシーサポートでしかうまくブートしません。あとで記述しますがUEFIで起動できる設定も記述します。

一度PXEブートを試みた後ログを確認してみました。

docker logs docker-dhcpd

このログは、DHCPサーバーが正常に起動し、指定されたネットワークインターフェースでリクエストを受け付けていることを示しています。

Starting up using the following:

UID: 1111
GID: 1112

Internet Systems Consortium DHCP Server 4.4.3-P1
Copyright 2004-2022 Internet Systems Consortium.
All rights reserved.
For info, please visit https://www.isc.org/software/dhcp/
Config file: /config/dhcpd.conf
Database file: /config/dhcpd.leases
PID file: /run/dhcp/dhcpd.pid
Wrote 1 leases to leases file.

No subnet declaration for veth69ce47c (no IPv4 addresses).
** Ignoring requests on veth69ce47c. If this is not what
you want, please write a subnet declaration
in your dhcpd.conf file for the network segment
to which interface veth69ce47c is attached. **

Listening on LPF/br-a180cb5a6bfa/02:42:6a:7c:7c:8f/172.20.0.0/16
Sending on LPF/br-a180cb5a6bfa/02:42:6a:7c:7c:8f/172.20.0.0/16

No subnet declaration for docker0 (172.17.0.1).
** Ignoring requests on docker0. If this is not what
you want, please write a subnet declaration
in your dhcpd.conf file for the network segment
to which interface docker0 is attached. **

No subnet declaration for wlp2s0 (192.168.0.107).
** Ignoring requests on wlp2s0. If this is not what
you want, please write a subnet declaration
in your dhcpd.conf file for the network segment
to which interface wlp2s0 is attached. **

Listening on LPF/enp1s0/f0:76:1c:88:14:76/10.0.0.0/24
Sending on LPF/enp1s0/f0:76:1c:88:14:76/10.0.0.0/24
Sending on Socket/fallback/fallback-net
Server starting service.
DHCPREQUEST for 10.0.0.100 from 54:e1:ad:33:d8:e2 (LAPTOP-U2IPTTLE) via enp1s0
DHCPACK on 10.0.0.100 to 54:e1:ad:33:d8:e2 (LAPTOP-U2IPTTLE) via enp1s0
DHCPDISCOVER from 54:e1:ad:33:d8:e2 via enp1s0
DHCPOFFER on 10.0.0.101 to 54:e1:ad:33:d8:e2 via enp1s0
DHCPREQUEST for 10.0.0.101 (10.0.0.1) from 54:e1:ad:33:d8:e2 via enp1s0
Wrote 2 leases to leases file.
DHCPACK on 10.0.0.101 to 54:e1:ad:33:d8:e2 via enp1s0
DHCPDISCOVER from 54:e1:ad:33:d8:e2 via enp1s0
DHCPOFFER on 10.0.0.100 to 54:e1:ad:33:d8:e2 (LAPTOP-U2IPTTLE) via enp1s0
DHCPREQUEST for 10.0.0.100 (10.0.0.1) from 54:e1:ad:33:d8:e2 (LAPTOP-U2IPTTLE) via enp1s0
DHCPACK on 10.0.0.100 to 54:e1:ad:33:d8:e2 (LAPTOP-U2IPTTLE) via enp1s0
DHCPDISCOVER from 54:e1:ad:33:d8:e2 via enp1s0
DHCPOFFER on 10.0.0.101 to 54:e1:ad:33:d8:e2 via enp1s0
DHCPREQUEST for 10.0.0.101 (10.0.0.1) from 54:e1:ad:33:d8:e2 via enp1s0
DHCPACK on 10.0.0.101 to 54:e1:ad:33:d8:e2 via enp1s0
reuse_lease: lease age 126 (secs) under 25% threshold, reply with unaltered, existing lease for 10.0.0.100
DHCPDISCOVER from 54:e1:ad:33:d8:e2 (LAPTOP-U2IPTTLE) via enp1s0
DHCPOFFER on 10.0.0.100 to 54:e1:ad:33:d8:e2 (LAPTOP-U2IPTTLE) via enp1s0
reuse_lease: lease age 127 (secs) under 25% threshold, reply with unaltered, existing lease for 10.0.0.100
DHCPDISCOVER from 54:e1:ad:33:d8:e2 (LAPTOP-U2IPTTLE) via enp1s0
DHCPOFFER on 10.0.0.100 to 54:e1:ad:33:d8:e2 (LAPTOP-U2IPTTLE) via enp1s0
reuse_lease: lease age 129 (secs) under 25% threshold, reply with unaltered, existing lease for 10.0.0.100
DHCPREQUEST for 10.0.0.100 (10.0.0.1) from 54:e1:ad:33:d8:e2 (LAPTOP-U2IPTTLE) via enp1s0
DHCPACK on 10.0.0.100 to 54:e1:ad:33:d8:e2 (LAPTOP-U2IPTTLE) via enp1s0
DHCPDISCOVER from 54:e1:ad:33:d8:e2 via enp1s0
DHCPOFFER on 10.0.0.102 to 54:e1:ad:33:d8:e2 via enp1s0
DHCPREQUEST for 10.0.0.102 (10.0.0.1) from 54:e1:ad:33:d8:e2 via enp1s0
DHCPACK on 10.0.0.102 to 54:e1:ad:33:d8:e2 via enp1s0
DHCPDISCOVER from 54:e1:ad:33:d8:e2 via enp1s0
DHCPOFFER on 10.0.0.100 to 54:e1:ad:33:d8:e2 via enp1s0
DHCPDISCOVER from 54:e1:ad:33:d8:e2 via enp1s0
DHCPOFFER on 10.0.0.100 to 54:e1:ad:33:d8:e2 via enp1s0
DHCPREQUEST for 10.0.0.100 (10.0.0.1) from 54:e1:ad:33:d8:e2 via enp1s0
DHCPACK on 10.0.0.100 to 54:e1:ad:33:d8:e2 via enp1s0
reuse_lease: lease age 71 (secs) under 25% threshold, reply with unaltered, existing lease for 10.0.0.102
DHCPDISCOVER from 54:e1:ad:33:d8:e2 via enp1s0
DHCPOFFER on 10.0.0.102 to 54:e1:ad:33:d8:e2 via enp1s0
reuse_lease: lease age 75 (secs) under 25% threshold, reply with unaltered, existing lease for 10.0.0.102
DHCPREQUEST for 10.0.0.102 (10.0.0.1) from 54:e1:ad:33:d8:e2 via enp1s0
DHCPACK on 10.0.0.102 to 54:e1:ad:33:d8:e2 via enp1s0
DHCPDISCOVER from 54:e1:ad:33:d8:e2 via enp1s0
DHCPOFFER on 10.0.0.100 to 54:e1:ad:33:d8:e2 (LAPTOP-U2IPTTLE) via enp1s0
DHCPREQUEST for 10.0.0.100 (10.0.0.1) from 54:e1:ad:33:d8:e2 (LAPTOP-U2IPTTLE) via enp1s0
DHCPACK on 10.0.0.100 to 54:e1:ad:33:d8:e2 (LAPTOP-U2IPTTLE) via enp1s0

このログは、DHCPサーバーがクライアントからのリクエストを受け取り、IPアドレスを割り当てるプロセスを示しています。

起動情報の表示:

  • ログの最初の部分では、DHCPサーバーが使用しているユーザーID (UID) とグループID (GID) を表示しています。これはシステム上でのアクセス権限を示しています。
Starting up using the following:
UID: 1111
GID: 1112

DHCPサーバーのバージョンと著作権情報:

  • DHCPサーバーのバージョンや著作権情報を表示しています。これは使用しているソフトウェアがどのバージョンかを確認するための情報です。
Internet Systems Consortium DHCP Server 4.4.3-P1
Copyright 2004-2022 Internet Systems Consortium.
All rights reserved.
For info, please visit https://www.isc.org/software/dhcp/

設定ファイルとデータベースファイル:

  • DHCPサーバーが使用している設定ファイル (/config/dhcpd.conf) と、リース情報を保存するデータベースファイル (/config/dhcpd.leases) を表示しています。これらのファイルはDHCPサーバーの動作に必要な情報を保持しています。
Config file: /config/dhcpd.conf
Database file: /config/dhcpd.leases
PID file: /run/dhcp/dhcpd.pid
Wrote 0 leases to leases file.

サブネット宣言の不足:

  • veth69ce47cdocker0 というネットワークインターフェースに対するサブネット宣言がないため、このインターフェースからのリクエストは無視されます。これはそのインターフェースがDHCPサーバーの対象ではないことを示しています。
No subnet declaration for veth69ce47c (no IPv4 addresses).
** Ignoring requests on veth69ce47c. If this is not what
you want, please write a subnet declaration
in your dhcpd.conf file for the network segment
to which interface veth69ce47c is attached. **

No subnet declaration for docker0 (172.17.0.1).
** Ignoring requests on docker0. If this is not what
you want, please write a subnet declaration
in your dhcpd.conf file for the network segment
to which interface docker0 is attached. **

No subnet declaration for wlp2s0 (192.168.0.107).
** Ignoring requests on wlp2s0. If this is not what
you want, please write a subnet declaration
in your dhcpd.conf file for the network segment
to which interface wlp2s0 is attached. **

リスニング状態:

  • DHCPサーバーがどのインターフェースでリクエストを受け付けているかを表示しています。以下のインターフェースでリスニングしています:
    • br-a180cb5a6bfa (172.20.0.0/16)
    • enp1s0 (10.0.0.0/24)
Listening on LPF/br-a180cb5a6bfa/02:42:6a:7c:7c:8f/172.20.0.0/16
Sending on LPF/br-a180cb5a6bfa/02:42:6a:7c:7c:8f/172.20.0.0/16

Listening on LPF/enp1s0/f0:76:1c:88:14:76/10.0.0.0/24
Sending on LPF/enp1s0/f0:76:1c:88:14:76/10.0.0.0/24

サーバーの開始:

  • 最後に、DHCPサーバーがサービスを開始したことを示しています。
Server starting service.

クライアントからのリクエスト処理:

  • DHCPサーバーはクライアントからのDHCPリクエストを受信し、それに応じてIPアドレスを割り当てます。
  • DHCPDISCOVERは、クライアントがネットワークに参加するためにIPアドレスを探していることを示しています。
  • DHCPOFFERは、サーバーがクライアントにIPアドレスを提供していることを示しています。
  • DHCPREQUESTは、クライアントが提供されたIPアドレスを要求していることを示しています。
  • DHCPACKは、サーバーがクライアントに対してIPアドレスを確認していることを示しています。
DHCPDISCOVER from 54:e1:ad:33:d8:e2 via enp1s0
DHCPOFFER on 10.0.0.100 to 54:e1:ad:33:d8:e2 (LAPTOP-U2IPTTLE) via enp1s0
DHCPREQUEST for 10.0.0.100 (10.0.0.1) from 54:e1:ad:33:d8:e2 (LAPTOP-U2IPTTLE) via enp1s0
DHCPACK on 10.0.0.100 to 54:e1:ad:33:d8:e2 (LAPTOP-U2IPTTLE) via enp1s0

まとめると次のような感じでしょうか。このログは、DHCPサーバーが正常に起動し、クライアントにIPアドレスを提供していることを示しています。一部のネットワークインターフェースに対してサブネット宣言が不足しているため、それらのインターフェースからのリクエストは無視されていますが、これは正常な動作です。

実際にインストールしてみる。
構築したDHCP兼PXEサーバーとクライアントを接続します。HUB経由で接続しました。ネットワークブートを最上位に優先した状態にしておきます。起動画面は以下のスクショの通りです。

しかし、どのディストリビューションも最新版がないうえ、インストールに失敗します。

解決方法
docker-compose.ymlの記述内容を見るとわかるように以下のURLをブラウザに入力することでnetboot.xyzの管理画面にログインすることができるのです。

http://サーバーのIPアドレス:3000/

この管理画面ではファイルを更新することができるので必ず実行しておきましょう。調べてみると以下のことがわかりました。

netboot.xyz-arm64-snp.efiのようなファイルが更新されている可能性が高いです。このファイルは、特にARM64アーキテクチャ用のネットブートイメージです。ほかにもファイルはあります。色々探していたら次のURLを見つけることができました。ここに説明が書いてあります。

Releases · netbootxyz/netboot.xyz
Your favorite operating systems in one place. A network-based bootable operating system installer based on iPXE. - netbo...

ファイルの詳細

  • netboot.xyz-arm64-snp.efi:
    これは、UEFI(Unified Extensible Firmware Interface)環境で使用されるARM64アーキテクチャ用のネットブートイメージです。snpは、Simple Network Protocolを意味し、ネットワークブートの際に使用されます。netboot.xyzは、このイメージを利用して、さまざまなLinuxディストリビューションやユーティリティをネットワーク経由でブート可能にするためのツールです。

この更新は、新しいブートオプションや修正を含んでいることが多く、次のような機能追加やバグ修正が行われた可能性があります。

  • ZFSBootMenuやVanillaOSなどの新しいオプションの追加: ユーザーは新たにこれらのシステムをネットワーク経由でブートできるようになります。
  • 既存のネットブートオプションに対するバグ修正やパフォーマンスの改善: たとえば、Ubuntu 24.04のインストール時の問題が修正されているかもしれません。

このファイルを更新することで、ネットワークブートの際にこれらの新しい機能や修正が反映され、よりスムーズにブートプロセスが進行するようになります。

おまけ
次のファイルはUEFIとレガシーサポートの両方に対応したDHCP設定ファイルです。

default-lease-time 600;
max-lease-time 7200;

# Subnet declaration for 10.0.0.x (enp1s0)
subnet 10.0.0.0 netmask 255.255.255.0 {
  range 10.0.0.100 10.0.0.200;
  option routers 10.0.0.1;
  option broadcast-address 10.0.0.255;
  option domain-name-servers 8.8.8.8, 8.8.4.4;
  next-server 10.0.0.1;  # NetBoot.XYZコンテナのIPアドレス

  # ブートファイルの選択
  if exists user-class and option user-class = "iPXE" {
      filename "netboot.xyz.kpxe";
  } else {
      if substring(option vendor-class-identifier, 0, 9) = "PXEClient" {
          if option vendor-class-identifier = "PXEClient:Arch:00000:UNDI:002001" {
              filename "netboot.xyz.kpxe";  # Legacy BIOS
          } else {
              filename "netboot.xyz.efi";  # UEFI
          }
      } else {
          filename "netboot.xyz.kpxe";  # Other
      }
  }
}

# Subnet declaration for 172.20.0.x (my_custom_network)
subnet 172.20.0.0 netmask 255.255.0.0 {
  range 172.20.0.10 172.20.0.100;
  option routers 172.20.0.1;
  option broadcast-address 172.20.255.255;
  option domain-name-servers 8.8.8.8, 8.8.4.4;

  # ブートファイルの選択
  if exists user-class and option user-class = "iPXE" {
      filename "netboot.xyz.kpxe";
  } else {
      if substring(option vendor-class-identifier, 0, 9) = "PXEClient" {
          if option vendor-class-identifier = "PXEClient:Arch:00000:UNDI:002001" {
              filename "netboot.xyz.kpxe";  # Legacy BIOS
          } else {
              filename "netboot.xyz.efi";  # UEFI
          }
      } else {
          filename "netboot.xyz.kpxe";  # Other
      }
  }
}
GitHub - superdoccimo/notepc: This project provides Docker Compose files and setup instructions to support the configuration of a DHCP and PXE server on a laptop.
This project provides Docker Compose files and setup instructions to support the configuration of a DHCP and PXE server ...
タイトルとURLをコピーしました