0. やりたいこと
AWSクラウド上で稼働している Amazon EC2 インスタンス (Amazon Linux) と拠点(YAMAHA RTX系)間を 「追加費用をかけずに」 プライベートIPv4アドレス で通信したい。
AWSでグローバルIPv4アドレスが有料化された現在、IPv6アドレスを使用してこれを実現する必要があります。
1. 実装方法を考える
一般にこういった用途ではVPN接続をするのでしょう。
AWSクラウドにもマネージドサービスで提供される AWS VPN サービスが各種あります。
しかし、それらは時間課金で結構な追加費用がかかります。
Vyatta等のソフトウェアルータや仮想アプライアンスをAWSクラウド上で稼働させる方法もあります。
しかし、これには専用のEC2インスタンスが必要で、AWS VPNよりは安いものの(インスタンスタイプによるが)やはり追加費用がかかります。
そこで、Linuxに標準実装されているIPIPで拠点側のルータと接続することを考えました。
これならば追加費用はかかりません。
もちろんIPIPには暗号化機能が無いことは重々承知しています。
通信内容はアプリケーションレイヤで暗号化されているので、ここではそれ以上のことは論じないこととします。
2. まずはIPv4でIPIPトンネルを張る
まずはグローバルIPv4アドレスでトンネルを張ってみます。これは非常に簡単です。
拠点側のグローバルIPアドレスを 1.1.1.1
, プライベートネットワークアドレスを 10.10.0.0/24
とします。
AWS側のグローバルIPアドレスを 2.2.2.2
, EC2インスタンスのIPアドレスを 172.22.2.2/24
とします。
2.1. 設定の投入
拠点側の設定(RTX1300)
# tunnel select 11
tunnel11# escription tunnel AWS/IPIP4
tunnel11# tunnel encapsulation ipip
tunnel11# tunnel endpoint address 2.2.2.2
tunnel11# tunnel enable 11
tunnel11# tunnel select none
# ip route 172.22.2.0/24 gateway tunnel 11
AWS側の設定(Amazon Linux)
# ip tunnel add aws0 mode ipip remote 1.1.1.1
# ip link set aws0 up
# ifconfig aws0 172.22.2.2/24 mtu 1280 up
# route add -net 10.10.0.0/24 dev aws0
2.2. 動作確認
設定が完了したのでまずは拠点から ping してみますが、うまくいきません。
$ ping 172.22.2.2
PING 172.22.2.2 (172.22.2.2) 56(84) bytes of data.
^C
--- 172.22.2.2 ping statistics ---
9 packets transmitted, 0 received, 100% packet loss, time 8739ms
$
何故か疎通できていないようです。
拠点側から状況を確認します。
> show status tunnel 11
TUNNEL[11]:
説明: AWS/IPIP4
インタフェースの種類: IP over IP
トンネルインタフェースは接続されています
開始: 2025/03/01 00:00:10
通信時間: 1日1時間1分1秒
受信: (IPv4) 0 パケット [0 オクテット]
(IPv6) 0 パケット [0 オクテット]
送信: (IPv4) 64 パケット [7097 オクテット]
(IPv6) 0 パケット [0 オクテット]
> show ip route 172.22.2.2
宛先ネットワーク ゲートウェイ インタフェース 種別 付加情報
172.22.2.0/24 - TUNNEL[11] static
>
インタフェースも上がっており経路も登録済み、パケットは送出されていますから拠点側の設定は問題なさそうです。
AWS側を見てみましょう。
$ ifconfig aws0
aws0 Link encap:IPIP Tunnel HWaddr
inet addr:172.22.2.2 P-t-P:172.22.2.2 Mask:255.255.255.0
UP POINTOPOINT RUNNING NOARP MTU:1280 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
$ route -n | grep 10.10.0.0
10.10.0.0 0.0.0.0 255.255.255.0 U 0 0 0 aws0
$
こちらも設定は問題なさそうです。
が、なんとAWS側にパケットは届いていないようです。
NACLやセキュリティグループを再確認しますが問題なし。
悩みました。。
2.3. AWSの謎仕様(?)
なんでだろうと悩んでいて、とりあえずEC2インスタンス側からpingしてみると
$ ping 10.10.0.1
PING 10.10.0.1 56(84) bytes of data.
64 bytes from 10.10.0.1: icmp_seq=1 ttl=64 time=2.72 ms
64 bytes from 10.10.0.1: icmp_seq=2 ttl=64 time=2.91 ms
64 bytes from 10.10.0.1: icmp_seq=3 ttl=64 time=2.87 ms
64 bytes from 10.10.0.1: icmp_seq=4 ttl=64 time=2.89 ms
64 bytes from 10.10.0.1: icmp_seq=5 ttl=64 time=2.85 ms
^C
--- 10.10.0.1 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4006ms
rtt min/avg/max/mdev = 2.726/2.853/2.914/0.066 ms
$
なんと疎通できてしまったのです。
やはり設定は問題なかった。何度か繰り返し実験を行い再現性を確認しました。
(有償のAWSサポートを契約していないので問い合わせができず想像の域を出ませんが)
EC2インスタンス側からパケットを送出するまでIPIPトンネルが開かない
というAWSの謎仕様があるようです。
EC2インスタンス上のOSにはプライベートIPv4アドレスのみ設定され、グローバルIPv4アドレスが付与されることはありません。
Elastic IP(EIP)でも動的なパブリックIPアドレスでも、全てOSとの間ではプライベートIPアドレスとNATされているからでしょうか。
そもそも 1:1 NAT ですからそのような問題は発生しないはずですが、何故かAWSではこのような問題が発生します。
拠点はさくらインターネットのVPSとも全く同じ設定で通信していますがこのような問題は発生しないので、AWSの謎仕様と結論づけました。
まぁ、IPIPトンネル作成時にpingを送出するだけで解決しますから、深追いしないことにします。
3. IPv6でIPIPトンネルを張る
それではIPv6アドレスでトンネルを張ってみましょう。
Linux側のコマンドラインオプション少し異なるだけで、これも非常に簡単です。
拠点側のIPv6アドレスを 2001::1
, プライベートネットワークアドレスを 10.10.0.0/24
とします。
AWS側のグローバルIPアドレスを 2406::2
, EC2インスタンスのIPアドレスを 172.22.2.2/24
とします。
3.1. 設定の投入
拠点側の設定(RTX1300)
# tunnel select 11
tunnel11# escription tunnel AWS/IPIP6
tunnel11# tunnel encapsulation ipip
tunnel11# tunnel endpoint address 2406::2
tunnel11# tunnel enable 11
tunnel11# tunnel select none
# ip route 172.22.2.0/24 gateway tunnel 11
AWS側の設定(Amazon Linux)
# ip -6 tunnel add aws0 mode ipip6 remote 2001::1
# ip link set aws0 up
# ifconfig aws0 172.22.2.2/24 mtu 1280 up
# route add -net 10.10.0.0/24 dev aws0
3.2. 動作確認
設定が完了したのでまずは拠点から ping してみますが、今回もうまくいきません。
$ ping 172.22.2.2
PING 172.22.2.2 (172.22.2.2) 56(84) bytes of data.
^C
--- 172.22.2.2 ping statistics ---
9 packets transmitted, 0 received, 100% packet loss, time 8739ms
$
何故か疎通できていないようです。
拠点側から状況を確認します。
> show status tunnel 11
TUNNEL[11]:
説明: AWS/IPIP6
インタフェースの種類: IP over IP
トンネルインタフェースは接続されています
開始: 2025/03/02 00:00:10
通信時間: 1日1時間1分1秒
受信: (IPv4) 0 パケット [0 オクテット]
(IPv6) 0 パケット [0 オクテット]
送信: (IPv4) 64 パケット [7097 オクテット]
(IPv6) 0 パケット [0 オクテット]
> show ip route 172.22.2.2
宛先ネットワーク ゲートウェイ インタフェース 種別 付加情報
172.22.2.0/24 - TUNNEL[11] static
>
インタフェースも上がっており経路も登録済み、パケットは送出されていますから拠点側の設定は問題なさそうです。
AWS側を見てみましょう。
$ ifconfig aws0
aws0 Link encap:UNSPEC HWaddr 20-01-00-00-00-00-00-00-00-00-00-00-00-00-00-00
inet addr:172.22.2.2 P-t-P:172.22.2.2 Mask:255.255.255.0
inet6 addr: fe80::5555:eeee:fe00:3333/64 Scope:Link
UP POINTOPOINT RUNNING NOARP MTU:1280 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
$ route -n | grep 10.10.0.0
10.10.0.0 0.0.0.0 255.255.255.0 U 0 0 0 aws0
$
こちらも設定は問題なさそうですが、
またしてもAWS側にパケットは届いていないようです。
NACLやセキュリティグループを再確認しますが問題なし。
IPv4の場合と同じ状況です。
3.3. IPv6の場合は解決しなかった
IPv4の場合と同様、EC2インスタンス側からpingすれば解決するかと期待してpingしてみます。
$ ping 10.10.0.1
PING 10.10.0.1 56(84) bytes of data.
^C
--- 10.10.0.1 ping statistics ---
9 packets transmitted, 0 received, 100% packet loss, time 8505ms
$
しかし解決しませんでした。
不思議なのはAWS側からは応答を返していることです。
$ ifconfig aws0
aws0: flags=209<UP,POINTOPOINT,RUNNING,NOARP> mtu 8953
inet 172.22.2.2 netmask 255.255.255.0 destination 172.22.2.2
inet6 fe80::fc74:bfff:fe73:fe3e prefixlen 64 scopeid 0x20<link>
unspec 24-06-DA-14-02-57-B9-00-00-00-00-00-00-00-00-00 txqueuelen 1000 (UNSPEC)
RX packets 46 bytes 4232 (4.1 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 95 bytes 8348 (8.1 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
$
拠点側からpingすると、それに対して応答を返しますがなぜか通信不能。
IPv6でのIPIPトンネルはどうにも疎通できないのでした。
3.4. 他の接続を試す
問題は本当にAWS側なのかを調べます。
他に考えられる原因は
- ヤマハルータ
- NGN
といったところでしょうか。
そこで、さくらインターネットで稼働中の RedHat Enterprise Linux と AWS を接続してみます。
さくらインターネット側のIPv6アドレスを 2003::3
, サーバのIPアドレスを 192.168.0.3/24
とします。
AWS側のグローバルIPアドレスを 2406::2
, EC2インスタンスのIPアドレスを 172.22.2.2/24
とします。
さくらインターネット側の設定(RHEL)
# ip -6 tunnel add sak0 mode ipip6 remote 2406::2
# ip link set sak0 up
# ifconfig sak0 192.168.0.3/24 mtu 1280 up
# route add -net 172.22.2.0/24 dev sak0
AWS側の設定(Amazon Linux)
# ip -6 tunnel add aws1 mode ipip6 remote 2003::3
# ip link set aws1 up
# ifconfig aws1 172.22.2.2/24 mtu 1280 up
# route add -net 192.168.0.0/24 dev aws1
共にLinuxですからコマンドは同じで値のみ異なっています。
設定を完了したので早速pingしてみましょう。
$ ping 172.22.2.2
PING 172.22.2.2 56(84) bytes of data.
^C
--- 172.22.2.2 ping statistics ---
9 packets transmitted, 0 received, 100% packet loss, time 8258ms
$
$ ping 192.168.0.3
PING 192.168.0.3 56(84) bytes of data.
^C
--- 192.168.0.3 ping statistics ---
9 packets transmitted, 0 received, 100% packet loss, time 8823ms
$
ヤマハルータ相手の場合と同様、双方向共に通信不能でした。
AWSのIPv6はNATも無く、グローバルIPv6アドレスがEC2インスタンスのOS上に直接付与されていますし、何故こうなってしまうのか謎であります。
セキュリティグループもNACLも全解放しており問題点が見あたらず、お蔵入りです。
4. まとめ
Amazon EC2 インスタンスにおけるIPIPトンネルは
- IPv4の場合、AWS側からパケットを送出するまでトンネルが疎通しないが
- IPv6では通信できなかた
と、詰んでしまいましたが他のブログを見ているとできている人もいる模様。
もう少し調べてみようと思います。