1. はじめに
IBM CloudのVPCにて、以下のようなネットワーク構成時に、
Server-A(172.16.5.6) -> Server-B(172.16.5.4, 172.16.7.4) -> Server-C(172.16.7.6)
という経路で接続できるか?(Server-Bがあたかもルーターであるかのように構成できるか?という確認をしてみました。(このあたりを手動で構成できるようになることは、今後VPC上でNFV機能を使うときの理解の一助にもなると思われます)
2. 結論を先にいうと
- Server-A: Server-Cへの経路がServer-Bを通るように設定。
- Server-C: Server-Aへの経路がServer-Bを通るように設定。
- Server-B: パケットが転送できるようにip_forward=1を設定。
- Server-B: Server-Bのインターフェースに設定していないIPをsource IPとして送信するため、eth1/eth3にてIP-Spoofingを有効化。
をすれば通信は可能になります。また、当然ですがSecurity GroupやNetwork ACLといったVPCのFW機能だったり、iptablesなどのOS Firewallでもこれらの通信を許可されているという前提で話を進めています。
また、今回は動作確認をしたかっただけなので、以下では非永続的な設定をしていることをご了承ください。
3. 経路設定
Server-AのDefault Gatewayは172.16.5.1であり、static routeは構成されていません。そのため、Server-Cに通信しようとしてもそのままでは172.16.5.1にパケットを送信してしまいます。Server-C宛のパケットはServer-Bに送信するように経路設定を変更する必要があります。同様のことはServer-Cにもあてはまります。
3-1. Server-Aの経路設定
[root@server-a ~]# ip r
default via 172.16.5.1 dev eth0
169.254.0.0/16 dev eth0 scope link metric 1002
172.16.5.0/24 dev eth0 proto kernel scope link src 172.16.5.6
[root@server-a ~]# ip route add 172.16.7.0/24 via 172.16.5.4
[root@server-a ~]# ip r
default via 172.16.5.1 dev eth0
169.254.0.0/16 dev eth0 scope link metric 1002
172.16.5.0/24 dev eth0 proto kernel scope link src 172.16.5.6
172.16.7.0/24 via 172.16.5.4 dev eth0
3-2. Server-Cの経路設定
[root@server-c ~]# ip r
default via 172.16.7.1 dev eth0
169.254.0.0/16 dev eth0 scope link metric 1002
172.16.7.0/24 dev eth0 proto kernel scope link src 172.16.7.6
[root@server-c ~]# ip route add 172.16.5.0/24 via 172.16.7.4
[root@server-c ~]# ip r
default via 172.16.7.1 dev eth0
169.254.0.0/16 dev eth0 scope link metric 1002
172.16.5.0/24 via 172.16.7.4 dev eth0
172.16.7.0/24 dev eth0 proto kernel scope link src 172.16.7.6
3-3. 経路設定後のテスト
[root@server-a ~]# ping 172.16.7.6
(出力なし)
[root@server-b ~]# tcpdump -i eth1 icmp -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes
18:22:02.698138 IP 172.16.5.6 > 172.16.7.6: ICMP echo request, id 31833, seq 1, length 64
18:22:03.697297 IP 172.16.5.6 > 172.16.7.6: ICMP echo request, id 31833, seq 2, length 64
18:22:04.697304 IP 172.16.5.6 > 172.16.7.6: ICMP echo request, id 31833, seq 3, length 64
18:22:05.697325 IP 172.16.5.6 > 172.16.7.6: ICMP echo request, id 31833, seq 4, length 64
[root@syasuda-router ~]# tcpdump -i eth3 icmp -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth3, link-type EN10MB (Ethernet), capture size 262144 bytes
(何も出力されない)
よって、Server-Bでの設定が足りていないことがわかります。
4. Server-Bでのパケット転送
Linuxサーバーではパケット転送はデフォルトで許可されていません。パケット転送を許可しルーターのように振る舞うためには、カーネルパラメーターの変更が必要です。
4-1. Server-Bにてip_forward=1を設定
ip_forward - BOOLEAN
0 - disabled (default)
not 0 - enabled
Forward Packets between interfaces.
This variable is special, its change resets all configuration
parameters to their default state (RFC1122 for hosts, RFC1812
for routers)
[root@server-b ~]# cat /proc/sys/net/ipv4/ip_forward
0
[root@server-b ~]# echo 1 > /proc/sys/net/ipv4/ip_forward
[root@server-b ~]# cat /proc/sys/net/ipv4/ip_forward
1
また、念の為iptablesでFORWARDチェーンがブロックされていないことも確認しておきます。(VPC上のVSIではiptablesはデフォルトでは有効化していないのでブロックされていないはず)
[root@syasuda-router ~]# iptables -L -v -n
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
4-2. ip_forward=1後のテスト
[root@syasuda17165 ~]# ping 172.16.7.6
PING 172.16.7.6 (172.16.7.6) 56(84) bytes of data.
(PINGの応答は返ってこない)
[root@server-b ~]# tcpdump -i eth1 icmp -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes
18:18:32.697942 IP 172.16.5.6 > 172.16.7.6: ICMP echo request, id 31749, seq 1, length 64
18:18:33.697256 IP 172.16.5.6 > 172.16.7.6: ICMP echo request, id 31749, seq 2, length 64
18:18:34.697301 IP 172.16.5.6 > 172.16.7.6: ICMP echo request, id 31749, seq 3, length 64
18:18:35.697375 IP 172.16.5.6 > 172.16.7.6: ICMP echo request, id 31749, seq 4, length 64
[root@server-b ~]# tcpdump -i eth1 icmp -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes
18:18:55.736464 IP 172.16.5.6 > 172.16.7.6: ICMP echo request, id 31750, seq 1, length 64
18:18:56.736199 IP 172.16.5.6 > 172.16.7.6: ICMP echo request, id 31750, seq 2, length 64
18:18:57.736289 IP 172.16.5.6 > 172.16.7.6: ICMP echo request, id 31750, seq 3, length 64
18:18:58.736299 IP 172.16.5.6 > 172.16.7.6: ICMP echo request, id 31750, seq 4, length 64
[root@server-b ~]# tcpdump -i any icmp -nn
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
18:16:57.750521 IP 172.16.5.6 > 172.16.7.6: ICMP echo request, id 31707, seq 1, length 64
18:16:57.750540 IP 172.16.5.6 > 172.16.7.6: ICMP echo request, id 31707, seq 1, length 64
18:16:58.750167 IP 172.16.5.6 > 172.16.7.6: ICMP echo request, id 31707, seq 2, length 64
18:16:58.750189 IP 172.16.5.6 > 172.16.7.6: ICMP echo request, id 31707, seq 2, length 64
18:16:59.750230 IP 172.16.5.6 > 172.16.7.6: ICMP echo request, id 31707, seq 3, length 64
18:16:59.750253 IP 172.16.5.6 > 172.16.7.6: ICMP echo request, id 31707, seq 3, length 64
18:17:00.750331 IP 172.16.5.6 > 172.16.7.6: ICMP echo request, id 31707, seq 4, length 64
18:17:00.750353 IP 172.16.5.6 > 172.16.7.6: ICMP echo request, id 31707, seq 4, length 64
[root@server-c ~]# tcpdump -i any icmp -nn
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
(何も出力されない)
よって、Server-Bからはパケットは送出されているため、OSの問題ではありません。この場合、Server-Cに届かない理由として考えられるのはVPC側の構成です。
5. IP Spoofingの有効化
5-1. Server-Bにて、eth1/eth3でのIP Spoofingの有効化
Security GroupやNetwork ACLでブロックしていないのであれば、別の問題が考えられます。
実は、これはServer-Bのeth3には172.16.7.4
が割り当てられているので、eth3から送信するパケットのSource IP通信は172.16.7.4
であるはずなのに、所有していないIPアドレス172.16.5.6
をsource addressとしてServer-Bが送信しているため、IPアドレスが偽装されていると見なされてVPC側でブロックされているのです。詳細はこちらもご参照ください。
これを防ぐためには、IP Spoofing
を有効化する必要があります。ここにも記載しているとおり、IAMでVPCにおけるIP Spoofing Operatorロール
を有効化しておけば、この変更が可能になります。
5-2. IP Spoofing後のテスト
ちゃんと届くようになりました!
[root@server-a ~]# ping 172.16.7.6
PING 172.16.7.6 (172.16.7.6) 56(84) bytes of data.
64 bytes from 172.16.7.6: icmp_seq=1 ttl=63 time=0.628 ms
64 bytes from 172.16.7.6: icmp_seq=2 ttl=63 time=0.711 ms
64 bytes from 172.16.7.6: icmp_seq=3 ttl=63 time=0.763 ms
64 bytes from 172.16.7.6: icmp_seq=4 ttl=63 time=0.808 ms
[root@server-c ~]# tcpdump -i any icmp -nn
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
06:20:29.528914 IP 172.16.5.6 > 172.16.7.6: ICMP echo request, id 6520, seq 1, length 64
06:20:29.528946 IP 172.16.7.6 > 172.16.5.6: ICMP echo reply, id 6520, seq 1, length 64
06:20:30.528934 IP 172.16.5.6 > 172.16.7.6: ICMP echo request, id 6520, seq 2, length 64
06:20:30.528962 IP 172.16.7.6 > 172.16.5.6: ICMP echo reply, id 6520, seq 2, length 64
06:20:31.529227 IP 172.16.5.6 > 172.16.7.6: ICMP echo request, id 6520, seq 3, length 64
06:20:31.529258 IP 172.16.7.6 > 172.16.5.6: ICMP echo reply, id 6520, seq 3, length 64