Azure-AWS間でVPN接続した環境をARMテンプレートとAWS CloudFormationで作成する

はじめに

検証でAzure環境とAWS環境をVPN接続した環境が必要となり、以下記事を参考に環境を構築しようとしました。
最低限のコストで、必要な時に作ったり消したりを気軽にできるよう、テンプレート化してみたという記事です。

チュートリアル - ポータルを使用して Azure と アマゾン ウェブ サービス (AWS) 間の BGP 対応接続を構成する - Azure VPN Gateway
このチュートリアルでは、アクティブ/アクティブ VPN Gateway と AWS 上の 2 つのサイト間接続を使用して Azure と AWS を接続する方法について説明します。

上記記事の完全体はアクティブ-アクティブ構成かつ2つのトンネルで構成されていますが、今回はアクティブ-アクティブを無効にしてトンネルを1つだけ構成してます。段階的には成長期です。
一時的な検証用途なので、最低限の構成でつながればいいやという思想です。イメージはこんな感じ。

概要図

図としては、以下のような感じです。

テンプレート

テンプレートは3つ用意しています。これはリソース構築後に払い出される値が必要なリソースがあるためです。
例えば、AWS側のカスタマーゲートウェイにAzureのパブリックIPが必要である、とか。
作成の大まかな流れは以下の通りです。

Step 作業項目 備考
Step1:【Azure】NW基盤作成 ①VNet・サブネットの作成
②Virtual Network Gateway用パブリックIPの作成
対応テンプレート:
azure_network_resource.json
Step2:【AWS】VPNリソース作成 ①VPC作成
②カスタマーゲートウェイ作成
③仮想ネットワークゲートウェイ作成
④VPN接続作成
⑤ルート伝搬の有効化
対応テンプレート:aws_vpn_resource.yaml
Step3:【Azure】VPNリソース作成 ①Local Network Gateway作成
②Virtual Network Gateway作成
③VPN接続作成
対応テンプレート:azure_vpn_resource.json

Step1 :【Azure】NW基盤作成

指定しているパラメータ

パラメータ名 デフォルト値 備考
vnetName VNet1 作成するVNetの名前
vnetAddressPrefix 10.1.0.0/16 作成するVNetのCIDR範囲
subnet1Prefix 10.1.0.0/24 GatewaySubnetのCIDR範囲
vpnpipName VNet1GWpip パブリックIPの名前

コード

ファイル名:azure_network_resource.json

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "metadata": {
      "_generator": {
        "name": "bicep",
        "version": "0.6.18.56646",
        "templateHash": "10806234693722113459"
      }
    },
    "parameters": {
      "vnetName": {
        "type": "string",
        "metadata": {
            "description": "VNet Name"
          },
        "defaultValue": "VNet1"
      },
      "vnetAddressPrefix": {
        "type": "string",
        "metadata": {
            "description": "VNet CIDR range"
          },
        "defaultValue": "10.1.0.0/16"
      },
      "subnet1Prefix": {
        "type": "string",
        "metadata": {
            "description": "Gateway Subnet CIDR range"
          },
        "defaultValue": "10.1.0.0/24"
      },
       "vpnpipName": {
        "type": "string",
        "metadata": {
            "description": "Public IP Name"
          },
        "defaultValue": "VNet1GWpip"
      }
    },
    "resources": [
      {
        "type": "Microsoft.Network/virtualNetworks",
        "apiVersion": "2024-05-01",
        "name": "[parameters('vnetName')]",
        "location": "[resourceGroup().location]",
        "properties": {
          "addressSpace": {
            "addressPrefixes": [
              "[parameters('vnetAddressPrefix')]"
            ]
          },
          "subnets": [
            {
              "name": "GatewaySubnet",
              "properties": {
                "addressPrefix": "[parameters('subnet1Prefix')]"
              }
            }
          ]
        }
      },
      {
        "type": "Microsoft.Network/publicIPAddresses",
        "apiVersion": "2024-05-01",
        "name": "[parameters('vpnpipName')]",
        "location": "[resourceGroup().location]",
        "sku": {
          "name": "Standard",
          "tier": "Regional"
        },
        "properties": {
          "publicIPAllocationMethod": "Static",
          "idleTimeoutInMinutes": 4
        }
      }
    ]
  }

Step2:【AWS】VPNリソース作成

指定しているパラメータ

パラメータ名 デフォルト値 備考
myVPCName VPC1 作成するVPCの名前
myVPCCIDR 10.2.0.0/16 作成するVPCのCIDR範囲
VGWName AzureGW 仮想ネットワークゲートウェイの名前
CGWName ToAzureInstance0 カスタマーゲートウェイの名前
VPNConnectionName ToAzureConnection VPN接続の名前
CustomBGPASN 65000 Azure側GatewayのASN
azurepip なし Step1で作成したパブリックIPを指定

