PC1台でお手軽にルーティングを学ぶ①

## はじめに

アプリ開発や通信試験を行う際に、ネットワークのルーティング設定をする事があるけど、あまり得意ではないという方も多いのではと思います。

また、ネットワークの勉強を書籍ではなく実機を使って動作させながら勉強したいが、なかなか準備が大変という事があると思います。

今回は、1台のMacのPC上でLinux（Ubuntu）の仮想環境を構築し、Ubuntuを使ってネットワークのルーティングについて学んでいきます。WindowsのPC上でLinux（Ubuntu）の仮想環境を構築してもOKです。

ちなみに、[こちらの本](https://www.amazon.co.jp/Linux%E3%81%A7%E5%8B%95%E3%81%8B%E3%81%97%E3%81%AA%E3%81%8C%E3%82%89%E5%AD%A6%E3%81%B6TCP-IP%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E5%85%A5%E9%96%80-%E3%82%82%E3%81%BF%E3%81%98%E3%81%82%E3%82%81-ebook/dp/B085BG8CH5)を読んで勉強した内容になります。


## Ubuntuの環境構築

まず、Ubuntuの環境を用意しましょう。MacでのUbuntuの環境構築については[こちらの記事](https://qiita.com/f-paico/items/4cf8c697bacba38ab0f5)に書きましたので、参照してみてください。

## 動作環境

- M1 Mac Book Pro
- MultipassというツールでUbuntu仮想環境構築
- Ubuntu 20.04

## 実験ネットワークの構成

以下のネットワーク構成で、computer1からcomputer2にpingを送り疎通を取れるようにします。

ルータを介したネットワークは通常、ネットワークのセグメントがわかれるため、ルーティングの設定を行わない事には、通信ができません。

例. computer1で`ping 192.168.100.2`を実行しても通信できません。

![図_【Ubuntu】ネットワークのルーティングを学ぶ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674933/0103447c-cafb-eaf1-3b61-c33ebd00dc27.png)

## 実験準備

- ターミナルを4つ開き、それぞれでUbuntu仮想環境にログインしておく
- それぞれ、terminal-computer1, tarminal-router, terminal-computer2, terminal-ubuntuと呼ぶ事にする

## Network Namespaceについて

今回は、1つのUbuntu仮想環境を用意し、その仮想環境の中にネットワークを作って実験を行います。

Linuxの中に壊しても大丈夫なネットワークが簡単に作れる環境を、Dockerなどで利用されている技術である、Network Namespaceによって実現します。

Network Namespaceは、複数の機器やネットワークをコンピュータの中に仮想的に用意し、ネットワークのシミュレーションを行う事ができるもの、とここでは考えておきましょう。

## Network Namespaceの作成

まず、Network Namespaceを作成してみましょう。上で説明したネットワーク構成図の通りに機器を準備します。4つ開いてるターミナルのうち、1つをterminal-ubuntuと名付けて、以下のコマンドを実行してください。

```:terminal-ubuntu
# terminal-ubuntuで実行
sudo ip netns add computer1
sudo ip netns add router
sudo ip netns add computer2
```
## Network Namespaceのシェルを起動

作成したそれぞれの機器を操作するために、シェルを起動しましょう。
残り3つのターミナルを使い、以下のコマンドでNetwork Namespaceのシェルを起動します。

```:terminal-computer1
# terminal-computer1で実行
sudo ip netns exec computer1 bash
```

```:terminal-router
# terminal-routerで実行
sudo ip netns exec router bash
```

```:terminal-computer2
# terminal-computer2で実行
sudo ip netns exec computer2 bash
```
ここまでで、上で説明したネットワーク構成図の通りに機器を準備しました。

## Network Namespace同士を繋ぐIFを作成

Network Namespace同士をつなぐvethインターフェイス(≒仮想LANケーブル)を作成します。以下のコマンドにより、上で説明した図に記載された4つのネットワークインタフェースを作成する事ができます。

```:terminal-ubuntu
# terminal-ubuntuで実行
sudo ip link add com1-veth0 type veth peer name gw-veth0
sudo ip link add com2-veth0 type veth peer name gw-veth1
```
## IFをそれぞれの機器に登録する

作成したvethインターフェイスは、それぞれの機器（Network Namespace）に登録する必要があります。以下の通り、機器とIFを対応づけてコマンドを実行します。

```:terminal-ubuntu
# terminal-ubuntuで実行
sudo ip link set com1-veth0 netns computer1
sudo ip link set gw-veth0 netns router
sudo ip link set gw-veth1 netns router
sudo ip link set com2-veth0 netns computer2
```
## vethインタフェースをUPの状態に設定する

登録したvethインターフェイスはDOWNの状態になっているため、使えるようにするにはUPの状態に設定する必要があります。以下のコマンドで、4つのネットワークインタフェースをUPに設定します。

```:terminal-computer1
# terminal-computer1で実行
ip link set com1-veth0 up
```

```:terminal-router
# terminal-routerで実行
ip link set gw-veth0 up
ip link set gw-veth1 up
```

```:terminal-computer2
# terminal-computer2で実行
ip link set com2-veth0 up
```
## IPアドレスの登録

computer1とrouterの間のそれぞれのネットワークインターフェイスに、IPアドレスを付与します。上で説明した図の通り、computer1とrouter間は192.168.0.0/24という同じセグメントになるように、192.168.0.2/24と192.168.0.254/24を設定します。

```:terminal-computer1
# terminal-computer1で実行
ip address add 192.168.0.2/24 dev com1-veth0
```

```:terminal-router
# terminal-routerで実行
ip address add 192.168.0.254/24 dev gw-veth0
```
同様に、computer2とrouterの間のそれぞれのネットワークインターフェイスに、IPアドレスを付与します。192.168.100.0/24という同じセグメントになるように、192.168.100.2/24と192.168.100.254/24を設定します。

```:terminal-computer2
# terminal-computer2で実行
ip address add 192.168.100.2/24 dev com2-veth0
```

```:terminal-router
# terminal-routerで実行
ip address add 192.168.100.254/24 dev gw-veth1
```
## 同じセグメント内でのPing疎通確認

ここまでで、同じセグメント内の機器間での通信が可能になっているはずです。

以下のコマンドで、computer1からrouterへのPingの疎通を確認します。

```:terminal-computer1
# terminal-computer1で実行
ping -c 3 192.168.0.254
```

以下のコマンドで、computer2からrouterへのPingの疎通を確認します。

```:terminal-computer2
# terminal-computer2で実行
ping -c 3 192.168.100.254
```
以上で、同じセグメント内（computerとrouter間）の疎通確認ができました。
次に、computer1とcomputer2の間で違うセグメント同士（router越し）での通信ができるように設定していきます。

## ホスト機器のルーティング設定

ここで、computer1のルーティングテーブルを確認してみます。

```:terminal-computer1
# terminal-computer1で実行
ip route show
```
出力結果は以下のとおりです。

```
192.168.0.0/24 dev com1-veth0 proto kernel scope link src 192.168.0.2 
```

computer1のルーティングテーブルには、ルーティングエントリが1つだけあります。意味としては、192.168.0.0/24宛は、com1-veth0というネットワークインターフェイスで通信する、という内容になります。

これだけでは、192.168.0.0/24以外のネットワークと通信するルートがないため、ルーティングエントリを追加する必要があります。

追加するルーティングエントリは、デフォルトルートです。デフォルトルートというのは他の宛先に一致しないとき使われるルーティングエントリです。

まずは、computer1にデフォルトルートとなるルーティングエントリを追加します。

```:terminal-computer1
# terminal-computer1で実行
ip route add default via 192.168.0.254
```
以下のように、送信先のアドレスを直接指定するやり方もありますが、通信したい相手の数だけルーティングエントリを追加しなければならず非常に手間です。そのため、デフォルトルートを設定するのが良いです。

```:terminal-computer1
# terminal-computer1で実行
ip route add 192.168.100.2 via 192.168.0.254
```
次に、computer2にも同じようにデフォルトルートとなるルーティングエントリを追加します。

```:terminal-computer2
# terminal-computer2で実行
ip route add default via 192.168.100.254
```
## ルータとしての動作設定

routerがIPv4のルータとして動作しているか確認するために、以下のコマンドを実行します。

```:terminal-router
sysctl net.ipv4.ip_forward
```
出力結果として、パラメータが0の場合は1に指定し直す必要があります。Linuxはこのパラメータが有効になっていないとルータとして動作しません。

このパラメータは、LinuxにおいてIPv4のルータとして動作するかを決めるパラメータです。一般的にデフォルトではこのパラメータは無効になっています。

```
net.ipv4.ip_forward = 0
```

パラメータを以下のコマンドで1に設定します。

```:terminal-router
sysctl net.ipv4.ip_forward=1
```

これで一通りの設定が完了しました。最後に、computer1からcomputer2にPingの疎通が通る事を確認しておきましょう。

```
ping -c 3 192.168.100.2
```

## おわりに

ネットワークの勉強を実機を使って動かしながら学ぶ方法として、Ubuntuの仮想環境を使った方法を紹介しました。

また、今回はネットワークのルーティングについて、基本的なルータ1台を介した別セグメント間の通信を扱いました。このようなケースで、ルーティング設定が必要な際のマニュアルとして使っていただけると幸いです。

応用ケースとしてルータを2台介した場合が考えられますが、今回の設定だけでは済まず、ルータにもルーティングの設定をしてあげる必要があります。次回、ルータ2台を介した別セグメント間の通信について解説しようと思います。
→[次回の記事はこちら](https://qiita.com/f-paico/items/bd5f75c38ceba3625157)

最後に、この記事が少しでも多くの方にとって有益になれば幸いです。