2022年11月号 特集 第1部サポート・ページ

●このページで解説すること

本サポート・ページでは,2022年11月号 特集 第1部「仮想ルータ作りで学ぶネットワークの基本」で作成するルータ・プログラムを動かす仮想ネットワーク環境の構築手順と,通信実験の手順を解説します.基本的には本誌と同じ内容ですが,ここではルータ・プログラムを試す手順に焦点を当てて,コマンドやプログラムの実行方法についてより詳しく説明します.

ここでは,Windows 10(ビルド番号19041以上)のWSL(Windows Subsystem for Linux)機能を使った場合を想定して説明します.WSLによるLinuxの仮想マシンには,Ubuntu 20.04を使用します.

 

●仮想ネットワーク環境の構築手順

▼手順1:WSL機能のインストール

Windowsのスタート・ボタンを右クリックして,[Windows Power Shell(管理者)]を選択し,コマンドを入力するターミナルを起動します.起動したら,次のコマンドを実行します.

> wsl --install

▼手順2:Linuxディストリビューションのインストール

Windows Power Shellで次のコマンドを実行します.

> wsl --install -d Ubuntu

インストールが完了すると,新しいターミナルが立ち上がり,ユーザ名の入力が求められます.ここでユーザ名とパスワードを登録するとLinux環境が利用できるようになります.

▼【補足】一括実行シェル・スクリプト

手順3~手順6のコマンドは,一括実行のシェル・スクリプトを用意しています.下記のコマンドを実行すれば,手順3~手順6をスキップできます.

$ git clone https://github.com/kametan0730/interface_2022_11.git

$ cd interface_2022_11/netns-scripts/

$ chmod 744 chapter1-netns.sh

$ sudo ./chapter1-netns.sh

▼手順3:namespaceを作成する

ここからは,図1に示す実験用のネットワークを仮想的に構築します.Ubuntuのターミナルで次のコマンドを実行して,4つのnamespaceを作成します.

$ sudo ip netns add host1

$ sudo ip netns add router1

$ sudo ip netns add router2

$ sudo ip netns add host2

 

図1 仮想的に構築する実験用ネットワークの構成

 

▼手順4:リンクを作成する

次のコマンドを実行して,リンクを作成します.

$ sudo ip link add name host1-router1 type veth peer name router1-host1 

$ sudo ip link add name router1-router2 type veth peer name router2-router1 

$ sudo ip link add name router2-host2 type veth peer name host2-router2 

▼手順5:作成したリンクをnamespaceに接続する

手順4で作成したリンクを,手順3で作成したnamespaceに接続します.

$ sudo ip link set host1-router1 netns host1

$ sudo ip link set router1-host1 netns router1

$ sudo ip link set router1-router2 netns router1

$ sudo ip link set router2-router1 netns router2

$ sudo ip link set router2-host2 netns router2

$ sudo ip link set host2-router2 netns host2 

▼手順6:リンクの設定

次のコマンドを実行して,各namespaceのリンクを設定します.ここでは,ip netns execコマンドを使ってnamespace内でコマンドを実行します.IPアドレスの設定,リンクのアップ,ネットワーク・インターフェースのオフローディングの無効化,経路の設定,ルータでのIPフォワーディングの有効化を行います.

# host1のリンクの設定

$ sudo ip netns exec host1 ip addr add 192.168.1.2/24 dev host1-router1

$ sudo ip netns exec host1 ip link set host1-router1 up

$ sudo ip netns exec host1 ethtool -K host1-router1 rx off tx off

$ sudo ip netns exec host1 ip route add default via 192.168.1.1

 

# router1のリンクの設定

$ sudo ip netns exec router1 ip addr add 192.168.1.1/24 dev router1-host1

$ sudo ip netns exec router1 ip link set router1-host1 up

$ sudo ip netns exec router1 ethtool -K router1-host1 rx off tx off

$ sudo ip netns exec router1 ip addr add 192.168.0.1/24 dev router1-router2

