[AWS] Site-to-Site VPNを使ってFortigateとオンプレ接続

AWSAWS,Fortigate,VPN

はじめに

AWSとオンプレ環境を安価に接続できるSit-to-Site VPNの構築について説明します。オンプレ側(カスタマー側)のVPN装置はFortigateです。FortigateはGUIではなくCLIで構築します。

Site-to-Site VPNは、AWSとオンプレ間のルーティングにスタティックルーティングとBGPの二種を選択することが可能です。今回はシングル構成のためスタティックルートでも問題はありませんが、一般的な本番環境の場合は回線冗長を行い片系に障害が発生してもBGPにて自動切り替わりするように設計します。そのため、今回はテスト的にBGPで構築します。

構成

構築開始時点の構成は下記の通りとなります。基本的なVPCやサブネット、EC2インスタンス等、またオンプレ側のFortigateは構築済みとします。

下図は今回の構築後の構成となり、オンプレ~AWSのVPN構築が対象となります。

早速ですが以降で設定方法について説明します。

設定(AWS)

AWS カスタマーゲートウェイの設定

『VPC』から、「仮想プライベートネットワーク (VPN)」>「カスタマーゲートウェイ」>「仮想プライベートゲートウェイを作成」を選択します。

「カスタマーゲートウェイを作成」の画面が表示されたら下図のようにパラメーターを入力します。
「BGP ASN」は4バイト形式が可能なので当方は2100000001としました。こちらのASNは後にFortigateのBGPで設定するASNです。
「IPアドレス」はFortigateのWAN側インタフェースのアドレスを指定します。(IPsecの終端IPアドレス)
全ての入力が完了したら、「カスタマーゲートウェイを作成」を押し完了させます。

「Available」になることを確認します。

仮想プライベートゲートウェイ

次に「仮想プライベートネットワーク (VPN)」>「仮想プライベートゲートウェイ」>「仮想プライベートゲートウェイを作成」を選択します。

「仮想プライベートゲートウェイを作成」の画面が表示されたら下図のようにパラメーターを入力していきます。
「カスタムASNの入力」があり、AmazonデフォルトASNでも問題はありませんが、当方はAS番号を管理したいのでカスタムASNを選択し、4200000001としました。こちらはAWS側のBGPで使用されるASNとなります。
入力が完了したら、「仮想プライベートゲートウェイを作成」を押し完了させます。

作成した仮想プライベートゲートウェイをVPNにアタッチします。

アタッチされると状態が「Attached」になります。

Site-to-Site VPN 接続

次に「仮想プライベートネットワーク (VPN)」>「Site-to-Site VPN 接続」>「VPN 接続を作成する」を選択します。

「VPN接続を作成する」の画面が表示されたら下図のようにパラメーターを入力/選択していきます。
「ターゲットゲートウェイのタイプ」と「カスタマーゲートウェイ」では上記で作成した二つを指定します。
「ルーティングオプション」はBGPを使用するので「動的(BGPが必要)」を選択します。
その他はデフォルトで「VPN接続を作成する」を押し完了させます。

ここまで進めるとAWS側のステータスが確認できます。先ほど作成した「vpn01」を選択し、「トンネルの詳細」を参照してみます。
トンネルは2本用意されるためTunnnel1とTunnel2が存在します。
「外部IPアドレス」がAWS側がIPsecを終端するIPアドレスです。
「内部IPv4CIDR」がトンネルインタフェースに設定するネットワークアドレスです。またBGPのネイバーアドレスとしても使用されます。
「ステータス」はVPNとBGPの状態を表します。

ルートテーブルのルート伝播

今回はBGPでルーティングをさせるため、予めVPCに割り当てている(またはサブネットに関連付けをしている)ルートテーブルにてルート伝播を設定します。

本設定を行うことで、仮想プライベートゲートウェイがBGPでオンプレ側のルート情報(192.168.0.0/24)を学習した後に、仮想プライベートゲートウェイから当該ルートテーブルにルート情報が伝播され、ルーティングが自動でインストールされます。

