はじめに
前回NATインスタンスをテンプレート化しました。今回はVPNServerをテンプレート化してみます。
AWSでは、以下のような3種類のVPNサービスが利用できますが、極力コストをかけたくないので、自前でテンプレートを用意します。
- AWS Client VPN($0.15/時間・クライアント)
- AWS Site-to-Site VPN(グローバルIPを割り当てたルーターが必要、安価)
- AWS Direct Connect(専用回線なので高い、個人で利用することはほぼない)
目指す構成
VPNソフトウェアとしてsoftetherVPNを利用します。dockerイメージのsiomiz/softethervpnを使用させていただきます。非常に便利です。
また、設定した内容をEFSに保存します。テンプレートではVPNを使用するときだけEC2を作成し、使用しないときはEC2を削除するため、設定情報を外部に保管して、EC2をまたいで設定を維持できるようにします。
前準備
設定を保存するためのEFSを作成します。以下のブログを参考にさせていただきました。
EFS用のセキュリティグループを作成します。VPNserverからインバウンド通信ポート番号2049を許可します。
EFSのファイルアクセスポリシーを設定して、VPNServerのEC2インスタンスプロファイルに設定したIamRoleからのみアクセスを許可する設定を行います。
{
"Version": "2012-10-17",
"Id": "efs-policy-wizard-01be5f25-bb15-4014-ab63-cb5dda33d33e",
"Statement": [
{
"Sid": "efs-statement-9e607ea3-d855-4067-b471-ec2a61203ba2",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::AWSアカウント:role/EC2に設定するインスタンスプロファイル"
},
"Action": [
"elasticfilesystem:ClientRootAccess",
"elasticfilesystem:ClientWrite",
"elasticfilesystem:ClientMount"
],
"Resource": "arn:aws:elasticfilesystem:ap-northeast-1:AWSアカウント:file-system/fs-xxxxxxxxxxxxxxxxxxxxxx",
"Condition": {
"Bool": {
"elasticfilesystem:AccessedViaMountTarget": "true"
}
}
}
]
}
テンプレート説明
ネットワーク設定部分です。本当はプライベートに配置して、NATトラバーサルを使用してNAT超えをしたかったのですが、うまくいかなかったため、パブリックに配置してグローバルIPアドレスを割当しています。どこからでもアクセスされたくないなので、事前に作成済みのセキュリティグループで自宅PCからのアクセスのみ許可しました。
NetworkInterfaces:
- AssociatePublicIpAddress: true
DeviceIndex: "0"
SubnetId: subnet-xxxxxxxxxxxxxx VPNServerを配置するパブリックサブネットのID
GroupSet:
- sg-xxxxxxxxxxxxxxxx VPNServer用のセキュリティグループ
efs-utilsをインストールして、EFSをIAM認証でマウントしています。
サーバのリブート自動マウントするようにしています。
# efsマウント
file_system_id_01=fs-xxxxxxxxxxxxxxx
efs_mount_point=/mnt/efs
mkdir -p $efs_mount_point
echo "${file_system_id_01}:/ ${efs_mount_point} efs _netdev,noresvport,tls,iam 0 0" >> /etc/fstab
dockerをインストールしています。
yum install -y docker
systemctl enable docker
service docker start
初期設定するためにsoftetherVPNのコンテナを起動します。コンテナのホスト名を指定しています。これはsoftetherのDDNS名を固定化する目的です。
docker run -d -e SPW=任意のパスワード --hostname my-vpnserver-container --name softether-server --cap-add NET_ADMIN --network host --privileged siomiz/softethervpn
テンプレートの完全版です。
Parameters:
EnableVPNServer:
Description: Enable VPN Server Instance.
Type: String
Default: false
AllowedValues: [true, false]
Conditions:
EnableVPNServer:
!Equals [true, !Ref EnableVPNServer]
Resources:
VPNServer:
Type: AWS::EC2::Instance
Condition: EnableVPNServer
Properties:
KeyName: "EC2 キーペア名"
ImageId: ami-0dfa284c9d7b2adad
InstanceType: t3.nano
IamInstanceProfile: "インスタンスプロファイル名"
NetworkInterfaces:
- AssociatePublicIpAddress: true
DeviceIndex: "0"
SubnetId: subnet-xxxxxxxxxxxxxx VPNServerを配置するパブリックサブネットのID
GroupSet:
- sg-xxxxxxxxxxxxxxxx VPNServer用のセキュリティグループ
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
VolumeType: gp3
VolumeSize: 8
DeleteOnTermination: true
Tags:
- Key: Name
Value: "VPNServer"
UserData:
Fn::Base64: |
#!/bin/bash
sudo su
# efs-utils インストール
yum update -y
yum install amazon-efs-utils -y
# efsマウント
file_system_id_01=fs-xxxxxxxxxxxxxxx
efs_mount_point=/mnt/efs
mkdir -p $efs_mount_point
echo "${file_system_id_01}:/ ${efs_mount_point} efs _netdev,noresvport,tls,iam 0 0" >> /etc/fstab
# dockerインストール
yum install -y docker
systemctl enable docker
service docker start
# 初期設定後は以下はコメントアウトしてください。
docker run -d -e SPW=任意のパスワード --hostname my-vpnserver-container --name softether-server --cap-add NET_ADMIN --network host --privileged siomiz/softethervpn
# 初期設定後は以下のコメントを外す
# docker run -d --hostname my-vpnserver-container --name softether-server --cap-add NET_ADMIN --network host --privileged -v $efs_mount_point/vpn_server.config:/usr/vpnserver/vpn_server.config siomiz/softethervpn
初回起動時
テンプレートの使い方はNATインスタンスと同様です。
「docker ps」でVPNServerのコンテナ名を確認し、「docker exec -it コンテナ名 bash」でログインします。
コンテナにログインしたら、「/usr/vpccmd/vpncmd」で、VPNserverの管理コマンドラインを起動します。
1の「Management of VPN Server or VPN Bridge」を選択します。
「Hostname of IP Address of Destination:」には空入力でOKです。
「Specify Virtual Hub Name:」にも空入力でOKです。
「Password:」に、テンプレートのSPW=に記入したパスワードを入力します。
うまくいくと、以下のようにVPN Serverのプロンプトが表示されます。
DDNS名を確認するため、「DynamicDNSGetStatus」と入力します。
赤枠部分をメモして、「exit」(2回)します。
次に、VPNServerの設定ファイルをEFS上にコピーします。
docker cp softether-server:/usr/vpnserver/vpn_server.config /mnt/efs/vpn_server.config
「Successfully copied 15.9kB to /mnt/efs/vpn_server.config」が表示されたら、設定ファイルの外部保存が成功していますので、一旦テンプレートを削除してVPNServerインスタンスを削除します。
テンプレートの編集
今度はefsの設定ファイルをdockerコンテナが読み込むようにテンプレートを編集して、VPNServerを起動します。
docker run -d --hostname my-vpnserver-container --name softether-server --cap-add NET_ADMIN --network host --privileged -v $efs_mount_point/vpn_server.config:/usr/vpnserver/vpn_server.config siomiz/softethervpn
GUIで管理画面に接続。
Windowsに「SoftEhter VPN Server Manager」をインストールします。インストール手順は省略します。
新しい接続設定のホスト名に事前にメモしたDDNS名を入力します。また、管理パスワードは前回の起動時に使用したテンプレートのSPW=に記入したパスワードを入力します。
うまくいけば、これで接続すると下図のようにログインでき、GUI操作が可能になります。
管理パスワードの変更や各種ネットワークの設定が可能となります。
※設定情報のConfigファイルへの反映は5分間隔です。強制的に反映させるためには管理コマンドラインで「flush」を実行します。
まとめ
VPNServerをテンプレート化することで、使いたいときだけ必要最小限のコストでVPN機能を利用できるようになりました。あくまでVPNServerをGUIで操作できるようになっただけで、まだVPNを設定したわけではないので、ようやくスタートラインに立った感じです。次は、このsoftehterVPNを設定して、ローカルPCとAWSのVPN接続を試してみようと思います。
また、NATインスタンスでSoftEtherのNATトラバーサルが機能しなかったことが気になりますので、余裕ができたら調べてみようと思います。
2024.1.7追記
この方法ではVPNServer側でローカルブリッジが機能しませんでした。SecureNATを有効にすれば機能します。
以下のフォーラムに書いてありましたが、EC2のNICがプロミスキャスモードに対応できないのが原因のようでした。
もともとAWSとの接続でアドレス変換をさせたくなかったため、今度はAWS側にVPNSeverではなくVPN Clientの設定を試してみようと思います。
2024.1.21追記
SoftetherでTAPデバイスを追加してブリッジさせることができそうなことがわかったため、AWSとローカルPC環境をアドレス変換せずにVPN接続について後日試してみる予定です。