iP
centos7
netns
namespace

ip netnsコマンドの使い方(ネットワークの実験の幅が広がるなぁ~)

1 ip netnsコマンドとは?

ネットワークネームスペース(以降、ネームスペースと略)を操作するコマンドです。
netnsはipコマンドのOBJECTの1つです。

ipコマンドの書式(manの抜粋)
# ip [ OPTIONS ] OBJECT { COMMAND | help }
  OBJECT := { link | address | addrlabel | route | rule | neigh | ntable | tunnel | tuntap | maddress | mroute |
                 mrule | monitor | xfrm | netns | l2tp | tcp_metrics | token }

2 環境

VMware Workstation 14 Playerでゲストマシンを作成しました。
ゲストマシンのOS版数は以下のとおりです。

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

[root@centos74 ~]# uname -r
3.10.0-693.el7.x86_64

3 オプション一覧

[root@centos74 ~]# ip netns help
Usage: ip netns list
       ip netns add NAME
       ip netns set NAME NETNSID
       ip [-all] netns delete [NAME]
       ip netns identify [PID]
       ip netns pids NAME
       ip [-all] netns exec [NAME] cmd ...
       ip netns monitor
       ip netns list-id

4 ネームスペースを表示する方法(list)

ネームスペースを確認する。ネームスペースが登録されていないことがわかる。
[root@centos74 ~]# ip netns list
[root@centos74 ~]#

5 ネームスペースを追加する方法(add)

ネームスペース(test1)を追加する。
[root@centos74 ~]# ip netns add test1

ネームスペースを確認する。test1が追加されたことがわかる。
[root@centos74 ~]# ip netns list
test1

ネームスペース(test2)を追加する。
[root@centos74 ~]# ip netns add test2

ネームスペースを確認する。test2が追加されたことがわかる。
[root@centos74 ~]# ip netns list
test2
test1

6 ネームスペースを削除する方法(delete)

6.1 個別に削除する方法

登録されているネームスペースの確認
[root@centos74 ~]# ip netns list
test2
test1
test1の削除
ネームスペース(test1)を削除する。
[root@centos74 ~]# ip netns delete test1
[root@centos74 ~]# ip netns list
test2
test2の削除
ネームスペース(test2)を削除する。
[root@centos74 ~]# ip netns delete test2
[root@centos74 ~]# ip netns list
[root@centos74 ~]#

6.2 一括削除する方法(-all)

登録されているネームスペースを確認する。
[root@centos74 ~]# ip netns list
test2
test1

ネームスペースを一括削除する。
[root@centos74 ~]# ip -all netns del

ネームスペースが全て削除されたことがわかる。
[root@centos74 ~]# ip netns list
[root@centos74 ~]#

7 ネームスペースの追加/削除をモニタする方法(monitor)

monitorオプションを使うと、ネームスペースに対する操作をモニタすることができます。
ターミナル1で操作をモニタします。ターミナル2でネームスペースに対して操作をします。

ターミナル1
[root@centos74 ~]# ip netns monitor
ターミナル2
ネームスペース(test1)を追加する。
[root@centos74 ~]# ip netns add test1
ターミナル1
ネームスペース(test1)が追加されたことがわかる。
[root@centos74 ~]# ip netns monitor
add test1
ターミナル2
ネームスペース(test1)を削除する。
[root@centos74 ~]# ip netns delete test1
ターミナル1
ネームスペース(test1)が削除されたことがわかる。
[root@centos74 ~]# ip netns monitor
delete test1

8 指定したネームスペースでコマンドを実行する方法(exec)

ここでは、test1というネームスペースを作成し、そのネームスペースでbashを実行してみます。

ネームスペース(test1)を追加する。
[root@centos74 ~]# ip netns add test1
[root@centos74 ~]# ip netns list
test1

ネームスペース(test1)でbashを実行する。
[root@centos74 ~]# ip netns exec test1 bash

ネームスペース(test1)でipコマンドを実行する。
[root@centos74 ~]# ip l
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

ネームスペース(test1)から抜ける。
[root@centos74 ~]# exit
exit

9 プロセスが動作しているネームスペースを調べる方法(identify)

ターミナル1(テスト用ネームスペース、プロセスの起動)
[root@centos74 ~]# tty
/dev/pts/1

ネームスペース(test1)を作成する。
[root@centos74 ~]# ip netns add test1

ネームスペースを確認する。test1が追加されたことがわかる。
[root@centos74 ~]# ip netns list
test1

test1でbashとncコマンドを起動する。
[root@centos74 ~]# ip netns exec test1 bash
[root@centos74 ~]# nc -kl 11111
ターミナル2
[root@centos74 ~]# tty
/dev/pts/0

ncプロセスのPIDを確認する。PID=1390であることがわかる。
[root@centos74 ~]# ps -C nc
   PID TTY          TIME CMD
  1390 pts/1    00:00:00 nc

ncプロセスが動作しているネームスペースを確認する。test1で動作していることがわかります。
[root@centos74 ~]# ip netns identify 1390
test1

