AWS サイト間 VPN の作成 + YAMAHA VPN ルーターへの設定投入の手順化
普段、単純な検証程度であれば、パブリックサブネットにインスタンス作ってパブリックな経路で SSH 接続をして軽めに検証しているので厳密な閉域接続が必要ないから、どうしても必要な時にだけ作って用途が終わったら壊して、ってしてるけど、いつも微妙に忘れて、どこをどうしたんだっけ?ってなるので、完全に自分のためだけ手順化。
手順
1. カスタマーゲートウェイの作成
1-1. カスタマーゲートウェイ側グローバル IP アドレスの設定
自宅は固定 IP アドレスではないため、ipecho.net を利用して作成時点でのグローバル IP アドレスを取得し、変数に格納する。
|  | GLOBAL_IP_ADDRESS=$(curl http://ipecho.net/plain)
 | 
1-2. カスタマーゲートウェイの作成
<1-1>で取得したグローバル IP アドレスを利用してカスタマーゲートウェイを作成。 
後の工程で利用しやすいようにタグ付与をするが、一旦決め打ちで Home というタグ値にしている。
|  | aws ec2 create-customer-gateway \
  --type ipsec.1 \
  --public-ip ${GLOBAL_IP_ADDRESS} \
  --tag-specifications "ResourceType=customer-gateway,Tags=[{Key=Name,Value=Home}]"
 | 
2. 仮想プライベートゲートウェイの作成
現時点では --type オプションは ipsec.1 という値しか取り得ないので決め打ち。 
タグ値は s2sVPN としている。
|  | aws ec2 create-vpn-gateway \
  --type ipsec.1 \
  --tag-specifications "ResourceType=vpn-gateway,Tags=[{Key=Name,Value=s2sVPN}]"
 | 
3. 仮想プライベートゲートウェイの VPC へのアタッチ
3-1. VPC ID の取得
ここでは、VPC に Name=Usual というタグが設定されている想定。
|  | VPC_ID=$(aws ec2 describe-vpcs \
  --filters "Name=tag:Name,Values=Usual" \
  --query "Vpcs[].VpcId" \
  --output text)
 | 
3-2. 仮想プライベートゲートウェイ ID の取得
|  | VPN_GATEWAY_ID=$(aws ec2 describe-vpn-gateways \
  --filters "Name=tag:Name,Values=s2sVPN" \
  --query "VpnGateways[].VpnGatewayId" \
  --output text)
 | 
3-3. 仮想プライベートゲートウェイの VPC へのアタッチ
|  | aws ec2 attach-vpn-gateway \
  --vpc-id ${VPC_ID} \
  --vpn-gateway-id ${VPN_GATEWAY_ID}
 | 
4. VPN 接続の作成
4-1. カスタマーゲートウェイ ID の取得
|  | CUSTOMER_GATEWAY_ID=$(aws ec2 describe-customer-gateways \
  --filters "Name=tag:Name,Values=Home" \
  --query "CustomerGateways[].CustomerGatewayId" \
  --output text)
 | 
4-2. VPN 接続の作成
ここでも --type オプションには ipsec.1 しか取り得ないため決め打ち。
|  | aws ec2 create-vpn-connection \
  --customer-gateway-id ${CUSTOMER_GATEWAY_ID} \
  --type ipsec.1 \
  --vpn-gateway-id ${VPN_GATEWAY_ID} \
  --tag-specifications "ResourceType=vpn-connection,Tags=[{Key=Name,Value=s2sVPN-connection}]"
 | 
5. 仮想プライベートゲートウェイの指定されたルートテーブルへのルート伝播の有効化
5-1. ルートテーブル ID の取得
--filters オプションで、指定した VPC ID に存在するすべてのルートテーブル ID を CSV ファイル route-tables-list.csv に集約する。
|  | aws ec2 describe-route-tables \
  --filters "Name=vpc-id,Values=${VPC_ID}" \
  --query "RouteTables[].RouteTableId" \
  --output text \
  | sed "s/\t/\n/g" > route-tables-list.csv
 | 
5-2. VPC に存在するすべてのルートテーブルで仮想プライベートゲートウェイのルート伝播の有効化を実施
<5-1>の手順で作成した CSV ファイルに存在するルートテーブル ID に対し、仮想プライベートゲートウェイのルート伝播の有効化を実施する。
|  | while read ROUTE_TABLE_ID; do
  aws ec2 enable-vgw-route-propagation \
    --gateway-id ${VPN_GATEWAY_ID} \
    --route-table-id ${ROUTE_TABLE_ID}
done < route-tables-list.csv
 | 
6. ルーターへのコンフィグ投入
6-1. サンプル設定のダウンロード
6-1-1. VpnConnectionDeviceTypeId の取得
自宅で利用しているのが YAMAHA の RTX シリーズなので、YAMAHA 決め打ちで VpnConnectionDeviceTypeId を取得する。
|  | VPN_CONNECTION_DEVICE_TYPE_ID=$(aws ec2 get-vpn-connection-device-types \
  --query 'VpnConnectionDeviceTypes[?Vendor==`Yamaha`].VpnConnectionDeviceTypeId' \
  --output text)
 | 
6-1-2. VPN 接続 ID の取得
|  | VPN_CONNECTION_ID=$(aws ec2 describe-vpn-connections \
  --filters "Name=tag:Name,Values=s2sVPN-connection" \
  --query "VpnConnections[].VpnConnectionId" \
  --output text)
 | 
6-1-3. サンプル設定のダウンロード
--internet-key-exchange-version オプションでは IKE のバージョンの指定ができるが、一旦 IKE v2 で決め打ち。
ダウンロードできるサンプルコンフィグを ${VPN_CONNECTION_ID}.txt という命名規則のテキストファイルへ書き込み保存する。
|  | aws ec2 get-vpn-connection-device-sample-configuration \
  --vpn-connection-id ${VPN_CONNECTION_ID} \
  --vpn-connection-device-type-id ${VPN_CONNECTION_DEVICE_TYPE_ID} \
  --internet-key-exchange-version ikev2 \
  --query "VpnConnectionDeviceSampleConfiguration" \
  --output text > ${VPN_CONNECTION_ID}.txt
 | 
6-2. ルーターへのコンフィグ投入
以下のようなコマンドで、コメント行、空白行を取り除いた上で、ルーター機器へコンフィグを投入する。
なお、AWS からダウンロードできるサンプルコンフィグでは、ipsec ike local address として記載されている IP アドレスがグローバル IP アドレスとなっているため、プライベート IP アドレス(ルーターのアドレス)に書き換える。 
6-2-1. プライベート IP アドレス文字列としてデフォルトゲートウェイの値を利用する例
|  | DEFAULT_GATEWAY=$(route -n get 0.0.0.0 | grep gateway | awk '{print $2}')
 | 
また、AWS からダウンロードできるサンプルコンフィグでは、bgp import filter で広告される経路が 0.0.0.0/0 となっているため、この部分も LAN のネットワークアドレスの修正する必要がある。
|  | eval `ifconfig | grep 172 | head -n 1 | awk '{ printf("LOCAL_IP_ADDRESS=\"%s\" ; NETMASK=\"%s\"",$2,$4) }'`
 | 
6-2-2. 接続中のネットワークからネットワークアドレス文字列の作成
この処理だけ、標準ではインストールされていない ipcalc コマンドを処理として利用している。
ipcalc コマンドは homebrew でインストールを実施
|  | NETWORK_ADDRESS=$(ipcalc ${LOCAL_IP_ADDRESS}/${NETMASK} \
  | grep Network \
  | awk '{print $2}' \
  | sed 's/\//\\\//g')
 | 
6-2-3.サンプルコンフィグを微調整して表示させる例
1回目の sed でグローバル IP アドレスからプライベート IP アドレス(ルーターのアドレス)に書き換えを、2回目の sed で bgp import filter 部分をネットワークアドレスに書き換えている。
|  | cat ${VPN_CONNECTION_ID}.txt \
  | grep -v -e '^\s*#' -e '^\s*$' \
  | sed "s/${GLOBAL_IP_ADDRESS}/${DEFAULT_GATEWAY}/g" \
  | sed "s/0.0.0.0\/0/${NETWORK_ADDRESS}/g"
 |