連載: VyOSで作るAWSハイブリッド接続(全4回)
- VyOSでつくるAWS Site-to-Site VPN — IPsec+BGPの基礎(この記事)
- AWS Site-to-Site VPNの冗長化とBGP経路制御
- VGWからTransit Gatewayへ — VPNのECMP冗長化
- マルチリージョン接続 — DX-GWの限界とTransit Gatewayピアリング
0. Overview
オンプレ拠点とAWS VPCを暗号化トンネルでつなぐのが AWS Site-to-Site VPN です。 本来はオンプレのルーターが担う「カスタマーゲートウェイ(顧客側VPN装置)」の役割を、ここでは VyOS(Linuxベースのソフトウェアルーター)で代用し、VirtualBox上に検証環境を作ります。
全体像と作業の流れ
この記事で一番つまずきやすいのは、後半に出てくる xx.xx.xx.xx や 169.254.244.109、PSK(事前共有鍵)といった**「謎の値」がどこから来るのか**です。結論から言うと、これらはAWS側でVPN接続を作ると自動生成される「設定ファイル」に全部書いてあります。だから作業順序が重要で、以下の順で進めます。
1. VyOS を起動して初期設定(SSH・タイムゾーン)
2. VyOS をインターネットに出す(AWSと鍵交換するため)
3. AWS側で VPN接続を作成 → 設定ファイルをダウンロード ← ここで全パラメータが決まる
4. ダウンロードした値を VyOS に流し込む(IPsec + BGP)
5. AWS側でルート伝搬を有効化
6. 双方向 ping で疎通確認
登場する主なコンポーネントを先に地図にしておきます。
| コンポーネント | 役割 |
|---|---|
| VGW(仮想プライベートゲートウェイ) | AWS側のVPN終端。VPCにアタッチする |
| CGW(カスタマーゲートウェイ) | オンプレ側VPN装置の「AWSへの登録情報」(=今回のVyOSのグローバルIPとASN) |
| VPN Connection | VGWとCGWを結ぶトンネル定義。作成すると2本のトンネルとPSK・内側IPが払い出される |
| IPsec(IKE/ESP) | トンネルを張り、中身を暗号化するプロトコル群 |
| VTI | 暗号化トンネルをOS上の仮想NICとして見せるインターフェース |
| BGP | トンネル越しに「このネットワークはこっちにあるよ」を動的に教え合うルーティングプロトコル |
参考: AWS White Paper
構成図

