AWS Site-to-Site VPNでオンプレミスとVPCをセキュアに接続する方法|Customer GatewayとVGW・BGPフェイルオーバー設計の実践手順

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)AWS(Amazon Linux) > AWS Site-to-Site VPNでオンプレミスとVPCをセキュアに接続する方法|Customer GatewayとVGW・BGPフェイルオーバー設計の実践手順
「社内の監視サーバーからAWSのEC2にSSHしたいのに、インターネット越しはセキュリティ的にNGと言われた」
AWSを本番環境として本格活用しはじめると、必ず突き当たるのがこの壁です。オンプレミスの開発環境・監視ツール・CI/CDパイプラインとVPCを安全につなぎたい——そのニーズを実現するのが、AWSのSite-to-Site VPNです。

この記事では、オンプレミスネットワークとAWS VPCをIPsec VPNで暗号化接続するSite-to-Site VPNの仕組み・構成手順・BGPによる2本トンネルの自動フェイルオーバー設計まで、AWS CLIを使って実践的に解説します。Amazon Linux 2023 / RHEL 9.4で動作確認しています。

この記事のポイント

・Site-to-Site VPNは1つのVPN接続に2本のIPsecトンネルを持ち、AWSが冗長性を提供する
・BGPを使えばトンネル障害時に自動で経路切り替えが起きる(静的ルーティングは手動対応が必要)
・CGW・VGW・VPN接続の3ステップをCLIで構成しルート伝播で経路をVPCに伝える
・VpwTelemetryのStatusとAcceptedRouteCountでトンネルとBGPの状態を最初に確認する


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

なぜSite-to-Site VPNが必要なのか(ハイブリッドクラウド構成の現場要件)

AWSに本番環境を移行しても、すべてがクラウド上に移るわけではありません。実際の現場では次のような構成が頻繁に登場します。

・社内のオンプレミス監視サーバー(Zabbix・Prometheusなど)からAWS上のEC2を監視したい
・JenkinsなどのCI/CDツールがオンプレミスにあり、AWSのデプロイ先にSSHでアクセスしたい
・オンプレミスのデータベースとAWSのアプリケーションサーバー間でプライベートIPで通信したい
・セキュリティポリシー上、サーバーの管理アクセスはインターネット経由を禁止している

これらの要件を満たす方法として、AWSは大きく2つを提供しています。

Site-to-Site VPN: インターネット上にIPsec暗号化トンネルを張る。初期費用0円、時間単価の課金。最大帯域幅は1.25Gbps。構築が簡単で数時間で使い始められる
AWS Direct Connect: 物理専用線でAWSデータセンターと接続する。低レイテンシ・安定帯域が得られるが、契約から開通まで数ヶ月かかり月額数万円以上の固定費が発生する

開発・テスト環境や中小規模の本番構成では、まずSite-to-Site VPNで始めて必要に応じてDirect Connectへ移行するのが現実的な判断です。Direct ConnectにVPNをフェイルオーバー経路として組み合わせるパターンも実務では多く見られます。

Site-to-Site VPNの構成要素と2本トンネルの冗長設計

Site-to-Site VPNを理解するには、3つのコンポーネントを正確に把握することが重要です。

Customer Gateway(CGW): オンプレミス側のVPNルーター(またはソフトウェアVPN)の情報をAWSに登録したリソース。パブリックIPアドレスとBGP ASNを指定する。実体はオンプレ側のデバイスであり、AWSにはその「参照情報」が登録される
Virtual Private Gateway(VGW): AWS側のVPNエンドポイント。VPCにアタッチして使う。複数VPCや複数オンプレ拠点をまとめてつなぐ場合はTransit Gatewayと組み合わせる
VPN接続(VPN Connection): CGWとVGWを紐付けたVPN接続リソース。AWSは1つのVPN接続に対して、2本のIPsecトンネルを自動的に作成する。この2本は互いに異なるAWS側エンドポイントIPに接続されており、一方のAWSエンドポイントで障害が起きても、もう一方のトンネルを通じて通信が維持される

この「1接続=2トンネル」という設計がSite-to-Site VPNの冗長性の核心です。オンプレ側のルーターは両方のトンネルを確立しておき、通常は両方でBGP経路を交換します。一方のトンネルが障害でDOWNするとBGPセッションも切れ、そのトンネル経由の経路が自動で撤退(Withdraw)されます。残った1本のトンネルを通じて経路が維持されるため、フェイルオーバーが自動で起きます。

AWSが各トンネルに割り当てるIPアドレスは「Outside IP(トンネル外側IPアドレス)」として、VPN接続作成後にCLIで確認できます。BGP通信用の「Inside IP(トンネル内側のリンクローカルアドレス)」はデフォルトで169.254.x.x/30の範囲から自動割り当てされます。

