DHCPサーバーを立ててみた - crashRT のブログ で立てたisc-dhcp-serverがEOLだったのでKeaDHCPを構築しました。 構築したのは結構前だったのですが書いていなかったので残しておきます。
追記 2025.5.27
色々あって作り直しました.以下のブログで紹介しています.
docker-compose.yml
追記 2025.4.28
コンテナのnetwork mode をbridgeネットワークにしていると server identifier が Docker Network のアドレスになってしまうようです(どこかで設定はできそう) もともと network mode を host にして運用していたのですが,きれいにしようと思って bridge ネットワークにしたら不具合が起きてました.お気をつけて...
services:
kea-dhcp4:
image: docker.cloudsmith.io/isc/docker/kea-dhcp4
container_name: kea-dhcp4
network_mode: host
volumes:
- ./config:/etc/kea
- ./data:/var/lib/kea
ボリュームはコンフィグと、今回はリース情報をmemfileで管理しているのでその永続化をしています。
data ディテクトリのファイルにKeaがリース情報などを書き込むので、以下のコマンドで権限を与えておきます。
chmod o+w data/
DBをバックエンドにするやつ今度やってみたい。
Storkとかでちゃんと監視するならunixソケットもバインドする必要がありそうです。 やろうと思ったままできてなかったのでこれも今度試してみようと思います。
kea-dhcp4.conf
./config の中に作成します。
設定に関するドキュメントは以下にあります。
{
"Dhcp4": {
"valid-lifetime": 6000,
"calculate-tee-times": true,
"lease-database": {
"type": "memfile",
"persist": true,
"name": "/var/lib/kea/dhcp4.leases"
},
"subnet4": [
{
"subnet": "192.168.2.0/24",
"pools": [
{"pool": "192.168.2.129 - 192.168.2.254"}
],
"id": 1,
"interface": "ens18",
"option-data": [
{
"name": "routers",
"data": "192.168.2.1"
}
]
}
],
"interfaces-config": {
"interfaces": ["ens18],
},
"option-data": [
{
"name": "domain-name-servers",
"data": "192.168.11.4",
"always-send": true
}
],
"control-socket": {
"socket-type": "unix",
"socket-name": "/run/kea/control_socket_4"
},
"loggers": [
{
"name": "*",
"output_options": [
{
"output": "stdout"
}
],
"severity": "INFO"
}
]
}
}
一部の設定についてコメントします。 他の部分はほぼデフォルト(バインドマウントせずにコンテナを起動した際に含まれていた)設定です。
リース期間の設定
valid-lifetime はリース期間です。とりあえず100分にしています。
その下のcalculate-tee-timesはRFC2131のT1とT2(リースの更新を管理するやつ。それぞれrenewとrebind)をRFC2131で示されたデフォルトの割合でいい感じに設定してくれる設定です。*1
僕の部屋のAndroidの端末が何故かrenew(DHCPサーバーにunicastでDHCP requestを送信してリース情報を更新)せずに最初からrebind(broadcastでDHCP requestを送信して)していてしょっちゅう途切れるので原因を調査中です。
DHCP4_INIT_REBOOT [hwtype=1 96:53:3e:d4:87:37], cid=[01:96:53:3e:d4:87:37], tid=0x982b38a: client is in INIT-REBOOT state and requests address 192.168.2.129
↑というログが表示されていて、どうやらクライアント側の状態がおかしいらしい...
2025.5.27追記
色々調べてみたところ,IPv6が不安定だったのが原因だったみたいです.
RAが届いた直後にネットワークと一旦切断し,再度接続しなおしているような挙動をしていました.
おそらくDHCPが原因ではなさそうです.
詳細を調べたらまた紹介します.
余談ですが,Androidはオプションの renewal time rebinding time を設定していてもこの値は使ってくれなくて,毎回 lease time から計算した値を使用することが分かりました.
クライアントに返す情報の設定
subnet4 でDHCPサーバーで管理するサブネットの設定をします
subnet は対象となるネットワークのサブネット、pools で実際に配布するアドレスの設定をします。
pools で 192.168.2.0/24 とも書けるのですが、ネットワークアドレスとかブロードキャストアドレスとかも含まれてしまうため非推奨のようです。*2
option-data は二箇所で指定しています。
subnet の中のものはサブネット固有の設定、その外のものはサブネット共通の設定として扱わるので、
デフォルトゲートウェイについてはサブネットの中で、DNSサーバーは共通で設定しました。
kea-ctrl-agent.conf
./config 内にこのファイルもないと起動しません。
以下はデフォルトの設定そのままです。
この辺もちゃんと使ってなんか面白いことやってみたい
{
"Control-agent": {
"http-host": "0.0.0.0",
"http-port": 8040,
"control-sockets": {
"dhcp4": {
"socket-type": "unix",
"socket-name": "/run/kea/control_socket_4"
}
},
"loggers": [
{
"name": "kea-ctrl-agent",
"output_options": [
{
"output": "stdout"
}
],
"severity": "INFO"
}
]
}
}
まとめ
雑に今動かしているKeaDHCPの設定ファイルを紹介しました。 まだまだ遊べそうなことはたくさんあるので色々試してみようと思います。
*1:
Times T1 and T2 are configurable by the server through options. T1 defaults to (0.5 * duration_of_lease). T2 defaults to (0.875 * duration_of_lease).
RFC 2131 - Dynamic Host Configuration Protocol
↑この割合です
*2:
When configuring a DHCPv4 server using prefix/length notation, please pay attention to the boundary values. When specifying that the server can use a given pool, it is also able to allocate the first (typically a network address) and the last (typically a broadcast address) address from that pool.