連載: VyOSで作るAWSハイブリッド接続(全4回)
0. この回のテーマ
第1回では、VyOSをカスタマーゲートウェイ(CGW)に見立てて、AWSとの間に 1本のSite-to-Site VPNトンネルを張りました。ただ実運用で1本だけ、というのはまずありません。AWSはVPN接続を作ると必ず2本のトンネル(別々のAWS側エンドポイント・別々の内側 /30)を払い出してきます。冗長化が前提の設計になっているからです。
そこで2本目を足すと、今度は新しい問題が出てきます。「2本あるとき、トラフィックはどっちのトンネルを通るのか? そしてそれを自分の意図どおりに制御できるのか?」 これがこの回の主題、BGPトラフィックエンジニアリングです。
結論を先に言うと、経路制御は 「行き」と「戻り」で使う道具が違います。ここを最初に掴んでおくと、後半が一気に楽になります。
| 制御したい方向 | 使う属性 | 性質 |
|---|---|---|
| VyOS → AWS(自分から出ていく経路の選択) | Weight | 自分のルータ内だけの判断。隣に伝わらない |
| AWS → VyOS(相手が自分宛に選ぶ経路への influence) | AS-Path Prepend | 広告に乗って相手に伝わる。相手の判断を動かす |
ネットワーク屋の感覚で言えば、Weightは「自分のルーティングテーブルのローカルな優先度」、AS-Path Prependは「相手に渡すルート広告をわざと遠回りに見せる小細工」です。前者は自分の意思で決められること、後者は相手にお願いすること、という非対称があります。
構成図
第1回の単一トンネルに、2本目(vti1)を足した姿です。

1. 2本目のトンネルを追加する
設定の中身は第1回のトンネル1とほぼ同じです。AWSのVPN設定ファイルに記載された トンネル2側のPSK・エンドポイントIP・内側 /30 を、vti1 と新しいピアに当てはめていきます。
## IPSec(トンネル2)
set vpn ipsec site-to-site peer AWS_backup authentication mode 'pre-shared-secret'
set vpn ipsec site-to-site peer AWS_backup authentication pre-shared-secret 'YOUR_PRE_SHARED_SECRET_2'
set vpn ipsec site-to-site peer AWS_backup description 'VPC tunnel 2'
set vpn ipsec site-to-site peer AWS_backup ike-group 'AWS'
set vpn ipsec site-to-site peer AWS_backup local-address '10.0.2.15'
set vpn ipsec site-to-site peer AWS_backup remote-address 'xx.xx.xx.xx' # トンネル2のAWS側IP
set vpn ipsec site-to-site peer AWS_backup vti bind 'vti1'
set vpn ipsec site-to-site peer AWS_backup vti esp-group 'AWS'
### NAT-T対応(第1回と同じ理由)
set vpn ipsec site-to-site peer AWS_backup authentication local-id 'yy.yy.yy.yy'
set vpn ipsec site-to-site peer AWS_backup authentication remote-id 'xx.xx.xx.xx'
## VTI(トンネル2の仮想インターフェース)
set interfaces vti vti1 address '169.254.61.114/30'
set interfaces vti vti1 description 'VPC tunnel 2'
set interfaces vti vti1 mtu '1436'
## BGP(トンネル2のネイバー)
set protocols bgp neighbor 169.254.61.113 address-family ipv4-unicast soft-reconfiguration inbound
set protocols bgp neighbor 169.254.61.113 remote-as '64512'
set protocols bgp neighbor 169.254.61.113 timers holdtime '30'
set protocols bgp neighbor 169.254.61.113 timers keepalive '10'
esp-group / ike-group は第1回で定義した AWS を使い回します(暗号化条件は両トンネルで同じ)。これで物理的には2本のトンネルとBGPネイバーが立ち上がります。
2. 初期状態の経路を観察する
何も制御を入れない状態でBGPテーブルを見ると、面白いことが起きています。
vyos@vyos:~$ show ip bgp ipv4 unicast
Network Next Hop Metric LocPrf Weight Path
*> 10.0.2.0/24 0.0.0.0 0 32768 i
*> 10.99.0.0/16 169.254.61.113 100 0 64512 i
* 169.254.234.49 200 0 64512 i
VPC(10.99.0.0/16)への経路が2本見えていて、*>(ベストパス)が付いているのは .113(トンネル2 = Backup側) の方です。Metric(MED)を見ると、トンネル2が 100、トンネル1が 200。
ここがVGW(仮想プライベートゲートウェイ)の挙動の肝です。AWSはトンネル1に200、トンネル2に100というMEDを付けて広告してきます。BGPはMEDが小さい方を優先するので、何もしなければBackup側(トンネル2)が勝つ。shutdown→復旧させても、MEDの差でちゃんとBackup側にトラフィックが戻ってきます(参考: Site-to-Site VPNのBGP経路制御)。
つまりデフォルトのままだと、自分が「Main」と思っているトンネル1が使われない、という状況です。これを意図どおりに寄せにいきます。
VGWの経路選択の優先順位
AWS(VGW)が複数経路から1つを選ぶときの順序を、先に整理しておきます。上から順に評価されます。
- ロンゲストマッチ(宛先がより詳細なルートが優先)
- Direct Connect > Site-to-Site VPN(DXがあればDX優先)
- 静的ルート > BGPルート(同じVPN内で)
- AS-PATHが最短のBGPルート
- AS-PATHが同じなら MEDが最小
今回いじれるのは下2つ、AS-PATHとMEDです。
3. TE1: VyOS → AWS の経路をMain系に寄せる(Weight)
まず「自分から出ていく」方向。VyOSがVPC宛のパケットをどちらのトンネルに流すかは、VyOS自身のBGPテーブルのベストパス選択で決まります。ここは相手は関係ない、自分のルータ内の話なので、Weightを使います。
Weightは特定のパスを選ぶために使う、そのルータ内だけで有効な属性です。他のBGPルータには一切交換されません。同じプレフィックスなら、値が大きい方のルートが優先されます。
トンネル1(.49)のWeightを大きくして、こちらをベストパスに引き上げます。
set protocols bgp neighbor 169.254.234.49 address-family ipv4-unicast weight 300
変更後:
vyos@vyos:~$ show ip bgp
Network Next Hop Metric LocPrf Weight Path
*> 10.0.2.0/24 0.0.0.0 0 32768 i
* 10.99.0.0/16 169.254.61.113 100 0 64512 i
*> 169.254.234.49 200 300 64512 i ## weight 300
MEDは200のまま(不利)なのに、Weight 300が効いて .49(Main側)がベストパスに変わりました。Weightはローカルの最優先属性なので、MEDの不利を上書きできるわけです。