AWS CLIでSite-to-Site VPNを構成する手順

前提として、以下が準備されているものとします。
・VPC(例: 10.0.0.0/16、vpc-0a1b2c3d4e5f6)
・オンプレミス側のルーターが持つ固定パブリックIPアドレス(例: 203.0.113.10)
・オンプレミス側に割り当てるBGP ASN(例: 65000。Private ASNは64512~65534の範囲)

1. Customer Gateway(CGW)を作成する

Customer GatewayはオンプレミスルーターのパブリックIPとBGP ASNをAWSに登録するだけです。

# Customer Gatewayを作成する(オンプレ側のパブリックIPとASNを指定) $ aws ec2 create-customer-gateway \ --type ipsec.1 \ --bgp-asn 65000 \ --public-ip 203.0.113.10 \ --tag-specifications 'ResourceType=customer-gateway,Tags=[{Key=Name,Value=onprem-cgw}]' { "CustomerGateway": { "CustomerGatewayId": "cgw-0a1b2c3d4e5f60001", "IpAddress": "203.0.113.10", "BgpAsn": "65000", "State": "available", "Type": "ipsec.1", "Tags": [{"Key": "Name", "Value": "onprem-cgw"}] } } # 作成されたCGWを一覧で確認する $ aws ec2 describe-customer-gateways \ --customer-gateway-ids cgw-0a1b2c3d4e5f60001 \ --query 'CustomerGateways[*].[CustomerGatewayId,IpAddress,BgpAsn,State]' \ --output table +------------------------+--------------+-------+-----------+ | cgw-0a1b2c3d4e5f60001 | 203.0.113.10 | 65000 | available | +------------------------+--------------+-------+-----------+

BGP ASNはオンプレ側のルーターに設定するASNです。AWS VGW側は指定しない場合デフォルトで64512が使われますが、VGW作成時に`--amazon-side-asn`で任意のPrivate ASNを指定することもできます。

注意点として、CGWのIPアドレスにはNATデバイスの背後にある場合のプライベートIPは使えません。インターネットに向けて開かれた固定のパブリックIPが必要です。

2. Virtual Private GatewayをVPCにアタッチする

次にAWS側のVPNエンドポイントであるVirtual Private Gateway(VGW)を作成し、VPCにアタッチします。

# Virtual Private Gatewayを作成する $ aws ec2 create-vpn-gateway \ --type ipsec.1 \ --tag-specifications 'ResourceType=vpn-gateway,Tags=[{Key=Name,Value=prod-vgw}]' { "VpnGateway": { "VpnGatewayId": "vgw-0a1b2c3d4e5f60002", "State": "available", "Type": "ipsec.1", "AmazonSideAsn": 64512 } } # VGWをVPCにアタッチする $ aws ec2 attach-vpn-gateway \ --vpc-id vpc-0a1b2c3d4e5f6 \ --vpn-gateway-id vgw-0a1b2c3d4e5f60002 { "VpcAttachment": { "State": "attaching", "VpcId": "vpc-0a1b2c3d4e5f6" } } # アタッチ完了を確認する(State が attached になるまで数十秒待つ) $ aws ec2 describe-vpn-gateways \ --vpn-gateway-ids vgw-0a1b2c3d4e5f60002 \ --query 'VpnGateways[0].VpcAttachments' [ { "State": "attached", "VpcId": "vpc-0a1b2c3d4e5f6" } ]

VGWは1つのVPCにのみアタッチできます。複数のVPCと接続したい場合はTransit Gatewayを使う構成に移行する必要があります。

3. VPN接続を作成してルーター設定ファイルを取得する

CGWとVGWが揃ったら、VPN接続を作成します。BGPを使う場合は`StaticRoutesOnly: false`を指定します。

