RHEL 7.4 でPolicy Based Routingを設定してみました。

記事タイトルとURLをコピーする

はじめまして、クラウドインテグレーション部の城と申します。
1月に入社したのですが、あっという間に1か月過ぎてしまいました。
時間の過ぎる速さに年齢を感じざるをえません。

さて本題へ入りますが、EC2インスタンスに別々のCIDRブロックのプライベートアドレスを付与し、それぞれと外部から通信させたいというケースがありました。
検証していたところ、ネットワークの設定でかなりつまづいてしまったので、一つの例として記録しておきたいと思います。
※インスタンス内のネットワーク設定にフォーカスしてお送りします。

実現したいこと

  • OS:RedHat Enterprize Linux 7.4
  • EC2インスタンスにそれぞれ別のCIDRブロックに所属するプライベートIPを設定する
  • それぞれのインターフェースと通信できるように設定する
  • インスタンス再起動時にも設定を維持する

用意した環境

次の環境を用意しました。
ENIが2つアタッチされています。

インターフェースの状態確認

インスタンスにログインしてネットワークインターフェースの確認をします。
所属するサブネットではない方のネットワークインターフェースeth1は設定されていません。

ip addr
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0:  mtu 9001 qdisc pfifo_fast state UP qlen 1000
    link/ether 06:37:94:00:c3:74 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.56/24 brd 10.0.0.255 scope global dynamic eth0
       valid_lft 3240sec preferred_lft 3240sec
    inet6 fe80::437:94ff:fe00:c374/64 scope link
       valid_lft forever preferred_lft forever
3: eth1:  mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 06:19:73:31:79:48 brd ff:ff:ff:ff:ff:ff

ネットワークインターフェースの設定

eth1の設定をします。
DHCPでネットワーク設定を取得するようにします。
グローバルのデフォルトルートが複数登録されてしまうことを防ぐため、
DEFROUTE=noを記載しておきます。

# cat << ETX > /etc/sysconfig/network-scripts/ifcfg-eth1
DEVICE=eth1
BOOTPROTO=dhcp
ONBOOT=yes
TYPE=Ethernet
USERCTL=no
DEFROUTE=no

ETX

ネットワーク再起動

前項の設定を反映させるため、ネットワークを再起動します。

# /etc/init.d/network restart
Restarting network (via systemctl):                        [  OK  ]

インターフェースの状態確認(設定後)

確認すると、eth1が設定されています。

# ip addr
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0:  mtu 9001 qdisc pfifo_fast state UP qlen 1000
    link/ether 06:37:94:00:c3:74 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.56/24 brd 10.0.0.255 scope global dynamic eth0
       valid_lft 3532sec preferred_lft 3532sec
    inet6 fe80::437:94ff:fe00:c374/64 scope link
       valid_lft forever preferred_lft forever
3: eth1:  mtu 9001 qdisc pfifo_fast state UP qlen 1000
    link/ether 06:19:73:31:79:48 brd ff:ff:ff:ff:ff:ff
    inet 10.1.0.12/24 brd 10.1.0.255 scope global dynamic eth1
       valid_lft 3532sec preferred_lft 3532sec
    inet6 fe80::419:73ff:fe31:7948/64 scope link
       valid_lft forever preferred_lft forever

通信確認

eth1のENIに設定したEIPに対して、local端末からpingしてみます。
この段階ではアクセスできません。

C:\>ping 54.249.223.19

54.249.223.19 に ping を送信しています 32 バイトのデータ:
要求がタイムアウトしました。
要求がタイムアウトしました。
要求がタイムアウトしました。
要求がタイムアウトしました。

54.249.223.19 の ping 統計:
    パケット数: 送信 = 4、受信 = 0、損失 = 4 (100% の損失)、

ルーティング確認

ルーティングを確認します。

# ip route show
default via 10.0.0.1 dev eth0 proto static metric 100
10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.56 metric 100
10.1.0.0/24 dev eth1 proto kernel scope link src 10.1.0.12 metric 100

外部ネットワークからeth1にアクセスすると、戻りのトラフィックがデフォルトルートにマッチしてしまい、下図NGの状態のようにeth0からトラフィックが出てしまうことがアクセスできない原因です。
そこで図中のOKの状態にすべく、ポリシーベースルーティングを設定します。

