LinuxにおけるIPフォワーディング
概要
LinuxにはIPパケットをフォワーディングする機能が具備されている。IPフォワーディングはあるネットワークから受け取ったパケットを別のネットワークに転送する技術である。言い換えると、2つのNICの間でパケットを転送する技術である。これにより、パケットが異なるネットワークの間を往き来できるようになる*1。
LinuxでIPフォワードを有効にするには、カーネルパラメータ net.ipv4.ip_forward
の値を1にする必要がある(設定方法は過去エントリを参照 カーネルパラメータの設定方法(CentOS 8) - Knのアウトプット)。
カーネルパラメータを設定した段階では2つのNIC間でパケットが転送できるようになっただけで、適切な通信が行われるようになったわけではない。実際にフォワーディングされるためにはルーティングテーブルを適切に設定する必要がある。
設定例
サーバーA、B、Cの3台があり、Bに対しフォワーディングの設定を行う。
Bは2つのネットワーク、192.168.0.0/24
と192.168.122.0/24
に所属している。
[root@nuc-centos8 ~]# ip a (略) 4: wlp0s20f3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 0c:7a:15:da:07:37 brd ff:ff:ff:ff:ff:ff inet 192.168.0.14/24 brd 192.168.0.255 scope global dynamic noprefixroute wlp0s20f3 (略) 5: virbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 52:54:00:9c:81:ac brd ff:ff:ff:ff:ff:ff inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0 (略)
サーバAは192.168.0.0/24
のみに所属している。
[root@virtualbox-centos7 ~]# ip a (略) 3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 08:00:27:08:35:9c brd ff:ff:ff:ff:ff:ff inet 192.168.0.92/24 brd 192.168.0.255 scope global noprefixroute enp0s8 (略)
サーバCは192.168.122.0/24
のみに所属している。
[root@kvm-centos8 ~]# ip a (略) 2: ens2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 52:54:00:34:01:09 brd ff:ff:ff:ff:ff:ff inet 192.168.122.100/24 brd 192.168.122.255 scope global noprefixroute ens2 (略)
サーバAからサーバCへpingを打つ。このときサーバBでIPフォワーディングが有効になっており、ルーティングテーブルが設定されていればpingは到達する。 なお、サーバAからサーバBにパケットが飛ぶようにするため、サーバAのデフォルトゲートウェイはサーバBのIPアドレスにしてある。
[root@virtualbox-centos7 ~]# nmcli con show enp0s8 (略) ipv4.addresses: 192.168.0.92/24 ipv4.gateway: 192.168.0.14 (略)
サーバBではすでにIPフォワーディングが有効( net.ipv4.ip_forward = 1
)で、ルーティングテーブルも設定済みである*2。
[root@nuc-centos8 ~]# sysctl -a | grep net.ipv4.ip.forward net.ipv4.ip_forward = 1 net.ipv4.ip_forward_update_priority = 1 net.ipv4.ip_forward_use_pmtu = 0 [root@nuc-centos8 ~]# ip r default via 192.168.0.1 dev wlp0s20f3 proto dhcp metric 600 192.168.0.0/24 dev wlp0s20f3 proto kernel scope link src 192.168.0.100 metric 600 192.168.0.0/24 dev wlp0s20f3 proto kernel scope link src 192.168.0.14 metric 600 192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1
サーバAからpingを打つ。応答が返ってきていることがわかる。
[root@virtualbox-centos7 ~]# ping 192.168.122.100 PING 192.168.122.100 (192.168.122.100) 56(84) bytes of data. 64 bytes from 192.168.122.100: icmp_seq=1 ttl=63 time=106 ms 64 bytes from 192.168.122.100: icmp_seq=2 ttl=63 time=22.9 ms 64 bytes from 192.168.122.100: icmp_seq=3 ttl=63 time=41.1 ms (略)
pingを打ちっぱなしのままサーバCでtcpdumpを使いパケットを監視してみると、ICMPのrequestが飛んできている。
[root@kvm-centos8 ~]# tcpdump -i any src host 192.168.0.92 -n tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes 11:07:47.686403 IP 192.168.0.92 > 192.168.122.100: ICMP echo request, id 2747, seq 57, length 64 11:07:48.710472 IP 192.168.0.92 > 192.168.122.100: ICMP echo request, id 2747, seq 58, length 64 11:07:49.734488 IP 192.168.0.92 > 192.168.122.100: ICMP echo request, id 2747, seq 59, length 64 11:07:50.656000 IP 192.168.0.92 > 192.168.122.100: ICMP echo request, id 2747, seq 60, length 64 (略)
pingとtcpdumpを仕掛けたまま、サーバB上でIPフォワーディングを無効化してみる。一時的に無効化するにはファイル/proc/sys/net/ipv4/ip_forward
の値を直接0に書き換える。
[root@nuc-centos8 ~]# echo 0 > /proc/sys/net/ipv4/ip_forward
サーバAのping応答が止まる。
(略) 64 bytes from 192.168.122.100: icmp_seq=126 ttl=63 time=98.5 ms 64 bytes from 192.168.122.100: icmp_seq=127 ttl=63 time=117 ms (ここで止まる)
サーバCでもtcpdumpの更新が止まる。
(略) 11:11:26.734165 IP 192.168.0.92 > 192.168.122.100: ICMP echo request, id 2748, seq 126, length 64 11:11:27.757086 IP 192.168.0.92 > 192.168.122.100: ICMP echo request, id 2748, seq 127, length 64 (ここで止まる)
サーバB上でIPフォワーディングを再び有効にするとpingの応答が返り、tcpdumpの更新が再開される(応答が返ってきている様子等は割愛する)。
[root@nuc-centos8 ~]# echo 1 > /proc/sys/net/ipv4/ip_forward