📝

ECS on EC2 で VPN サーバーを構築してみた

に公開

VPN とは? - 仮想プライベートネットワークの説明 - AWS

仮想プライベートネットワーク (VPN) は、デバイスと、インターネットの残りの部分との間のプライベート接続です。

VPN とはインターネット経由でプライベートネットワーク接続を確立する方法です。
本記事ではまず VPN の概要を紹介し、ECS on EC2 で VPN サーバーを構築して他国のサイトにアクセスする方法についても紹介します。

VPN とは

VPN とは? - 仮想プライベートネットワークの説明 - AWS
AWS 公式サイトの内容をもとに紹介します。

機能概要

  • 通信を暗号化して機密情報をプライベートに保つ
  • ユーザーの IP アドレスを隠す
  • 疑わしいアクティビティがある場合には自動的に特定のプログラムをシャットダウンする
  • 専用ネットワークよりも低コスト

組織におけるユースケース

  • 企業におけるセキュアなリモートアクセス
  • モバイル認証システムとの統合
  • オンプレミスからクラウドへのセキュアなデータ移行
  • 遠隔地間でのセキュアな通信

個人におけるユースケース

  • パブリック Wi-Fi などでの通信保護
  • 検索履歴を非公開にする
  • 他国のサイトへのアクセス
  • 匿名性の保護

VPN のリソース

  • VPN クライアント
    • 物理的な端末にインストールするソフトウェア
    • サーバーへの安全な接続を介する
  • VPN サーバー
    • クライアントの接続先
    • クライアントからの通信を適切な宛先にルーティング
  • VPN プロトコル
    • クライアントとサーバーの間でデータを安全に転送する方法を定義
    • OpenVPN, IPsec, L2TP, WireGuard, IKEv2 など
    • 暗号化のレベル、接続速度、信頼性などを決定する

AWS の VPN サービス

  • AWS Site-to-Site VPN
    • 企業の遠隔地間のプライベートネットワークとして機能
    • IPsec を使用
  • AWS Client VPN
    • ネットワーク管理者が VPN サービスのセットアップと設定を担当
    • 従業員の端末にクライアントをインストール
  • ソフトウェア VPN
    • AWS Marketplace で購入可能なサードパーティ VPN
    • EC2 インスタンスなどにソフトウェアをインストールして使用

VPN サーバーを構築してみた

ECS on EC2 で VPN サーバーを構築してみました。
なお、Fargate では特権モードがサポートされていないため構築できませんでした。
Amazon ECS タスクおよびコンテナのセキュリティのベストプラクティス - Amazon Elastic Container Service

AWS Fargate 上の Amazon ECS では、コンテナを privileged として実行することはサポートされていません。

前提

  • VPN クライアント: Windows 11 PC
  • 他国のサイトにアクセスしたい場合は適切なリージョンを選択してください
    • 例: アメリカのサイトにアクセスしたい場合はバージニア北部リージョンを選択する

01. ECS クラスターの作成

EC2 起動タイプでクラスターを作成します。
必要な容量で最小、最大を 1 に設定しましたが、その他の設定はデフォルト値です。


02. セキュリティグループのルール変更

VPN サーバーへの接続にあたり、以下のインバウンドルールを追加しました。

  • カスタム UDP
    • ポート範囲: 500
    • ソース: マイ IP
  • カスタム UDP
    • ポート範囲: 4500
    • ソース: マイ IP
  • カスタム TCP
    • ポート範囲: 1701
    • ソース: マイ IP

03. タスク定義の作成

以下の内容で作成しました。

