目次
こんにちは!エンジニアのよっしーです。
AWS や Google Cloud (GCP) などのクラウドサービスを利用するとき、作成した VM に ssh でアクセスしたり、データベースにコマンドレベルでアクセスしたり、あるいはファイルを転送したりという作業は必須ですよね。通常はセキュリティ確保のため、グローバル IP アドレスを持つ「踏み台 VM」を作成し、外部から踏み台 VM を経由してグローバル IP アドレスを持たない内部の VM やデータベースにアクセスすることが多いと思います。
また、AWS であれば ”Session Manager” を利用して、グローバル IP アドレスを持たない VM に外部から直接アクセスできるサービスもありますが、データベースへの直接アクセスやファイル転送を外部から ”Session Manager” を利用して実行するにはひと工夫必要だったりします。
そこで、グローバル IP アドレスを持たない内部 VM や、データベースに直接 TCP/IP レベルでアクセスできる “Client VPN” を使ってみました。
AWS Client VPN とは?
Client VPN の主な仕様は
- Windows/Mac/Linux などの PC や iOS/Android などのスマートフォンなどの端末から AWS の 指定した VPC にVPN 接続が可能
- PC には各 OS に対応した VPN 接続アプリを提供。スマートフォンでは OpenVPN に準拠したアプリを使用可能
- サーバ証明書をクライアント証明書を利用した相互認証を利用可能
- ユーザ別の認証には、アクティブディレクトリ認証または、フェデレーション認証を利用可能
- 証明書による相互認証とユーザ認証を併せた複合認証も可能
Client VPN の構成は
今回 Client VPN を検証した簡単な構成図を以下に示す
AWS Client VPN の設定
それでは Client VPN を設定していこう!まずは相互認証で使用する証明書の作成から。
サーバ証明書、クライアント証明書の作成
今回は “easy-rsa” を使用するため、まず、”easy-rsa” を準備する
$ git clone https://github.com/OpenVPN/easy-rsa.git
$ easy-rsa/easyrsa3/easyrsa init-pki
- ca 証明書の作成
- pki/ca.crt が作成される
$ easy-rsa/easyrsa3/easyrsa build-ca nopass
- サーバ証明書の作成
- pki/issued/server.crt ( 証明書) および pki/private/server.key (秘密鍵)が作成される
$ easy-rsa/easyrsa3/easyrsa build-server-full server nopass
- クライアント証明書の作成
- pki/issued/vpn-test.grasys.domain.crt ( 証明書) および pki/private/vpn-test.grasys.domain.key (秘密鍵)が作成される
$ easy-rsa/easyrsa3/easyrsa build-client-full vpn-test.grasys.domain nopass
サーバ証明書、クライアント証明書の登録
- AWS のコンソールから “AWS Certificate Manager“を選択
- ”インポート”ボタンをクリック
- 下図の画面に作成した証明書、秘密鍵、ca 証明書を入力し手順に従い登録
- 登録された証明書。証明書作成時に使用したドメイン名を確認。
クライアント VPN エンドポイントの作成
- AWS のコンソールから “VPC” → “クライアント VPN エンドポイント” を選択
- ”クライアント VPN エンドポイントを作成” ボタンをクリック
- 下図の画面に必要事項を入力
①エンドポイントの名称を指定
②Client VPN 上で使用する IP アドレスレンジ(CIDR)を指定。接続先 VPC の CIDR 範囲は指定不可。ここで指定した CIDR の中からクライアント側 (PCまたはスマートフォン) に 1つ IP アドレスが割り当てられる。
③先程 ACM に登録した「サーバー証明書」を指定
④「相互認証を使用」をチェックし、同様に ACM に登録したクライアント証明書を指定
下図のように「認証情報」にて「ユーザーベースの認証を使用」をチェックすると、アクティブディレクトリ認証または、フェデレーション認証を指定可能 (今回の検証では使用しない)
- (設定画面の続き)
⑤ Client VPN のアクセスログを記録する場合は CloudWatch Logs のロググループ名とストリーム名を入力(ロググループ名とストリーム名は事前設定が必要)
⑥DNS サーバのアドレスを登録。多くの場合、AWS では Public Subnet に指定した CIDR の2つ目のホストアドレスがその Public Subnet のDNS アドレスになっていることが多い。(例:10.100.0.0/20 → 10.100.0.2, 10.100.16.0/20 → 10.100.16.2)
⑦ エンドポイントに設定するセキュリティグループを指定(事前作成が必要)。 クライアントから AWS のリソースに向けてアクセスするだけであれば、指定するセキュリティグループのインバウンドルールは空で OK。
⑧VPNポートとして、443 または 1194 が使用可能。プロトコルも TCP または UDP の指定が可能。
- 上記項目を入力し、”クライアント VPN エンドポイントを作成” ボタンをクリックするとエンドポイントが作成される。
- エンドポイントの作成にはしばらく時間を要するため、下図の通り、状態が “Pending-associate” から “Available” になると利用可能となる。
⇩
クライアント側の設定
① クライアント設定ファイル (プロファイル) の作成
VPN 接続のためのプロファイルのテンプレートは以下のボタンからダウンロードできる
テンプレートファイルは以下通り
client
dev tun
proto tcp
remote cvpn-endpoint-0c10319cebe1523e2.prod.clientvpn.ap-northeast-1.amazonaws.com 1194
remote-random-hostname
resolv-retry infinite
nobind
remote-cert-tls server
cipher AES-256-GCM
verb 3
<ca>
-----BEGIN CERTIFICATE-----
MIIDNTCCAh2gAwIBAgIJAN/OwksaVDwQMA0GCSqGSIb3DQ.....
<中略>
-----END CERTIFICATE-----
</ca>
reneg-sec 0
このテンプレートの以下部分を修正・追加
- リモートホスト名の修正
- Windows/Mac/Linux 用のプロファイル:変更なし
- iOS 用プロファイル:ホスト名を “cvpn-endpoint-…” → “*.cvpn-endpoint-…” に変更
- Android 用プロファイル:ホスト名を “cvpn-endpoint-…” → “asdfa.cvpn-endpoint-…” に変更 (asdfa は任意文字列)
- クライアント証明書および、クライアント秘密鍵を追加登録。
- <cert> 証明書 </cert>, <key> 秘密鍵 </key> のフォーマットで指定
修正後のプロファイルは以下の通り
client
dev tun
proto tcp
remote cvpn-endpoint-0c10319cebe1523e2.prod.clientvpn.ap-northeast-1.amazonaws.com 1194
remote-random-hostname
resolv-retry infinite
nobind
remote-cert-tls server
cipher AES-256-GCM
verb 3
<ca>
-----BEGIN CERTIFICATE-----
MIIDNTCCAh2gAwIBAgIJAN/OwksaVDwQMA0GCSqGSIb3DQ.....
<中略>
-----END CERTIFICATE-----
</ca>
<cert>
-----BEGIN CERTIFICATE-----
MIIDWTCCAkGgAwIBAgIQOFxJvTVbw6pQFQdY7yf0/zANBg.....
<中略>
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAo.....
<中略>
-----END PRIVATE KEY-----
</key>
reneg-sec 0
作成したプロファイルを VPN 接続したいクライアントに配布。
②クライアント側の VPN 接続用アプリ設定
- Windows/Mac/Linux PC
下記 リンクから使用するOS の Client VPN 接続アプリをインストールする
https://docs.aws.amazon.com/ja_jp/vpn/latest/clientvpn-user/connect-aws-client-vpn-connect.html
上記リンク先ページの手順にしたがい、アプリのインストールおよび、プロファイルの登録を実施
Client VPN 接続アプリによる VPN 接続が成功すると、アプリが下図のような表示となる
- iOS/Android スマートフォン
iOS/Android では OpenVPN に準拠した VPN 接続アプリを使用できる。
今回は “OpenVPN Connect” アプリを使用
“OpenVPN Connect”をインストール後、プロファイルを “OpenVPN Connect” を指定して起動すると
“OpenVPN Connect”にプロファイルを登録できる。
赤囲みスイッチを右にスライドさせることにより、VPN 接続が開始される
接続後の状態
エンドポイント作成時に指定した クライアント IPv4 CIDR の中から1アドレスがアサインされる
( 172.20.16.0/20 から 172.20.17.2 がアサインされる)
以上で、クライアントから Client VPN エンドポイントへの VPN 接続が完了
AWS Client VPN と AWS リソースとの接続のための設定
ターゲットネットワークの設定
クライアント VPN エンドポイント から エンドポイントのある VPC 上に作成した AWS リソースにアクセスするためには、その VPC 配下にあるサブネットをターゲットネットワークとして指定します。ターゲットネットワークは、
- 各 zone に 1 つずつサブネットを指定できる。
- 複数指定したサブネットは同じ VPC 配下であることが必要。
- ターゲットネットワークに指定されたサブネットには VPN のインターフェイスとして ネットワークインターフェイスが自動的に作成され、サブネットに指定されている CIDR から IPアドレスがアサインされる。 VPN から AWS リソースへのアクセスはこの IP アドレスが使用される。
今回は Private subnet である、vpc01-prv01 (10.100.128.0/20) と vpc01-prv02 (10.100.144.0/20) をターゲットネットワークとして指定した。
ターゲットネットワークのリスト画面。ターゲットネットワークの設定には VPC とサブネットを指定する(下図)
ターゲットネットワークを指定後、ネットワークインターフェイスが自動的に作成される。
vpc01-prv01 側には 10.100.131.84、vpc01-prv02 側には 10.100.155.227 の IP アドレスがアサインされた(下図)
ルートテーブルの設定
Client VPN から AWS リソースや NAT-GW 経由でのインターネットアクセスを行うためのルートを設定する。転送先はターゲットネットワークとなる。
- デフォルトルートとして、エンドポイントを作成した VPC の CIDR へのルートは自動的に作成される。
- NAT-GW を経由したインターネットアクセスのルートを追加する場合は、送信先 CIDR を 0.0.0.0/0 としルートを作成。転送先はターゲットネットワークとなるため、「ターゲットネットワークのルートテーブルに NAT-GW 経由でのインターネットアクセスのルート設定が必要」
エンドポイントのルートテーブル(下図)
ターゲットネットワークに指定したサブネットのルートテーブル。0.0.0.0/0 の転送先に NAT-GW が指定されている(下図)
承認ルールの設定
Client VPN では、ルートおよびセキュリティグループの設定だけではなく、エンドポイントからアクセスしたいリソースを含む送信先 IP アドレスに対して、接続のための承認設定が必要となる
- 接続先 IP アドレスは CIDR で指定
- VPN を ユーザ認証で認証した場合、アクセスできるユーザの指定が可能 (アクティブディレクトリ SID または IDP のグループ名 を使用)
- 証明書による相互認証の場合はユーザ指定はできず、全てのユーザにアクセスを承認
承認ルールリスト(下図)下記の例ではインターネットを含む全ての宛先 (0.0.0.0/0) へのアクセスを承認
AWS リソース (EC2, RDS Aurora 等) 側の設定
VPN からアクセスされる AWS リソース側のセキュリティグループに クライアント VPN エンドポイントに指定したセキュリティグループを送信元とするアクセス許可ルールをインバウンド側に登録する必要がある
①EC2 の場合
エンドポイントのセキュリティグループ (test-vpn-endpoint) から port 22 (ssh) へのアクセスを許可
②RDS Aurora の場合
エンドポイントのセキュリティグループ (test-vpn-endpoint) から port 3306 (MYSQL/Aurora) へのアクセスを許可
接続してみよう!
VPNの接続
AWS VPN Client アプリや、OpenVPN Connect あぷりにて、 Client VPN のプロファイルを選択し、接続をクリックするだけ。
EC2 への接続
接続先の EC2 はプライベートアドレス (10.100.137.33) のみがアサインされている
ローカル環境のターミナルアプリにて
$ ssh -i ~/.ssh/test-vpn.pem ec2-user@10.100.137.33
の実行によりssh アクセス可能
localuser@local ~ $ ssh -i ~/.ssh/test-vpn.pem ec2-user@10.100.137.33
Last login: Mon Jul 11 04:18:12 2022 from ip-10-100-131-84.ap-northeast-1.compute.internal
__| __|_ )
_| ( / Amazon Linux 2 AMI
___|\___|___|
https://aws.amazon.com/amazon-linux-2/
[ec2-user@test-ec2-vpc01 ~]$
接続先 EC2 (test-ec2-vpc01) の /var/log/security ログには以下の記述があり
Jul 11 04:20:23 i-xxxxxxxx sshd[22304]: Accepted publickey for ec2-user from 10.100.131.84 port 49508 ssh2: RSA SHA256:6cux6....
Jul 11 04:20:23 i-xxxxxxxx sshd[22304]: pam_unix(sshd:session): session opened for user ec2-user by (uid=0)
ログから、 接続元 IP アドレスが 10.100.131.84 (ターゲットネットワークに作成されたネットワークインターフェイス) であることが分かる。
EC2 に直接 ssh によるアクセスができるということは、 EC2 に直接 sftp や scp によるファイル転送が可能!
localuser@local ~ $ sftp -i ~/.ssh/test-vpn.pem ec2-user@10.100.137.33
Connected to 10.100.137.33.
sftp> pwd
Remote working directory: /home/ec2-user
sftp>
RDS Aurora への接続
接続先の Aurora のエンドポイントにはプライベートアドレス (10.100.158.127) のみがアサインされている
$ dig test-vpn-database.cluster-xxxxxx.ap-northeast-1.rds.amazonaws.com
<中略>
;; ANSWER SECTION:
test-vpn-database.cluster-xxxxxx.ap-northeast-1.rds.amazonaws.com. 5 IN CNAME test-vpn-database-instance-1.xxxxxx.ap-northeast-1.rds.amazonaws.com.
test-vpn-database-instance-1.xxxxxx.ap-northeast-1.rds.amazonaws.com. 5 IN A 10.100.158.127
;; Query time: 20 msec
;; SERVER: 10.100.0.2#53(10.100.0.2)
<以下略>
ローカル環境のターミナルアプリにて
$ mysql -h test-vpn-database.cluster-xxxxxx.ap-northeast-1.rds.amazonaws.com -u testvpnuser -p
の実行により mysql cli でのアクセスが可能となり、SQL 実行等直接操作が可能
localuser@local ~ $ mysql -h test-vpn-database.cluster-xxxxxx.ap-northeast-1.rds.amazonaws.com -u testvpnuser -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 23
Server version: 5.7.12 MySQL Community Server (GPL)
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
NAT-GW を経由したインターネットアクセス
検証環境の NAT-GW ではグローバルアドレスとして 35.73.95.24 の eip が設定
ローカル環境から接続元 IP アドレス確認サイトの https://www.cman.jp/network/support/go_access.cgi にアクセスすると
と表示され、接続元 IPアドレスが NAT-GW の eip となっていることが分かる
Client VPN 接続状態の確認方法
AWS コンソール から “VPV” → “クライアント VPN エンドポイント” の ”接続” タブから Client VPN の接続履歴、および現在の状態などを確認可能
また、CloudWatch Logs にログ保存の設定がされている場合は CloudWatch Logs での接続ログ確認が可能
おわりに
AWS Client VPN を使用することにより、踏み台 VM 等を 経由することなく、プライベートアドレスしか持たない AWS リソースにコマンドレベルで直接接続することが可能であることを確認できました。
今回は証明書による相互認証のみを検証しましたが、ユーザ認証を導入することによりユーザ毎にアクセス可能なリソースの制限ができるなど、細やかなアクセス設定も可能です。
また、今回はインターネットアクセスを VPN 経由の NAT-GW からのアクセスとして検証しましたが、「スプリットトンネル」の機能を利用すれば、 AWS リソースへのアクセスは VPN へ、インターネットアクセスはローカル環境から直接インターネットへとルートを分ける事も可能です。
しっかりとユーザのアクセス管理ができるようであれば、AWS Client VPN は是非使ってみたい機能です。