VPC PrivateLink でクロスVPCサービス公開を試してみた
はじめに
かつまたです。
VPC間の通信というと VPC Peering や Transit Gateway がまず思い浮かびますが、「特定のサービスだけを一方向に公開したい」というユースケースには VPC PrivateLink が適しています。今回は Web サーバー側 VPC の Web サービスを クライアント側 VPC からプライベートに利用する構成を実際に構築してみました。
やりたいことまとめ
- Web サーバー側 VPC 内の Web サービスを クライアント側 VPC からプライベートに利用する
- VPC Peering・TGW・DXは使わない
- 一方向のサービス公開(クライアント → Web サーバー)によるセキュリティメリットを体感する
- Web サーバー側の IP アドレスを クライアント 側から見えない状態にする
構成図

前提条件
以下は構築済みの前提とします。操作は Admin 権限で実施しています。
| 項目 | 値 |
|---|---|
| リージョン | ap-northeast-1 |
| Web サーバー側 VPC | 10.1.0.0/16(プライベートサブネット 1a: 10.1.1.0/24、1c: 10.1.2.0/24) |
| クライアント側 VPC | 10.2.0.0/16(プライベートサブネット 1a: 10.2.1.0/24) |
| SSM 用 VPC エンドポイント | 各 VPC に ssm / ssmmessages / ec2messages の3種 |
| S3 Gateway エンドポイント | Web サーバー側 VPC(ユーザデータでの Amazon Linux 2023 リポジトリ接続用) |
| IAM インスタンスプロファイル | AmazonSSMManagedInstanceCore ポリシーをアタッチしたロールを紐付け |
セキュリティグループ
| SG 名 | 配置 VPC | インバウンドルール |
|---|---|---|
| Web サーバー EC2 用 | Web サーバー側 | TCP 80 ← 10.1.0.0/16(NLB ENI からの転送を受ける) |
| NLB 用 | Web サーバー側 | TCP 80 ← 10.0.0.0/8(PrivateLink 経由のクライアントトラフィックを受ける) |
| Web サーバー側 SSM エンドポイント用 | Web サーバー側 | TCP 443 ← 10.1.0.0/16 |
| クライアント EC2 用 | クライアント側 | (不要。egress デフォルト全許可で OK) |
| PrivateLink エンドポイント用 | クライアント側 | TCP 80 ← クライアント EC2 用 SG |
| クライアント側 SSM エンドポイント用 | クライアント側 | TCP 443 ← 10.2.0.0/16 |
アウトバウンドは全 SG ともデフォルト(全許可)のままで問題ありません。
やってみた
マネジメントコンソールで以下の手順を実施します。
1. Webサーバー用インスタンス作成
EC2 コンソール →「インスタンスを起動」
| 設定項目 | 値 |
|---|---|
| AMI | Amazon Linux 2023(最新) |
| インスタンスタイプ | t3.micro |
| キーペア | なし(SSM で接続) |
| VPC | Web サーバー側 VPC |
| サブネット | プライベートサブネット |
| パブリック IP 自動割り当て | 無効 |
| セキュリティグループ | 事前作成した Web サーバー EC2 用SG |
| IAM インスタンスプロファイル | 事前作成したSSM用ロール |

「高度な詳細」→「ユーザーデータ」に以下を貼り付けます。簡易的な Web ページを構築します。
#!/bin/bash
dnf install -y nginx
systemctl enable --now nginx
TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" \
-H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
INSTANCE_ID=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \
http://169.254.169.254/latest/meta-data/instance-id)
PRIVATE_IP=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \
http://169.254.169.254/latest/meta-data/local-ipv4)
cat > /usr/share/nginx/html/index.html << HTML
<h1>Hello from Web サーバー側 VPC via PrivateLink!</h1>
<p>Instance ID: ${INSTANCE_ID} / Private IP: ${PRIVATE_IP}</p>
HTML

「インスタンスを起動」をクリックします。
2. クライアント用インスタンス作成
同じく EC2 コンソール →「インスタンスを起動」
| 設定項目 | 値 |
|---|---|
| AMI | Amazon Linux 2023(最新) |
| インスタンスタイプ | t3.micro |
| キーペア | なし(SSM で接続) |
| VPC | クライアント側 VPC |
| サブネット | プライベートサブネット |
| パブリック IP 自動割り当て | 無効 |
| セキュリティグループ | 事前作成したクライアント EC2 用 SG |
| IAM インスタンスプロファイル | 事前作成したSSM用ロール |
両方のインスタンスが running になったら、Systems Manager のフリートマネージャーでインスタンスが表示されることを確認します。

3. NLB の作成
3-1. ターゲットグループの作成
EC2 コンソール → 左メニュー「ターゲットグループ」→「ターゲットグループの作成」
| 設定項目 | 値 |
|---|---|
| ターゲットタイプ | インスタンス |
| プロトコル | TCP |
| ポート | 80 |
| VPC | Web サーバー側 VPC |
| ヘルスチェックプロトコル | HTTP |
| ヘルスチェックパス | / |