ルート伝播の設定は以上です。

構築

設定(オンプレ Fortigate)

続けてFortigate側の設定を行いますが、その前に、AWS側でSite-to-Site VPNの設定を完了させると各ベンダーのサンプルコンフィグと設定手順がセットになったテキストをダウンロードできます。カスタマーゲートウェイや仮想プライベートゲートウェイで入力した値が反映されたサンプルコンフィグであり設定作業に活用すると便利なのでダウンロードします。

残念ながらあらゆる機種/バージョン用のコンフィグは用意されていません。そのため、機種やOSバージョンによっては不完全なコンフィグとなっているので環境に沿った多少の改変が必要です。今回はサンプルコンフィグの説明は省き、当方が投入し問題なくVPN+BGPが動作したコンフィグを紹介します。(ベースはサンプルコンフィグです)

config vpn ipsec phase1-interface
    edit "P1_AWS-vpn1-T1"
        set interface "wan1"
        set local-gw 61.26.71.188
        set keylife 28800
        set peertype any
        set proposal aes256-sha256
        set dpd on-idle
        set dhgrp 2
        set nattraversal disable
        set remote-gw 35.75.134.253
        set psksecret *********************     ★サンプルコンフィグに記載あり
        set dpd-retryinterval 10
    next
    edit "P1_AWS-vpn1-T2"
        set interface "wan1"
        set local-gw 61.26.71.188
        set keylife 28800
        set peertype any
        set proposal aes256-sha256
        set dpd on-idle
        set dhgrp 2
        set nattraversal disable
        set remote-gw 54.150.121.161
        set psksecret *********************     ★サンプルコンフィグに記載あり
        set dpd-retryinterval 10
    next
end

config vpn ipsec phase2-interface
    edit "P2_AWS-vpn1-T1"
        set phase1name "P1_AWS-vpn1-T1"
        set proposal aes256-sha256
        set dhgrp 2
        set keepalive enable
        set keylifeseconds 3600
    next
    edit "P2_AWS-vpn1-T2"
        set phase1name "P1_AWS-vpn1-T2"
        set proposal aes256-sha256
        set dhgrp 2
        set keepalive enable
        set keylifeseconds 3600
    next
end

config system interface
    edit "P1_AWS-vpn1-T1"
        set vdom "root"
        set ip 169.254.244.158 255.255.255.255
        set allowaccess ping
        set type tunnel
        set tcp-mss 1379
        set remote-ip 169.254.244.157 255.255.255.252
        set snmp-index 15
        set interface "wan1"
    next
    edit "P1_AWS-vpn1-T2"
        set vdom "root"
        set ip 169.254.218.34 255.255.255.255
        set allowaccess ping
        set type tunnel
        set tcp-mss 1379
        set remote-ip 169.254.218.33 255.255.255.252
        set snmp-index 17
        set interface "wan1"
    next
end

config router access-list
    edit "ACL-192.168.0.0/24"
        config rule
            edit 1
                set prefix 192.168.0.0 255.255.255.0
                set exact-match enable
            next
        end
    next
end
config router aspath-list
    edit "ASP_LIST1"
        config rule
            edit 1
                set action permit
                set regexp "_4200000001_"
            next
        end
    next
end

config router route-map
    edit "RM_IN_1"
        config rule
            edit 1
                set match-as-path "ASP_LIST1"
                set set-local-preference 200
            next
        end
    next
    edit "RM_IN_2"
        config rule
            edit 1
                set match-as-path "ASP_LIST1"
                set set-local-preference 150
            next
        end
    next
    edit "RM_OUT_2"
        config rule
            edit 1
                set match-ip-address "ACL-192.168.0.0/24"
                set set-aspath "2100000901" "2100000902"
            next
        end
    next
end