コード

ファイル名:aws_vpn_resource.yaml

AWSTemplateFormatVersion: '2010-09-09'
Description: Create a Virtual Private Gateway and Customer Gateway

Parameters:
  myVPCName:
    Type: String
    Default: "VPC1" # VPCの名前
  myVPCCIDR:
    Type: String
    Default: "10.2.0.0/16" # VPCのCIDR範囲
  VGWName:
    Type: String
    Default: "AzureGW" # 仮想ネットワークゲートウェイのリソース名
  CGWName:
    Type: String
    Default: "ToAzureInstance0" # カスタムネットワークゲートウェイのリソース名
  VPNConnectionName:
    Type: String
    Default: "ToAzureConnection" # VPN接続の名前
  CustomBGPASN:
    Type: Number
    Default: 65000 # 任意のASNを入力
  azurepip: # スタック作成時にAzure側のパブリックIPを入力する。
    Type: String

Resources:
  # VPCの作成
  myVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref myVPCCIDR
      Tags:
        - Key: Name
          Value: !Ref myVPCName

  MyVpcDefaultRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref myVPC

  # 仮想プライベートゲートウェイの作成
  VirtualPrivateGateway:
    Type: AWS::EC2::VPNGateway
    Properties:
      Type: ipsec.1
      Tags:
        - Key: Name
          Value: !Ref VGWName

  # 仮想プライベートゲートウェイをVPCにアタッチ
  VPCGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref myVPC
      VpnGatewayId: !Ref VirtualPrivateGateway

  # カスタマーゲートウェイの作成
  CustomerGateway:
    Type: AWS::EC2::CustomerGateway
    Properties:
      BgpAsn: !Ref CustomBGPASN
      IpAddress: !Ref azurepip  # カスタマーゲートウェイのパブリックIPアドレス
      Type: ipsec.1
      Tags:
        - Key: Name
          Value: !Ref CGWName

  # VPN接続の作成
  VPNConnection:
    Type: AWS::EC2::VPNConnection
    Properties:
      Type: ipsec.1
      CustomerGatewayId: !Ref CustomerGateway
      VpnGatewayId: !Ref VirtualPrivateGateway
      StaticRoutesOnly: false  # 動的ルーティングとする。
      Tags:
        - Key: Name
          Value: !Ref VPNConnectionName
      VpnTunnelOptionsSpecifications:
        - TunnelInsideCidr: "169.254.21.0/30"  # トンネル1の内部IPv4 CIDR
        - TunnelInsideCidr: "169.254.22.0/30"  # トンネル2の内部IPv4 CIDR

  # ルート伝搬の有効化

  EnableRoutePropagation:
    Type: AWS::EC2::VPNGatewayRoutePropagation
    Properties:
      RouteTableIds:
        - !Ref MyVpcDefaultRouteTable
      VpnGatewayId: !Ref VirtualPrivateGateway
    DependsOn: VPCGatewayAttachment

Outputs:
  VirtualPrivateGatewayId:
    Description: "The ID of the Virtual Private Gateway"
    Value: !Ref VirtualPrivateGateway

  CustomerGatewayId:
    Description: "The ID of the Customer Gateway"
    Value: !Ref CustomerGateway

  VPNConnectionId:
    Description: "The ID of the VPN Connection"
    Value: !Ref VPNConnection

Step3:【Azure】VPNリソース作成

指定しているパラメータ

パラメータ名 デフォルト値 備考
myVNet VNet1 Step1で作成したVNetの名前
publicIpName
VNet1GWpip
Step1で作成したパブリックIPの名前
localNetworkGatewayName
lngw_test
Local Network Gatewayの名前
asn
64512 AWS側のASN
bgpPeeringAddress
169.254.21.1 Local Network GatewayのピアIP
customBgpIpAddress
169.254.21.2 Virtual Network GatewayのピアIP
virtualNetworkGatewayName
vngw_test
Virtual Network Gatewayの名前
vngwasn
65000 Azure側のASN
gatewaySku
VpnGw1
VPN GatewayのSKUを指定
virtualNetworkConnectionName
AWSTunnel1toAzureInstance0
VPN接続の名前
gatewayIpAddress
なし
Step2で作成したVPN接続(トンネル1)のパブリックIPを指定
PreSharedKey
なし
Step2で作成したVPN接続の事前共有鍵を指定

コード

