hana_shinのLinux技術ブログ

Linuxの技術情報を掲載しています。特にネットワークをメインに掲載していきます。

ip netnsコマンドの使い方(host-router-host環境構築編)



1 はじめに

ネームスペースを使って、ホストールーターホストの環境を構築してみます。

ip netnsコマンドの基本的な使い方は、以下を参照ください。
ip netnsコマンドの使い方(ネットワークの実験の幅が広がるなぁ~) - hana_shinのLinux技術ブログ

2 検証環境

CentOS版数は以下のとおりです。

[root@server ~]# cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)

カーネル版数は以下のとおりです。

[root@server ~]# uname -r
3.10.0-1160.el7.x86_64

3 構築する環境

ルータにホストが2台接続する環境を仮想マシンに構築してみます。

+-- host1 --+                       +--- router ---+                      +-- host2 --+
|           |    192.168.100.0/24   |              |   192.168.200.0/24   |           |
|      veth1-h1 ------------------ veth2-rt  veth3-rt ------------------ veth1-h2     |
|           | .10               .20 |              | .20              .10 |           |
+-----------+                       +--------------+                      +-----------+

4 構築手順

4.1 ホストの作成

ホストを2つ作成します。

[root@server ~]# ip netns add host1
[root@server ~]# ip netns add host2

4.2 ルータの作成

ルータを1つ作成します。

[root@server ~]# ip netns add router

ネームスペースを確認します。ホストとルータが追加されたことがわかります。

[root@server ~]# ip netns list
router
host2
host1

4.3 ポートの作成

ホストとルータに接続するポートを作成します。

[root@server ~]# ip link add name veth1-h1 type veth peer name veth2-rt
[root@server ~]# ip link add name veth1-h2 type veth peer name veth3-rt

4.4 ポートの接続

作成したポートをホスト1に接続します。

[root@server ~]# ip link set veth1-h1 netns host1

作成したポートをホスト2に接続します。

[root@server ~]# ip link set veth1-h2 netns host2

作成したポートをルータに接続します。

[root@server ~]# ip link set veth2-rt netns router
[root@server ~]# ip link set veth3-rt netns router

4.5 IPアドレスの設定

ホスト1のポートにIPアドレスを設定します。

[root@server ~]# ip netns exec host1 ip addr add 192.168.100.10/24 dev veth1-h1

ホスト2のポートにIPアドレスを設定します。

[root@server ~]# ip netns exec host2 ip addr add 192.168.200.10/24 dev veth1-h2

ルータのポートにIPアドレスを設定します。

[root@server ~]# ip netns exec router ip addr add 192.168.100.20/24 dev veth2-rt
[root@server ~]# ip netns exec router ip addr add 192.168.200.20/24 dev veth3-rt

4.6 ポートのリンクアップ

ホスト1のポートをリンクアップします。

[root@server ~]# ip netns exec host1 ip link set veth1-h1 up
[root@server ~]# ip netns exec host1 ip link set lo up

ホスト2のポートをリンクアップします。

[root@server ~]# ip netns exec host2 ip link set veth1-h2 up
[root@server ~]# ip netns exec host2 ip link set lo up

ルータのポートをリンクアップします。

[root@server ~]# ip netns exec router ip link set veth2-rt up
[root@server ~]# ip netns exec router ip link set veth3-rt up
[root@server ~]# ip netns exec router ip link set lo up

4.7 ルーティングテーブルの設定

ルータにルーティングテーブルを設定します。

[root@server ~]# ip netns exec host1 ip route add 192.168.200.0/24 via 192.168.100.20 dev veth1-h1
[root@server ~]# ip netns exec host2 ip route add 192.168.100.0/24 via 192.168.200.20 dev veth1-h2

4.8 ルーティングの有効化

ルーティングを有効化します。

[root@server ~]# ip netns exec router sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1

5 設定内容の確認

5.1 IPアドレスの確認

ホスト1のIPアドレスを確認します。

[root@server ~]# ip netns exec host1 ip a
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
4: veth1-h1@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 36:5d:1c:41:41:0e brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet 192.168.100.10/24 scope global veth1-h1
       valid_lft forever preferred_lft forever
    inet6 fe80::345d:1cff:fe41:410e/64 scope link
       valid_lft forever preferred_lft forever

ホスト2のIPアドレスを確認します。

[root@server ~]# ip netns exec host2 ip a
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
6: veth1-h2@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 02:84:23:df:85:c5 brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet 192.168.200.10/24 scope global veth1-h2
       valid_lft forever preferred_lft forever
    inet6 fe80::84:23ff:fedf:85c5/64 scope link
       valid_lft forever preferred_lft forever

ルータのIPアドレスを確認します。

[root@server ~]# ip netns exec router ip a
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
3: veth2-rt@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 1e:d0:cf:6d:34:4c brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.100.20/24 scope global veth2-rt
       valid_lft forever preferred_lft forever
    inet6 fe80::1cd0:cfff:fe6d:344c/64 scope link
       valid_lft forever preferred_lft forever
5: veth3-rt@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 02:25:3f:6b:a1:7d brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet 192.168.200.20/24 scope global veth3-rt
       valid_lft forever preferred_lft forever
    inet6 fe80::25:3fff:fe6b:a17d/64 scope link
       valid_lft forever preferred_lft forever