config router bgp
    set as 2100000001
    set router-id 61.26.71.188
    set keepalive-timer 10
    set holdtime-timer 30
    config neighbor
        edit "169.254.244.157"
            set remote-as 4200000001
            set route-map-in "RM_IN_2"
        next
        edit "169.254.218.33"
            set soft-reconfiguration enable
            set remote-as 4200000001
            set route-map-in "RM_IN_1"
            set route-map-out "RM_OUT_2"
        next
    end
    config network
        edit 1
            set prefix 192.168.0.0 255.255.255.0
        next
    end
end

config firewall policy
    edit 201
        set name "ALL<--AWS"
        set srcintf "P1_AWS-vpn1-T1" "P1_AWS-vpn1-T2"
        set dstintf "any"
        set srcaddr "all"
        set dstaddr "all"
        set action accept
        set schedule "always"
        set service "ALL"
    next
    edit 202
        set name "ALL-->AWS"
        set srcintf "any"
        set dstintf "P1_AWS-vpn1-T1" "P1_AWS-vpn1-T2"
        set srcaddr "all"
        set dstaddr "all"
        set action accept
        set schedule "always"
        set service "ALL"
    next
end

BGPの設定について補足します。今回、Tunnelとしては1と2の2本構成です。それぞれTunnel毎にBGPネイバーを張るので、Active/Standby構成となります。(Active/Activeにすると通信の行きと戻りで違うTunnelを通る可能性があります。今回のFortigateのようにFirewall製品をVPN装置にすると行きと戻りが変わるとステートフルインスペクションが効き通信できません)

Active/Standbyの設計ですが、AWSのBGPは「AS_PATHプリペンド」「Local Preference」のパス属性を使って経路制御を行います。

「AS_PATHプリペンド」はオンプレのルート情報(192.168.0.0/24)を「オンプレからAWSに広報するルート」に対しASパスとして遠く見させることでStanby経路とさせます。今回は、「192.168.0.0/24」ルートを広報するときはASパス「"2100000901″ “2100000902"」を追加して広報する設定をしています。

「Local Preference」はAWSのルート情報(10.1.0.0/16)を「AWSからオンプレに広報されてくるルート」に対して優先度をつける設定になります。今回は、Tunnel1から「ASN:4200000001」が含まれているルート情報を受信した場合「値200」、Tunnel2から同様のルート情報を受信した場合は「値150」を付ける、という設定を行い、通常であればTunnel1をActiveとし、Tunnele2をStandbyにしています。

参考までに受信ルートと広報ルートを載せときます。

■受信ルート

FGT60D # get router info bgp network
BGP table version is 37, local router ID is 61.26.71.188
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              S Stale
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight RouteTag Path
*> 10.1.0.0/16      169.254.218.33         200    200      0        0 4200000001 i
*                   169.254.244.157        100    150      0        0 4200000001 i
*> 192.168.0.0      0.0.0.0                       100  32768        0 i

Total number of prefixes 2
■Tunnel1の広報ルート

FGT60D # get router info bgp neighbors 169.254.244.157 advertised-routes
BGP table version is 37, local router ID is 61.26.71.188
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight RouteTag Path
*> 10.1.0.0/16      169.254.244.158               200      0        0 4200000001 i
*> 192.168.0.0      169.254.244.158               100  32768        0 i

Total number of prefixes 2
■Tunnel2の広報ルート

FGT60D # get router info bgp neighbors 169.254.218.33 advertised-routes
BGP table version is 37, local router ID is 61.26.71.188
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight RouteTag Path
*> 192.168.0.0      169.254.218.34                100  32768        0 2100000901 2100000902 i

Total number of prefixes 1

Fortigate側の設定変更は以上です。

ステータス確認(VPNとBGP)

AWS側のステータス確認

『VPC』から、「仮想プライベートネットワーク (VPN)」>「Site-to-Site VPN 接続」を選択し、先ほど作成した「vpn01」を選択します。
VPNとBGPが正常の場合ステータスが「Up」となり、詳細が「1 BGP ROUTES」となります。

続いてルートテーブルを選択し、仮想プライベートゲートウェイからオンプレ環境のルート情報を学習していることを確認します。(192.168.0.0/24のルートが表示されていること)