ファイル名:aws_vpn_resource.yaml

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
      "myVNet": {
        "type": "string",
        "metadata": {
          "description": "VNet Name"
        },
        "defaultValue": "VNet1"
      },
      "publicIpName": {
        "type": "string",
        "metadata": {
          "description": "PublicIPAddress Name"
        },
        "defaultValue": "VNet1GWpip"
      },
      "localNetworkGatewayName": {
        "type": "string",
        "metadata": {
          "description": "LocalNetworkGateway Name"
        },
        "defaultValue": "lngw_test"
      },
      "asn": {
        "type": "int",
        "metadata": {
          "description": "Autonomous System Number (ASN) for BGP"
        },
        "defaultValue": 64512
      },
      "bgpPeeringAddress": {
        "type": "string",
        "metadata": {
          "description": "BGP peering address for LocalNetworkGateway"
        },
        "defaultValue": "169.254.21.1"
      },
      "customBgpIpAddress": {
        "type": "string",
        "metadata": {
          "description": "BGP peering address for VirtualNetworkGateway"
        },
        "defaultValue": "169.254.21.2"
      },
      "virtualNetworkGatewayName": {
        "type": "string",
        "metadata": {
          "description": "Name of the virtual network gateway"
        },
        "defaultValue": "vngw_test"
      },
      "vngwasn": {
        "type": "int",
        "metadata": {
          "description": "Autonomous System Number (ASN) for BGP"
        },
        "defaultValue": 65000
      },    
      "gatewaySku": {
        "type": "string",
        "metadata": {
          "description": "SKU for the virtual network gateway"
        },
        "defaultValue": "VpnGw1",
        "allowedValues": [
          "Basic",
          "VpnGw1",
          "VpnGw2",
          "VpnGw3",
          "VpnGw4",
          "VpnGw5"
        ]
      },
      "virtualNetworkConnectionName": {
        "type": "string",
        "metadata": {
          "description": "Name of the VPN Connection"
        },
        "defaultValue": "AWSTunnel1toAzureInstance0"
      },
      "gatewayIpAddress": {
        "type": "string",
        "metadata": {
            "description": "AWS Public IP Address"
          }
      },
      "PreSharedKey": {
        "type": "string",
        "metadata": {
          "description": "Pre-SharedKey"
        }
      }
    },
    "resources": [
      {
        "type": "Microsoft.Network/localNetworkGateways",
        "apiVersion": "2024-05-01",
        "name": "[parameters('localNetworkGatewayName')]",
        "location": "[resourceGroup().location]",
        "properties": {
          "gatewayIpAddress": "[parameters('gatewayIpAddress')]",
          "bgpSettings": {
            "asn": "[parameters('asn')]",
            "bgpPeeringAddress": "[parameters('bgpPeeringAddress')]"
          }
        }
      },
      {
        "type": "Microsoft.Network/virtualNetworkGateways",
        "apiVersion": "2024-05-01",
        "name": "[parameters('virtualNetworkGatewayName')]",
        "location": "[resourceGroup().location]",
        "properties": {
          "ipConfigurations": [
            {
              "name": "vnetGatewayConfig",
              "properties": {
                "privateIPAllocationMethod": "Dynamic",
                "subnet": {
                  "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('myVNet'), 'GatewaySubnet')]"
                },
                "publicIPAddress": {
                  "id": "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIpName'))]"
                }
              }
            }
          ],
          "gatewayType": "Vpn",
          "vpnType": "RouteBased",
          "enableBgp": true,
          "activeActive": false,
          "sku": {
            "name": "[parameters('gatewaySku')]",
            "tier": "[parameters('gatewaySku')]"
          },
          "bgpSettings": {
            "asn": "[parameters('vngwasn')]",
            "bgpPeeringAddresses": [
              {
                "ipconfigurationId": "[resourceId('Microsoft.Network/virtualNetworkGateways/ipConfigurations', parameters('virtualNetworkGatewayName'), 'vnetGatewayConfig')]",
                "customBgpIpAddresses": [ "[parameters('customBgpIpAddress')]" ]
              }
            ]
          }
        }
      },
      {
        "type": "Microsoft.Network/connections",
        "apiVersion": "2024-05-01",
        "name": "[parameters('virtualNetworkConnectionName')]",
        "location": "[resourceGroup().location]",
        "dependsOn": [
          "[resourceId('Microsoft.Network/virtualNetworkGateways', parameters('virtualNetworkGatewayName'))]",
          "[resourceId('Microsoft.Network/localNetworkGateways', parameters('localNetworkGatewayName'))]"
        ],
        "properties": {
          "virtualNetworkGateway1": {
            "id": "[resourceId('Microsoft.Network/virtualNetworkGateways', parameters('virtualNetworkGatewayName'))]"
          },
          "localNetworkGateway2": {
            "id": "[resourceId('Microsoft.Network/localNetworkGateways', parameters('localNetworkGatewayName'))]"
          },
          "connectionType": "IPsec",
          "sharedKey": "[parameters('PreSharedKey')]",
          "enableBgp": true
        }
      }
    ],
    "outputs": {
      "localNetworkGatewayId": {
        "type": "string",
        "value": "[resourceId('Microsoft.Network/localNetworkGateways', parameters('localNetworkGatewayName'))]"
      },
      "VirtualNetworkGatewayId": {
        "type": "string",
        "value": "[resourceId('Microsoft.Network/localNetworkGateways', parameters('localNetworkGatewayName'))]"
      }
    }
  }

