dhcpd 代替 の次世代 DHCP サーバー isc-kea を構築してみた。

## isc-kea とは
isc が開発している dhcpd 代替の DHCP サーバーです。
dhcpd (isc-DHCP) が EOL を迎えているので、今から DHCP サーバーを構築するのであればこの製品を使うのが良いと思います。
## 環境
サーバー IP アドレス: `192.168.182.15`
AlmaLinux 9.5
isc-kea 2.6.2
MariaDB 11.4.5
SELinux 有効

## Keaのインストール
cloudsmith のリポジトリからインストールを行います。
一部の依存パッケージが epel にのみ存在するため、事前に epel を有効化しておきます。
```
# dnf install epel-release && dnf upgrade
# curl -1sLf \
  'https://dl.cloudsmith.io/public/isc/kea-2-6/setup.rpm.sh' \
  | sudo -E bash
# dnf install isc-kea
```
## MariaDBのインストール
執筆時点の最新 LTS リリースである 11.4 を使用します。
リポを追加してインストールします。
```
# cat <<'EOF' >/etc/yum.repos.d/MariaDB.repo
# MariaDB 11.4 RedHatEnterpriseLinux repository list - created 2025-05-01 01:28 UTC
# https://mariadb.org/download/
[mariadb]
name = MariaDB
# rpm.mariadb.org is a dynamic mirror if your preferred mirror goes offline. See https://mariadb.org/mirrorbits/ for details.
# baseurl = https://rpm.mariadb.org/11.4/rhel/$releasever/$basearch
baseurl = https://ftp.yz.yamagata-u.ac.jp/pub/dbms/mariadb/yum/11.4/rhel/$releasever/$basearch
# gpgkey = https://rpm.mariadb.org/RPM-GPG-KEY-MariaDB
gpgkey = https://ftp.yz.yamagata-u.ac.jp/pub/dbms/mariadb/yum/RPM-GPG-KEY-MariaDB
gpgcheck = 1
EOF
# dnf install MariaDB-server MariaDB-client
```
### MariaDBの初期設定
MariaDBを起動し、初期設定を行います。
一番最初に `root` ユーザーのパスワードを要求されますが、設定されていないので何も入力せず `Enter` を押下します。
```
# systemctl enable mariadb
# systemctl start mariadb
# mariadb-secure-installation

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!

In order to log into MariaDB to secure it, we'll need the current
password for the root user. If you've just installed MariaDB, and
haven't set the root password yet, you should just press enter here.

Enter current password for root (enter for none):
OK, successfully used password, moving on...

Setting the root password or using the unix_socket ensures that nobody
can log into the MariaDB root user without the proper authorisation.

You already have your root account protected, so you can safely answer 'n'.

Switch to unix_socket authentication [Y/n] n
 ... skipping.

You already have your root account protected, so you can safely answer 'n'.

Change the root password? [Y/n] Y
New password:
Re-enter new password:
Password updated successfully!
Reloading privilege tables..
 ... Success!


By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] Y
 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] Y
 ... Success!

By default, MariaDB comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] Y
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] Y
 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!
```
以下の通り編集します。
``` diff:/etc/my.cnf.d/server.cnf
#
# These groups are read by MariaDB server.
# Use it for options that only the server (but not clients) should see
#

# this is read by the standalone daemon and embedded servers
[server]

# This group is only read by MariaDB servers, not by MySQL.
# If you use the same .cnf file for MySQL and MariaDB,
# you can put MariaDB-only options here
[mariadb]
+ innodb_flush_log_at_trx_commit=2
# This group is read by both MariaDB and MySQL servers
[mysqld]

#
# * Galera-related settings
#
[galera]
# Mandatory settings
#wsrep_on=ON
#wsrep_provider=
#wsrep_cluster_address=
#binlog_format=row
#default_storage_engine=InnoDB
#innodb_autoinc_lock_mode=2
#
# Allow server to accept connections on all interfaces.
#
+ bind-address=127.0.0.1
#
# Optional setting
#wsrep_slave_threads=1
#innodb_flush_log_at_trx_commit=0

# this is only for embedded server
[embedded]

# This group is only read by MariaDB servers, not by MySQL.
# If you use the same .cnf file for MySQL and MariaDB,
# you can put MariaDB-only options here
[mariadb]

# This group is only read by MariaDB-10.11 servers.
# If you use the same .cnf file for MariaDB of different versions,
# use this group for options that older servers don't understand
[mariadb-10.11]
```
MariaDBを再起動します。
```
# systemctl restart mariadb
```
### データベースの作成
以下の通りデータベース、ユーザーを作成し、`kea-admin`コマンドでテーブル等を作成します。
```
# mariadb -p
# create database dhcp;
# CREATE USER 'dhcp'@'localhost' IDENTIFIED BY '<パスワード>';
# GRANT ALL ON dhcp.* TO 'dhcp'@'localhost';
# quit
# kea-admin db-init mysql -u dhcp -p <パスワード> -n dhcp
```
## Keaの設定
以下の定義ファイルを作成します。
```/etc/kea/kea-dhcp4.conf
{
"Dhcp4": {

    "interfaces-config": {
        "interfaces": [ "ens192" ] //使用するインターフェイス 環境に合わせて変更する
    },
    
    "lease-database": {            // DB 接続設定
        "type": "mysql",
        "name": "dhcp",
        "host": "127.0.0.1",
        "user": "dhcp",
        "password": "<パスワード>",
        "lfc-interval": 3600
    },
    
    "expired-leases-processing": {     // リース回収の設定
        "reclaim-timer-wait-time": 10,
        "flush-reclaimed-timer-wait-time": 25,
        "hold-reclaimed-time": 3600,
        "max-reclaim-leases": 100,
        "max-reclaim-time": 250,
        "unwarned-reclaim-cycles": 5
    },
    
    "valid-lifetime": 86400,       // リース期間
    "calculate-tee-times": true, // T1 T2 の自動計算を設定

    "option-data": [
        {
            "name": "domain-name-servers",
            "data": "192.168.182.12" // 配布する DNS サーバーのアドレス
        },
        {
            "code": 15, 
            "data": "example.com" // 配布するドメイン名
        }
    ],
    
    "reservations-global": false, // DHCP 予約をグローバルでは行わない設定
    "reservations-in-subnet": true, // DHCP 予約をサブネット内でのみ使用する設定
    "reservations-out-of-pool": true, // DHCP 予約をサブネット内かつプール外でのみ使用する設定
    "host-reservation-identifiers": ["hw-address"], // DHCP 予約を MAC アドレスでのみ使用する設定
    
    "subnet4": [
        {
            "id": 1,
            "subnet": "192.168.182.0/24", // サブネット
            "pools": [ { "pool": "192.168.182.16 - 192.168.182.19" } ], // 開始 - 終了アドレス
            "option-data": [
                {
                    "name": "routers",
                    "data": "192.168.182.1" // 配布する GW のアドレス
                }
            ],
            
            "reservations": [

                {
                    "hw-address": "00:50:56:a8:68:5f", // MAC アドレス
                    "ip-address": "192.168.182.20" // 払い出す IP アドレス
                }

            ]
        }
        
    ],
    
    "loggers": [
        {
            "name": "kea-dhcp4",
            "output-options": [
                {
                    "output": "/var/log/kea/dhcp4.log",
                    "pattern": "%D{%Y-%m-%d %H:%M:%S.%q} %-5p [%c] %m\n",
                     "maxsize": 1048576,
                     "maxver": 8
                }
            ],
            "severity": "INFO",
            "debuglevel": 0
        }
    ]
}
}
```
以下のコマンドで設定ファイルの内容を確認します。
```
# kea-dhcp4 -t /etc/kea/kea-dhcp4.conf
```
INFO 以外の出力が以下のみであればOKです。
```
WARN  [kea-dhcp4.dhcpsrv/4169.140411106564224] DHCPSRV_MT_DISABLED_QUEUE_CONTROL disabling dhcp queue control when multi-threading is enabled.
WARN  [kea-dhcp4.dhcp4/4169.140411106564224] DHCP4_RESERVATIONS_LOOKUP_FIRST_ENABLED Multi-threading is enabled and host reservations lookup is always performed first.
```
### 起動設定
MariaDBの起動以前にkea-dhcp4が起動しないよう、依存関係を設定します。
```/etc/systemd/system/kea-dhcp4.service.d/dependency.conf
[Unit]
Requires=mariadb.service
After=mariadb.service
```
リロードして設定を反映後、自動起動を設定し、起動します。
```
# systemctl daemon-reload
# systemctl enable kea-dhcp4
# systemctl start kea-dhcp4
```
## 確認
正常にIPアドレスがリースできています。
またDHCPにより配布する各情報についても問題なく配布が行えています。
```
ipconfig /all

Windows IP 構成

   ホスト名. . . . . . . . . . . . . . .: DHCP-TEST
   プライマリ DNS サフィックス . . . . .:
   ノード タイプ . . . . . . . . . . . .: ハイブリッド
   IP ルーティング有効 . . . . . . . . .: いいえ
   WINS プロキシ有効 . . . . . . . . . .: いいえ
   DNS サフィックス検索一覧. . . . . . .: example.com

イーサネット アダプター Ethernet0:

   接続固有の DNS サフィックス . . . . .: example.com
   説明. . . . . . . . . . . . . . . . .: Intel(R) 82574L Gigabit Network Connection
   物理アドレス. . . . . . . . . . . . .: 00-50-56-A8-8B-2F
   DHCP 有効 . . . . . . . . . . . . . .: はい
   自動構成有効. . . . . . . . . . . . .: はい
   IPv4 アドレス . . . . . . . . . . . .: 192.168.182.16(優先)
   サブネット マスク . . . . . . . . . .: 255.255.255.0
   リース取得. . . . . . . . . . . . . .: 2025年5月1日 15:41:12
   リースの有効期限. . . . . . . . . . .: 2025年5月2日 15:41:11
   デフォルト ゲートウェイ . . . . . . .: 192.168.182.1
   DHCP サーバー . . . . . . . . . . . .: 192.168.182.15
   DNS サーバー. . . . . . . . . . . . .: 192.168.182.12
   NetBIOS over TCP/IP . . . . . . . . .: 有効
```
MACアドレスを指定した予約も正常に行えています。
```
ipconfig /all

Windows IP 構成

   ホスト名. . . . . . . . . . . . . . .: DHCP-MAC
   プライマリ DNS サフィックス . . . . .:
   ノード タイプ . . . . . . . . . . . .: ハイブリッド
   IP ルーティング有効 . . . . . . . . .: いいえ
   WINS プロキシ有効 . . . . . . . . . .: いいえ
   DNS サフィックス検索一覧. . . . . . .: example.com

イーサネット アダプター Ethernet0:

   接続固有の DNS サフィックス . . . . .: example.com
   説明. . . . . . . . . . . . . . . . .: Intel(R) 82574L Gigabit Network Connection
   物理アドレス. . . . . . . . . . . . .: 00-50-56-A8-68-5F
   DHCP 有効 . . . . . . . . . . . . . .: はい
   自動構成有効. . . . . . . . . . . . .: はい
   IPv4 アドレス . . . . . . . . . . . .: 192.168.182.20(優先)
   サブネット マスク . . . . . . . . . .: 255.255.255.0
   リース取得. . . . . . . . . . . . . .: 2025年5月1日 15:33:37
   リースの有効期限. . . . . . . . . . .: 2025年5月2日 15:33:38
   デフォルト ゲートウェイ . . . . . . .: 192.168.182.1
   DHCP サーバー . . . . . . . . . . . .: 192.168.182.15
   DNS サーバー. . . . . . . . . . . . .: 192.168.182.12
   NetBIOS over TCP/IP . . . . . . . . .: 有効
```