これでVyOSから出ていくトラフィックはMain系に乗りました。ただしこれは片方向だけの解決です。
4. TE2: AWS → VyOS の経路をMain系に寄せる(AS-Path Prepend)
次に「相手から戻ってくる」方向。AWS側がVyOS(10.0.2.0/24)宛にどちらのトンネルを選ぶかは、AWSのBGPテーブルの判断です。こちらのWeightは相手に伝わらないので無力。代わりに、相手に渡すルート広告を細工して、相手の判断を動かします。
使うのは AS-Path Prepend。広告するルートに自分のAS番号を余分に付け足して、「この経路は遠回りですよ」と相手に見せかける手法です。AWSの選択順位(前述)で4番目の「AS-PATH最短」が効くので、Backup側のAS-PATHを長くすれば、相手はMain側を短い=近いと判断します。
Backup側(.113)に向けて広告するときだけ、AS-PATHを1つ伸ばします。
set policy route-map VPC-Tunnel-2-OUT rule 10 action permit
set policy route-map VPC-Tunnel-2-OUT rule 10 set as-path prepend 65000
set protocols bgp neighbor 169.254.61.113 address-family ipv4-unicast route-map export VPC-Tunnel-2-OUT
Main側(.49)へ広告した経路はAS-PATHが素のまま:
vyos@vyos:~$ show ip bgp ipv4 unicast neighbors 169.254.234.49 advertised-routes
Network Next Hop Metric LocPrf Weight Path
*> 10.0.2.0/24 0.0.0.0 0 32768 i
*> 10.99.0.0/16 0.0.0.0 300 64512 i
Backup側(.113)へ広告した経路はAS-PATHに 65000 が水増しされている:
vyos@vyos:~$ show ip bgp ipv4 unicast neighbors 169.254.61.113 advertised-routes
Network Next Hop Metric LocPrf Weight Path
*> 10.0.2.0/24 0.0.0.0 0 32768 65000 i ## prependされている
*> 10.99.0.0/16 0.0.0.0 300 65000 64512 i
AWSから見ると、Backup経由のVyOS宛経路はAS-PATHが1ホップ長い=遠回りに見えるので、Main側を選ぶようになります。