手順

ここからは上記テンプレートを用いた簡単な構築手順を記載します。なお、細かい画面遷移等は手順を省いていますのでご了承ください。
なお、Azure CLIがインストールされていることが前提となります。インストール手順は以下参照です。

Azure CLI をインストールする方法
Azure CLI は、Windows、macOS、および Linux 環境にインストールできます。 Docker コンテナーおよび Azure Cloud Shell でも実行できます。

リソース構築手順

①Azure CLIを使うため以下コマンドでAzureにログインします。

az login

②Azure側にリソースグループがない場合は以下コマンドでリソースグループを作成して下さい。

az group create --name <リソースグループ名> --location japaneast

③以下コマンドでAzureリソース(NW関連)をデプロイします。

az deployment group create --resource-group <リソースグループ名> --template-file azure_network_resource.json

 デプロイ後、作成したパブリックIPのアドレスを控えます。

④AWSコンソール画面のCloudFormationよりスタックを作成してください。

  テンプレートファイルを読み込ませます。

  パラメータとして③で確認したAzure側のパブリックIPアドレスを入力します。
  その他はデフォ設定のままスタックを送信すればOKです。

⑤CloudFormationが正常終了したら、VPN接続画面でトンネルのパブリックIPを確認します。

⑥また、構成ファイルをダウンロードします。


ダウンロードしたファイル内に事前共有鍵が書かれてるので、後ほど使います。

⑦最後に以下コマンドでAzureリソース(VPN関連)をデプロイします。
gatewayIpAddressで⑤で確認したパブリックIPを、PreSharedKeyで⑥で確認した事前共有鍵を指定します。

az deployment group create --resource-group <リソースグループ名> --template-file azure_vpn_resource.json --parameters gatewayIpAddress=<⑤で確認したパブリックIP> PreSharedKey=<⑥で確認した事前共有鍵>

➇以下のようになってれば、つながってるはずです。
※Azure上で仮想VM、AWS上でEC2をたて、疎通できることを確認しました。
【Azure側】

【AWS側】

リソース削除手順

【Azure】
リソースグループを削除することで作成したリソースが全部消えます。以下コマンドを実行ください。

az group delete --name <リソースグループ名>

【AWS】
CloudFormationのスタックを削除することで作成したリソースが全部消えます。

 

おわりに

以上、AWSとAzureをVPN接続してみた、でした。本当に接続するとこだけしか作ってませんが。。
ちなみに構築全体流すので大体40分くらいかかります。※AzureのVPNリソース作成が30分超かかる。

コンセプトとしてはAzure、AWSに何もない状態で0から作るってことと手数をできるだけ少なくってことを意識しました。
とはいえ、AzureとAWSという異なるプラットフォームから値を引っ張ってくる必要があるので1つのテンプレートにおさめるのは難しく、手順も何ステップかに分かれてるのでもう少し工夫できないかなあと思っているところです。

余裕がでてくればそのうち冒頭のMicrosoft記事の完全体を作れるように…したいところです。

著者について

主にWindows基盤とかAWS基盤とか作ってます。Azureも最近かかわり中。

三坂慎一郎をフォローする

クラウドに強いによるエンジニアブログです。

SCSKクラウドサービス(AWS)は、企業価値の向上につながるAWS 導入を全面支援するオールインワンサービスです。AWS最上位パートナーとして、多種多様な業界のシステム構築実績を持つSCSKが、お客様のDX推進を強力にサポートします。


クラウドに強いによるエンジニアブログです。

SCSKクラウドサービス(Azure)は、Azureを最大限活用するためのオールインワンサービスです。40年以上の様々なシステム構築・運用実績で得た業界理解と、Azure構築ナレッジを強みに、クラウドへの移行から運用までトータルでサポートし、お客様のAzure活用を実現します。

AWSAzureクラウドソリューションネットワーク
シェアする
タイトルとURLをコピーしました