CUBE SUGAR CONTAINER

技術系のこと書きます。

Linux の Network Namespace と dhcpcd / dnsmasq で DHCPv4 を試す

ISC DHCP 1 のメンテナンスが 2022 年末で終了してしまった。 ISC によると DHCP サーバの実装については Kea DHCP 2 への移行が推奨されている。 ただ、ISC DHCP には DHCP クライアントの実装も含まれていた。 ところが Kea DHCP には DHCP クライアントが含まれていないようだ。 そこで、代替になる DHCP クライアントはないものかと探したところ、どうやら dhcpcd 3 が良さそうなことが分かった。 今回は dnsmasq(8) を DHCP サーバに使って、DHCP クライアントに dhcpcd(8) を使う構成を試してみる。

使った環境は次のとおり。

$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=22.04
DISTRIB_CODENAME=jammy
DISTRIB_DESCRIPTION="Ubuntu 22.04.2 LTS"
$ uname -srm
Linux 5.15.0-75-generic aarch64
$ dhcpcd --version
dhcpcd 7.1.0
Copyright (c) 2006-2019 Roy Marples
Compiled in features: INET ARP ARPing IPv4LL INET6 DHCPv6 AUTH
$ dnsmasq --version
Dnsmasq version 2.86  Copyright (c) 2000-2021 Simon Kelley
Compile time options: IPv6 GNU-getopt DBus no-UBus i18n IDN2 DHCP DHCPv6 no-Lua TFTP conntrack ipset auth cryptohash DNSSEC loop-detect inotify dumpfile

This software comes with ABSOLUTELY NO WARRANTY.
Dnsmasq is free software, and you are welcome to redistribute it
under the terms of the GNU General Public License, version 2 or 3.

もくじ

下準備

まずは dnsmasq と dhcpcd をインストールする。

$ sudo apt-get install dnsmasq dhcpcd5

インストールすると systemd のサービスが稼働する。 今回は systemd 経由では使わないため止める。

$ sudo systemctl stop dhcpcd
$ sudo systemctl disable dhcpcd
$ sudo systemctl stop dnsmasq
$ sudo systemctl disable dnsmasq

ネットワークを作る

続いて Network Namespace を使ってネットワークを用意する。 作るネットワークはセグメントが 1 つしかないシンプルなもの。

まずは Network Namespace を 2 つ作る。 それぞれ DHCP クライアントとサーバに対応する。

$ sudo ip netns add server
$ sudo ip netns add client

間をつなぐ Virtual Ethernet Device のインターフェイスを用意する。

$ sudo ip link add s-veth0 type veth peer name c-veth0

インターフェイスを、それぞれの Network Namespace に所属させる。

$ sudo ip link set s-veth0 netns server
$ sudo ip link set c-veth0 netns client

インターフェイスの MAC アドレスをドキュメンテーションアドレスに変更しておく。

$ sudo ip netns exec server ip link set dev s-veth0 address 00:00:5E:00:53:01
$ sudo ip netns exec client ip link set dev c-veth0 address 00:00:5E:00:53:02

インターフェイスをリンクアップさせる。

$ sudo ip netns exec server ip link set s-veth0 up
$ sudo ip netns exec client ip link set c-veth0 up

DHCP サーバのインターフェイスには IPv4 アドレスを付与しておく。

$ sudo ip netns exec server ip address add 192.0.2.254/24 dev s-veth0

DHCP サーバを起動する

ネットワークが完成したので DHCP サーバとして dnsmasq(8) を起動する。

$ sudo ip netns exec server dnsmasq \
  --dhcp-range=192.0.2.100,192.0.2.200,255.255.255.0 \
  --interface=s-veth0 \
  --port 0 \
  --no-resolv \
  --no-daemon

この段階では、当然ながらまだ DHCP クライアント側のインターフェイスには IPv4 アドレスは付与されていない。

$ sudo ip netns exec client ip address show
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
3: c-veth0@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 00:00:5e:00:53:02 brd ff:ff:ff:ff:ff:ff link-netns server
    inet6 fe80::200:5eff:fe00:5302/64 scope link 
       valid_lft forever preferred_lft forever

DHCP クライアントを起動する

DHCP クライアント側の Netowork Namespace で dhcpcd(8) を起動する。 このとき --nobackground オプションを指定するとフォアグラウンドでプログラムが実行される。 また --ipv4only オプションを指定すると DHCPv4 だけが処理される。 これは dhcpcd(8) が DHCPv6 にも対応しているため。

$ sudo ip netns exec client dhcpcd c-veth0 --ipv4only --nobackground

少し待つと、次のように DHCP がやり取りされてアドレスやデフォルトルートが設定された旨がログに出てくる。

$ sudo ip netns exec client dhcpcd c-veth0 --ipv4only --nobackground
DUID 00:01:00:01:2c:2c:1b:c2:00:00:5e:00:53:02
c-veth0: IAID 5e:00:53:02
c-veth0: soliciting a DHCP lease
c-veth0: offered 192.0.2.177 from 192.0.2.254
c-veth0: ignoring offer of 192.0.2.177 from 192.0.2.254
c-veth0: probing address 192.0.2.177/24
c-veth0: leased 192.0.2.177 for 3600 seconds
c-veth0: adding route to 192.0.2.0/24
c-veth0: adding default route via 192.0.2.254

その後 IPv4 アドレスを確認すると、ちゃんとインターフェイスに付与されている。

$ sudo ip netns exec client ip -4 address show
3: c-veth0@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link-netns server
    inet 192.0.2.177/24 brd 192.0.2.255 scope global noprefixroute c-veth0
       valid_lft forever preferred_lft forever

ルーティングテーブルを確認するとデフォルトルートも設定されている。

$ sudo ip netns exec client ip -4 route show
default via 192.0.2.254 dev c-veth0 proto dhcp src 192.0.2.177 metric 203 
192.0.2.0/24 dev c-veth0 proto dhcp scope link src 192.0.2.177 metric 203 

めでたしめでたし。