「次へ」でターゲット登録画面に進み、Web サーバー用インスタンス を選択して「保留中として以下を含める」→「ターゲットグループの作成」をクリックします。
3-2. NLB 本体の作成
EC2 コンソール →「ロードバランサー」→「ロードバランサーの作成」→「Network Load Balancer」を選択。
| 設定項目 | 値 |
|---|---|
| スキーム | 内部(Internal) |
| IP アドレスタイプ | IPv4 |
| VPC | Web サーバー側 VPC |
| マッピング | ap-northeast-1a → Web サーバー側 VPC のプライベートサブネット 1a / ap-northeast-1c → Web サーバー側 VPC のプライベートサブネット 1c |
| セキュリティグループ | 事前作成した NLB 用 SG |
| リスナー | TCP:80 → 上記で作成したターゲットグループ |
作成後、NLB の状態が Active になり、ターゲットのヘルスチェックが healthy になるまで 2〜5分待ちます。

4. VPC Endpoint Service の作成(Web サーバー側)
VPC コンソール → 左メニュー「エンドポイントサービス」→「エンドポイントサービスを作成」
| 設定項目 | 値 |
|---|---|
| ロードバランサーのタイプ | ネットワーク |
| 使用可能なロードバランサー | 先ほど作成したNLB |
| 承諾が必要 | 有効(接続リクエストを手動承認) |
| サポートされる IP アドレスタイプ | IPv4 |
作成後、サービス名(com.amazonaws.vpce.ap-northeast-1.vpce-svc-xxxxxxxx)をメモします。

続いて「プリンシパルを許可」タブで、プリンシパルを登録します。
設定例
arn:aws:iam::<アカウントID>:root
arn:aws:iam::<アカウントID>:role/<操作ロール名>


5. VPC Endpoint の作成(クライアント 側)
VPC コンソール → 左メニュー「エンドポイント」→「エンドポイントを作成」
| 設定項目 | 値 |
|---|---|
| サービスカテゴリ | NLB と GWLB を使用するエンドポイントサービス |
| サービス名 | 4 でメモしたサービス名 |
| VPC | クライアント側 VPC |
| サブネット | ap-northeast-1a → クライアント側 VPC のプライベートサブネット |
| IP アドレスタイプ | IPv4 |
| セキュリティグループ | 事前作成した PrivateLink エンドポイント用 SG |

サービス名を入力した後、「サービスの検証」で サービス名が検証されました。 と表示されることを確認してから作成します。
6. 接続リクエストの承認(Web サーバー側)
VPC コンソール →「エンドポイントサービス」→ 4 で作成したエンドポイントサービスを選択 →「エンドポイント接続」タブ。
作成したエンドポイントを選択し、「アクション」→「エンドポイント接続リクエストの承諾」→「承諾」をクリックします。

7. Endpoint DNS 名の確認
VPC コンソール →「エンドポイント」→ 5 で作成したエンドポイントの「詳細」タブにある DNS 名 をメモします。
これが クライアント側 VPC 内からサービスにアクセスするための URL になります。
動作確認
クライアント EC2 に SSM Session Manager で接続して動作確認します。
テスト1:PrivateLink 経由のアクセス確認
$ curl <7 で記録した DNS 名>
出力例
<h1>Hello from Provider VPC via PrivateLink!</h1>
<p>Instance ID: i-0d4060bc7079c4b22 / Private IP: 10.1.1.73</p>
Web サーバー側 VPC の Nginx からレスポンスが返ってきました。
テスト2:Web サーバー IP への直接通信が不可能なことの確認
$ curl --connect-timeout 5 http://<Web サーバー IP>
出力例
curl: (28) Connection timed out after 5001 milliseconds
VPC Peering も TGW も無いため、IP 直接の通信はタイムアウトします。PrivateLink は 一方向のサービス公開であり、クライアント側から Web サーバー側のネットワークに侵入することはできません。
おわりに
ご覧いただきありがとうございました。
VPC PrivateLink を使い、Web サーバー側の IP アドレスを完全に隠蔽した上で、特定のサービスだけを一方向に公開できることが実機で確認できました。VPC Peering や TGW のように VPC 全体を相互接続する必要がなく、「サービス提供側が誰に公開するかを制御できる」点が大きなセキュリティメリットです。
参考
クラスメソッドオペレーションズ株式会社について
クラスメソッドグループのオペレーション企業です。
運用・保守開発・サポート・情シス・バックオフィスの専門チームが、IT・AIをフル活用した「しくみ」を通じて、お客様の業務代行から課題解決や高付加価値サービスまでを提供するエキスパート集団です。
当社は様々な職種でメンバーを募集しています。
「オペレーション・エクセレンス」と「らしく働く、らしく生きる」を共に実現するカルチャー・しくみ・働き方にご興味がある方は、クラスメソッドオペレーションズ株式会社 コーポレートサイト をぜひご覧ください。※2026年1月 アノテーション㈱から社名変更しました