$ sudo ip netns exec router1 ip link set router1-router2 up

$ sudo ip netns exec router1 ethtool -K router1-router2 rx off tx off

$ sudo ip netns exec router1 ip route add default via 192.168.0.2

$ sudo ip netns exec router1 sysctl -w net.ipv4.ip_forward=1

 

# router2のリンクの設定

$ sudo ip netns exec router2 ip addr add 192.168.0.2/24 dev router2-router1

$ sudo ip netns exec router2 ip link set router2-router1 up

$ sudo ip netns exec router2 ethtool -K router2-router1 rx off tx off

$ sudo ip netns exec router2 ip route add default via 192.168.0.1

$ sudo ip netns exec router2 ip addr add 192.168.2.1/24 dev router2-host2

$ sudo ip netns exec router2 ip link set router2-host2 up

$ sudo ip netns exec router2 ethtool -K router2-host2 rx off tx off

$ sudo ip netns exec router2 sysctl -w net.ipv4.ip_forward=1

 

# host2のリンクの設定

$ sudo ip netns exec host2 ip addr add 192.168.2.2/24 dev host2-router2

$ sudo ip netns exec host2 ip link set host2-router2 up

$ sudo ip netns exec host2 ethtool -K host2-router2 rx off tx off

$ sudo ip netns exec host2 ip route add default via 192.168.2.1

▼手順7:namespace同士で通信してみる

次のコマンドでhost1のbashを実行します.

$ sudo ip netns exec host1 bash

host1からhost2のIPアドレスである192.168.2.2に向けてpingを打ってみます.

(host1):~# ping 192.168.2.2

PING 192.168.2.2 (192.168.2.2) 56(84) bytes of data.

64 bytes from 192.168.2.2: icmp_seq=1 ttl=63 time=0.094 ms

正しくnamespaceの設定ができていれば,pingが疎通します.シェルを実行したnamespaceから抜けるときはexitコマンドを使います.

▼手順8:router1のルータ機能を無効化する

次のコマンドを実行して,router1のルータ機能を無効化します.

$ sudo ip netns exec router1 sysctl -w net.ipv4.ip_forward=0

▼手順9:namespace名をプロンプトに表示する

次のコマンドを実行して,rootユーザのホーム・ディレクトリにある.bashrcを開きます.

$ sudo nano /root/.bashrc

.bashrcを開いたら,ファイルの最後に次の内容を追加します.

if [ `ip netns identify| wc -m` -gt 1 ]; then
    PS1='\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\[\033[01;36m\]\u@\h($(ip netns identify))\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
fi

 

追加したら,次のコマンドを実行して,プロンプトにnamespace名が表示されるか確認します.
$ sudo ip netns exec router1 bash
root@asus1(router1):/home/daiya#

以上で環境構築は完了です.

 

●第1章実験…受信プログラムを動かしてみる

先ほど構築した仮想ネットワーク環境を使って,実際にプログラムを動かしてみます.第1章で作成した受信プログラムのソースコードは,次のURLからも入手できます.

https://github.com/kametan0730/interface_2022_11

▼手順1:プログラムを入手する

次のコマンドを実行して,受信プログラムのソースコードをダウンロードします.

$ git clone https://github.com/kametan0730/interface_2022_11.git

▼手順2:プログラムをビルドする

次のコマンドを実行して,受信プログラムのソースコードが入っているディレクトリに移動します.

$ cd interface_2022_11/chapter1/

次のコマンドを実行して,受信プログラムのソースコードをビルドします.

$ make all

▼手順3:router1のnamespaceから受信プログラムを実行する

次のコマンドを実行して,router1のbashを実行します.

$ sudo ip netns exec router1 bash

次のコマンドを実行して,受信プログラムを実行します.

(router1):# sudo make run

./build/curo
Skipped to enable interface lo
Skipped to enable interface tunl0
Skipped to enable interface sit0
Created device router1-host1 socket 3 address 22:3b:ab:6b:40:fa
Created device router1-router2 socket 4 address 8a:cb:22:99:c8:0a

