この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、VPN 芸人のトランです。みなさんいかがお過ごしでしょうか?
きょうは、トンネリングによるクラウド接続の可能性を探るべく GRE over IPsec を IPv6 トランスポートで行う方法についてご紹介したいと思います。
GRE over IPsec とは?
GRE over IPsec は、GRE のパケットを IPsec でカプセル化するための仕組みです。この際、IPsec SA は一般的なトンネルモードではなくトランスポートモードで確立され、ESP によるカプセル化の際に GRE パケットの IP ヘッダは削除されます。これは、IPsec におけるトランスポートモードがトンネルモードと対照的に Host-to-Host の VPN 接続で使用することを想定しており、トランスポートモードで GRE パケットの IP ヘッダを省略することによってオーバーヘッドの削減、カプセル化に必要な計算リソースの低減を実現しているためです。
なお、一般的に GRE over IPsec はルーター同士で安全なチャネル (IPsec) を確立しつつ IPsec のトンネルモード (Layer 3 VPN) では使用できない IGP (EIGRP、OSPF、IS-IS、RIPv2 など) を使用するための仕組みとされます。
今回は、Linux の世界で用いられることがごく稀であるとされる GRE over IPsec を AWS 側では Debian + strongSwan の組み合わせで終端する一方、オンプレミスでは IOS ルーターで終端、かつトランスポートとして IPv6 を使用するアーキテクチャが有効であるか検証してみたいと思います。
なぜ Debian と strongSwan なのか
Amazon Linux 2 では Libreswan と呼ばれる IPsec 実装がサポートされますが、残念ながら Libreswan では IOS ルーターとの IPsec over IPv6 が期待通りに動作しません。strongSwan (スイス生まれ!) は Debian 系のディストリビューションで多用される IPsec 実装ですが、Libreswan より活発にメンテナンスが行われており、様々なシチュエーション (Host-to-HostかSite-to-Siteか、IKEv1かIKEv2か、IPv4かIPv6か...) で実際にテストされた設定例が公開されているのが利点です。Amazon Linux 2 でサポートされる IPsec 実装でないのが残念ですが、Debian の AMI は AWS Marketplace で提供される一方で ENA への対応もいち早く行われていることから今回は strongSwan を使って検証していきたいと思います。
検証
まず、通常の GRE トンネルを over IPv6 で作成します。Debian では以下の要領で行いましょう。なお、実は一番難しかったステップがここです (Linux における GRE over IPv6 構成例の少なさ!)
# ip -f inet6 tunnel add ip6gre4 mode ip6gre remote 2001:1620:1111:2222:3333:4444:5555:6666 local 2a05:d014:9c9:2100:9049:489e:d66e:41e9
# ip -f inet6 tunnel show ip6gre4
ip6gre4: gre/ipv6 remote 2001:1620:1111:2222:3333:4444:5555:6666 local 2a05:d014:9c9:2100:9049:489e:d66e:41e9 encaplimit 4 hoplimit 64 tclass 0x00 flowlabel 0x00000 (flowinfo 0x00000000)
# ip address add 169.254.123.1/30 dev ip6gre4
# ip address show dev ip6gre4
7: ip6gre4@NONE: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 8949 qdisc noqueue state UNKNOWN group default qlen 1
link/gre6 2a:05:d0:14:09:c9:21:00:90:49:48:9e:d6:6e:41:e9 peer 20:01:16:20:11:11:22:22:33:33:44:44:55:55:66:66
inet 169.254.123.1/30 scope global ip6gre4
valid_lft forever preferred_lft forever
# ip link set ip6gre4 up
# ip link show ip6gre4
7: ip6gre4@NONE: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 8949 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1
link/gre6 2a:05:d0:14:09:c9:21:00:90:49:48:9e:d6:6e:41:e9 peer 20:01:16:20:11:11:22:22:33:33:44:44:55:55:66:66
ip コマンドを使用して作成したトンネルインターフェイスは OS を再起動すると失われてしまうので、以下を /etc/network/interfaces に追加するのがおすすめです。ここが本当に難しかった... 探した中ではこのページが唯一、再起動を生き延びる GRE over IPv6 の設定例を示したページでした。
auto ip6gre4
iface ip6gre4 inet static
address 169.254.123.1/30
pre-up ip -family inet6 tunnel add ip6gre4 mode ip6gre remote 2001:1620:1111:2222:3333:4444:5555:6666 local 2a05:d014:9c9:2100:9049:489e:d66e:41e9
オンプレミスの IOS ルーターでも、以下の要領で GRE over IPv6 のトンネルを作成します。
!
interface Tunnel46
ip address 169.254.123.2 255.255.255.252
tunnel source 2001:1620:1111:2222:3333:4444:5555:6666
tunnel mode gre ipv6
tunnel destination 2A05:D014:9C9:2100:9049:489E:D66E:41E9
end
!
Debian の GRE インターフェイスへ ICMP Echos を送ります。問題なく疎通できていますね!
ip-10-189-112-1(config)#do ping 169.254.123.1
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 169.254.123.1, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 12/14/16 ms
GRE トンネルが用意できたので、GRE パケットを IPsec (ESP) でカプセル化すべく必要な設定を行います。ステップは以下の通りです。
- IPsec の Phase 1 SA に必要な Proposal を作成します。
- IPsec の Phase 1 SA に必要な Profile を作成します。
- IPsec の Phase 2 SA に必要な Transform-Set を作成します。
- Crypto Map で使用する Access-List を作成します。
- 物理インターフェイスに適用するための Crypto Map を作成します。
- 物理インターフェイスに Crypto Map を適用します。
まず、1から3を以下の要領で行います。既に IPsec 関連の設定が存在する場合、コンフリクトしないように注意しましょう。
!
crypto ikev2 proposal 10
encryption aes-cbc-128
integrity sha1
group 2
exit
!
crypto ikev2 profile 10
match address local 2001:1620:1111:2222:3333:4444:5555:6666
match identity remote address 2A05:D014:9C9:2100:97B7:D1BB:CF83:7B6D/128
identity local address 2001:1620:1111:2222:3333:4444:5555:6666
authentication remote pre-share key MyFavouriteMealIsRaclette
authentication local pre-share key MyFavouriteMealIsRaclette
lifetime 28800
exit
!
crypto ipsec transform-set 10 esp-aes esp-sha-hmac
mode tunnel
exit
!
次に、物理インターフェイス (今回は Dialer0) から Debian インスタンスへ向かう GRE パケットを ESP でカプセル化するような Crypto Map を用意します。
!
ipv6 access-list gre-over-ipsec-10
permit 47 host 2001:1620:1111:2222:3333:4444:5555:6666 host 2A05:D014:9C9:2100:97B7:D1BB:CF83:7B6D
exit
!
crypto map ipv6 gre-over-ipsec-10 local-address Dialer0
!
crypto map ipv6 gre-over-ipsec-10 10 ipsec-isakmp
set peer 2A05:D014:9C9:2100:97B7:D1BB:CF83:7B6D
set transform-set 10
set pfs group2
set ikev2-profile 10
match address gre-over-ipsec-10
exit
!
interface Dialer0
ipv6 crypto map gre-over-ipsec-10
exit
!
Debian インスタンスで strongSwan をインストールします。
# apt-get update
# apt-get install charon-systemd
# systemctl status strongswan-swanctl
● strongswan-swanctl.service - strongSwan IPsec IKEv1/IKEv2 daemon using swanctl
Loaded: loaded (/lib/systemd/system/strongswan-swanctl.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2019-02-15 13:39:37 UTC; 15s ago
Process: 8954 ExecStartPost=/usr/sbin/swanctl --load-all --noprompt (code=exited, status=0/SUCCESS)
Main PID: 8934 (charon-systemd)
Status: "charon-systemd running, strongSwan 5.5.1, Linux 4.9.0-8-amd64, x86_64"
Tasks: 17 (limit: 4915)
CGroup: /system.slice/strongswan-swanctl.service
└─8934 /usr/sbin/charon-systemd
strongSwan のインストール時に作成された設定例をバックップします。
# mv /etc/swanctl/swanctl.conf /etc/swanctl/swanctl.conf.original
新しい設定ファイルを作成します。
# nano /etc/swanctl/swanctl.conf
connections {
gw-gw {
local_addrs = 2a05:d014:9c9:2100:9049:489e:d66e:41e9
remote_addrs = 2001:1620:1111:2222:3333:4444:5555:6666
local {
auth = psk
id = 2a05:d014:9c9:2100:9049:489e:d66e:41e9
}
remote {
auth = psk
id = 2001:1620:1111:2222:3333:4444:5555:6666
}
children {
gre {
local_ts = dynamic[gre]
remote_ts = dynamic[gre]
mode = transport
updown = /usr/local/libexec/ipsec/_updown iptables
esp_proposals = aes128-sha1-modp1024
}
}
version = 2
proposals = aes128-sha1-modp1024
}
}
secrets {
ike-1 {
id-1a = 2a05:d014:9c9:2100:9049:489e:d66e:41e9
id-1b = 2001:1620:1111:2222:3333:4444:5555:6666
secret = MyFavouriteMealIsRaclette
}
}
作成した設定ファイルを strongSwan に読み込みます。
# swanctl --load-all
# swanctl --list-conns
gre-over-ipv6: IKEv2, no reauthentication, rekeying every 14400s
local: 2a05:d014:9c9:2100:9049:489e:d66e:41e9
remote: 2001:1620:1111:2222:3333:4444:5555:6666
local pre-shared key authentication:
id: 2a05:d014:9c9:2100:9049:489e:d66e:41e9
remote pre-shared key authentication:
id: 2001:1620:1111:2222:3333:4444:5555:6666
gre: TRANSPORT, rekeying every 3600s
local: dynamic[gre]
remote: dynamic[gre]
改めて ICMP Echos を送ってみます。きちんと通っていますね!
ip-10-189-112-1(config)#do ping 169.254.123.1
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 169.254.123.1, timeout is 2 seconds:
.!!!!
Success rate is 80 percent (4/5), round-trip min/avg/max = 12/14/16 ms
実際に GRE パケットが IPsec でカプセル化されていることを確認するには、show crypto ikev2 や show crypto ipsec が有効です。うっかり Crypto Map が外れて GRE パケットが平文でインターネットに流れることを心配する場合、セキュリティグループやアクセスリストで GRE パケットを拒否してしまうのが有効です。
ip-10-189-112-1(config)#do show crypto ikev2 session
IPv4 Crypto IKEv2 Session
IPv6 Crypto IKEv2 Session
Session-id:4, Status:UP-ACTIVE, IKE count:1, CHILD count:1
Tunnel-id fvrf/ivrf Status
1 none/none READY
Local 2001:1620:1111:2222:3333:4444:5555:6666/500
Remote 2A05:D014:9C9:2100:97B7:D1BB:CF83:7B6D/500
Encr: AES-CBC, keysize: 128, PRF: SHA1, Hash: SHA96, DH Grp:2, Auth sign: PSK, Auth verify: PSK
Life/Active Time: 28800/390 sec
Child sa: local selector 2001:1620:1111:2222:3333:4444:5555:6666/0 - 2001:1620:1111:2222:3333:4444:5555:6666/65535
remote selector 2A05:D014:9C9:2100:97B7:D1BB:CF83:7B6D/0 - 2A05:D014:9C9:2100:97B7:D1BB:CF83:7B6D/65535
ESP spi in/out: 0xE54FA0A2/0xCCA92CD0
せっかくなので、別のインスタンス (100.82.142.123) で起動した iperf3 と手元のホスト (10.189.10.6) で GRE over IPsec 経由のスループットを計ってみました!
$ ./iperf3 -f m -c 100.82.142.123 -P 4 -R
Connecting to host 100.82.142.123, port 5201
Reverse mode, remote host 100.82.142.123 is sending
[ 4] local 10.189.10.6 port 61728 connected to 100.82.142.123 port 5201
[ 6] local 10.189.10.6 port 61729 connected to 100.82.142.123 port 5201
[ 8] local 10.189.10.6 port 61730 connected to 100.82.142.123 port 5201
[ 10] local 10.189.10.6 port 61731 connected to 100.82.142.123 port 5201
[ ID] Interval Transfer Bandwidth
[ 4] 0.00-1.00 sec 1.76 MBytes 14.7 Mbits/sec
[ 6] 0.00-1.00 sec 950 KBytes 7.78 Mbits/sec
[ 8] 0.00-1.00 sec 991 KBytes 8.12 Mbits/sec
[ 10] 0.00-1.00 sec 1009 KBytes 8.27 Mbits/sec
[SUM] 0.00-1.00 sec 4.64 MBytes 38.9 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 1.00-2.00 sec 1.32 MBytes 11.1 Mbits/sec
[ 6] 1.00-2.00 sec 1.07 MBytes 8.98 Mbits/sec
[ 8] 1.00-2.00 sec 732 KBytes 6.00 Mbits/sec
[ 10] 1.00-2.00 sec 1.11 MBytes 9.34 Mbits/sec
[SUM] 1.00-2.00 sec 4.22 MBytes 35.4 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 2.00-3.00 sec 1.43 MBytes 12.0 Mbits/sec
[ 6] 2.00-3.00 sec 722 KBytes 5.92 Mbits/sec
[ 8] 2.00-3.00 sec 671 KBytes 5.49 Mbits/sec
[ 10] 2.00-3.00 sec 842 KBytes 6.90 Mbits/sec
[SUM] 2.00-3.00 sec 3.61 MBytes 30.3 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 3.00-4.00 sec 1.21 MBytes 10.1 Mbits/sec
[ 6] 3.00-4.00 sec 911 KBytes 7.47 Mbits/sec
[ 8] 3.00-4.00 sec 1.21 MBytes 10.1 Mbits/sec
[ 10] 3.00-4.00 sec 1.43 MBytes 12.0 Mbits/sec
[SUM] 3.00-4.00 sec 4.74 MBytes 39.8 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 4.00-5.00 sec 1.20 MBytes 10.1 Mbits/sec
[ 6] 4.00-5.00 sec 1.31 MBytes 11.0 Mbits/sec
[ 8] 4.00-5.00 sec 1.51 MBytes 12.7 Mbits/sec
[ 10] 4.00-5.00 sec 1.71 MBytes 14.4 Mbits/sec
[SUM] 4.00-5.00 sec 5.73 MBytes 48.1 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 5.00-6.00 sec 1.24 MBytes 10.4 Mbits/sec
[ 6] 5.00-6.00 sec 940 KBytes 7.70 Mbits/sec
[ 8] 5.00-6.00 sec 1.54 MBytes 12.9 Mbits/sec
[ 10] 5.00-6.00 sec 1.06 MBytes 8.89 Mbits/sec
[SUM] 5.00-6.00 sec 4.76 MBytes 39.9 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 6.00-7.00 sec 1.08 MBytes 9.08 Mbits/sec
[ 6] 6.00-7.00 sec 790 KBytes 6.47 Mbits/sec
[ 8] 6.00-7.00 sec 1.44 MBytes 12.1 Mbits/sec
[ 10] 6.00-7.00 sec 835 KBytes 6.84 Mbits/sec
[SUM] 6.00-7.00 sec 4.11 MBytes 34.5 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 7.00-8.00 sec 748 KBytes 6.10 Mbits/sec
[ 6] 7.00-8.00 sec 918 KBytes 7.49 Mbits/sec
[ 8] 7.00-8.00 sec 1.31 MBytes 11.0 Mbits/sec
[ 10] 7.00-8.00 sec 1.22 MBytes 10.2 Mbits/sec
[SUM] 7.00-8.00 sec 4.16 MBytes 34.8 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 8.00-9.00 sec 1.06 MBytes 8.92 Mbits/sec
[ 6] 8.00-9.00 sec 1.10 MBytes 9.23 Mbits/sec
[ 8] 8.00-9.00 sec 1.38 MBytes 11.6 Mbits/sec
[ 10] 8.00-9.00 sec 1.42 MBytes 11.9 Mbits/sec
[SUM] 8.00-9.00 sec 4.95 MBytes 41.7 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 9.00-10.00 sec 1.28 MBytes 10.7 Mbits/sec
[ 6] 9.00-10.00 sec 1.10 MBytes 9.20 Mbits/sec
[ 8] 9.00-10.00 sec 1.18 MBytes 9.86 Mbits/sec
[ 10] 9.00-10.00 sec 1.51 MBytes 12.7 Mbits/sec
[SUM] 9.00-10.00 sec 5.06 MBytes 42.4 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bandwidth Retr
[ 4] 0.00-10.00 sec 12.5 MBytes 10.5 Mbits/sec 117 sender
[ 4] 0.00-10.00 sec 12.5 MBytes 10.5 Mbits/sec receiver
[ 6] 0.00-10.00 sec 9.84 MBytes 8.26 Mbits/sec 99 sender
[ 6] 0.00-10.00 sec 9.84 MBytes 8.26 Mbits/sec receiver
[ 8] 0.00-10.00 sec 12.1 MBytes 10.2 Mbits/sec 101 sender
[ 8] 0.00-10.00 sec 12.1 MBytes 10.2 Mbits/sec receiver
[ 10] 0.00-10.00 sec 12.2 MBytes 10.3 Mbits/sec 74 sender
[ 10] 0.00-10.00 sec 12.2 MBytes 10.3 Mbits/sec receiver
[SUM] 0.00-10.00 sec 46.7 MBytes 39.2 Mbits/sec 391 sender
[SUM] 0.00-10.00 sec 46.7 MBytes 39.2 Mbits/sec receiver
iperf Done.
すごく遅い...
結論
GRE over IPsec は Linux と IOS ルーター、IPv6 トランスポートの組み合わせでもきちんと動くことがわかりました。ただしエントリークラスのルーター (890 Series ISR) では 40 Mbps 程度のスループットしか出ないことがわかったので、IPsec は Linux VM などで終端することを考えたいと思います。
したっけまた!
謝辞
今回の検証にあたり、以下を参考にさせていただきました。この場を借りて心から御礼申し上げます。
IT Blogtorials: Decrypt IPsec packets - Linux to Cisco VPN http://ithitman.blogspot.com/2012/05/how-to-decrypt-ipsec-packets.html
Decrypting ESP payloads using Wireshark - Fortinet Cookbook
[hsmr] Hackspace Marburg · Freifunk/IC Peering Konfiguration https://hsmr.cc/Freifunk/ICPeeringKonfiguration
Route-based VPNs - strongSwan https://wiki.strongswan.org/projects/strongswan/wiki/RouteBasedVPN
Security for VPNs with IPsec Configuration Guide, Cisco IOS Release 15M&T - Cisco https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/sec_conn_vpnips/configuration/15-mt/sec-sec-for-vpns-w-ipsec-15-mt-book.html
Point-to-Point GRE over IPsec Design Guide - Preface [Design Zone for IPv6] - Cisco https://www.cisco.com/c/en/us/td/docs/solutions/Enterprise/WAN_and_MAN/P2P_GRE_IPSec/P2P_GRE/p2pGREPf.html
CCIE Routing & Switching v5.1 Advanced Technologies - INE https://streaming.ine.com/c/route-switch-atc