Fortigateのステータス確認

続いてFortigate側のステータスを確認していきます。

 - diagnose vpn ike gateway list … IKEの状態確認です。IKEの接続が行われていると以下のように表示されます。
 - diagnose vpn tunnel list … VPN接続が正常の場合、中段にある「SA:」行より下の項目が表示されるようになります。

FGT60D # diagnose vpn ike gateway list

vd: root/0
name: P1_AWS-vpn1-T1
version: 1
interface: wan1 5
addr: 61.26.71.188:500 -> 35.75.134.253:500
virtual-interface-addr: 169.254.244.158 -> 169.254.244.157
created: 97s ago
IKE SA: created 1/1  established 1/1  time 20/20/20 ms
IPsec SA: created 1/1  established 1/1  time 10/10/10 ms

  id/spi: 1033 20d8355009e10b62/c747807e667e2dfb
  direction: initiator
  status: established 97-96s ago = 20ms
  proposal: aes256-sha256
  key: 3a98944f9fc8e679-7e9b226f40603975-1894a5dd2cad6bce-309a8c12df9853c1
  lifetime/rekey: 28800/28403
  DPD sent/recv: 00000004/234cbd2d

vd: root/0
name: P1_AWS-vpn1-T2
version: 1
interface: wan1 5
addr: 61.26.71.188:500 -> 54.150.121.161:500
virtual-interface-addr: 169.254.218.34 -> 169.254.218.33
created: 97s ago
IKE SA: created 1/1  established 1/1  time 20/20/20 ms
IPsec SA: created 1/1  established 1/1  time 10/10/10 ms

  id/spi: 1034 07ccf56926072fb6/9aa20ac3255b43ec
  direction: initiator
  status: established 97-96s ago = 20ms
  proposal: aes256-sha256
  key: ea53a3ea1ae00772-7130cdcfcb4ea762-5470c7475ed7eb68-502d44849c0c8841
  lifetime/rekey: 28800/28403
  DPD sent/recv: 00000004/1506db74

FGT60D #

FGT60D # diagnose vpn tunnel list
------------------------------------------------------
name=P1_AWS-vpn1-T1 ver=1 serial=6 61.26.71.188:0->35.75.134.253:0
bound_if=5 lgwy=static/1 tun=intf/0 mode=auto/1 encap=none/8 options[0008]=npu
proxyid_num=1 child_num=0 refcnt=6 ilast=0 olast=0 ad=/0
stat: rxp=1 txp=1 rxb=124 txb=60
dpd: mode=on-idle on=1 idle=10000ms retry=3 count=0 seqno=6
natt: mode=none draft=0 interval=0 remote_port=0
proxyid=P2_AWS-vpn1-T1 proto=0 sa=1 ref=2 serial=1
  src: 0:0.0.0.0/0.0.0.0:0
  dst: 0:0.0.0.0/0.0.0.0:0
  SA:  ref=6 options=10227 type=00 soft=0 mtu=1358 expire=3215/0B replaywin=1024
       seqno=17 esn=0 replaywin_lastseq=00000001 itn=0
  life: type=01 bytes=0/0 timeout=3303/3600
  dec: spi=ba4eece7 esp=aes key=32 2dad952128c494a9de9dbd9bd4b90f595599a83c59b0e1913b6f030acb685295
       ah=sha256 key=32 b110aa3cece99c2712f0986bc6d1a6ad9b55da091d1df8b457eb2495796046e5
  enc: spi=c40ec561 esp=aes key=32 16f60d0490d676a2cf3a83ced6a2b00dc5721037c7700b8c8aa90665b00ee3a7
       ah=sha256 key=32 3134db492e47d05fdeec7bf563195190876d2ba43fdd34d1c0ca5f9758077e2b
  dec:pkts/bytes=1/60, enc:pkts/bytes=22/3032
  npu_flag=03 npu_rgwy=35.75.134.253 npu_lgwy=61.26.71.188 npu_selid=6