bashプロセスのPIDを確認する。PID=1375であることがわかる。
[root@centos74 ~]# ps -C bash -o comm,pid,lstart,tty
COMMAND            PID                  STARTED TT
bash              1064 Sun May  6 15:39:37 2018 pts/0 ★ターミナル2
bash              1139 Sun May  6 15:53:07 2018 pts/1 ★ターミナル1
bash              1375 Sun May  6 16:21:49 2018 pts/1 ★ターミナル1(ip netns execで起動したbash)

bashプロセスが動作しているネームスペースを確認する。test1で動作していることがわかります。
bashプロセス(PID=1375)は、test1で動作していることがわかります。
[root@centos74 ~]# ip netns identify 1375
test1

10 ネームスペースで動作しているプロセスのPIDを調べる方法(pids)

test1で2つのプロセス(PID=1375,1390)が動作していることがわかる。
[root@centos74 ~]# ip netns pids test1
1375
1390

PID=1375はbashであることがわかる。
[root@centos74 ~]# ps -p 1375
   PID TTY          TIME CMD
  1375 pts/1    00:00:00 bash

PID=1390はncであることがわかる。
[root@centos74 ~]# ps -p 1390
   PID TTY          TIME CMD
  1390 pts/1    00:00:00 nc

11 ホスト、ルータの環境構築

ネームスペースを使って、ルーティング可能なネットワーク環境をゲストマシン上に構築してみます。

11.1 構築する環境

ゲストマシン上にネームスペースを3つ作成(host1,host2,router)します。
ネットワークは2つあります。host1とhost2は、それぞれ別々のネットワークに所属します。
host1でpingを実行します。宛先はhost2です。routerがICMPパケットのルーティングをおこないます。

 +-------------------------------- Guest Machine(CentOS7.4) -------------------------------+
 |                                                                                         |
 |                                                                                         |
 |                                                                                         |
 | +-- 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 |           | |
 | +-----------+                       +--------------+                      +-----------+ |
 |                                                                                         |
 |                                                                                         |
 +-----------------------------------------------------------------------------------------+

11.2 設定手順

11.2.1 ホスト、ルータの作成

ネームスペースを作成する。
[root@centos74 ~]# ip netns add host1
[root@centos74 ~]# ip netns add host2
[root@centos74 ~]# ip netns add router

ネームスペースを確認する。ネームスペースが3つ作成されたことがわかる。
[root@centos74 ~]# ip netns list
router
host2
host1

11.2.2 インタフェースの作成

インタフェースの作成
[root@centos74 ~]# ip link add name veth1-h1 type veth peer name veth2-rt
[root@centos74 ~]# ip link add name veth1-h2 type veth peer name veth3-rt
作成したインタフェースの確認
[root@centos74 ~]# ip l|grep veth
9: veth2-rt@veth1-h1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
10: veth1-h1@veth2-rt: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
11: veth3-rt@veth1-h2: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
12: veth1-h2@veth3-rt: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000

11.2.3 ホスト、ルータにインタフェース設定

インタフェースの移動
ゲストマシン上のインタフェースをルータ、ホストに移動します。
[root@centos74 ~]# ip link set veth1-h1 netns host1
[root@centos74 ~]# ip link set veth1-h2 netns host2
[root@centos74 ~]# ip link set veth2-rt netns router
[root@centos74 ~]# ip link set veth3-rt netns router

11.2.4 IPアドレスの設定

[root@centos74 ~]# ip netns exec host1 ip addr add 192.168.100.10/24 dev veth1-h1
[root@centos74 ~]# ip netns exec host2 ip addr add 192.168.200.10/24 dev veth1-h2
[root@centos74 ~]# ip netns exec router ip addr add 192.168.100.20/24 dev veth2-rt
[root@centos74 ~]# ip netns exec router ip addr add 192.168.200.20/24 dev veth3-rt

11.2.5 インタフェースのUP

[root@centos74 ~]# ip netns exec host1 ip link set veth1-h1 up
[root@centos74 ~]# ip netns exec host2 ip link set veth1-h2 up
[root@centos74 ~]# ip netns exec router ip link set veth2-rt up
[root@centos74 ~]# ip netns exec router ip link set veth3-rt up

[root@centos74 ~]# ip netns exec host1 ip link set lo up
[root@centos74 ~]# ip netns exec host2 ip link set lo up
[root@centos74 ~]# ip netns exec router ip link set lo up

11.2.6 インタフェースの確認

host1
host1のインタフェースを確認する。
[root@centos74 ~]# ip netns exec host1 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    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
20: veth1-h1@if19: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
    link/ether 1a:f0:9d:f2:cc:cd 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::18f0:9dff:fef2:cccd/64 scope link
       valid_lft forever preferred_lft forever
host2
host2のインタフェースを確認する。
[root@centos74 ~]# ip netns exec host2 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    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
22: veth1-h2@if21: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
    link/ether aa:08:a6:71:d3:e4 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::a808:a6ff:fe71:d3e4/64 scope link
       valid_lft forever preferred_lft forever