▼手順4:host1からpingコマンドを実行してみる

別のターミナル・ウィンドウを起動して,次のコマンドを実行します.host1からpingコマンドを実行してみます.

$ sudo ip netns exec host1 bash

(host1):~# ping 192.168.2.2

すると,router1のターミナルに,次のような標準出力が表示されます.

Received 98 bytes from router1-host1: 223bab6b40fa224f8cb562b…
Received 98 bytes from router1-host1: 223bab6b40fa224f8cb562b…

以上で受信プログラムの動作確認は完了です.

 

●第2章実験…ルータ・プログラムによるARPの解決

▼手順1:環境構築用シェル・スクリプトの実行

次のコマンドを実行して,実験用の仮想ネットワーク環境を構築します.

$ cd interface_2022_11/netns-scripts/

$ chmod 744 chapter2-netns.sh

$ sudo ./chapter2-netns.sh

▼手順2:arpingコマンドでARPリクエストを生成する

次のコマンドを実行して,arpingコマンドをインストールします.

$ sudo apt install arping

router1のnamespace でルータ・プログラムを動かします.

$ cd interface_2022_11/chapter2/

$ make all

$ sudo ip netns exec router1 bash

(router1):# sudo make run

host1のnamespaceで次のコマンドを実行し,ARPリクエストを生成します.

$ sudo ip netns exec host1 bash

(host1):~# arping -i host1-router1 192.168.1.1

次に示すようなARPの応答が返ってきたら成功です.

ARPING 192.168.1.1
60 bytes from ce:5b:bc:cd:13:b6 (192.168.1.1): index=0 time=7.300 usec
60 bytes from ce:5b:bc:cd:13:b6 (192.168.1.1): index=1 time=117.000 usec

 

●第3章 実験1…pingコマンドの実行

実験用の仮想ネットワーク環境は,第2章で構築したものと同じです.

▼手順1:ルータ・プログラムの実行

router1のnamespace でルータ・プログラムを動かします.

$ cd interface_2022_11/chapter3/

$ make all

$ sudo ip netns exec router1 bash

(router1):# sudo make run

▼手順2:pingコマンドの実行

host1のnamespaceでpingコマンドを実行します.

$ sudo ip netns exec host1 bash

(host1):~# ping 192.168.1.1

PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=255 time=0.485 ms
64 bytes from 192.168.1.1: icmp_seq=2 ttl=255 time=0.091 ms

ping応答が無事返ってきたら成功です.

 

●第3章 実験2…tracerouteコマンドを実行する

実験用の仮想ネットワーク環境は,第2章で構築したものと同じです.

第3章 実験1のときにrouter1で実行したルータ・プログラムは,実行したままにします.

▼手順1:tracerouteコマンドをインストールする

次のコマンドを実行して,tracerouteコマンドをインストールします.

$ sudo apt install traceroute

▼手順2:tracerouteコマンドを実行してみる

host1のnamespaceで,tracerouteコマンドを実行します.

(本誌のp.61 ↓10行目のコマンドは誤りです.お詫びして訂正します)

(host1):~# traceroute 192.168.1.1 -n

traceroute to 192.168.1.1 (192.168.1.1), 30 hops max, 60 byte packets
1 192.168.1.1 0.075 ms 0.105 ms 0.155 ms

 

●第4章 実験①…分岐の無いネットワークでルーティング機能を試す

実験用の仮想ネットワーク環境は,第2章で構築したものと同じです.

▼手順1:ルータ・プログラムの実行

router1のnamespace でルータ・プログラムを動かします.

$ cd interface_2022_11/chapter4/

$ make all

$ sudo ip netns exec router1 bash

(router1):# sudo make run

▼手順2:ping/tracerouteコマンドを打ってみる

host1のnamespaceでpingコマンドを実行します.

$ sudo ip netns exec host1 bash

