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

## はじめに

[前回](https://qiita.com/f-paico/items/48d47f74eaa36db0b149)に引き続き、1台のMacのPC上でLinux（Ubuntu）の仮想環境を構築し、Ubuntuを使ってネットワークのルーティングについて学んでいきます。WindowsのPC上でLinux（Ubuntu）の仮想環境を構築してもOKです。

今回は、ルータ2台を介した別セグメント間（ネットワークが違うホスト機器同士）の通信について、ルーティング設定を行いつつ動作確認していきたいと思います。

今回も、[こちらの本](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を送り疎通を取れるようにします。

ホスト機器の間にルータを2台介したネットワーク構成になっています。この場合、ホスト機器だけでなく、ルータにもルーティング設定が必要となります。

![図_【Ubuntu】ネットワークのルーティングを学ぶ(2) .png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674933/7479f873-a83e-d109-1c4e-69063c82dfe5.png)

## 実験準備

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

## Network Namespaceについて

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

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

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

## Network Namespaceの作成

まず、Network Namespaceを作成します。上で説明したネットワーク構成図の通りに機器を準備します。以下のコマンドを実行してください。

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

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

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

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

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

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

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

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

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

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

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

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

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

```:terminal-router1
# terminal-router1で実行
ip link set gw1-veth0 up
ip link set gw1-veth1 up
```

```:terminal-router2
# terminal-router2で実行
ip link set gw2-veth0 up
ip link set gw2-veth1 up
```

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

上で作成した6つのネットワークインタフェースに、上で説明した図の通りにIPアドレスを付与します。

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

```:terminal-router1
# terminal-router1で実行
ip address add 192.168.0.254/24 dev gw1-veth0
ip address add 203.103.0.2/24 dev gw1-veth1
```

```:terminal-router2
# terminal-router2で実行
ip address add 192.168.100.254/24 dev gw2-veth0
ip address add 203.103.0.3/24 dev gw2-veth1
```

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

## 同じセグメント内でのPing疎通確認

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

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

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

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

```:terminal-computer2
# terminal-computer2で実行
ping -c 3 192.168.100.254
```

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

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

```:terminal-computer1
# terminal-computer1で実行
ip route add default via 192.168.0.254
```

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

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

router1, router2をIPv4のルータとして動作させるため、以下のコマンドを実行します。

```:terminal-router1
# terminal-router1で実行
sysctl net.ipv4.ip_forward=1
```

```:terminal-router2
# terminal-router2で実行
sysctl net.ipv4.ip_forward=1
```
## ルータ機器のルーティング設定

今回のネットワーク構成では、router1, router2が直接つながっていないセグメントがあります。

router1は198.168.100.0/24のセグメント宛のパケットを受け取っても、次に渡す相手がわかりません。

また、router2は192.168.0.0/24のセグメント宛のパケットを受けとっても、次に渡す相手がわかりません。

この問題を解決するには、ルータにもルーティングエントリを追加する必要があります。自分自身が直接つながっていないセグメント宛のパケットを、どう扱えば良いのかを設定します。

まず、router1には、192.168.100.0/24宛のパケットは203.103.0.3に送るように設定をします。

```:terminal-router1
# terminal-router1で実行
ip route add 192.168.100.0/24 via 203.103.0.3

# もしくは、以下のようにデフォルトルートとして設定する
ip route add default via 203.103.0.3
```

次に、router2には、192.168.0.0/24宛のパケットは203.103.0.2に送るように設定をします。

```:terminal-router2
# terminal-router2で実行
ip route add 192.168.0.0/24 via 203.103.0.2

# もしくは、以下のようにデフォルトルートとして設定する
ip route add default via 203.103.0.2
```

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

```
ping -c 3 192.168.100.2
```

## おわりに

前回に引き続き、別セグメント間の通信を行うためのルーティングについてUbuntuの仮想環境を使って動作確認をしつつ説明をしました。

今回は、前回のルータ1台を介した別セグメント間の通信の応用として、ルータ2台を介した別セグメント間の通信を扱いました。

このようなケースで、ルーティング設定が必要な際のマニュアルとして使っていただけると幸いです。

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