router
routerのインタフェースを確認する。
[root@centos74 ~]# ip netns exec router ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    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
23: veth2-rt@if24: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
    link/ether 06:f1:e8:7b:02:71 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::4f1:e8ff:fe7b:271/64 scope link
       valid_lft forever preferred_lft forever
25: veth3-rt@if26: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
    link/ether 42:1a:08:4d:d0:32 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::401a:8ff:fe4d:d032/64 scope link
       valid_lft forever preferred_lft forever

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

ルーティングテーブルの設定(host1,host2で実施)
[root@centos74 ~]# ip netns exec host1 ip route add 192.168.200.0/24 via 192.168.100.20 dev veth1-h1
[root@centos74 ~]# ip netns exec host2 ip route add 192.168.100.0/24 via 192.168.200.20 dev veth1-h2
ルーティング機能の有効化(routerで実施)
[root@centos74 ~]# ip netns exec router sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1

11.2.8 ルーティングの確認

ルーティングテーブルの確認(host1,host2で実施)
host1のルーティングテーブルを確認する。
[root@centos74 ~]# ip netns exec host1 ip r
192.168.100.0/24 dev veth1-h1 proto kernel scope link src 192.168.100.10
192.168.200.0/24 via 192.168.100.20 dev veth1-h1

host2のルーティングテーブルを確認する。
[root@centos74 ~]# ip netns exec host2 ip r
192.168.100.0/24 via 192.168.200.20 dev veth1-h2
192.168.200.0/24 dev veth1-h2 proto kernel scope link src 192.168.200.10
ルーティング機能の確認(routerで実施)
ルーティング機能を確認する。有効になっていることがわかる。
[root@centos74 ~]# ip netns exec router sysctl -a|grep -w ip_forward
net.ipv4.ip_forward = 1

11.3 実行結果(tcpdumpによる確認)

host1でpingを実行してみます。宛先はhost2(veth1-h2)です。
ICMPパケットがrouterのインタフェース(veth3-rt)を通過していることがわかります。
tcpdumpの使い方は、ここ(tcpdumpの使い方)を参照してください。

routerでtcpdump実行
[root@centos74 ~]# ip netns exec router tcpdump -i veth3-rt icmp
host1でpingの実行
host1でpingを実行します。pingの宛先はhost2です。
[root@centos74 ~]# ip netns exec host1 ping -c 1 192.168.200.10
tcpdumpの実行結果
ICMPパケットがrouterのveth3-rtを通過していることがわかる。
[root@centos74 ~]# ip netns exec router tcpdump -i veth3-rt icmp
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:08:17.745798 IP 192.168.100.10 > 192.168.200.10: ICMP echo request, id 2902, seq 1, length 64
20:08:17.745823 IP 192.168.200.10 > 192.168.100.10: ICMP echo reply, id 2902, seq 1, length 64

11.4 実行結果(iptablesによる確認)

ここでは、routerを通過するICMPパケットをiptablesを使って確認してみます。
iptablesの使い方は、ここ(iptablesの使い方)を参照してください。

ターミナル1(iptablesの初期状態の確認)
FORWARDチェインにルールを追加します。
[root@centos74 ~]# ip netns exec router bash
[root@centos74 ~]# iptables -A FORWARD -p icmp
[root@centos74 ~]# iptables -nvL FORWARD
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0            icmp --  *      *       0.0.0.0/0            0.0.0.0/0
ターミナル2(pingの実行)
host1でpingを実行します。pingの宛先はhost2です。
[root@centos74 ~]# ip netns exec host1 ping -c 1 192.168.200.10
ターミナル1(iptablesの確認)
2つのパケット(ICMP echo request/ICMP echo reply)がFORWARDチェインを通過していることがわかる。
[root@centos74 ~]# iptables -nvL FORWARD
Chain FORWARD (policy ACCEPT 2 packets, 168 bytes)
 pkts bytes target     prot opt in     out     source               destination
    2   168            icmp --  *      *       0.0.0.0/0            0.0.0.0/0

11.5 環境構築用シェル

[root@centos74 ~]# cat net.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 host2 ip link set veth1-h2 up
ip netns exec router ip link set veth2-rt up
ip netns exec router ip link set veth3-rt up
ip netns exec host1 ip link set lo up
ip netns exec host2 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

12 ホスト、ルータ、ブリッジの環境構築

12.1 構築する環境

ルータ(router)とホスト(host1,host2)がブリッジを介して接続する環境を構築します。
ネットワークアドレスは、192.168.100.0/24です。
()内はポート名を表しています。

                     192.168.100.0/24

                      +-- bridge --+
                      |            |
                      |          (p2-br) --- (p-h1)host1
                      |            |        .20
  router(p-rt) --- (p1-br)         |
         .10          |            |
                      |          (p3-br) --- (p-h2)host2
                      |            |         .30
                      +------------+

12.2 設定手順

12.2.1 ホストの作成

ネームスペースを作成する。
[root@centos74 ~]# ip netns add router
[root@centos74 ~]# ip netns add host1
[root@centos74 ~]# ip netns add host2

ネームスペースを確認する。ネームスペースが3つ作成されたことがわかる。
[root@centos74 ~]# ip netns list
host2
host1
router