# VPN接続を作成する(BGP有効、2本トンネルが自動作成される) $ aws ec2 create-vpn-connection \ --type ipsec.1 \ --customer-gateway-id cgw-0a1b2c3d4e5f60001 \ --vpn-gateway-id vgw-0a1b2c3d4e5f60002 \ --options '{"StaticRoutesOnly":false}' \ --tag-specifications 'ResourceType=vpn-connection,Tags=[{Key=Name,Value=prod-vpn-conn}]' { "VpnConnection": { "VpnConnectionId": "vpn-0a1b2c3d4e5f60001", "State": "pending", "CustomerGatewayId": "cgw-0a1b2c3d4e5f60001", "VpnGatewayId": "vgw-0a1b2c3d4e5f60002", "Type": "ipsec.1" } } # ルーター設定ファイル(XML)を取得する(オンプレ側デバイスの設定参考に使う) $ aws ec2 describe-vpn-connections \ --vpn-connection-ids vpn-0a1b2c3d4e5f60001 \ --query 'VpnConnections[0].CustomerGatewayConfiguration' \ --output text > vpn-router-config.xml # 取得したXMLからOutside IP(トンネル外側IP)を確認する $ grep -o '[^<]*' vpn-router-config.xml | head -4 52.199.xxx.xxx # トンネル1のAWS側Outside IP 203.0.113.10 # トンネル1のオンプレ側Outside IP 52.198.yyy.yyy # トンネル2のAWS側Outside IP 203.0.113.10 # トンネル2のオンプレ側Outside IP

取得した`vpn-router-config.xml`には2本のトンネル設定(Outside IP・Pre-Shared Key・Inside IP・BGP設定)が含まれています。Cisco ASA・Juniper・FortiGateなどのルーター向けのテンプレートはAWSコンソールの「設定をダウンロード」ボタンからデバイス種別を選んで取得できます。

LinuxサーバーをソフトウェアVPNルーターとして使う場合はstrongSwanを利用します。xmlから抽出したOutside IP・PSK(Pre-Shared Key)・Inside IPを`/etc/ipsec.conf`と`/etc/ipsec.secrets`に設定します。

4. VPNトンネルの状態を確認する

オンプレ側の設定が完了し、IPsecとBGPが確立されると、AWSのTelemetryに状態が反映されます。

# VPNトンネルの状態を確認する(VgwTelemetryで2本のトンネルを確認) $ aws ec2 describe-vpn-connections \ --vpn-connection-ids vpn-0a1b2c3d4e5f60001 \ --query 'VpnConnections[0].VgwTelemetry[*].[OutsideIpAddress,Status,StatusMessage,AcceptedRouteCount]' \ --output table ---------------------------------------------------------------------- | DescribeVpnConnections | +------------------+------+----------------------------+-----------+ | 52.199.xxx.xxx | UP | 1 BGP ROUTES | 1 | | 52.198.yyy.yyy | UP | 1 BGP ROUTES | 1 | +------------------+------+----------------------------+-----------+ # Status が UP かつ AcceptedRouteCount が 1 以上であればBGP経路交換が成功している # StatusMessage の "1 BGP ROUTES" はオンプレ側から受信したBGP経路数を示す

両トンネルのStatusが`UP`になり、AcceptedRouteCountに数字が入れば疎通準備完了です。

この時点でVPCのルートテーブルにVGW経由の経路が伝播するよう「ルート伝播(Route Propagation)」を有効化します。

# ルートテーブルへのVGWルート伝播を有効化する $ aws ec2 enable-vgw-route-propagation \ --route-table-id rtb-0a1b2c3d4e5f6 \ --gateway-id vgw-0a1b2c3d4e5f60002 # ルートテーブルの内容を確認する(VGW由来の経路が PropagatingVgws 経由で表示される) $ aws ec2 describe-route-tables \ --route-table-ids rtb-0a1b2c3d4e5f6 \ --query 'RouteTables[0].Routes[*].[DestinationCidrBlock,GatewayId,Origin]' \ --output table +-----------------+-------------------------+----------------------------+ | 10.0.0.0/16 | local | CreateRouteTable | | 192.168.0.0/16 | vgw-0a1b2c3d4e5f60002 | EnableVgwRoutePropagation | +-----------------+-------------------------+----------------------------+ # 192.168.0.0/16 がオンプレ側からBGP広報されたネットワーク

BGPで経路を動的に制御する方法(静的ルーティングとの違い)

Site-to-Site VPNでは静的ルーティングとBGP(動的ルーティング)の2種類を選べます。実務ではBGPを強く推奨します。

静的ルーティング: VPN接続作成時にオンプレ側のCIDR(例: 192.168.0.0/16)を手動で登録する。シンプルだが、トンネルが1本DOWNしても経路は変わらず、残った1本のトンネルへの自動切り替えは行われない。復旧には静的ルートの手動操作が必要
BGP(Border Gateway Protocol): オンプレ側ルーターとAWSのVGW間でBGPセッションを張り、経路情報を自動交換する。トンネル1本がDOWNするとBGPセッションも切れ、そのトンネル経由の経路が自動で撤退(Withdraw)される。もう1本のトンネルを通じて経路が維持されるため、フェイルオーバーが自動で起きる

BGPの接続パラメーターは次の通りです。

