CentOS8 でネットワークインターフェイスが複数存在する場合、利用方法は幾つか考えられると思います。
- そのまま扱う (全インターフェイス同じルーティングテーブルに所属させる)
- インターフェイスごとに VLAN を分ける (8021q モジュールが必要)
- インターフェイスごとに VRF を分ける (カーネル 4.4 以上が必要)
- インターフェイスごとに Network Namespace を分ける (対応版カーネルと iproute2 パッケージが必要)
今回は 4 番目の Network Namespace を使った設定方法をメモしておきます。 尚、このメモは Network Namespaceを使ってLinuxのルーティングテーブルを分離させる を参考にさせて頂いている為、出来れば (このメモよりも) 元記事をご覧になることをお勧めします。
ゴール
最終的には以下の構成を作ります。 Linux には CentOS8 を使いました。
Linux にはふたつのインターフェイスが存在しますが、以下のように Network Space を分離します。
インターフェイス | Network Namespace | 設定方法 | 想定利用イメージ |
---|---|---|---|
ens192 |
default |
nmcli で設定 |
管理用 |
ens224 |
0 |
起動スクリプト内で iproute2 を使って設定 |
検証用 |
尚、Linux 上の接続名は以下である前提で設定を進めます (デバイス名と接続名を同じにしてあります)。
# nmcli connection show
NAME UUID TYPE DEVICE
ens224 775414a8-1b43-4b4f-8f06-d89254f4b75c ethernet ens224
ens192 d3a6ca7a-f8cd-4855-a60d-24fa62debce3 ethernet ens192
Network Namespace の設定には iproute2
の ip netns
コマンドを利用しますが、設定しただけでは OS を再起動すると未設定の状態に戻ってしまいます。 その為、systemd にサービスを登録し、起動時に意図したネットワーク設定が行われるようにします。 サービス名は nsctrl
としました。
Step.1
管理用に利用する ens192
は任意にアドレス設定やゲートウェイ、DNS の設定を行います。
nmcli connection modify ens192 \
ipv4.addresses 10.0.0.1/24 \
ipv4.gateway 10.0.0.254 \
ipv4.dns "1.1.1.1 1.0.0.1" \
ipv4.method manual
Step.2
OS 再起動時もネットワーク設定がされるように、後の手順で systemd へサービスを登録します。 そのサービスから呼び出される想定の設定用スクリプトを用意します。 今回は以下の内容で /usr/local/sbin/nsctrl
というファイルを新規作成しました。 このファイルの内容は「設定したいネットワークのパラメータ」に合わせて修正します。
尚、Network Namespace を操作する ip netns
コマンドは「元々存在しているデフォルトの Network Namespace」を明示的に指定することが出来ません。 この操作を可能にする為、ln -s /proc/1/ns/net /var/run/netns/default
というシンボリックリンクを作成することで ip netns
コマンドから default
という名前でデフォルトの Network Namespace を参照出来るように設定します。
#!/bin/bash
SSHD_CMD=`which sshd`
SSHD_CONF="/etc/ssh/sshd_config"
DEFAULT_NS="default"
DEFAULT_IF="ens192"
NS0_NS="0"
NS0_IF="ens224"
NS0_ADDR="192.168.0.1"
NS0_MASK="255.255.255.0"
NS0_GW="192.168.0.254"
NS0_SSHD_PID="/var/run/sshd-$NS0_NS-$NS0_IF.pid"
case $1 in
"start")
echo "Create namespace settings."
# default
mkdir -p /var/run/netns/
ln -s /proc/1/ns/net /var/run/netns/$DEFAULT_NS
# nw1
ip netns add $NS0_NS
ip link set $NS0_IF netns $NS0_NS up
ip netns exec $NS0_NS ip address add $NS0_ADDR/$NS0_MASK dev $NS0_IF
ip netns exec $NS0_NS ip route add 0.0.0.0/0 via $NS0_GW dev $NS0_IF
ip netns exec $NS0_NS $SSHD_CMD -f $SSHD_CONF -o "PidFile $NS0_SSHD_PID"
;;
"stop")
echo "Delete namespace settings."
ip netns delete $NS0_NS
kill -9 `cat $NS0_SSHD_PID`
rm $NS0_SSHD_PID
rm /var/run/netns/default
;;
"status")
echo "-----[ip netns list]"
ip netns list
echo "-----[ip address show]"
echo "(default)"
ip address show
echo "($NS0_NS)"
ip netns exec $NS0_NS ip address show
echo "-----[ip route show]"
echo "(default)"
ip route show
echo "($NS0_NS)"
ip netns exec $NS0_NS ip route show
echo "-----[ip neigh show]"
echo "(default)"
ip neigh show
echo "($NS0_NS)"
ip netns exec $NS0_NS ip neigh show
esac
スクリプトを用意したら実行権限を付与しておきます。
chmod u+x /usr/local/sbin/nsctrl
Step.3
systemd にサービス登録する為のファイルを作成します。 以下の内容で /etc/systemd/system/nsctrl.service
というファイルを新規作成します。
[Unit]
Description = Control network namespace.
After=networking.service.target
[Service]
ExecStart=/bin/bash /usr/local/sbin/nsctrl start
ExecStop=/bin/bash /usr/local/sbin/nsctrl stop
Type=Simple
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
作成したファイルを systemd に反映する為、systemctl daemon-reload
を実行しておきます。
systemctl daemon-reload
これで systemd へサービスが登録されました。
# systemctl list-unit-files | grep nsctrl
nsctrl.service disabled
Step.4
登録したサービスが OS 起動時に自動実行されるようにしておきます。
systemctl enable nsctrl
Step.5
「意図した通りに動作するか?」を確認する為、OS ごと再起動します。
reboot
Step.6
再起動が完了したら OS へログインし直し、下記のコマンドなどを使って意図した設定がされていることを確認します。
ip netns list
ip netns exec default ip address show
ip netns exec default ip route show
ip netns exec 0 ip address show
ip netns exec 0 ip route show
ip netns list
を実行すると定義された Network Namespace の一覧を表示することが出来ます。 下記では default
と 0
の、ふたつの Network Namespace が定義されていることを確認出来ます。
# ip netns list
0 (id: 0)
default
sshd も default
と 0
の各々で動作しています。
# ls -l /var/run/sshd*
-rw-r--r-- 1 root root 4 May 9 12:55 /var/run/sshd-0-ens224.pid
-rw-r--r-- 1 root root 4 May 9 12:55 /var/run/sshd.pid
コマンドを個々に実行していくのが面倒な場合は今回、作成したスクリプトを nsctrl status
のように実行することで一度に状態確認することも出来ます。 以下は nsctrl status
を実行した場合の出力例です。
# nsctrl status
-----[ip netns list]
0 (id: 0)
default
-----[ip address show]
(default)
1: lo: <LOOPBACK,UP,LOWER_UP> 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
valid_lft forever preferred_lft forever
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:50:56:be:73:c1 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.1/24 brd 10.0.0.255 scope global noprefixroute ens192
valid_lft forever preferred_lft forever
inet6 fe80::d9aa:bd1d:2f0:808b/64 scope link noprefixroute
valid_lft forever preferred_lft forever
(0)
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: ens224: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:50:56:be:d2:06 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.1/24 scope global ens224
valid_lft forever preferred_lft forever
inet6 fe80::250:56ff:febe:d206/64 scope link
valid_lft forever preferred_lft forever
-----[ip route show]
(default)
default via 10.0.0.254 dev ens192 proto static metric 100
10.0.0.0/24 dev ens192 proto kernel scope link src 10.0.0.1 metric 100
(0)
default via 192.168.0.254 dev ens224
192.168.0.0/24 dev ens224 proto kernel scope link src 192.168.0.1
-----[ip neigh show]
(default)
10.0.0.254 dev ens192 lladdr 00:0a:b8:d0:6f:c1 REACHABLE
(0)
192.168.0.254 dev ens224 FAILED
Network Namespace を削除する
Network Namespace を削除したい場合は以下のように実行します。
systemctl stop nsctrl
これで Network Namespace は削除されました。
# ip netns list
#
プロンプトに Network Namespace 名を表示する
bash のプロンプトに Network Namespace 名を表示するには以下の内容で /etc/profile.d/prompt.sh
を新規作成します。
NETNS=`ip netns identify $BASHPID`
if [ `id -u` = 0 ]; then
if [ $NETNS ]; then
PS1="[\[\033[1;31m\]\u@\h\[\033[00m\] \W]($NETNS)\\$ "
else
PS1="[\[\033[1;31m\]\u@\h\[\033[00m\] \W]\\$ "
fi
else
if [ $NETNS ]; then
PS1="[\[\033[1;36m\]\u@\h\[\033[00m\] \W]($NETNS)\\$ "
else
PS1="[\[\033[1;36m\]\u@\h\[\033[00m\] \W]\\$ "
fi
fi
これでシェルにログインするとプロンプトが以下のように表示されます。
[root@localhost ~](default)#
コメント