5. 完成形
これで「行き(Weight)」も「戻り(AS-Path Prepend)」も、両方Main系(トンネル1)に寄りました。Mainが落ちればBGPが自動でBackupに切り替え、復旧すればMainに戻ってくる、アクティブ/スタンバイの冗長構成です。

ポイントを一枚にまとめると:
| 方向 | 制御点はどこ | 道具 | なぜそれか |
|---|---|---|---|
| VyOS → AWS | VyOS自身のベストパス選択 | Weight | ローカルで完結。相手に伝える必要がない |
| AWS → VyOS | AWSのベストパス選択 | AS-Path Prepend | 自分のWeightは伝わらない。広告を細工して相手を動かす |
この回時点のVyOS設定(全体・秘匿値はプレースホルダ)
set interfaces ethernet eth0 address 'dhcp'
set interfaces ethernet eth2 address '169.254.153.1/16'
set interfaces ethernet eth2 description 'Host-Only'
set interfaces vti vti0 address '169.254.234.50/30'
set interfaces vti vti0 description 'VPC tunnel 1'
set interfaces vti vti0 mtu '1436'
set interfaces vti vti1 address '169.254.61.114/30'
set interfaces vti vti1 description 'VPC tunnel 2'
set interfaces vti vti1 mtu '1436'
set policy route-map VPC-Tunnel-2-OUT rule 10 action 'permit'
set policy route-map VPC-Tunnel-2-OUT rule 10 set as-path prepend '65000'
set protocols bgp address-family ipv4-unicast network 10.0.2.0/24
set protocols bgp neighbor 169.254.61.113 address-family ipv4-unicast route-map export 'VPC-Tunnel-2-OUT'
set protocols bgp neighbor 169.254.61.113 address-family ipv4-unicast soft-reconfiguration inbound
set protocols bgp neighbor 169.254.61.113 remote-as '64512'
set protocols bgp neighbor 169.254.61.113 timers holdtime '30'
set protocols bgp neighbor 169.254.61.113 timers keepalive '10'
set protocols bgp neighbor 169.254.234.49 address-family ipv4-unicast soft-reconfiguration inbound
set protocols bgp neighbor 169.254.234.49 address-family ipv4-unicast weight '300'
set protocols bgp neighbor 169.254.234.49 remote-as '64512'
set protocols bgp neighbor 169.254.234.49 timers holdtime '30'
set protocols bgp neighbor 169.254.234.49 timers keepalive '10'
set protocols bgp system-as '65000'
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'
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_1'
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'
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'
set vpn ipsec site-to-site peer AWS_backup authentication mode 'pre-shared-secret'
set vpn ipsec site-to-site peer AWS_backup authentication pre-shared-secret 'YOUR_PRE_SHARED_SECRET_2'
set vpn ipsec site-to-site peer AWS_backup authentication local-id 'yy.yy.yy.yy'
set vpn ipsec site-to-site peer AWS_backup authentication remote-id 'xx.xx.xx.xx'
set vpn ipsec site-to-site peer AWS_backup ike-group 'AWS'
set vpn ipsec site-to-site peer AWS_backup local-address '10.0.2.15'
set vpn ipsec site-to-site peer AWS_backup remote-address 'xx.xx.xx.xx'
set vpn ipsec site-to-site peer AWS_backup vti bind 'vti1'
set vpn ipsec site-to-site peer AWS_backup vti esp-group 'AWS'
まとめ
- AWSは冗長化前提でVPNトンネルを2本払い出す。両方使うなら経路制御が必要になる
- VGWはデフォルトでトンネル1にMED 200、トンネル2にMED 100を付ける(放置するとBackup側が優先される)
- 経路制御は方向で道具が変わる。出ていく方向はWeight(ローカル完結)、戻る方向はAS-Path Prepend(広告を細工して相手を動かす)
- このアクティブ/スタンバイ構成に対し、次回はVGWをTransit Gatewayに置き換え、2本を**同時に使う(ECMP)**構成へ進みます。MEDの挙動もVGWとは変わります。