------------------------------------------------------
name=P1_AWS-vpn1-T2 ver=1 serial=7 61.26.71.188:0->54.150.121.161:0
bound_if=5 lgwy=static/1 tun=intf/0 mode=auto/1 encap=none/8 options[0008]=npu
proxyid_num=1 child_num=0 refcnt=6 ilast=1 olast=1 ad=/0
stat: rxp=1 txp=1 rxb=124 txb=60
dpd: mode=on-idle on=1 idle=10000ms retry=3 count=0 seqno=4
natt: mode=none draft=0 interval=0 remote_port=0
proxyid=P2_AWS-vpn1-T2 proto=0 sa=1 ref=2 serial=1
  src: 0:0.0.0.0/0.0.0.0:0
  dst: 0:0.0.0.0/0.0.0.0:0
  SA:  ref=6 options=10227 type=00 soft=0 mtu=1358 expire=3214/0B replaywin=1024
       seqno=1d esn=0 replaywin_lastseq=00000001 itn=0
  life: type=01 bytes=0/0 timeout=3301/3600
  dec: spi=ba4eece8 esp=aes key=32 8a2500d622f863b785023850ffa03c8f23ddcacb4387398fe4a166c72e13e7b5
       ah=sha256 key=32 b24f59d76728fd3e8a0f1fdb663394257fd551b53bcf9def0dd403361173fb8c
  enc: spi=ccab7328 esp=aes key=32 c73f9f1fb27c2eab8a5d165886a3391c7ec1c6018249792124e8ef1f4c755f71
       ah=sha256 key=32 c15211347b1e7807ef8fe6a64478f06a265e2d3b91def77409e89749e6b34a3c
  dec:pkts/bytes=1/60, enc:pkts/bytes=28/3792
  npu_flag=03 npu_rgwy=54.150.121.161 npu_lgwy=61.26.71.188 npu_selid=7

FGT60D #

 - get router info bgp summary … 正常の場合、各ネイバーのUp時間が表示され、State/PfxRcdが1(または1以上の整数)になります。

FGT60D # get router info bgp summary
BGP router identifier 61.26.71.188, local AS number 2100000001
BGP table version is 4
2 BGP AS-PATH entries
0 BGP community entries

Neighbor        V         AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
169.254.218.33  4 4200000001      19      19        3    0    0 00:02:16        1
169.254.244.157 4 4200000001      15      17        3    0    0 00:01:57        1

Total number of neighbors 2


FGT60D #

 - get router info routing-table all … VPCの10.1.0.0/16をBGPで学習していることを確認します。

FGT60D # get router info routing-table all

Routing table for VRF=0
Codes: K - kernel, C - connected, S - static, R - RIP, B - BGP
       O - OSPF, IA - OSPF inter area
       N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2
       E1 - OSPF external type 1, E2 - OSPF external type 2
       i - IS-IS, L1 - IS-IS level-1, L2 - IS-IS level-2, ia - IS-IS inter area
       * - candidate default

S*      0.0.0.0/0 [5/0] via 61.26.71.129, wan1
B       10.1.0.0/16 [20/100] via 169.254.244.157, P1_AWS-vpn1-T1, 00:04:07
C       61.26.71.128/25 is directly connected, wan1
C       169.254.218.32/30 is directly connected, P1_AWS-vpn1-T2
C       169.254.218.34/32 is directly connected, P1_AWS-vpn1-T2
C       169.254.244.156/30 is directly connected, P1_AWS-vpn1-T1
C       169.254.244.158/32 is directly connected, P1_AWS-vpn1-T1
S       192.168.0.0/16 [10/0] is directly connected, P1_IPSEC_RTX
C       192.168.0.0/24 is directly connected, internal1


FGT60D #

疎通確認と障害試験

疎通確認

続けてオンプレの環境からpingとssh確認をします。

C:\Users\ktrwa>ping 10.1.1.100