(host1):~# ping 192.168.2.2
PING 192.168.2.2 (192.168.2.2) 56(84) bytes of data.
64 bytes from 192.168.2.2: icmp_seq=3 ttl=62 time=0.081 ms
64 bytes from 192.168.2.2: icmp_seq=4 ttl=62 time=0.249 ms

host1のnamespaceでtracerouteコマンドを実行します.

(host1):~# traceroute 192.168.2.2 -n
traceroute to 192.168.2.2 (192.168.2.2), 30 hops max, 60 byte packets
1 192.168.1.1 0.059 ms 0.065 ms 0.034 ms
2 192.168.0.2 0.473 ms 0.746 ms 0.890 ms
3 192.168.2.2 1.081 ms 1.074 ms 1.073 ms

 

●第4章 実験②…分岐のあるネットワークでルーティング機能を試す

▼手順1:環境構築用シェル・スクリプトの実行

次のコマンドを実行して,実験用の仮想ネットワーク環境を構築します.

$ cd interface_2022_11/netns-scripts/

$ chmod 744 chapter4-2-netns.sh

$ sudo ./chapter4-2-netns.sh

図2 ルーティング機能を試す実験の仮想ネットワーク環境構成

▼手順2:ルータの設定を変更する

main.cppを編集して,ルータの設定を変更します.

【変更前】

void configure(){
  configure_ip_address(
    get_net_device_by_name("router1-host1"),
    IP_ADDRESS(192, 168, 1, 1),
    IP_ADDRESS(255, 255, 255, 0));
  configure_ip_address(
    get_net_device_by_name("router1-router2"),
    IP_ADDRESS(192, 168, 0, 1),
    IP_ADDRESS(255, 255, 255, 0));
  configure_ip_net_route(
    IP_ADDRESS(192, 168, 2, 0), 24,
    IP_ADDRESS(192, 168, 0, 2));
}

【変更後】

void configure(){

  configure_ip_address(
    get_net_device_by_name("router1-host1"),
    IP_ADDRESS(192, 168, 1, 1),
    IP_ADDRESS(255, 255, 255, 0));
  configure_ip_address(
    get_net_device_by_name("router1-router2"),
    IP_ADDRESS(192, 168, 0, 1),
    IP_ADDRESS(255, 255, 255, 0));
 configure_ip_address(get_net_device_by_name("router1-router3"),
    IP_ADDRESS(192, 168, 3, 1),
    IP_ADDRESS(255, 255, 255, 0));
  configure_ip_net_route(
    IP_ADDRESS(192, 168, 2, 0), 24,
    IP_ADDRESS(192, 168, 0, 2));
  configure_ip_net_route(
    IP_ADDRESS(192, 168, 4, 0), 24,
    IP_ADDRESS(192, 168, 3, 2));
}

▼手順3:ルータ・プログラムの実行

router1のnamespace でルータ・プログラムを動かします.

$ cd interface_2022_11/chapter4/

$ make all

$ sudo ip netns exec router1 bash

(router1):# sudo make run

▼手順4:pingコマンドを打ってみる

host1のnamespaceでhost2に対するpingコマンドを実行します.

$ sudo ip netns exec host1 bash

(host1):~# ping 192.168.2.2
PING 192.168.2.2 (192.168.2.2) 56(84) bytes of data.
64 bytes from 192.168.2.2: icmp_seq=2 ttl=62 time=0.915 ms
64 bytes from 192.168.2.2: icmp_seq=3 ttl=62 time=0.218 ms

続いて,host1のnamespaceでhost3に対するpingコマンドを実行します.

(host1):~# ping 192.168.4.2
PING 192.168.4.2 (192.168.4.2) 56(84) bytes of data.
64 bytes from 192.168.4.2: icmp_seq=2 ttl=62 time=0.498 ms
64 bytes from 192.168.4.2: icmp_seq=3 ttl=62 time=0.422 ms

★第5章の実験手順については近日中に公開します★