Raspberry Pi (raspbian stretch)でLANとモバイル通信を併用するときの経路設定

#この記事について
Raspberry Piで、LAN接続とUSBドングル(SIMを使ってのモバイル通信)を併用しているときに、思い通りにモバイル側にパケットが飛んでいかないことがありませんか？
そんなときにモバイル側へのルートを設定する方法です。

# 環境
- Raspberry Pi(機種は問わず)
- raspbian stretch
- LAN(`eth0`) と USBドングル(`usb0`) の2つのインターフェースを接続している

# 設定
## 設定前
こんな感じで、LAN(`eth0`)とモバイル(`usb0`)のネットワークインターフェースがあります。
IPアドレスはどちらもdhcpで受け取っています。

なお、Raspberry Pi 3B/3B+/ZeroW で有線LANではなく無線LANを使用している場合は、以下`eth0`を`wlan0`に置き換えて見てください。
モバイル側も、インターフェース名が異なる場合は、以降の記述を置き換えて見てください。

```
$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.10.10.10  netmask 255.255.254.0  broadcast 10.10.10.255
        ether 00:00:00:00:00:00  txqueuelen 1000  (イーサネット)
        RX packets 3046  bytes 253826 (247.8 KiB)
        RX errors 0  dropped 1424  overruns 0  frame 0
        TX packets 165  bytes 30964 (30.2 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (ローカルループバック)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

usb0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.200  netmask 255.255.255.0  broadcast 192.168.0.255
        ether 11:11:11:11:11:11  txqueuelen 1000  (イーサネット)
        RX packets 10  bytes 1257 (1.2 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 36  bytes 5011 (4.8 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
```

経路の設定を見てみるとこんな感じ。

```bash
$ route
カーネルIP経路テーブル
受信先サイト    ゲートウェイ    ネットマスク   フラグ Metric Ref 使用数 インタフェース
default         10.10.10.1      0.0.0.0         UG    202    0        0 eth0
default         192.168.0.1     0.0.0.0         UG    203    0        0 usb0
10.10.10.0      0.0.0.0         255.255.254.0   U     202    0        0 eth0
192.168.0.0     0.0.0.0         255.255.255.0   U     203    0        0 usb0
```

この状態でパケットを飛ばしても、`usb0` ではなく `eth0` 経由になってしまいます。

```bash
$ traceroute 10.64.0.11
traceroute to 10.64.0.11 (10.64.0.11), 30 hops max, 60 byte packets
 1  10.10.10.1 (10.10.10.1)  0.879 ms  0.630 ms  0.804 ms           ←eth0のゲートウェイを通っている
 ...(以下略)...
```

## 設定内容
ここで、以下のような設定に変更してみます。

- `10.64.0.0/24` 宛のパケットは `usb0` に送る
- それ以外は `eth0` に送る

## 実際の設定内容
### usb0のデフォルトゲートウェイの設定を削除
`usb0`側のデフォルトゲートウェイの設定を削除します。
`/etc/dhcpcd.conf` を修正します。

```bash
sudo vi /etc/dhcpcd.conf
```

最下行に以下を追加

```
interface usb0
static routers=
```

### 静的ルートの設定
`/lib/dhcpcd/dhcpcd-hooks/` 以下に、静的ルートを設定するためのスクリプトを配置します。

```bash
sudo vi /lib/dhcpcd/dhcpcd-hooks/60-staticroute
```

以下の内容を記述します。
今回は、`10.64.0.0/24` 宛のパケットを `usb0`のゲートウェイである `192.168.0.1` に送る設定を追加します。

```
#!/bin/sh
/sbin/ip route add 10.64.0.0/24 via 192.168.0.1
```

### 再起動
ここまで設定したらOSを再起動します。

```bash
sudo reboot
```

## 動作確認

経路設定を念の為確認します。

```bash
$ route
カーネルIP経路テーブル
受信先サイト    ゲートウェイ    ネットマスク   フラグ Metric Ref 使用数 インタフェース
default         10.10.10.1      0.0.0.0         UG    202    0        0 eth0
10.64.0.0       192.168.0.1     255.255.255.0   UG    0      0        0 usb0
10.10.10.0      0.0.0.0         255.255.254.0   U     202    0        0 eth0
192.168.0.0     0.0.0.0         255.255.255.0   U     203    0        0 usb0
```

`10.64.0.0/24` 宛のパケットが、`usb0` を経由した経路になっているか確認します。

```bash
$ traceroute 10.64.0.11
traceroute to 10.64.0.11 (10.64.0.11), 30 hops max, 60 byte packets
 1  192.168.0.1 (192.168.0.1)  0.958 ms  0.998 ms  1.096 ms            ←usb0のゲートウェイを通っている
 ....（以下略)...
```

`10.64.0.0/24` 宛にパケットが飛ぶか確認します。

```bash
$ ping 10.64.0.11
PING 10.64.0.11 (10.64.0.11) 56(84) bytes of data.
64 bytes from 10.64.0.11: icmp_seq=1 ttl=59 time=67.6 ms
64 bytes from 10.64.0.11: icmp_seq=2 ttl=59 time=53.9 ms
64 bytes from 10.64.0.11: icmp_seq=3 ttl=59 time=53.8 ms
64 bytes from 10.64.0.11: icmp_seq=4 ttl=59 time=52.8 ms
```