VyOS Version
VyOSは設定構文がバージョンで変わるため、まず版を控えておきます(後述のIPsec構文は1.4系前提)。
vyos@vyos:~$ show version
Version: VyOS 1.4-rolling-202211190627
Release train: current
Built by: autobuild@vyos.net
Built on: Sat 19 Nov 2022 06:27 UTC
Build UUID: 687dfd47-11ca-4c0c-8045-944ed60279be
Build commit ID: cd6f8ab1040139
Architecture: x86_64
Boot via: installed image
System type: KVM guest
Hardware vendor: innotek GmbH
Hardware model: VirtualBox
Hardware S/N: 0
Hardware UUID: 91d658fc-16f6-074b-b5a6-59f4f5c3c14b
Copyright: VyOS maintainers and contributors
1. VyOS初期設定
ライブCDから起動した直後はメモリ上で動いているだけなので、install image でディスクへインストールしてから各種設定を入れます。ここでは管理用にホストオンリーアダプタ(PCとVMだけが通信できる閉じたネットワーク)を割り当て、SSHで入れるようにします。
VirtualBox側
- LAN3 を Host Only Adapter として有効化(管理アクセス用。eth2 に対応)
VyOS Config
//起動後
$ install image //各種設定の後、CDを取り出し再起動。
//管理インターフェース & SSH
set interfaces ethernet eth2 address '169.254.153.1/16'
set interfaces ethernet eth2 description 'HOST-Only'
set service ssh
set system time-zone 'Asia/Tokyo'
2. インターネット接続
IPsecのIKE(鍵交換)はインターネット越しにAWSのVPNエンドポイントと行うため、VyOSが外に出られる必要があります。VirtualBoxのNATを使い、eth0をDHCPで自動設定します。
補足: この構成ではVyOSはVirtualBoxのNATの内側にいます(VyOSが受け取るのは
10.0.2.15のようなプライベートIP)。カスタマーゲートウェイがNAT配下にある=NAT-T(NAT Traversal)が必要になり、これが後のIPsec設定に効いてきます(セクション4で再登場)。
VirtualBox側
- LAN1 を NAT として有効化(eth0 に対応)
VyOS Config
//追加
set interfaces ethernet eth0 address 'dhcp'
//ルーティングテーブル確認(デフォルトルートがeth0に向いていればOK)
vyos@vyos:~$ show ip route
~~
S>* 0.0.0.0/0 [210/0] via 10.0.2.2, eth0, 00:00:11
C>* 10.0.2.0/24 is directly connected, eth0, 00:00:13
C>* 169.254.0.0/16 is directly connected, eth2, 00:07:14
//外部疎通確認
vyos@vyos:~$ ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: icmp_seq=0 ttl=56 time=27.054 ms
64 bytes from 8.8.8.8: icmp_seq=1 ttl=56 time=17.119 ms
3. AWS側でVPN接続を作成し、設定をダウンロードする
ここが後半のすべての「謎の値」の出どころです。VyOSの設定を書く前に、必ずAWS側を先に作ります。
作成するリソース(順番)
- 仮想プライベートゲートウェイ(VGW) を作成し、対象のVPCに アタッチ
- ASNはデフォルトの 64512(AWS側のBGP AS番号。後でVyOSのBGPネイバー
remote-asに書く値になる)
- ASNはデフォルトの 64512(AWS側のBGP AS番号。後でVyOSのBGPネイバー
- カスタマーゲートウェイ(CGW) を作成
- IPアドレス = VyOS(オンプレ装置)のグローバルIP
- BGP ASN = 自分側のAS番号。プライベートAS番号の範囲(64512〜65534)から選び、今回は 65000
- Site-to-Site VPN接続 を作成
- 上で作ったVGWとCGWを指定
- ルーティングは 動的(Dynamic / BGP) を選択
設定ファイルのダウンロード
VPN接続を選び 「設定をダウンロード」 から、ベンダー/プラットフォーム/ソフトウェアを選びます(一覧にVyOSが無ければ Generic を選択。CLIなら aws ec2 get-vpn-connection-device-sample-configuration でも取得可)。
ダウンロードしたファイルには、VyOSに流し込む値がほぼ全部入っています。後半のコマンドに出てくるプレースホルダと対応づけると:
| 設定ファイル内の項目 | VyOSコマンドのどこに使うか |
|---|---|
| Pre-Shared Key(トンネル1の鍵) | authentication pre-shared-secret |
| Virtual Private Gateway の外部IP | peer AWS remote-address(xx.xx.xx.xx) |
| Customer Gateway の外部IP | local-id / local-address 相当 |
| Tunnel Inside IP(CGW側 /30) | interfaces vti vti0 address(169.254.244.110/30) |
| Tunnel Inside IP(AWS側 /30) | BGPネイバー(169.254.244.109) |
| Virtual Private Gateway ASN | BGP remote-as(64512) |
| 暗号化/ハッシュ/DHグループ/ライフタイム | esp-group / ike-group の各値 |
トンネルが2本ある理由: AWSは冗長化のため必ず2本のトンネル(別々のAWS側エンドポイント・別々の
169.254.x.x/30)を払い出します。本記事は片側(Tunnel 1,vti0)のみ設定しています。本番では両方設定し、BGPでアクティブ/スタンバイを取るのが推奨です。
4. VyOSのIPsec / BGP設定
VyOS 1.4から
vpn ipsec系の構文が変更されています(1.2/1.3系のブログをそのまま真似ると通りません)。以下は1.4系の構文です。
ダウンロードした設定ファイルの値を、VyOSのコマンドに流し込んでいきます。ブロックごとに「何をしているか」を補足します。
① ESP / IKE グループ(暗号化の条件を定義)
IPsecは2段構えです。IKE(Internet Key Exchange)がまず鍵を安全に交換してトンネルの「制御チャネル」を作り、ESP(Encapsulating Security Payload)が実際のデータを暗号化して運びます。ここで定義する暗号化方式・ハッシュ・DHグループ・ライフタイムは、AWS側とピッタリ一致していないとトンネルが上がりません(だからダウンロードした値をそのまま使う)。
## ESP & IKE
set vpn ipsec esp-group AWS lifetime '3600'
set vpn ipsec esp-group AWS mode 'tunnel'
set vpn ipsec esp-group AWS pfs 'enable'
set vpn ipsec esp-group AWS proposal 1 encryption 'aes128'
set vpn ipsec esp-group AWS proposal 1 hash 'sha1'
set vpn ipsec ike-group AWS dead-peer-detection action 'restart'
set vpn ipsec ike-group AWS dead-peer-detection interval '15'
set vpn ipsec ike-group AWS dead-peer-detection timeout '30'
set vpn ipsec ike-group AWS lifetime '28800'
set vpn ipsec ike-group AWS proposal 1 dh-group '2'
set vpn ipsec ike-group AWS proposal 1 encryption 'aes128'
set vpn ipsec ike-group AWS proposal 1 hash 'sha1'
主なパラメータの意味:
| パラメータ | 意味 | 補足 |
|---|---|---|
lifetime | 鍵の有効期間(秒)。切れると自動で再交換 | IKE=28800秒(8h)、ESP=3600秒(1h)はAWSの既定値 |
pfs enable | Perfect Forward Secrecy。鍵更新ごとに新しいDH鍵を使う | 過去の鍵が漏れても過去通信は復号されない |
dh-group 2 | Diffie-Hellman鍵交換のグループ(鍵強度) | グループ2は古い。両端が対応するなら14以上を推奨 |
dead-peer-detection | 相手の生死を定期確認し、死んでいたら張り直す | interval 15 / timeout 30 ごとに検知 |
encryption/hash | AES128 / SHA1 | AWSの最小要件。両端が対応すればAES256/SHA256に上げる方が望ましい |
セキュリティ注記(迎合しないために正直に書くと): AES128 + SHA1 + DH2 はAWSが受け付ける最低ラインで、現代の基準では弱めです。検証用途なら問題ありませんが、実運用なら両端の対応状況を見て AES256 / SHA256 / DH14以上 に引き上げてください。
② VTI(暗号化トンネルを仮想NICにする)
IPsecで張ったトンネルを、OSから「普通のネットワークインターフェース」として扱えるようにするのが VTI(Virtual Tunnel Interface) です。こうすることで、トンネル上でBGPのような通常のルーティングプロトコルを素直に喋れます(=ルートベースVPN)。
## vti
set interfaces vti vti0 address '169.254.244.110/30'
set interfaces vti vti0 description 'VPC tunnel 1'
set interfaces vti vti0 mtu '1436'
169.254.244.110/30: トンネル内側のリンクローカルアドレス。AWSが払い出した /30 のうちCGW側。対向(.109)がAWS側で、後のBGPネイバーになります。mtu 1436: IPsecはパケットにヘッダ(暗号化のオーバーヘッド)を付け足すため、通常の1500のままだと中身が入りきらず断片化やブラックホール化を招きます。トンネル用に小さくするのが定石で、AWSの生成configもこの値を指定してきます。
③ Site-to-Site Peer(トンネルの相手と認証)
「誰と」「どの鍵で」トンネルを張るかを定義します。
## IPSec
set vpn ipsec site-to-site peer AWS authentication mode 'pre-shared-secret'
set vpn ipsec site-to-site peer AWS authentication pre-shared-secret 'YOUR_PRE_SHARED_SECRET'
set vpn ipsec site-to-site peer AWS description 'VPC tunnel 1'
set vpn ipsec site-to-site peer AWS ike-group 'AWS'
set vpn ipsec site-to-site peer AWS local-address '10.0.2.15'
set vpn ipsec site-to-site peer AWS remote-address 'xx.xx.xx.xx'
set vpn ipsec site-to-site peer AWS vti bind 'vti0'
set vpn ipsec site-to-site peer AWS vti esp-group 'AWS'
### NAT-T 対応(VyOSがNAT配下にいるため)
set vpn ipsec site-to-site peer AWS authentication local-id 'yy.yy.yy.yy'
set vpn ipsec site-to-site peer AWS authentication remote-id 'xx.xx.xx.xx'
pre-shared-secret: ダウンロードしたPSKに置き換える。remote-address xx.xx.xx.xx: AWS側VPNエンドポイントのグローバルIP(設定ファイルに記載)。local-address 10.0.2.15: VyOSが認識している自分のIP。今回はVirtualBox NAT配下なのでグローバルではなくプライベートになっている点に注意。local-id / remote-id: NAT-T対策。VyOSがNATの内側にいるとIPsecが本来見るIPと実際のIPがズレるため、IDを明示してIKEを成立させます。local-idには自分のグローバルIP(=CGWに登録したIP)、remote-idにはAWS側IPを指定します。
④ BGP(経路を動的に教え合う)
トンネルが上がっただけでは「どのサブネットがトンネルの先にあるか」をお互い知りません。BGPで「自分側には 10.0.2.0/24 があるよ」と広告し、AWSからはVPC内のネットワークを受け取ります。静的ルートを手で書く代わりに自動化できるのが動的ルーティングの利点です。
//BGP Config
set protocols bgp system-as '65000'
set protocols bgp neighbor 169.254.244.109 address-family ipv4-unicast soft-reconfiguration inbound
set protocols bgp neighbor 169.254.244.109 remote-as '64512'
set protocols bgp neighbor 169.254.244.109 timers holdtime '30'
set protocols bgp neighbor 169.254.244.109 timers keepalive '10'
set protocols bgp address-family ipv4-unicast network 10.0.2.0/24
system-as 65000: 自分側のAS番号(CGWで登録した値と一致させる)。neighbor 169.254.244.109 ... remote-as 64512: BGPの相手はトンネル内側 /30 のAWS側アドレス、そのAS番号はVGWの 64512。network 10.0.2.0/24: 自分側ネットワークをAWSへ広告。timers: keepalive 10秒 / holdtime 30秒で生死監視(holdtimeはkeepaliveの3倍が定石)。
Note
- bgp soft reconfiguration の設定がVyOS1.2より変更となっているため注意
set protocols bgp 65000 neighbor 169.254.233.169 address-family ipv4-unicast soft-reconfiguration inbound # この事前設定により、ソフトウェアは、アップデートがインバウンド ポリシーによって受け入れられるかどうかに関係なく、受信したすべてのアップデートを変更せずに保存します。 # アップデートの保存は大量のメモリを要するため、可能な限り回避する必要があります。
- VyOSでのNATトラバーサル設定
5. AWS側でルート伝搬を有効化
BGPでAWSが受け取った経路(=VyOS側の 10.0.2.0/24)を、実際にVPCのルートテーブルへ反映させる設定です。これを忘れると、トンネルとBGPは上がっているのにVPC内のEC2からオンプレ宛のパケットが返らない、という「半分つながった」状態になります。
対象VPCのルートテーブルで 「ルート伝搬(Route Propagation)」を有効化 し、VGWを指定します。

6. 疎通確認
トンネルは双方向で確認します。片方向だけ通っても、戻りの経路(ルート伝搬やBGP広告)が欠けていると実用にならないためです。
AWS => VyOS
VPC内のホストから、VyOS側のアドレスへ。
:~/environment/ans-exam (master) $ ping 10.0.2.15
PING 10.0.2.15 (10.0.2.15) 56(84) bytes of data.
64 bytes from 10.0.2.15: icmp_seq=1 ttl=64 time=19.6 ms
64 bytes from 10.0.2.15: icmp_seq=2 ttl=64 time=18.2 ms
VyOS => AWS
VyOSからVPC内のホストへ。source-address を付けるのは、広告している 10.0.2.0/24 を送信元にしないとBGPで学習した経路に乗らないためです。
vyos@vyos:~$ ping 10.99.31.172 source-address 10.0.2.15
PING 10.99.31.172 (10.99.31.172) from 10.0.2.15 : 56(84) bytes of data.
64 bytes from 10.99.31.172: icmp_seq=1 ttl=254 time=16.3 ms
64 bytes from 10.99.31.172: icmp_seq=2 ttl=254 time=30.0 ms
64 bytes from 10.99.31.172: icmp_seq=3 ttl=254 time=24.4 ms
64 bytes from 10.99.31.172: icmp_seq=4 ttl=254 time=18.3 ms
両方向で応答が返れば、IPsecトンネル・BGP経路・ルート伝搬がすべて噛み合っている状態です。
7. うまくいかないときの確認ポイント
つながらない場合、上のレイヤーから順に切り分けると早いです。
| 症状 | 確認コマンド / 見るところ |
|---|---|
| トンネルが上がらない | show vpn ipsec sa でIKE/ESPのSA状態を確認。down なら暗号化条件(esp/ike-group)の不一致かPSK誤りを疑う |
| IKEは上がるがESPが張れない | 暗号化方式・DHグループ・ライフタイムがAWS側設定ファイルと一致しているか再確認 |
| トンネルは上がるがBGPが上がらない | show ip bgp summary でネイバー状態を確認。ネイバーIP(AWS側 /30)とASNが正しいか |
| BGPは上がるが通信できない | show ip route bgp で経路学習を確認。AWS側はルート伝搬(セクション5)が有効か |
| NAT配下で全く張れない | NAT-Tの local-id / remote-id 設定漏れを疑う |