12.2.2 ブリッジの作成

"bridge"という名前のブリッジを作成する。
[root@centos74 ~]# brctl addbr bridge

ブリッジを表示する。
[root@centos74 ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
bridge          8000.000000000000       no

12.2.2 インタフェースの作成

[root@centos74 ~]# ip link add p-rt type veth peer name p1-br
[root@centos74 ~]# ip link add p-h1 type veth peer name p2-br
[root@centos74 ~]# ip link add p-h2 type veth peer name p3-br

インタフェースを確認する。
[root@centos74 ~]# ip l
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
    link/ether 00:0c:29:f0:6e:a2 brd ff:ff:ff:ff:ff:ff
3: bridge: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether ca:a3:4a:01:05:f1 brd ff:ff:ff:ff:ff:ff
4: p1-br@p-rt: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether 06:dd:fe:5d:f9:67 brd ff:ff:ff:ff:ff:ff
5: p-rt@p1-br: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether ce:51:77:ae:2a:6d brd ff:ff:ff:ff:ff:ff
6: p2-br@p-h1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether 8a:37:0c:05:f2:93 brd ff:ff:ff:ff:ff:ff
7: p-h1@p2-br: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether ee:29:1c:d0:32:f8 brd ff:ff:ff:ff:ff:ff
8: p3-br@p-h2: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether 6e:9b:cf:cc:cb:22 brd ff:ff:ff:ff:ff:ff
9: p-h2@p3-br: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether ea:2f:f7:6b:c7:01 brd ff:ff:ff:ff:ff:ff

12.2.3 ホスト、ルータ、ブリッジにインタフェース設定

ホスト、ルータにインタフェース設定
[root@centos74 ~]# ip link set p-rt netns router
[root@centos74 ~]# ip link set p-h1 netns host1
[root@centos74 ~]# ip link set p-h2 netns host2
ブリッジにインタフェース設定
[root@centos74 ~]# brctl addif bridge p1-br
[root@centos74 ~]# brctl addif bridge p2-br
[root@centos74 ~]# brctl addif bridge p3-br

12.2.4 IPアドレスの設定

[root@centos74 ~]# ip netns exec router ip addr add 192.168.100.10/24 dev p-rt
[root@centos74 ~]# ip netns exec host1 ip addr add 192.168.100.20/24 dev p-h1
[root@centos74 ~]# ip netns exec host2 ip addr add 192.168.100.30/24 dev p-h2

12.2.5 インタフェースのUP

ルータ、ホストのインタフェースUP
[root@centos74 ~]# ip netns exec router ip link set p-rt up
[root@centos74 ~]# ip netns exec host1 ip link set p-h1 up
[root@centos74 ~]# ip netns exec host2 ip link set p-h2 up
ルータ、ホストのループバックデバイスUP
[root@centos74 ~]# ip netns exec router ip link set lo up
[root@centos74 ~]# ip netns exec host1 ip link set lo up
[root@centos74 ~]# ip netns exec host2 ip link set lo up
ブリッジのインタフェースUP
[root@centos74 ~]# ip link set p1-br up
[root@centos74 ~]# ip link set p2-br up
[root@centos74 ~]# ip link set p3-br up
[root@centos74 ~]# ip link set bridge up

12.2.6 インタフェースの確認

router
[root@centos74 ~]# ip netns exec router ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    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
45: p-rt@if44: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
    link/ether 6a:69:1d:0b:30:98 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.100.10/24 scope global p-rt
       valid_lft forever preferred_lft forever
    inet6 fe80::6869:1dff:fe0b:3098/64 scope link
       valid_lft forever preferred_lft forever
host1
[root@centos74 ~]# ip netns exec host1 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    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
47: p-h1@if46: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
    link/ether 0a:3f:54:84:b8:c9 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.100.20/24 scope global p-h1
       valid_lft forever preferred_lft forever
    inet6 fe80::83f:54ff:fe84:b8c9/64 scope link
       valid_lft forever preferred_lft forever
host2
[root@centos74 ~]# ip netns exec host2 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    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
49: p-h2@if48: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
    link/ether d2:00:5d:5d:5d:76 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.100.30/24 scope global p-h2
       valid_lft forever preferred_lft forever
    inet6 fe80::d000:5dff:fe5d:5d76/64 scope link
       valid_lft forever preferred_lft forever
ブリッジのインタフェース確認
[root@centos74 ~]# brctl show bridge
bridge name     bridge id               STP enabled     interfaces
bridge          8000.06ddfe5df967       no              p1-br
                                                        p2-br
                                                        p3-br

12.3 環境構築用シェル

[root@centos74 ~]# cat br.sh
#!/usr/bin/bash

ip netns add router
ip netns add host1
ip netns add host2
brctl addbr bridge

ip link add p-rt type veth peer name p1-br
ip link add p-h1 type veth peer name p2-br
ip link add p-h2 type veth peer name p3-br

ip link set p-rt netns router
ip link set p-h1 netns host1
ip link set p-h2 netns host2

brctl addif bridge p1-br
brctl addif bridge p2-br
brctl addif bridge p3-br

ip netns exec router ip addr add 192.168.100.10/24 dev p-rt
ip netns exec host1 ip addr add 192.168.100.20/24 dev p-h1
ip netns exec host2 ip addr add 192.168.100.30/24 dev p-h2

ip netns exec router ip link set p-rt up
ip netns exec host1 ip link set p-h1 up
ip netns exec host2 ip link set p-h2 up

ip netns exec router ip link set lo up
ip netns exec host1 ip link set lo up
ip netns exec host2 ip link set lo up

ip link set p1-br up
ip link set p2-br up
ip link set p3-br up
ip link set bridge up

12.4 環境削除手順

[root@centos74 ~]# ip -all netns del
[root@centos74 ~]# ip link set bridge down
[root@centos74 ~]# brctl delbr bridge

13 NATの環境構築

13.1 構築する環境

Source NATの環境を構築してみます。
host1,host2からhost3にアクセスする際、ルータ(router)のp3-rインタフェースで
Source NATを実施します。より正確に記述すると、NAPT(MASQUERADE)を実行します。
つまり、送信元IPに加え、送信元ポート番号の変換もおこないます。

                                      +-- router --+
               192.168.100.0/24       |            |
host1(p-h1) ---------------------- (p1-r)          |
         .10                     .1   |            |
                                      |            |      192.168.200.0/24 
                                      |         (p3-r) ---------------------- (p-h3)host3
                                      |            | .1                     .10
               192.168.110.0/24       |            |
host2(p-h2) ---------------------- (p2-r)          | ★ここで、MASQUERADEを実施する
          .10                    .1   |            |
                                      +------------+

13.2 設定手順

13.2.1 ホスト、ルータの作成

[root@centos74 ~]# ip netns add host2
[root@centos74 ~]# ip netns add host3
[root@centos74 ~]# ip netns add router

作成したネームスペースを確認する。
[root@centos74 ~]# ip netns list
host3
router
host2 (id: 1)
host1 (id: 0)

13.2.2 インタフェースの作成

[root@centos74 ~]# ip link add p-h1 type veth peer name p1-r
[root@centos74 ~]# ip link add p-h2 type veth peer name p2-r
[root@centos74 ~]# ip link add p-h3 type veth peer name p3-r

13.2.3 ホスト、ルータにインタフェース設定

ホストにインタフェース設定
[root@centos74 ~]# ip link set p-h1 netns host1
[root@centos74 ~]# ip link set p-h2 netns host2
[root@centos74 ~]# ip link set p-h3 netns host3
ルータにインタフェース設定
[root@centos74 ~]# ip link set p1-r netns router
[root@centos74 ~]# ip link set p2-r netns router
[root@centos74 ~]# ip link set p3-r netns router

13.2.4 IPアドレスの設定

ホストにIPアドレス設定
[root@centos74 ~]# ip netns exec host1 ip addr add 192.168.100.10/24 dev p-h1
[root@centos74 ~]# ip netns exec host2 ip addr add 192.168.110.10/24 dev p-h2
[root@centos74 ~]# ip netns exec host3 ip addr add 192.168.200.10/24 dev p-h3
ルータにIPアドレス設定
[root@centos74 ~]# ip netns exec router ip addr add 192.168.100.1/24 dev p1-r
[root@centos74 ~]# ip netns exec router ip addr add 192.168.110.1/24 dev p2-r
[root@centos74 ~]# ip netns exec router ip addr add 192.168.200.1/24 dev p3-r

13.2.5 インタフェースのUP

ホストのインタフェースUP
[root@centos74 ~]# ip netns exec host1 ip link set p-h1 up
[root@centos74 ~]# ip netns exec host2 ip link set p-h2 up
[root@centos74 ~]# ip netns exec host3 ip link set p-h3 up
ルータのインタフェースUP
[root@centos74 ~]# ip netns exec host1 ip link set lo up
[root@centos74 ~]# ip netns exec host2 ip link set lo up
[root@centos74 ~]# ip netns exec host3 ip link set lo up

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

ネームスペースを使った環境では、ネームスペース内の/etc/sysconfig/network-scripts/ifcfg-xxxに
デフォルトゲートウェイの設定ができないようです。うまい方法があるかもしれませんが。
ここでは、下記のように、各ホストで静的にルーティングテーブルを設定しました。

ホスト1
[root@centos74 ~]# ip netns exec host1 ip route add 192.168.110.0/24 via 192.168.100.1 dev p-h1
[root@centos74 ~]# ip netns exec host1 ip route add 192.168.200.0/24 via 192.168.100.1 dev p-h1
ホスト2
[root@centos74 ~]# ip netns exec host2 ip route add 192.168.100.0/24 via 192.168.110.1 dev p-h2
[root@centos74 ~]# ip netns exec host2 ip route add 192.168.200.0/24 via 192.168.110.1 dev p-h2
ホスト3
[root@centos74 ~]# ip netns exec host3 ip route add 192.168.100.0/24 via 192.168.200.1 dev p-h3
[root@centos74 ~]# ip netns exec host3 ip route add 192.168.110.0/24 via 192.168.200.1 dev p-h3

13.2.7 MASQUERADEの設定

[root@centos74 ~]# ip netns exec router bash
[root@centos74 ~]# iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -d 192.168.200.0/24 -p tcp -j MASQUERADE
[root@centos74 ~]# iptables -t nat -A POSTROUTING -s 192.168.110.0/24 -d 192.168.200.0/24 -p tcp -j MASQUERADE
[root@centos74 ~]# iptables -t nat -nvL POSTROUTING
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 MASQUERADE  tcp  --  *      *       192.168.100.0/24     192.168.200.0/24
    0     0 MASQUERADE  tcp  --  *      *       192.168.110.0/24     192.168.200.0/24

13.2.8 環境構築用シェル

[root@centos74 ~]# cat nat.sh
#!/usr/bin/bash

ip netns add host1
ip netns add host2
ip netns add host3
ip netns add router

ip link add p-h1 type veth peer name p1-r
ip link add p-h2 type veth peer name p2-r
ip link add p-h3 type veth peer name p3-r

ip link set p-h1 netns host1
ip link set p-h2 netns host2
ip link set p-h3 netns host3
ip link set p1-r netns router
ip link set p2-r netns router
ip link set p3-r netns router

ip netns exec host1 ip addr add 192.168.100.10/24 dev p-h1
ip netns exec host2 ip addr add 192.168.110.10/24 dev p-h2
ip netns exec host3 ip addr add 192.168.200.10/24 dev p-h3
ip netns exec router ip addr add 192.168.100.1/24 dev p1-r
ip netns exec router ip addr add 192.168.110.1/24 dev p2-r
ip netns exec router ip addr add 192.168.200.1/24 dev p3-r

ip netns exec host1 ip link set p-h1 up
ip netns exec host1 ip link set lo up
ip netns exec host2 ip link set p-h2 up
ip netns exec host2 ip link set lo up
ip netns exec host3 ip link set p-h3 up
ip netns exec host3 ip link set lo up

ip netns exec router ip link set p1-r up
ip netns exec router ip link set p2-r up
ip netns exec router ip link set p3-r up
ip netns exec router ip link set lo up

ip netns exec host1 ip route add 192.168.110.0/24 via 192.168.100.1 dev p-h1
ip netns exec host1 ip route add 192.168.200.0/24 via 192.168.100.1 dev p-h1
ip netns exec host2 ip route add 192.168.100.0/24 via 192.168.110.1 dev p-h2
ip netns exec host2 ip route add 192.168.200.0/24 via 192.168.110.1 dev p-h2
ip netns exec host3 ip route add 192.168.100.0/24 via 192.168.200.1 dev p-h3
ip netns exec host3 ip route add 192.168.110.0/24 via 192.168.200.1 dev p-h3

ip netns exec router sysctl -w net.ipv4.ip_forward=1

13.3 実験結果

ホスト3でncコマンドを実行する。11111番ポートでListenする。
ncコマンドは、ここ(ncコマンドの使い方)を参照ください。
tcpdumpは、ここ(tcpdumpの使い方)を参照ください。

ホスト3
[root@centos74 ~]# nc -kl 11111

ホスト1からホスト3の11111番ポート宛てに"11111"を送信する。

ホスト1
[root@centos74 ~]# nc 192.168.200.10 11111
11111

ホスト2からホスト3の11111番ポート宛てに"11111"を送信する。

ホスト2
[root@centos74 ~]# nc 192.168.200.10 11111
22222

ホスト1,2から"11111"と"22222"を受信していることがわかる。

ホスト3
[root@centos74 ~]# nc -kl 11111
11111
22222

ホスト1,2から送信したTCPパケットの送信元IPが、ルータのインタフェース(p3-r)のIPになっていることがわかる。

ホスト3(tcpdumpの実行結果)
[root@centos74 ~]# tcpdump -i p-h3 tcp port 11111 -nn
18:59:28.370417 IP 192.168.200.1.58256 > 192.168.200.10.11111: Flags [P.], seq 961546566:961546572, ack 3583082731, win 229, options [nop,nop,TS val 12525282 ecr 12235217], length 6
18:59:28.370447 IP 192.168.200.10.11111 > 192.168.200.1.58256: Flags [.], ack 6, win 227, options [nop,nop,TS val 12525282 ecr 12525282], length 0

18:59:31.418047 IP 192.168.200.1.51032 > 192.168.200.10.11111: Flags [P.], seq 843490975:843490981, ack 1445090778, win 229, options [nop,nop,TS val 12528330 ecr 12239769], length 6
18:59:31.418082 IP 192.168.200.10.11111 > 192.168.200.1.51032: Flags [.], ack 6, win 227, options [nop,nop,TS val 12528330 ecr 12528330], length 0

14 OVS(OpenvSwitch)の環境構築

OVSを使ってTAG VLANの環境を構築してみます。

14.1 構築する環境

host1,host2は、192.168.100.0/24に所属します。
ovs1,ovs2はovsです。宛先MACアドレスにもとずいて出力ポートを決定する仮想スイッチです。
また、OVSのポートにはtag=10の設定をします。

                              192.168.100.0/24

   +------- host1 ------+                           +------- host2 ------+
   |                    |                           |                    |
   |                    |                           |                    |
   +-------(p-h1)-------+                           +-------(p-h2)-------+
             | .10                                            | .20
             |                                                |
             |                                                |
             | tag=10                                         | tag=10
   +------(p1-ovs1)-----+                           +------(p1-ovs2)-----+
   |                    |                           |                    |
   |        ovs1     (p2-ovs1) ----------------- (p2-ovs2)    ovs2       |
   |                    |             A             |                    |
   +--------------------+             |             +--------------------+
                                      |
                                      |
                                      |
                                      |
             ovs1<->ovs2のリンクで、tag=10のフレームが流れることを確認する。

14.2 OVSパッケージのインストール

[root@centos74 ~]# yum -y install openvswitch
[root@centos74 ~]# ovs-vsctl --version
ovs-vsctl (Open vSwitch) 2.0.0
Compiled Apr 19 2018 17:57:34

14.3 ovs-vswitchdの起動

[root@centos74 ~]# systemctl start openvswitch
[root@centos74 ~]# systemctl status openvswitch
● openvswitch.service - Open vSwitch
   Loaded: loaded (/usr/lib/systemd/system/openvswitch.service; disabled; vendor preset: disabled)
   Active: active (exited) since 金 2018-05-18 17:24:22 JST; 1min 15s ago
  Process: 4262 ExecStart=/bin/true (code=exited, status=0/SUCCESS)
 Main PID: 4262 (code=exited, status=0/SUCCESS)

 5月 18 17:24:22 centos74 systemd[1]: Starting Open vSwitch...
 5月 18 17:24:22 centos74 systemd[1]: Started Open vSwitch.

14.4 設定手順

14.4.1 ホスト作成

[root@centos74 ~]# ip netns add host1
[root@centos74 ~]# ip netns add host2
[root@centos74 ~]# ip netns list
host2
host1

14.4.2 OVS作成

[root@centos74 ~]# ovs-vsctl add-br ovs1
[root@centos74 ~]# ovs-vsctl add-br ovs2

作成したブリッジを確認する。
[root@centos74 ~]# ovs-vsctl list-br
ovs1
ovs2

14.4.3 インタフェース作成

[root@centos74 ~]# ip link add p-h1 type veth peer name p1-ovs1
[root@centos74 ~]# ip link add p-h2 type veth peer name p1-ovs2
[root@centos74 ~]# ip link add p2-ovs1 type veth peer name p2-ovs2

14.4.4 ホストにインタフェース設定

[root@centos74 ~]# ip link set p-h1 netns host1
[root@centos74 ~]# ip link set p-h2 netns host2

14.4.5 OVSポートにtag設定

[root@centos74 ~]# ovs-vsctl add-port ovs1 p1-ovs1 tag=10
[root@centos74 ~]# ovs-vsctl add-port ovs2 p1-ovs2 tag=10

14.4.6 ovs1,ovs2のポート接続

[root@centos74 ~]# ovs-vsctl add-port ovs1 p2-ovs1
[root@centos74 ~]# ovs-vsctl add-port ovs2 p2-ovs2

14.4.7 OVSのポートUP

[root@centos74 ~]# ip link set p1-ovs1 up
[root@centos74 ~]# ip link set p2-ovs1 up
[root@centos74 ~]# ip link set p1-ovs2 up
[root@centos74 ~]# ip link set p2-ovs2 up

14.4.8 ホストのポートUP

vethのUP
[root@centos74 ~]# ip netns exec host1 ip link set p-h1 up
[root@centos74 ~]# ip netns exec host2 ip link set p-h2 up
ループバックデバイスのUP
[root@centos74 ~]# ip netns exec host1 ip link set lo up
[root@centos74 ~]# ip netns exec host2 ip link set lo up

14.4.9 ホストにIPアドレス設定

[root@centos74 ~]# ip netns exec host1 ip addr add 192.168.100.10/24 dev p-h1
[root@centos74 ~]# ip netns exec host2 ip addr add 192.168.100.20/24 dev p-h2

14.5 実験結果

ホスト1からホスト2に対してpingを実行する。

ホスト1からホスト2に対してping実行
[root@centos74 ~]# ip netns exec host1 bash
[root@centos74 ~]# ping 192.168.100.20
PING 192.168.100.20 (192.168.100.20) 56(84) bytes of data.
64 bytes from 192.168.100.20: icmp_seq=1 ttl=64 time=1.95 ms
64 bytes from 192.168.100.20: icmp_seq=2 ttl=64 time=0.104 ms
ovs-dpctl実行結果
[root@centos74 ~]#  ovs-dpctl dump-flows
skb_priority(0),in_port(4),eth(src=2e:86:93:76:77:57,dst=3a:d8:55:55:a8:2a),eth_type(0x0800),ipv4(src=192.168.100.20/0.0.0.0,dst=192.168.100.10/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0xff), packets:31, bytes:3038, used:0.896s, actions:push_vlan(vid=10,pcp=0),6
skb_priority(0),in_port(5),eth(src=2e:86:93:76:77:57,dst=3a:d8:55:55:a8:2a),eth_type(0x8100),vlan(vid=10,pcp=0),encap(eth_type(0x0800),ipv4(src=192.168.100.20/0.0.0.0,dst=192.168.100.10/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0xff)), packets:31, bytes:3162, used:0.896s, actions:pop_vlan,3
skb_priority(0),in_port(6),eth(src=3a:d8:55:55:a8:2a,dst=2e:86:93:76:77:57),eth_type(0x8100),vlan(vid=10,pcp=0),encap(eth_type(0x0800),ipv4(src=192.168.100.10/0.0.0.0,dst=192.168.100.20/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0xff)), packets:31, bytes:3162, used:0.896s, actions:pop_vlan,4
skb_priority(0),in_port(3),eth(src=3a:d8:55:55:a8:2a,dst=2e:86:93:76:77:57),eth_type(0x0800),ipv4(src=192.168.100.10/0.0.0.0,dst=192.168.100.20/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0xff), packets:31, bytes:3038, used:0.896s, actions:push_vlan(vid=10,pcp=0),5

14.6 環境構築用シェル

[root@centos74 ~]# cat ovs.sh
#!/usr/bin/bash

ip netns add host1
ip netns add host2

ovs-vsctl add-br ovs1
ovs-vsctl add-br ovs2

ip link add p-h1 type veth peer name p1-ovs1
ip link add p-h2 type veth peer name p1-ovs2
ip link add p2-ovs1 type veth peer name p2-ovs2

ip link set p-h1 netns host1
ip link set p-h2 netns host2

ovs-vsctl add-port ovs1 p1-ovs1 tag=10
ovs-vsctl add-port ovs2 p1-ovs2 tag=10

ovs-vsctl add-port ovs1 p2-ovs1
ovs-vsctl add-port ovs2 p2-ovs2

ip link set p1-ovs1 up
ip link set p2-ovs1 up
ip link set p1-ovs2 up
ip link set p2-ovs2 up

ip netns exec host1 ip link set p-h1 up
ip netns exec host2 ip link set p-h2 up
ip netns exec host1 ip link set lo up
ip netns exec host2 ip link set lo up

ip netns exec host1 ip addr add 192.168.100.10/24 dev p-h1
ip netns exec host2 ip addr add 192.168.100.20/24 dev p-h2

14.7 環境削除

[root@centos74 ~]# ovs-vsctl show
46b839f4-c748-4511-a714-68644cfff6e5
    Bridge "ovs2"
        Port "p1-ovs2"
            tag: 10
            Interface "p1-ovs2"
        Port "p2-ovs2"
            Interface "p2-ovs2"
        Port "ovs2"
            Interface "ovs2"
                type: internal
    Bridge "ovs1"
        Port "p2-ovs1"
            Interface "p2-ovs1"
        Port "p1-ovs1"
            tag: 10
            Interface "p1-ovs1"
        Port "ovs1"
            Interface "ovs1"
                type: internal
    ovs_version: "2.0.0

[root@centos74 ~]# ovs-vsctl list-br
ovs1
ovs2
[root@centos74 ~]# ovs-vsctl list-ports ovs1
p1-ovs1
p2-ovs1
[root@centos74 ~]# ovs-vsctl list-ports ovs2
p1-ovs2
p2-ovs2

[root@centos74 ~]# ovs-vsctl del-port ovs1 p1-ovs1
[root@centos74 ~]# ovs-vsctl del-port ovs1 p2-ovs1
[root@centos74 ~]# ovs-vsctl list-ports ovs1
[root@centos74 ~]#

[root@centos74 ~]# ovs-vsctl del-port ovs2 p1-ovs2
[root@centos74 ~]# ovs-vsctl del-port ovs2 p2-ovs2
[root@centos74 ~]# ovs-vsctl list-ports ovs2
[root@centos74 ~]#

[root@centos74 ~]# ovs-vsctl del-br ovs1
[root@centos74 ~]# ovs-vsctl del-br ovs2
[root@centos74 ~]# ovs-vsctl list-br
[root@centos74 ~]#

[root@centos74 ~]# ip -all netns del
[root@centos74 ~]# ip l del p2-ovs2
[root@centos74 ~]# ip l
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
    link/ether 00:0c:29:f0:6e:a2 brd ff:ff:ff:ff:ff:ff
9: ovs-system: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether 02:67:fa:e5:46:d7 brd ff:ff:ff:ff:ff:ff

Z 参考情報

第6回 Linuxカーネルのコンテナ機能[5] ─ネットワーク
netnsでネットワークの勉強
Linux Network Namespace で遊んでみる
OpenvSwitchとnamespaceで仮想ネットワークにVLANを構築する
Linux のネットワークネームスペース機能と Open vSwitch で仮想ネットワーク
OpenvSwitch関連コマンドのチートシート的な何か
Openstack(Neutron)が中でやっていることを確認してみた