ポリシーベースルーティング設定

ポリシーベースルーティングは設定した条件により、ルーティングを行うことができます。
今回は送信元IPアドレスを条件に、別々のデフォルトゲートウェイを設定します。

ルートテーブルIDの設定

rule01rule02を追記します。
IDはmainより小さい(優先度が高い)ものを指定します。

cat << ETX >> /etc/iproute2/rt_tables
100     rule01
101     rule02

ETX

ルールを追加

rule-eth0の場合、
「送信元が10.0.0.56/32の場合、テーブルrule01のルーティングを参照」
という意味になります。
送信元には各インターフェースのプライベートIPを指定します。

cat << ETX > /etc/sysconfig/network-scripts/rule-eth0
from 10.0.0.56/32 table rule01 priority 100

ETX
cat << ETX > /etc/sysconfig/network-scripts/rule-eth1
from 10.1.0.12/32 table rule02 priority 200

ETX

ルーティングを追加

設定したルールrule01rule02に該当する場合のルーティングを追加します。

cat << ETX > /etc/sysconfig/network-scripts/route-eth0
10.0.0.0/24 dev eth0 table rule01
default via 10.0.0.1 dev eth0 table rule01

ETX
cat << ETX > /etc/sysconfig/network-scripts/route-eth1
10.1.0.0/24 dev eth1 table rule02
default via 10.1.0.1 dev eth1 table rule02

ETX

NetworkManagerを停止する

私はここでハマってしまいました。
NetworkManagerが起動している場合、ネットワーク再起動しても、
/etc/sysconfig/network-scripts/以下のroute-rule-のファイルが設定反映されませんでした。
/var/log/messagesを見ると、下記確認できました。

NetworkManager[3173]:   [1518060079.2120] ifcfg-rh:     'rule-' or 'rule6-' file is present; you will need to use a dispatcher script to apply these routes

解決策を探していたところ、公式サイトにはこのような記載がありました。

NetworkManager は現在、RHEL 7 でデフォルトで使用されています。NetworkManager を無効すると、ネットワークインターフェイス管理には代わりに initscripts が使用されます。

NetworkManagerを停止し、initscriptsを使用してみます。

# systemctl stop NetworkManager.service

自動起動の停止

自動起動についても停止しておきます。

# systemctl disable NetworkManager.service

ネットワーク再起動

設定を反映させるため、ネットワークを再起動します。

# /etc/init.d/network restart
Restarting network (via systemctl):                        [  OK  ]

ルーティングテーブルの確認

設定内容が反映されたことが確認でき、eth1についても、 外部ネットワークからアクセスできるようになりました。

# ip rule show
0:      from all lookup local
100:    from 10.0.0.56 lookup rule01
200:    from 10.1.0.12 lookup rule02
32766:  from all lookup main
32767:  from all lookup default

# ip route show table rule01
default via 10.0.0.1 dev eth0
10.0.0.0/24 dev eth0 scope link

# ip route show table rule02
default via 10.1.0.1 dev eth1
10.1.0.0/24 dev eth1 scope link
C:\>ping 54.249.223.19

54.249.223.19 に ping を送信しています 32 バイトのデータ:
54.249.223.19 からの応答: バイト数 =32 時間 =7ms TTL=50
54.249.223.19 からの応答: バイト数 =32 時間 =20ms TTL=50
54.249.223.19 からの応答: バイト数 =32 時間 =8ms TTL=50
54.249.223.19 からの応答: バイト数 =32 時間 =9ms TTL=50

54.249.223.19 の ping 統計:
    パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 7ms、最大 = 20ms、平均 = 11ms

最後に

複数のENIを利用する場合のネットワーク設定の例を紹介しました。
このような構成の場合、どうしても設定内容が複雑になってしまいがちです。
システムやネットワークの構成をしっかりと検討した上で、どうしても必要な場合に利用することをお勧めいたします。

城 航太 (記事一覧)

サイトリライアビリティエンジニアリング部・CSM課・課長

AWSへの移行、AWSアカウントセキュリティ、ネットワーク広く浅くといった感じです。最近はAmazon WorkSpacesやAmazon AppStream2.0が好きです。APN Ambassador 2019,2020