10.1.1.100 に ping を送信しています 32 バイトのデータ:
10.1.1.100 からの応答: バイト数 =32 時間 =20ms TTL=253
10.1.1.100 からの応答: バイト数 =32 時間 =19ms TTL=253
10.1.1.100 からの応答: バイト数 =32 時間 =15ms TTL=253
10.1.1.100 からの応答: バイト数 =32 時間 =14ms TTL=253

10.1.1.100 の ping 統計:
    パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 14ms、最大 = 20ms、平均 = 17ms

C:\Users\ktrwa>

障害試験

AWSのSite-to-Site VPNは先述の通りTunnelを2本張ってBGPでルーティングさせています。そのため、片方のTunnelが落ちてももう片方のTunnelで通信が継続するはずです。
早速ですが、Tunnel1のインタフェースをdownさせ疑似障害を発生させ通信が継続するか確認します。

FGT60D # config system interface
<省略>
FGT60D (interface) #
FGT60D (interface) #     edit "P1_AWS-vpn1-T1"

FGT60D (P1_AWS-vpn1-T1) # set status down

FGT60D (P1_AWS-vpn1-T1) # end

FGT60D #

ルーティングテーブルを参照すると、10.1.0.0/16のルート情報はBGPで学習していますが、出力インタフェースが「P1_AWS-vpn1-T2」となり、Tunnel2になっています。(先ほどの正常時「P1_AWS-vpn1-T1」でTunnel1でした)

FGT60D # get router info routing-table all

Routing table for VRF=0
Codes: K - kernel, C - connected, S - static, R - RIP, B - BGP
       O - OSPF, IA - OSPF inter area
       N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2
       E1 - OSPF external type 1, E2 - OSPF external type 2
       i - IS-IS, L1 - IS-IS level-1, L2 - IS-IS level-2, ia - IS-IS inter area
       * - candidate default

S*      0.0.0.0/0 [5/0] via 61.26.71.129, wan1
B       10.1.0.0/16 [20/100] via 169.254.218.33, P1_AWS-vpn1-T2, 00:01:05
C       61.26.71.128/25 is directly connected, wan1
C       169.254.218.32/30 is directly connected, P1_AWS-vpn1-T2
C       169.254.218.34/32 is directly connected, P1_AWS-vpn1-T2
S       192.168.0.0/16 [10/0] is directly connected, P1_IPSEC_RTX
C       192.168.0.0/24 is directly connected, internal1


FGT60D #

一応、AWSのSite-to-Site VPNで状態を確認したところ、片側はDown状態であることが確認できます。

この状態で、オンプレのクライアントからpingとsshで疎通確認をしてみると問題ありません。

C:\Users\ktrwa>ping 10.1.1.100

10.1.1.100 に ping を送信しています 32 バイトのデータ:
10.1.1.100 からの応答: バイト数 =32 時間 =17ms TTL=253
10.1.1.100 からの応答: バイト数 =32 時間 =18ms TTL=253
10.1.1.100 からの応答: バイト数 =32 時間 =17ms TTL=253
10.1.1.100 からの応答: バイト数 =32 時間 =16ms TTL=253

10.1.1.100 の ping 統計:
    パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 16ms、最大 = 18ms、平均 = 17ms

C:\Users\ktrwa>

以上で片方のTunnelが落ちても通信が問題ないことが確認できました。(当然ではありますがFortigate側のインターネット回線が落ちてしまった場合はTunnel1も2も落ちるため通信不可となります。)

まとめ

以上がSite-to-Site VPNを使った構築手順でした。AWS側のGUIが非常にわかりやすく作られており、エンタープライズ系の製品にてVPNを設計したことのある方ならすぐにでも構築ができると思います。また、サンプルコンフィグをダウンロードすることでカスタマーの負荷を減らし工数の削減に繋がるつくりになっておりオンプレ側の方も非常に簡単に構築ができました。

今後は別の記事にてトランジットゲートウェイの構築や今回構築したVPNとの連携なども記事にしていこうと思います。