・AWS側のASN: デフォルト64512(VGW作成時に`--amazon-side-asn`で変更可能)
・オンプレ側のASN: CGW作成時に指定した値(例: 65000)
・BGPのピアIPアドレス: 各トンネルの「Inside IP」(169.254.x.x/30の範囲で自動割り当て。XMLファイルで確認できる)

トンネル1を優先させたい場合は、トンネル2のBGP経路に対して「AS_PATHプリペンド」を使います。BGPのベストパス選択でAS_PATHが短いほど優先されるため、トンネル2側に自ASNを重ねて設定することでトンネル1が優先的に使われるよう制御できます。この設定はオンプレ側ルーターのBGP設定で行います。

マルチAZ全体の冗長設計パターンについてはAWSマルチAZ冗長設計の実践ガイドでも詳しく解説しています。

LinuxサーバーからVPN経由で疎通確認する手順

VPNトンネルが両方UPになったら、実際にLinuxから通信できるかを確認します。疎通確認の順序は「ルート確認 → ping → ポート確認」の3ステップです。

1. オンプレLinuxサーバーでVPC側への経路を確認する

オンプレのLinuxサーバーから、VPC側のネットワークへの経路がBGP経由で学習されているかを確認します。

# オンプレLinuxサーバーでVPC側ネットワークへの経路を確認する $ ip route show | grep 10.0.0.0 10.0.0.0/16 via 192.168.1.254 dev eth0 proto bgp metric 20 # 10.0.0.0/16(VPCのCIDR)が BGP(proto bgp)経由で学習されていれば設定成功 # via のアドレスはオンプレルーターのLAN側IP

2. VPC内のEC2へpingで疎通を確認する

# VPC内のプライベートIPへpingを打つ # (EC2のセキュリティグループでICMPがオンプレCIDRから許可されていること) $ ping -c 3 10.0.11.50 PING 10.0.11.50 (10.0.11.50) 56(84) bytes of data. 64 bytes from 10.0.11.50: icmp_seq=1 ttl=253 time=8.3 ms 64 bytes from 10.0.11.50: icmp_seq=2 ttl=253 time=7.9 ms 64 bytes from 10.0.11.50: icmp_seq=3 ttl=253 time=8.2 ms --- 10.0.11.50 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2004ms rtt min/avg/max/mdev = 7.9/8.1/8.3/0.166 ms # RTT 8ms前後はVPN(インターネット経由・東京リージョン)として標準的な値

3. SSH接続でVPN経由の管理アクセスを確認する

# VPC内のEC2にSSH接続を試みる $ ssh -v ec2-user@10.0.11.50 -i ~/.ssh/prod-ec2-key.pem 2>&1 | \ grep -E 'Connecting|Connection established|Authenticating' debug1: Connecting to 10.0.11.50 [10.0.11.50] port 22. debug1: Connection established. debug1: Authenticating to 10.0.11.50:22 as 'ec2-user' # VPN経由でSSH接続が確立できれば設定完了

ポート確認には`ss`コマンドが便利です。VPN経由で確立されているTCPコネクションの状態を確認するには、Linuxのポート確認コマンド(ss・lsof)の使い方も参照してください。

VPN接続ではオンプレとAWS間でのDNS名前解決も実務の重要ポイントです。VPC側のプライベートIPをDNS名で解決したい場合は、Route 53リゾルバーのアウトバウンドエンドポイントを設定し、オンプレ側のDNSサーバーに条件付きフォワーダーを追加します。LinuxサーバーのDNS設定についてはLinux DNS設定(resolv.conf)の基本とnmcliでの永続設定を参考にしてください。

もう1点、VPN・BGPの安定動作には時刻同期が必須です。オンプレのLinuxサーバーとAWSのEC2が正確な時刻を持っていないと、IPsecのSAネゴシエーションが失敗することがあります。時刻同期の設定はntpd・chronyd 時刻同期設定の手順を参照してください。

トラブルシュート|VPNトンネルがUPにならない時の切り分け

VPNの構成は複数のレイヤーにまたがるため、問題の切り分けを順序立てて行うことが重要です。

「DPD failure」でトンネルがDOWNを繰り返す

DPD(Dead Peer Detection)はIPsecトンネルの生存確認の仕組みです。オンプレ側ルーターがAWSからのDPDパケットに応答できていない場合に発生します。

# トンネル状態とStatusMessageを確認する $ aws ec2 describe-vpn-connections \ --vpn-connection-ids vpn-0a1b2c3d4e5f60001 \ --query 'VpnConnections[0].VgwTelemetry[*].[Status,StatusMessage,LastStatusChange]' \ --output table +-------+----------------------------+---------------------------+ | DOWN | DPD failure | 2026-07-30T09:00:00.000Z | | UP | 1 BGP ROUTES | 2026-07-29T08:00:00.000Z | +-------+----------------------------+---------------------------+