{
    "compatibilities": [
        "EC2"
    ],
    "containerDefinitions": [
        {
            "cpu": 0,
            "environment": [
                {
                    "name": "USERS",
                    "value": "test-user:test2025"
                },
                {
                    "name": "PSK",
                    "value": "test2025"
                }
            ],
            "essential": true,
            "image": "siomiz/softethervpn",
            "logConfiguration": {
                "logDriver": "awslogs",
                "options": {
                    "awslogs-group": "/ecs/vpn-server-task",
                    "awslogs-create-group": "true",
                    "awslogs-region": "ap-northeast-1",
                    "awslogs-stream-prefix": "ecs"
                }
            },
            "mountPoints": [],
            "name": "vpn-server",
            "portMappings": [
                {
                    "containerPort": 500,
                    "hostPort": 500,
                    "protocol": "udp"
                },
                {
                    "containerPort": 4500,
                    "hostPort": 4500,
                    "protocol": "udp"
                },
                {
                    "containerPort": 1701,
                    "hostPort": 1701,
                    "name": "vpn-server-1701-tcp",
                    "protocol": "tcp"
                }
            ],
            "privileged": true,
            "systemControls": [],
            "volumesFrom": []
        }
    ],
    "cpu": "1024",
    "enableFaultInjection": false,
    "executionRoleArn": "arn:aws:iam::012345678901:role/ecsTaskExecutionRole",
    "family": "vpn-server-task",
    "memory": "3072",
    "networkMode": "host",
    "placementConstraints": [],
    "registeredAt": "2025-08-26T04:28:53.846Z",
    "registeredBy": "xxx",
    "requiresAttributes": [
        {
            "name": "com.amazonaws.ecs.capability.logging-driver.awslogs"
        },
        {
            "name": "ecs.capability.execution-role-awslogs"
        },
        {
            "name": "com.amazonaws.ecs.capability.docker-remote-api.1.19"
        },
        {
            "name": "com.amazonaws.ecs.capability.privileged-container"
        },
        {
            "name": "com.amazonaws.ecs.capability.docker-remote-api.1.18"
        },
        {
            "name": "com.amazonaws.ecs.capability.docker-remote-api.1.29"
        }
    ],
    "requiresCompatibilities": [
        "EC2"
    ],
    "revision": 2,
    "runtimePlatform": {
        "cpuArchitecture": "X86_64",
        "operatingSystemFamily": "LINUX"
    },
    "status": "ACTIVE",
    "taskDefinitionArn": "xxx",
    "volumes": [],
    "tags": []
}

04. タスクの作成

手順 03 のタスク定義でタスクを作成します。
クラスターは手順 01 で作成したクラスターを指定します。

05. VPN サーバーへの接続

タスクが起動したらパブリック IP を確認しておきます。

Windows のネットワークとインターネットの設定を開き、VPN を追加します。

VPN 追加時の設定値は以下の通りです。

  • 接続名: 任意の名称
  • サーバー名または IP アドレス: タスクのパブリック IP アドレス
  • VPN の種類: 事前共有キーを使った L2TP/IPsec
  • 事前共有キー: test2025
  • ユーザー名: test-user

上記設定で保存後、接続をクリックします。

サインインのポップアップが表示されるので以下の値を入力して OK をクリックします。

  • メールアドレス: test-user
  • パスワード: test2025

接続済みになれば VPN 接続完了です。

06. 他国のサイトにアクセスしてみる

私の場合は別途ロンドンリージョンにも上記手順で VPN サーバーを構築して Sky Sports のサイトで試してみました。
Sky Sports - Sports News, Transfers, Scores | Watch Live Sport

Sky Sports ではスポーツのハイライトを動画で配信していますが、日本からのアクセスでは以下のメッセージが表示されて動画を再生できませんでした。

Unsupported location
The video you are trying to watch cannot be viewed from your current country or location

一方で、VPN での接続では動画を再生できることを確認しました。
ロンドンリージョンに VPN サーバーを構築したため、Sky Sports への接続元の IP アドレスがイギリスのアドレスであると判断されていると思われます。

実際、以下のようなグローバル IP アドレスの確認サイトにアクセスすると、自身の端末の IP アドレスではなく EC2 インスタンスの IP アドレスが表示されました。
checkip.amazonaws.com

そのため、「ユーザーの IP アドレスを隠す」という点についても確認できました。

まとめ

今回は ECS on EC2 で VPN サーバーを構築してみました。
どなたかの参考になれば幸いです。

参考資料

Discussion