RasberryPi(stretch) で複数の NIC について static route を設定する

前置き

RaspberryPi に USB-Ether などを挿入して、複数の NIC に対して、異なるネットワーク用意したとき、
ある特定の通信はこちらの interface から、別の通信はこちらの interface から、という設定が必要になるときがあります。

例えば、以下のような状況です。

インターネットには 192.168.1.1 を介して出ていきますが、
別サブネットの LAN 内にあるサーバとやり取りするときは、 192.168.100.1 を介して行いたい、ということ状況です。
そのようなときの設定方法を説明します。

検証環境

$ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 9.1 (stretch)
Release:        9.1
Codename:       stretch

RaspberryPi のネットワーク設定

RaspberryPi は stretch から、通常の NetworkManager (/etc/network/interfaces)では、 ネットワークの設定ができなくなりました。
正確に言うと、 NetworkManager でネットワークの設定をすると、別のツールと競合して、動作が不安定になります。

代わりに dhcpcd というマネージャが使われ、これは /etc/dhcpcd.conf という設定ファイルによって設定されます。
初期ファイルから変更していなければ、中身を読むと example が書いてあります。
その example に従って、 static に ip を設定してみます。

interface eth0
static ip_address=192.168.1.200/24
static routers=192.168.1.1
static domain_name_servers=192.168.1.1 8.8.8.8

これでマシンの再起動を行うと、 static に ip が払い出されます。

今回は eth0 と eth1 を用意して、以下のように設定します。

interface eth0
static ip_address=192.168.1.200/24
static routers=192.168.1.1
static domain_name_servers=192.168.1.1 8.8.8.8

interface eth1
static ip_address=192.168.100.102/24

インターネットと通信する場合は、 eth0 から行い、 別サブネットの LAN とは、 eth1 から通信を行う想定をしています。
eth1 については routers の設定を行いません。
なぜならば、 後に route で確認するのですが、 default route が複数設定されてしまうからです。

route の設定

再起動を行った後、 route を確認してみます。
おそらく以下のような感じになっているのではないかと思います(dockerは無視してください)。

$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.1.1     0.0.0.0         UG    202    0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.1.0     0.0.0.0         255.255.255.0   U     202    0        0 eth0
192.168.100.0   0.0.0.0         255.255.255.0   U     203    0        0 eth1

default gateway が eth0 側に向いており、
宛先が 192.168.100.0/24 以外 の全ての通信は eth0 を通して行われることがわかります。

ここから eth1 側のルータのさらに奥にある 192.168.222.10 のマシンと通信がしたい、ということがあります。
このとき RasPi から単純に 192.168.222.10 と指定しても、
この通信は default gateway を通過するため、目的の PC と通信することができません(すなわち eth0 からでていきます)。

では、どうするかというと route にたいして static route を付けて、
192.168.222.10/32 の通信は eht1 から出るように設定してあげます。

$ ip route add 192.168.222.10/32 via 192.168.100.1
 $ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.1.1     0.0.0.0         UG    202    0        0 eth0
192.168.222.10  192.168.100.1   255.255.255.255 UG    0      0        0 eth1
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.1.0     0.0.0.0         255.255.255.0   U     202    0        0 eth0
192.168.100.0   0.0.0.0         255.255.255.0   U     203    0        0 eth1

これで 192.168.222.10/32 への通信は eth1 を介して行われるようになりました。
永続的にこの設定を反映させるには /etc/dhcpcd.exit-hook に記述します。

$ cat dhcpcd.exit-hook
ip route add 192.168.222.10/32 via 192.168.100.1

再起動しても、 route が設定されていることがわかります。

以上で設定は終了です。