確認ポイント:
・オンプレ側ファイアウォールでUDP 500(IKE)およびUDP 4500(NAT-T)のアウトバウンドがAWS側Outside IPへ許可されているか確認する
・NATデバイスの背後にある場合はNAT-Traversal(NAT-T)が有効になっているか確認する
・Pre-Shared Key(PSK)がAWSのXMLで配布されたものと完全一致しているか確認する(スペースや改行の混入に注意)

BGPセッションが確立しない(AcceptedRouteCount = 0)

トンネルはUPだがBGPが動いていない状態です。

$ aws ec2 describe-vpn-connections \ --vpn-connection-ids vpn-0a1b2c3d4e5f60001 \ --query 'VpnConnections[0].VgwTelemetry[*].[Status,StatusMessage,AcceptedRouteCount]' \ --output table +-------+-----------------------+-----------------+ | UP | IPSEC IS UP | 0 | | UP | IPSEC IS UP | 0 | +-------+-----------------------+-----------------+ # IPSEC IS UP だが AcceptedRouteCount が 0 → BGPセッション未確立

確認ポイント:
・オンプレルーターのBGP設定でAWS側のASN(例: 64512)が正しいか確認する
・BGPのピアIPアドレスはトンネルのInside IPである169.254.x.x系を使っているか確認する(XMLファイルに記載)
・オンプレ側から広報するネットワーク(`network`ステートメントなど)が正しく設定されているか確認する

ルートがVPCのルートテーブルに現れない

BGPが確立してもVPCのルートテーブルに経路が出てこない場合は、ルート伝播(Route Propagation)が有効化されていない可能性があります。

# ルートテーブルの伝播設定を確認する $ aws ec2 describe-route-tables \ --route-table-ids rtb-0a1b2c3d4e5f6 \ --query 'RouteTables[0].PropagatingVgws' [] # PropagatingVgws が空の場合は enable-vgw-route-propagation を実行する $ aws ec2 enable-vgw-route-propagation \ --route-table-id rtb-0a1b2c3d4e5f6 \ --gateway-id vgw-0a1b2c3d4e5f60002

またVPC側EC2のセキュリティグループに、オンプレのCIDR(192.168.0.0/16など)からの必要なポートへのインバウンド許可が追加されているかも確認してください。VPNトンネルはOSI第3層(IPレイヤー)の通信を通過させますが、セキュリティグループはそれとは独立して評価されます。

本記事のまとめ

Site-to-Site VPNの構成と冗長設計のポイントをまとめます。

やりたいこと コマンド
Customer Gatewayを作成する aws ec2 create-customer-gateway --type ipsec.1 --bgp-asn 65000 --public-ip X.X.X.X
Virtual Private Gatewayを作成する aws ec2 create-vpn-gateway --type ipsec.1
VGWをVPCにアタッチする aws ec2 attach-vpn-gateway --vpc-id vpc-xxx --vpn-gateway-id vgw-xxx
VPN接続を作成する(BGP有効) aws ec2 create-vpn-connection --type ipsec.1 --customer-gateway-id cgw-xxx --vpn-gateway-id vgw-xxx --options '{"StaticRoutesOnly":false}'
ルーター設定ファイルを取得する aws ec2 describe-vpn-connections --query 'VpnConnections[0].CustomerGatewayConfiguration' --output text
トンネル状態を確認する aws ec2 describe-vpn-connections --query 'VpnConnections[0].VgwTelemetry'
ルート伝播を有効化する aws ec2 enable-vgw-route-propagation --route-table-id rtb-xxx --gateway-id vgw-xxx
Site-to-Site VPNはオンプレミスとAWSをつなぐ最初の一歩として、コストと構築速度のバランスに優れています。1つのVPN接続に2本のトンネルを持ち、BGPを使えばフェイルオーバーは自動です。トラフィック量が増加してレイテンシや安定性に課題が出てきたら、Direct Connectへの移行、またはSite-to-Site VPNをDirect Connectのバックアップ経路として残すハイブリッド設計への移行を検討してください。

AWSのVPC設計・冗長化をより体系的に学びたい方はAWSマルチAZ冗長設計の実践ガイドも合わせてご確認ください。

VPN設計の手順は分かった——でも「本番で判断できるか」が問題です

aws ec2 create-vpn-connection のコマンドは調べれば分かります。でも「静的かBGPかどちらを選ぶべきか」「トラブル時に何から確認するか」を、自信を持って判断できますか?
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。

「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。