5.2 ルーティングテーブルの確認

ルータのルーティングテーブルを確認します。

[root@server ~]# ip netns exec router ip r
192.168.100.0/24 dev veth2-rt proto kernel scope link src 192.168.100.20
192.168.200.0/24 dev veth3-rt proto kernel scope link src 192.168.200.20

6 動作確認

host1に入ります。これをターミナル1と呼びます。

[root@server ~]# ip netns exec host1 bash

もう1つターミナルをオープンします。これをターミナル2と呼びます。そして、ルータに入ります。

[root@server ~]# ip netns exec router bash

ターミナル2で、tcpdumpを実行してパケットの流れを確認してみます。パケットキャプチャに使用できるインタフェースを確認します。本手順で作成したインタフェース(veth2-rt,veth3-rt)が、インタフェースに指定できることがわかります。なお、tcpdumpの使い方は、tcpdumpの使い方(基本編) - hana_shinのLinux技術ブログを参照してください。

[root@server ~]# tcpdump -D
1.nflog (Linux netfilter log (NFLOG) interface)
2.nfqueue (Linux netfilter queue (NFQUEUE) interface)
3.usbmon1 (USB bus number 1)
4.veth2-rt
5.usbmon2 (USB bus number 2)
6.veth3-rt
7.any (Pseudo-device that captures on all interfaces)
8.lo [Loopback]

ターミナル1で、host1からhost2に対してpingを実行してみます。host2から応答があることがわかります。

[root@server ~]# ping -c 1 192.168.200.10
PING 192.168.200.10 (192.168.200.10) 56(84) bytes of data.
64 bytes from 192.168.200.10: icmp_seq=1 ttl=63 time=0.125 ms

--- 192.168.200.10 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.125/0.125/0.125/0.000 ms

次に、tcpdumpの実行結果を確認します。ホスト1とホスト2でやりとりするICMPパケットを確認することができます。

[root@server ~]# tcpdump -i veth3-rt icmp -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on veth3-rt, link-type EN10MB (Ethernet), capture size 262144 bytes
20:24:27.284258 IP 192.168.100.10 > 192.168.200.10: ICMP echo request, id 21990, seq 1, length 64
20:24:27.284318 IP 192.168.200.10 > 192.168.100.10: ICMP echo reply, id 21990, seq 1, length 64

7 環境構築用シェルスクリプト

今まで説明した手順をシェルスクリプトに記述して、環境構築/削除の自動化をしてみたいと思います。

7.1 構築

環境を構築するスクリプトです。

[root@server ~]# cat build.sh
#!/usr/bin/bash

ip netns add host1
ip netns add host2
ip netns add router
ip link add name veth1-h1 type veth peer name veth2-rt
ip link add name veth1-h2 type veth peer name veth3-rt
ip link set veth1-h1 netns host1
ip link set veth1-h2 netns host2
ip link set veth2-rt netns router
ip link set veth3-rt netns router
ip netns exec host1 ip addr add 192.168.100.10/24 dev veth1-h1
ip netns exec host2 ip addr add 192.168.200.10/24 dev veth1-h2
ip netns exec router ip addr add 192.168.100.20/24 dev veth2-rt
ip netns exec router ip addr add 192.168.200.20/24 dev veth3-rt
ip netns exec host1 ip link set veth1-h1 up
ip netns exec host1 ip link set lo up
ip netns exec host2 ip link set veth1-h2 up
ip netns exec host2 ip link set lo up
ip netns exec router ip link set veth2-rt up
ip netns exec router ip link set veth3-rt up
ip netns exec router ip link set lo up
ip netns exec host1 ip route add 192.168.200.0/24 via 192.168.100.20 dev veth1-h1
ip netns exec host2 ip route add 192.168.100.0/24 via 192.168.200.20 dev veth1-h2
ip netns exec router sysctl -w net.ipv4.ip_forward=1

シェルを実行して環境を構築する。

[root@server ~]# ./build.sh

host1からhost2に対してpingを実行します。host2から応答があることがわかります。

[root@server ~]# ping -c 1 192.168.200.10
PING 192.168.200.10 (192.168.200.10) 56(84) bytes of data.
64 bytes from 192.168.200.10: icmp_seq=1 ttl=63 time=0.087 ms

--- 192.168.200.10 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.087/0.087/0.087/0.000 ms

7.2 削除

環境を削除するスクリプトです。

[root@server ~]# cat del.sh
#!/usr/bin/bash
ip netns exec host1 ip link set veth1-h1 down
ip netns exec host1 ip link set lo down
ip netns exec host2 ip link set veth1-h2 down
ip netns exec host2 ip link set lo down
ip netns exec router ip link set veth2-rt down
ip netns exec router ip link set veth3-rt down
ip netns exec router ip link set lo down
ip netns delete host1
ip netns delete host2
ip netns delete router

シェルを実行して環境を削除する。

[root@server ~]# ./del.sh

Z 参考情報

私が業務や記事執筆で参考にした書籍を以下のページに記載します。
Linux技術のスキルアップをしよう! - hana_shinのLinux技術ブログ