Linux Network Namespace で遊んでみる
Linux Network Namespace を使うと 1 つの Linux ホストの中に仮想的なネットワーク環境を複数作れる。今回はサーバ、ゲートウェイ、クライアントの 3 つのネームスペースを作って通信させてみる。この機能を使うには新しめの Linux カーネルとツール群が必要みたいなのでディストリビューションには Ubuntu 13.04 を使った。
$ sudo ip netns add server $ sudo ip netns add gateway $ sudo ip netns add client $ ip netns list client gateway server
ネームスペース gateway をルータにしたいので IP 転送を有効にする。 ip netns exec コマンドを使うことで各ネームスペース上でコマンドを実行できる。
$ sudo ip netns exec gateway sysctl net.ipv4.ip_forward=1 net.ipv4.ip_forward = 1
次に、各ネームスペースを繋ぐための veth インターフェースを作る。 対になる veth インターフェースは、片方にパケットが入ると反対側から出てくる。
$ sudo ip link add svr-veth type veth peer name svrgw-veth $ sudo ip link add cli-veth type veth peer name cligw-veth $ ip link show | grep veth 3: svrgw-veth: mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000 4: svr-veth: mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000 5: cligw-veth: mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000 6: cli-veth: mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
作った veth インターフェースをネームスペースに参加させる。 参加させると、インタフェースが元々あったホストからは見えなくなる。
$ sudo ip link set svr-veth netns server $ sudo ip link set svrgw-veth netns gateway $ sudo ip link set cligw-veth netns gateway $ sudo ip link set cli-veth netns client $ ip link show | grep veth
各ネームスペース上からはインターフェースが見えるようになった。
$ sudo ip netns exec server ip link show | grep veth 4: svr-veth: mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
各 veth インターフェースに IP アドレスを付ける。
$ sudo ip netns exec server ifconfig svr-veth 192.168.100.1 $ sudo ip netns exec gateway ifconfig svrgw-veth 192.168.100.254 $ sudo ip netns exec gateway ifconfig cligw-veth 10.0.100.254 $ sudo ip netns exec client ifconfig cli-veth 10.0.100.1
veth インターフェース間の疎通を ping で確認してみる。
$ sudo ip netns exec gateway ping 192.168.100.1 -I 192.168.100.254 PING 192.168.100.1 (192.168.100.1) from 192.168.100.254 : 56(84) bytes of data. 64 bytes from 192.168.100.1: icmp_req=1 ttl=64 time=0.044 ms 64 bytes from 192.168.100.1: icmp_req=2 ttl=64 time=0.036 ms 64 bytes from 192.168.100.1: icmp_req=3 ttl=64 time=0.040 ms ^C --- 192.168.100.1 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 1999ms rtt min/avg/max/mdev = 0.036/0.040/0.044/0.003 ms $ sudo ip netns exec gateway ping 10.0.100.1 -I 10.0.100.254 PING 10.0.100.1 (10.0.100.1) from 10.0.100.254 : 56(84) bytes of data. 64 bytes from 10.0.100.1: icmp_req=1 ttl=64 time=0.107 ms 64 bytes from 10.0.100.1: icmp_req=2 ttl=64 time=0.037 ms 64 bytes from 10.0.100.1: icmp_req=3 ttl=64 time=0.037 ms ^C --- 10.0.100.1 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 1998ms rtt min/avg/max/mdev = 0.037/0.060/0.107/0.033 ms
次はルーティングの設定。 クライアントとサーバが使うデフォルトゲートウェイを、ネームスペース gateway の持つ veth の IP アドレスに向ける。
$ sudo ip netns exec client route add default gw 10.0.100.254 $ sudo ip netns exec client netstat -rn Kernel IP routing table Destination Gateway Genmask Flags MSS Window irtt Iface 0.0.0.0 10.0.100.254 0.0.0.0 UG 0 0 0 cli-veth 10.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 cli-veth $ sudo ip netns exec server route add default gw 192.168.100.254 $ sudo ip netns exec server netstat -rn Kernel IP routing table Destination Gateway Genmask Flags MSS Window irtt Iface 0.0.0.0 192.168.100.254 0.0.0.0 UG 0 0 0 svr-veth 192.168.100.0 0.0.0.0 255.255.255.0 U 0 0 0 svr-veth
これで準備は整ったのでクライアントからサーバに対して ping を打ってみる。
$ sudo ip netns exec client ping 192.168.100.1 -I 10.0.100.1 PING 192.168.100.1 (192.168.100.1) from 10.0.100.1 : 56(84) bytes of data. 64 bytes from 192.168.100.1: icmp_req=1 ttl=63 time=0.106 ms 64 bytes from 192.168.100.1: icmp_req=2 ttl=63 time=0.076 ms 64 bytes from 192.168.100.1: icmp_req=3 ttl=63 time=0.050 ms ^C --- 192.168.100.1 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 1999ms rtt min/avg/max/mdev = 0.050/0.077/0.106/0.024 ms
上手いこと動いてる。 めでたしめでたし。
Linux Network Namespace を使うと複数ホストを用意しなくてもネットワークの実験なんかができて便利そう。 ハードウェア仮想化とも相性が良いんじゃないかな。 IaaS 基盤ソフトウェアの OpenStack ではこれを積極的に活用してるみたい。
NAT 編はコチラ