本当に動く!? IPv6 で GRE over IPsec を試す

2019.02.15

この記事は公開されてから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) でカプセル化すべく必要な設定を行います。ステップは以下の通りです。

  1. IPsec の Phase 1 SA に必要な Proposal を作成します。
  2. IPsec の Phase 1 SA に必要な Profile を作成します。
  3. IPsec の Phase 2 SA に必要な Transform-Set を作成します。
  4. Crypto Map で使用する Access-List を作成します。
  5. 物理インターフェイスに適用するための Crypto Map を作成します。
  6. 物理インターフェイスに 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

Decrypting ESP payloads using Wireshark

[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