この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
みなさん、こんにちは!
AWS事業本部の青柳@福岡オフィスです。
静的ルーティングによる サイト間VPN接続 を検証する必要があったため、オープンソースのソフトウェアルーターである VyOS を使ってVPN環境を構築しました。
なお、VyOSを利用した動的ルーティング (BGP) によるVPN接続については、下記のブログエントリで紹介されています。
VyOS1.2を利用したVPN環境構築 | Developers.IO
VyOSを利用したVPN環境構築 | Developers.IO
構成
下図のような構成を構築します。
東京リージョンをAWS側、シンガポールリージョンをオンプレミス側にそれぞれ見立ててサイト間VPN接続を構築します。
東京リージョンには 仮想プライベートゲートウェイ (VGW) を配置します。
シンガポールリージョンには カスタマーゲートウェイデバイス (オンプレミス側ルーター) としてVyOSがインストールされたEC2インスタンスを配置します。
各リージョンのプライベートサブネットに、動作検証用のEC2インスタンス (Linux+nginx) を配置します。
構築手順
1. ベース環境の作成
VPN環境の構築を始める前に、まず、ベースとなるネットワーク環境 (VPC、サブネットなど) と動作確認用EC2インスタンスを作成します。
今回はCloudFormationで作成しました。
ベース環境作成CloudFormationテンプレート (クリックすると展開します)
vpn-test-base.yaml
---
AWSTemplateFormatVersion: "2010-09-09"
Description: "VPN TEST: Base environment (VPC and EC2)"
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: "General Information"
Parameters:
- SystemName
- Environment
- Label:
default: "Network Configuration"
Parameters:
- CidrBlockVPC
- CidrBlockSubnetPublic1
- CidrBlockSubnetPrivate1
- CidrBlockRemoteNetwork
- Label:
default: "EC2 Instance Configuration"
Parameters:
- EC2ImageID
- EC2InstanceType
- EC2KeyName
- EC2VolumeType
- EC2VolumeSize
Parameters:
SystemName:
Type: String
AllowedValues:
- tokyo
- singapore
Environment:
Type: String
Default: dev
AllowedValues:
- dev
- str
- prd
CidrBlockVPC:
Type: String
AllowedValues:
- 10.0.0.0/16
- 192.168.0.0/16
CidrBlockSubnetPublic1:
Type: String
AllowedValues:
- 10.0.0.0/24
- 192.168.0.0/24
CidrBlockSubnetPrivate1:
Type: String
AllowedValues:
- 10.0.128.0/24
- 192.168.128.0/24
CidrBlockRemoteNetwork:
Type: String
AllowedValues:
- 192.168.128.0/24
- 10.0.128.0/24
EC2ImageID:
Type: AWS::SSM::Parameter::Value<String>
Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
EC2InstanceType:
Type: String
Default: t3.micro
EC2KeyName:
Type: AWS::EC2::KeyPair::KeyName
EC2VolumeType:
Type: String
Default: gp2
EC2VolumeSize:
Type: String
Default: 8
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref CidrBlockVPC
EnableDnsSupport: true
EnableDnsHostnames: true
InstanceTenancy: default
Tags:
- Key: Name
Value: !Sub "${SystemName}-${Environment}-vpc"
- Key: System
Value: !Ref SystemName
- Key: Environment
Value: !Ref Environment
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: !Sub "${SystemName}-${Environment}-igw"
- Key: System
Value: !Ref SystemName
- Key: Environment
Value: !Ref Environment
VPCGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId: !Ref InternetGateway
VpcId: !Ref VPC
SubnetPublic1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select
- 0
- Fn::GetAZs: !Ref AWS::Region
CidrBlock: !Ref CidrBlockSubnetPublic1
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub "${SystemName}-${Environment}-public1-subnet"
- Key: System
Value: !Ref SystemName
- Key: Environment
Value: !Ref Environment
SubnetPrivate1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select
- 0
- Fn::GetAZs: !Ref AWS::Region
CidrBlock: !Ref CidrBlockSubnetPrivate1
Tags:
- Key: Name
Value: !Sub "${SystemName}-${Environment}-private1-subnet"
- Key: System
Value: !Ref SystemName
- Key: Environment
Value: !Ref Environment
EIPNatGateway:
DependsOn:
- VPCGatewayAttachment
Type: AWS::EC2::EIP
Properties:
Domain: vpc
NatGateway:
DependsOn:
- EIPNatGateway
- SubnetPublic1
Type: AWS::EC2::NatGateway
Properties:
AllocationId: !GetAtt EIPNatGateway.AllocationId
SubnetId: !Ref SubnetPublic1
Tags:
- Key: Name
Value: !Sub "${SystemName}-${Environment}-natgateway"
- Key: System
Value: !Ref SystemName
- Key: Environment
Value: !Ref Environment
RouteTablePublic:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub "${SystemName}-${Environment}-public-rtb"
- Key: System
Value: !Ref SystemName
- Key: Environment
Value: !Ref Environment
RouteTablePrivate:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub "${SystemName}-${Environment}-private-rtb"
- Key: System
Value: !Ref SystemName
- Key: Environment
Value: !Ref Environment
RouteIGW:
DependsOn:
- VPCGatewayAttachment
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref RouteTablePublic
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
RouteNatGateway:
DependsOn:
- NatGateway
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref RouteTablePrivate
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NatGateway
RouteTableAssociationPublic1:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref SubnetPublic1
RouteTableId: !Ref RouteTablePublic
RouteTableAssociationPrivate1:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref SubnetPrivate1
RouteTableId: !Ref RouteTablePrivate
IAMRoleSSM:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${SystemName}-${Environment}-ssm-role"
AssumeRolePolicyDocument: |
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
Path: /
IAMInstanceProfileSSM:
Type: AWS::IAM::InstanceProfile
Properties:
InstanceProfileName: !Sub "${SystemName}-${Environment}-ssm-role"
Roles:
- !Ref IAMRoleSSM
Path: /
SecurityGroupServer:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub "${SystemName}-${Environment}-server-sg"
GroupDescription: "Security group for servers"
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: !Ref CidrBlockRemoteNetwork
Description: "HTTP access from remote network"
- IpProtocol: icmp
FromPort: -1
ToPort: -1
CidrIp: !Ref CidrBlockRemoteNetwork
Description: "ICMP access from remote network"
Tags:
- Key: Name
Value: !Sub "${SystemName}-${Environment}-server-sg"
- Key: System
Value: !Ref SystemName
- Key: Environment
Value: !Ref Environment
EC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref EC2ImageID
InstanceType: !Ref EC2InstanceType
KeyName: !Ref EC2KeyName
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
VolumeType: !Ref EC2VolumeType
VolumeSize: !Ref EC2VolumeSize
NetworkInterfaces:
- DeviceIndex: 0
SubnetId: !Ref SubnetPrivate1
GroupSet:
- !Ref SecurityGroupServer
IamInstanceProfile: !Ref IAMInstanceProfileSSM
UserData:
Fn::Base64: !Sub |
#!/bin/bash -xe
amazon-linux-extras install -y nginx1
systemctl enable nginx
systemctl start nginx
SYSTEM_NAME=${SystemName}
echo Hello! I\'m ${!SYSTEM_NAME^^} Web Server! > /usr/share/nginx/html/index.html
Tags:
- Key: Name
Value: !Sub "${SystemName}-${Environment}-server"
- Key: System
Value: !Ref SystemName
- Key: Environment
Value: !Ref Environment
Outputs:
VPC:
Value: !Ref VPC
Export:
Name: !Sub "${AWS::StackName}::VPC"
SubnetPublic1:
Value: !Ref SubnetPublic1
Export:
Name: !Sub "${AWS::StackName}::SubnetPublic1"
SubnetPrivate1:
Value: !Ref SubnetPrivate1
Export:
Name: !Sub "${AWS::StackName}::SubnetPrivate1"
RouteTablePublic:
Value: !Ref RouteTablePublic
Export:
Name: !Sub "${AWS::StackName}::RouteTablePublic"
RouteTablePrivate:
Value: !Ref RouteTablePrivate
Export:
Name: !Sub "${AWS::StackName}::RouteTablePrivate"
IAMRoleSSM:
Value: !Ref IAMRoleSSM
Export:
Name: !Sub "${AWS::StackName}::IAMRoleSSM"
IAMInstanceProfileSSM:
Value: !Ref IAMInstanceProfileSSM
Export:
Name: !Sub "${AWS::StackName}::IAMInstanceProfileSSM"
SecurityGroupServer:
Value: !Ref SecurityGroupServer
Export:
Name: !Sub "${AWS::StackName}::SecurityGroupServer"
EC2Instance:
Value: !Ref EC2Instance
Export:
Name: !Sub "${AWS::StackName}::EC2Instance"
CloudFormationテンプレートは東京・シンガポールの各リージョンで共通です。
各リージョン毎に、パラメータは以下のように指定してください。
パラメータ名 | 設定値 (東京リージョン) | 設定値 (シンガポールリージョン) |
---|---|---|
SystemName | tokyo | singapore |
CidrBlockVPC | 10.0.0.0/16 | 192.168.0.0/16 |
CidrBlockSubnetPublic1 | 10.0.0.0/24 | 192.168.0.0/24 |
CidrBlockSubnetPrivate1 | 10.0.128.0/24 | 192.168.128.0/24 |
CidrBlockRemoteNetwork | 192.168.128.0/24 | 10.0.128.0/24 |
EC2KeyName | (任意のキーペア) | (任意のキーペア) |
このCloudFormationテンプレートで作成される「動作確認用EC2インスタンス」のポイントは以下の通りです:
- UserDataを使ってnginxを自動的にインストール
- Systems Managerのセッションマネージャーを使って操作できるように、IAMインスタンスプロファイルを設定
- 対向リージョンのプライベートサブネットからのICMPおよびHTTPによるアクセスを許可するセキュリティグループ
2. VyOSインスタンスの作成
シンガポールリージョンに、ルーターとなるVyOSインスタンスを作成します。
こちらも同様にCloudFormationで作成します。
VyOSインスタンス作成CloudFormationテンプレート (クリックすると展開します)
vpn-test-vyos.yaml
---
AWSTemplateFormatVersion: "2010-09-09"
Description: "VPN TEST: VyOS EC2 Instance (site-to-site VPN router)"
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: "General Information"
Parameters:
- SystemName
- Environment
- Label:
default: "Network Configuration"
Parameters:
- CidrBlockAllowAccessRouter
- IPAddressAllowSSH
- Label:
default: "EC2 Instance Configuration"
Parameters:
- EC2ImageID
- EC2InstanceType
- EC2KeyName
- EC2VolumeType
- EC2VolumeSize
- Label:
default: "CloudFormation Stack Reference"
Parameters:
- StackVPC
Parameters:
SystemName:
Type: String
Default: singapore
Environment:
Type: String
Default: dev
AllowedValues:
- dev
- str
- prd
CidrBlockAllowAccessRouter:
Type: String
Default: 192.168.128.0/24
IPAddressAllowSSH:
Type: String
EC2ImageID:
Type: AWS::EC2::Image::Id
Default: ami-070a39a224bab5d4f # VyOS (HVM) 1.2.4-9c9395f4-e891-4577-82e9-a6d5bccfb3c9-ami-00c8302b5b62b168a.4 @ ap-southeast-1
EC2InstanceType:
Type: String
Default: t3.large
EC2KeyName:
Type: AWS::EC2::KeyPair::KeyName
EC2VolumeType:
Type: String
Default: gp2
EC2VolumeSize:
Type: String
Default: 10
StackVPC:
Type: String
Resources:
SecurityGroupVyOS:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub "${SystemName}-${Environment}-router-sg"
GroupDescription: "Security group for servers"
VpcId: {"Fn::ImportValue": !Sub "${StackVPC}::VPC"}
SecurityGroupIngress:
- IpProtocol: -1
FromPort: -1
ToPort: -1
CidrIp: !Ref CidrBlockAllowAccessRouter
Description: "Access by all protocols from allowed network"
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: !Ref IPAddressAllowSSH
Description: "SSH access from my IP address"
Tags:
- Key: Name
Value: !Sub "${SystemName}-${Environment}-router-sg"
- Key: System
Value: !Ref SystemName
- Key: Environment
Value: !Ref Environment
EC2InstanceVyOS:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref EC2ImageID
InstanceType: !Ref EC2InstanceType
KeyName: !Ref EC2KeyName
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
VolumeType: !Ref EC2VolumeType
VolumeSize: !Ref EC2VolumeSize
NetworkInterfaces:
- DeviceIndex: 0
SubnetId: {"Fn::ImportValue": !Sub "${StackVPC}::SubnetPublic1"}
GroupSet:
- !Ref SecurityGroupVyOS
SourceDestCheck: false
Tags:
- Key: Name
Value: !Sub "${SystemName}-${Environment}-router"
- Key: System
Value: !Ref SystemName
- Key: Environment
Value: !Ref Environment
EIPVyOS:
Type: AWS::EC2::EIP
Properties:
Domain: vpc
EIPAssociationVyOS:
Type: AWS::EC2::EIPAssociation
Properties:
AllocationId: !GetAtt EIPVyOS.AllocationId
InstanceId: !Ref EC2InstanceVyOS
Outputs:
SecurityGroupVyOS:
Value: !Ref SecurityGroupVyOS
Export:
Name: !Sub "${AWS::StackName}::SecurityGroupVyOS"
EC2InstanceVyOS:
Value: !Ref EC2InstanceVyOS
Export:
Name: !Sub "${AWS::StackName}::EC2InstanceVyOS"
EC2InstanceVyOSPublicIP:
Value: !GetAtt EC2InstanceVyOS.PublicIp
Export:
Name: !Sub "${AWS::StackName}::EC2InstanceVyOSPublicIP"
EC2InstanceVyOSPrivateIP:
Value: !GetAtt EC2InstanceVyOS.PrivateIp
Export:
Name: !Sub "${AWS::StackName}::EC2InstanceVyOSPrivateIP"
パラメータは以下のように指定してください。
パラメータ名 | 設定値 |
---|---|
IPAddressAllowSSH | SSH接続元IPアドレス (例:11.22.33.44/32) |
EC2KeyName | (任意のキーペア) |
StackVPC | 「1. ベース環境の構築」で作成したCloudFormationスタック名 |
マネジメントコンソールで作成する場合は、以下の点に留意してください。
- AMIは、キーワード「VyOS」で検索してヒットした中から「AWS Marketplace」のものを選択
- セキュリティグループは以下のインバウンドルールを設定
- すべてのトラフィック: シンガポールリージョンのプライベートサブネット (192.168.128.0/24)
- SSH: マイIP
- インスタンス作成後、「送信元/送信先チェック」を「無効」に設定
3. VPN関連リソースの作成
東京リージョンで、VPN関連のAWSリソースを設定していきます。
(1) カスタマーゲートウェイを作成する
マネジメントコンソールで [VPC]-[カスタマーゲートウェイ] を開きます。
[カスタマーゲートウェイの作成] をクリックします。
項目 | 設定値 |
---|---|
名前 | 任意の名前 (例:tokyo-dev-cgw) |
ルーティング | 「静的」 |
IPアドレス | 作成したVyOSインスタンスのパブリックIPアドレス |
(「Certificate ARN」「Device」は省略します)
(2) 仮想プライベートゲートウェイを作成して、VPCにアタッチする
マネジメントコンソールで [VPC]-[仮想プライベートゲートウェイ] を開きます。
[仮想プライベートゲートウェイの作成] をクリックします。
項目 | 設定値 |
---|---|
名前 | 任意の名前 (例:tokyo-dev-vgw) |
ASN | 「AmazonのデフォルトASN」 |
作成した仮想プライベートゲートウェイを選択して、[アクション]-[VPCにアタッチ]を選択します。
「tokyo-dev-vpc」を選択して「はい、アタッチします」を選択します。
(3) VPN接続を作成する
マネジメントコンソールで [VPC]-[サイト間のVPN接続] を開きます。
[VPN接続の作成] をクリックします。
項目 | 設定値 |
---|---|
名前タグ | 任意の名前 (例:tokyo-dev-vpn) |
Target Gateway Type | 「Virtual Private Gateway」 |
仮想プライベートゲートウェイ | 作成した仮想プライベートゲートウェイ (tokyo-dev-vgw) |
カスタマーゲートウェイ | 「既存」 |
Customer Gateway ID | 作成したカスタマーゲートウェイ (tokyo-dev-cgw) |
ルーティングオプション | 「静的」 |
静的IPプレフィックス | 192.168.128.0/24 |
(「トンネルオプション」は全てデフォルトのままにします)
作成直後は「状態」が「保留中」になります。
状態が「使用可能」になるまで待ちます。(数分間)
(4) ルートテーブルでルート伝播を有効にする
マネジメントコンソールで [VPC]-[ルートテーブル] を開きます。
プライベートサブネットのルートグループ「tokyo-dev-private-rtb」を選択します。
[ルート伝播] タブを開いて、[ルート伝達の編集] をクリックします。
仮想プライベートゲートウェイ「tokyo-dev-vgw」の [伝播] にチェックを入れて、[保存] をクリックします。
「伝播」欄が「はい」になったことを確認します。
なお、この時点では、実際のルート追加はまだ行われません。
4. VyOSの設定
シンガポールリージョンで、VyOSインスタンスにルーターの設定を行っていきます。
(1) ルーター設定ファイルのテンプレートをダウンロードする
ルーターの設定を行う前に、東京リージョン側で「サイト間VPN接続」画面で [設定のダウンロード] をクリックして、ルーター設定ファイルのテンプレート をダウンロードします。
ここが今回の作業のポイントの一つです。
動的ルーティング (BGPあり) のVPN接続を作成した場合、ここで「ベンダー」に「Vyatta」を選択してVyOS向けの設定ファイルをダウンロードすることができました。(VyattaはVyOSの前身となるソフトウェア)
ところが、静的ルーティングのVPN接続の場合は、同じ画面で「Vyatta」が選択肢に現れないため、ダウンロードすることができません。
そのため、ここでは「Generic」を選択して汎用の設定ファイルを入手することにします。
(汎用と言っても、ダウンロードした設定ファイルが各ベンダーのルーターにそのまま投入できる訳ではなく、設定に必要なパラメーターが列挙されたファイルになっています)
(2) VyOSの設定ファイルを準備する
VyOS向けの設定ファイルをダウンロードすることができませんので、一から記述することにします。
ただし、大部分の設定内容は動的ルーティングの場合と同じですので、動的ルーティング用Vyatta向け設定ファイルを基に記述することができます。
今回、以下のような 静的ルーティング用VyOS向け設定ファイルのテンプレート を用意しました。
# Site-to-Site VPN Configuration for VyOS (v1.2) using static routing
# IKE Configuration
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 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'
# ESP Configuration
set vpn ipsec esp-group AWS compression 'disable'
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'
# WAN Interface Configuration
set vpn ipsec ipsec-interfaces interface 'eth0'
# Tunnel Interface Configuration
# (Tunnel #1)
set interfaces vti vti0 address '<<TUNNEL1_LOCAL_INTERNAL_IP_ADDRESS>>/30'
set interfaces vti vti0 description 'VPC tunnel 1'
set interfaces vti vti0 mtu '1436'
# (Tunnel #2)
set interfaces vti vti1 address '<<TUNNEL2_LOCAL_INTERNAL_IP_ADDRESS>>/30'
set interfaces vti vti1 description 'VPC tunnel 2'
set interfaces vti vti1 mtu '1436'
# Tunnel IPsec Configuration
# (Tunnel #1)
set vpn ipsec site-to-site peer <<TUNNEL1_REMOTE_EXTERNAL_IP_ADDRESS>> authentication mode 'pre-shared-secret'
set vpn ipsec site-to-site peer <<TUNNEL1_REMOTE_EXTERNAL_IP_ADDRESS>> authentication pre-shared-secret '<<TUNNEL1_PRE_SHARED_KEY>>'
set vpn ipsec site-to-site peer <<TUNNEL1_REMOTE_EXTERNAL_IP_ADDRESS>> description 'VPC tunnel 1'
set vpn ipsec site-to-site peer <<TUNNEL1_REMOTE_EXTERNAL_IP_ADDRESS>> ike-group 'AWS'
set vpn ipsec site-to-site peer <<TUNNEL1_REMOTE_EXTERNAL_IP_ADDRESS>> local-address '<<ROUTER_LAN_IP_ADDRESS>>'
set vpn ipsec site-to-site peer <<TUNNEL1_REMOTE_EXTERNAL_IP_ADDRESS>> vti bind 'vti0'
set vpn ipsec site-to-site peer <<TUNNEL1_REMOTE_EXTERNAL_IP_ADDRESS>> vti esp-group 'AWS'
# (Tunnel #2)
set vpn ipsec site-to-site peer <<TUNNEL2_REMOTE_EXTERNAL_IP_ADDRESS>> authentication mode 'pre-shared-secret'
set vpn ipsec site-to-site peer <<TUNNEL2_REMOTE_EXTERNAL_IP_ADDRESS>> authentication pre-shared-secret '<<TUNNEL2_PRE_SHARED_KEY>>'
set vpn ipsec site-to-site peer <<TUNNEL2_REMOTE_EXTERNAL_IP_ADDRESS>> description 'VPC tunnel 2'
set vpn ipsec site-to-site peer <<TUNNEL2_REMOTE_EXTERNAL_IP_ADDRESS>> ike-group 'AWS'
set vpn ipsec site-to-site peer <<TUNNEL2_REMOTE_EXTERNAL_IP_ADDRESS>> local-address '<<ROUTER_LAN_IP_ADDRESS>>'
set vpn ipsec site-to-site peer <<TUNNEL2_REMOTE_EXTERNAL_IP_ADDRESS>> vti bind 'vti1'
set vpn ipsec site-to-site peer <<TUNNEL2_REMOTE_EXTERNAL_IP_ADDRESS>> vti esp-group 'AWS'
# Static Routing Configuration
# (Tunnel #1)
set protocols static route <<REMOTE_NETWORK_CIDR>> next-hop <<TUNNEL1_REMOTE_INTERNAL_IP_ADDRESS>>
# (Tunnel #2)
set protocols static route <<REMOTE_NETWORK_CIDR>> next-hop <<TUNNEL2_REMOTE_INTERNAL_IP_ADDRESS>>
<<プレースホルダ名>> の部分を、下表に準じて値を当てはめていくことで設定ファイルを作成します。
ルーター全体の設定
マネジメントコンソールで各値を確認して、該当する項目の値を当てはめます。
プレースホルダ項目 | 設定値 |
---|---|
ROUTER_LAN_IP_ADDRESS |
VyOSインスタンスのプライベートIPアドレス |
LOCAL_NETWORK_CIDR |
192.168.128.0/24 (シンガポール側のプライベートサブネットCIDR) |
REMOTE_NETWORK_CIDR |
10.0.128.0/24 (東京側のプライベートサブネットCIDR) |
Tunnel #1 の設定
ダウンロードした汎用設定ファイルの「IPSec Tunnel #1」セクションを参照して、該当する項目の値を当てはめます。
プレースホルダ項目 | 参照する値 |
---|---|
TUNNEL1_PRE_SHARED_KEY |
#1: Internet Key Exchange Configuration > Pre-Shared Key |
TUNNEL1_LOCAL_INTERNAL_IP_ADDRESS |
#3: Tunnel Interface Configuration > Inside IP Addresses > Customer Gateway |
TUNNEL1_REMOTE_INTERNAL_IP_ADDRESS |
#3: Tunnel Interface Configuration > Inside IP Addresses > Virtual Private Gateway |
TUNNEL1_REMOTE_EXTERNAL_IP_ADDRESS |
#3: Tunnel Interface Configuration > Outside IP Addresses > Virtual Private Gateway |
以下は、ダウンロードした汎用設定ファイルの抜粋です。
IPSec Tunnel #1
================================================================================
#1: Internet Key Exchange Configuration
(中略)
- IKE version : IKEv1
- Authentication Method : Pre-Shared Key
- Pre-Shared Key : XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- Authentication Algorithm : sha1
- Encryption Algorithm : aes-128-cbc
- Lifetime : 28800 seconds
- Phase 1 Negotiation Mode : main
- Diffie-Hellman : Group 2
(中略)
#3: Tunnel Interface Configuration
(中略)
Outside IP Addresses:
- Customer Gateway : xx.xx.xx.xx
- Virtual Private Gateway : xx.xx.xx.xx
Inside IP Addresses
- Customer Gateway : 169.254.xx.xx/30
- Virtual Private Gateway : 169.254.xx.xx/30
(後略)
Tunnel #2 の設定
「Tunnel #1」と同様にして、ダウンロードした汎用設定ファイルの「IPSec Tunnel #2」セクションを参照して、該当する項目の値を当てはめます。
プレースホルダ項目 | 参照する値 |
---|---|
TUNNEL2_PRE_SHARED_KEY |
#1: Internet Key Exchange Configuration > Pre-Shared Key |
TUNNEL2_LOCAL_INTERNAL_IP_ADDRESS |
#3: Tunnel Interface Configuration > Inside IP Addresses > Customer Gateway |
TUNNEL2_REMOTE_INTERNAL_IP_ADDRESS |
#3: Tunnel Interface Configuration > Inside IP Addresses > Virtual Private Gateway |
TUNNEL2_REMOTE_EXTERNAL_IP_ADDRESS |
#3: Tunnel Interface Configuration > Outside IP Addresses > Virtual Private Gateway |
(3) VyOSに設定ファイルを投入する
VyOSインスタンスにSSHで接続します。(ユーザー名:vyos)
設定モードに遷移します。
$ configure
プロンプトが「#」に変わります。
設定ファイルの内容をコピー&ペーストします。(コメント行も含めて丸ごとコピペして構いません)
# # Site-to-Site VPN Configuration for VyOS (v1.2) using static routing
#
# # IKE Configuration
# 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'
(中略)
# # Static Routing Configuration
# # (Tunnel #1)
# set protocols static route <<REMOTE_NETWORK_CIDR>> next-hop <<TUNNEL1_REMOTE_INTERNAL_IP_ADDRESS>>
# # (Tunnel #2)
# set protocols static route <<REMOTE_NETWORK_CIDR>> next-hop <<TUNNEL2_REMOTE_INTERNAL_IP_ADDRESS>>
設定をコミットします。
# commit
コミット結果がエラーとならないことを確認して、設定を保存します。
# save
設定モードから抜けます。
# exit
(4) VyOS側でIPsec状態を確認する
参照モード (プロンプトが「$」) で以下のコマンドを実行します。
$ show vpn ike sa
Peer ID / IP Local ID / IP
------------ -------------
XX.XX.XX.XX 192.168.0.XX
Description: VPC tunnel 1
State IKEVer Encrypt Hash D-H Group NAT-T A-Time L-Time
----- ------ ------- ---- --------- ----- ------ ------
up IKEv1 aes128 sha1_96 2(MODP_1024) no 3600 28800
Peer ID / IP Local ID / IP
------------ -------------
XX.XX.XX.XX 192.168.0.XX
Description: VPC tunnel 2
State IKEVer Encrypt Hash D-H Group NAT-T A-Time L-Time
----- ------ ------- ---- --------- ----- ------ ------
up IKEv1 aes128 sha1_96 2(MODP_1024) no 3600 28800
$ show vpn ipsec sa
Connection State Up Bytes In/Out Remote address Remote ID Proposal
---------------------------- ------- ----------- -------------- ---------------- ----------- ------------------------------------------------
peer-XX.XX.XX.XX-tunnel-vti up 118 seconds 0B/0B XX.XX.XX.XX N/A AES_CBC_128/HMAC_SHA1_96/PRF_HMAC_SHA1/MODP_1024
peer-XX.XX.XX.XX-tunnel-vti up 118 seconds 0B/0B XX.XX.XX.XX N/A AES_CBC_128/HMAC_SHA1_96/PRF_HMAC_SHA1/MODP_1024
いずれのコマンドも「State」欄が「up」になっていることを確認します。
(5) VyOSインスタンスを参照するようにルートテーブルを設定
マネジメントコンソールで [EC2]-[インスタンス] を開きます。
VyOSのインスタンス「singapore-dev-router」を選択して、ENIのIDを確認します。
[VPC]-[ルーティングテーブル] を開きます。
プライベートサブネットのルートテーブル「singapore-dev-private-rbt」を選択します。
[ルート] タブを開いて、[ルートの編集] をクリックします。
[ルートの追加] をクリックして、以下のルートを追加します。
項目 | 設定値 |
---|---|
送信先 | 10.0.128.0/24 (東京側のプライベートサブネットCIDR) |
ターゲット | 上で確認した「VyOSインスタンスのENI ID」 |
[ルートの保存] をクリックして設定を保存します。
5. 仮想プライベートゲートウェイ側の確認
東京リージョンで、仮想プライベートゲートウェイとルートテーブルの状態を確認します。
(1) VPN接続のトンネルが「アップ」になっていることを確認
マネジメントコンソールで [VPC]-[サイト間のVPN接続] を開きます。
[tokyo-dev-vpn] を選択して、[Tunnel Details] タブを開きます。
[Tunnel State] で各トンネルの「スタータス」欄が「アップ」になっていることを確認します。
(2) ルートテーブルにルートが伝播していることを確認
マネジメントコンソールで [VPC]-[ルートテーブル] を開きます。
プライベートサブネットのルートグループ「tokyo-dev-private-rtb」を選択します。
[ルート] タブを開きます。
以下のルートが追加されていることを確認します。
- 送信先: 192.168.128.0/24
- ターゲット: 仮想プライベートゲートウェイ
- ステータス: active
- 伝播済み: はい
6. 疎通確認を行う
まず、東京リージョン・シンガポールリージョンの各サーバー間でICMPによる疎通確認を行います。
各サーバーのプライベートIPアドレスを確認して、pingを実行しましょう。
(サーバーへはSystems Managerのセッションマネージャーで接続することができます)
東京 → シンガポール
sh-4.2$ ping 192.168.128.151
PING 192.168.128.151 (192.168.128.151) 56(84) bytes of data.
64 bytes from 192.168.128.151: icmp_seq=1 ttl=254 time=71.9 ms
64 bytes from 192.168.128.151: icmp_seq=2 ttl=254 time=71.9 ms
64 bytes from 192.168.128.151: icmp_seq=3 ttl=254 time=71.8 ms
64 bytes from 192.168.128.151: icmp_seq=4 ttl=254 time=71.9 ms
64 bytes from 192.168.128.151: icmp_seq=5 ttl=254 time=72.0 ms
・・・
シンガポール → 東京
sh-4.2$ ping 10.0.128.50
PING 10.0.128.50 (10.0.128.50) 56(84) bytes of data.
64 bytes from 10.0.128.50: icmp_seq=1 ttl=253 time=72.1 ms
64 bytes from 10.0.128.50: icmp_seq=2 ttl=253 time=72.0 ms
64 bytes from 10.0.128.50: icmp_seq=3 ttl=253 time=71.9 ms
64 bytes from 10.0.128.50: icmp_seq=4 ttl=253 time=72.0 ms
64 bytes from 10.0.128.50: icmp_seq=5 ttl=253 time=72.0 ms
・・・
続いて、各サーバー間でアプリケーションによる通信確認を行います。
ここでは、curl
コマンドにより双方にHTTPリクエストを行ってみます。
東京 → シンガポール
sh-4.2$ curl http://192.168.128.151
Hello! I'm SINGAPORE Web Server!
シンガポール → 東京
sh-4.2$ curl http://10.0.128.50
Hello! I'm TOKYO Web Server!
正常に通信が行えました!
※ IPsecの状態が正常であることを確認している場合、サーバー間の通信がうまくいかないのは「ルーティングの設定」「セキュリティグループの設定」である可能性が大です。各設定を見直してみてください。
おわりに
ルーターが冗長化されていなかったり、ネットワーク構成がそれほど複雑でない場合は、静的ルーティングで運用している場合も多いかと思います。
そのような環境で検証を行う際の参考になれば幸いです。