Amazon-VPC

AWS Client VPNとVPCピアリングを使用したセキュアな接続

はじめに

こんにちは、ディーネットの牛山です。

AWS Client VPN相互認証を利用した、Amazon EC2へのprivate ipでssh接続してみたので紹介します。

AWS Client VPN側でスプリットトンネルを有効状態とし、AWS宛てのトラフィックのみVPNトンネルを通過するようにしています。

構成図

VPN用VPC、検証環境用VPC、本番環境用VPCの3つ用意している構成です。

VPN用VPCから検証環境用VPCと本番環境用VPCへピアリング接続をおこないVPC間の接続をおこなっています。



前置き

大まかな流れを次の通り示します。

  1. AWS Client VPNで利用するサーバ証明書やクライアント証明書を作成します。
  2. Terraformより、1.で作成した証明書を利用しAWS環境へAWS Client VPN、private EC2へssh接続する環境一式を展開します。
  3. AWS Client VPNに対してWindows環境から接続し、private EC2へssh接続できることを確認します。
  4. インターネット向けの通信は、AWSを介さずクライアントのネットワークを利用し接続することを確認します。

それでは実際におこなっていきます。

証明書関連の作成

簡単認証局 作成ツールインストール

easy-rsaと呼ばれるサーバ証明書やクライアント証明書を簡単に作成できるツールをインストールします。

インストールには、epelレポジトリが必要になりますので、epelパッケージがインストールされているかの確認をおこないます。

次のようにdnf repolistコマンド結果に出てこない場合は、dnf install epel-releaseコマンドでepelパッケージをインストールしてください。

# dnf repolist | grep epel

epel                 Extra Packages for Enterprise Linux 9 - aarch64

※出てこない場合、dnf repolist --enablerepo=epel | grep epelコマンドで念の為、確認するようにしてください。

その後、dnf install easy-rsaコマンドを使用し、easy-rsaをインストールします。

簡単認証局 作成ツール作成スクリプトの設置

easy-rsa設置ディレクトリを作成します。

# mkdir -pv /etc/openvpn/easyRsa

mkdir: created directory '/etc/openvpn'
mkdir: created directory '/etc/openvpn/easyRsa'

easy-rsaは/usr/share/easy-rsa/配下にインストールされていますので先ほど作成したディレクトリへコピーします。

# cp --preserve=all -vir /usr/share/easy-rsa/3.1.6/. /etc/openvpn/easyRsa

'/usr/share/easy-rsa/3.1.6/./easyrsa' -> '/etc/openvpn/easyRsa/./easyrsa'
'/usr/share/easy-rsa/3.1.6/./openssl-easyrsa.cnf' -> '/etc/openvpn/easyRsa/./openssl-easyrsa.cnf'
'/usr/share/easy-rsa/3.1.6/./x509-types' -> '/etc/openvpn/easyRsa/./x509-types'
'/usr/share/easy-rsa/3.1.6/./x509-types/COMMON' -> '/etc/openvpn/easyRsa/./x509-types/COMMON'
'/usr/share/easy-rsa/3.1.6/./x509-types/ca' -> '/etc/openvpn/easyRsa/./x509-types/ca'
'/usr/share/easy-rsa/3.1.6/./x509-types/client' -> '/etc/openvpn/easyRsa/./x509-types/client'
'/usr/share/easy-rsa/3.1.6/./x509-types/code-signing' -> '/etc/openvpn/easyRsa/./x509-types/code-signing'
'/usr/share/easy-rsa/3.1.6/./x509-types/email' -> '/etc/openvpn/easyRsa/./x509-types/email'
'/usr/share/easy-rsa/3.1.6/./x509-types/kdc' -> '/etc/openvpn/easyRsa/./x509-types/kdc'
'/usr/share/easy-rsa/3.1.6/./x509-types/server' -> '/etc/openvpn/easyRsa/./x509-types/server'
'/usr/share/easy-rsa/3.1.6/./x509-types/serverClient' -> '/etc/openvpn/easyRsa/./x509-types/serverClient'

証明書の有効期限を変更

EasyRSAツールに付属している、Easy-RSA設定の組み込み例が記載されている「vars.example」ファイル中にある「EASYRSA_CERT_EXPIRE」「EASYRSA_CRL_DAYS」設定を変更します。

設定ファイルのコピーおよびバックアップをおこないます。

# cp -p /usr/share/doc/easy-rsa/vars.example /etc/openvpn/easyRsa/vars

# cp -p /etc/openvpn/easyRsa/vars /etc/openvpn/easyRsa/vars.org

# cp -p /etc/openvpn/easyRsa/vars /etc/openvpn/easyRsa/vars_$(date +%Y%m%d)

有効期限変更をおこないます。

先ほどコピーしたvarsファイルの設定変更をおこないます。

  • EASYRSA_CA_EXPIRE、認証局 (CA) 証明書の有効期間(日数)を10年にします。
  • EASYRSA_CERT_EXPIRE、サーバー証明書やクライアント証明書などの個々の証明書の有効期間(日数)を10年にします。
  • EASYRSA_CRL_DAYS、証明書失効リスト (CRL) の有効期間(日数)を10年にします。

※それぞれ、先頭に # コメントが付いていますので、アンコメントするようにします。

子細変更内容については以下に記載していますのでご参考にしてください。

# diff -u /etc/openvpn/easyRsa/vars.org /etc/openvpn/easyRsa/vars

--- /etc/openvpn/easyRsa/vars.org       2023-08-18 14:28:23.000000000 +0000
+++ /etc/openvpn/easyRsa/vars   2024-08-04 12:10:44.097867532 +0000

 # In how many days should the root CA key expire?
 #
-#set_var EASYRSA_CA_EXPIRE     3650
+set_var EASYRSA_CA_EXPIRE      36500

 # In how many days should certificates expire?
 #
-#set_var EASYRSA_CERT_EXPIRE   825
+set_var EASYRSA_CERT_EXPIRE    36500

 # How many days until the next CRL publish date?  Note that the CRL can still
 # be parsed after this timeframe passes. It is only used for an expected next
 # publication date.
 #
-#set_var EASYRSA_CRL_DAYS      180
+set_var EASYRSA_CRL_DAYS       36500

 # Random serial numbers by default.
 # Set to 'no' for the old incremental serial numbers.

認証局 ( CA ) の作成

認証局作成のため初期化をおこないます。

cd /etc/openvpn/easyRsa/ でeasyRsaに移動します。

# ./easyrsa init-pki

Notice
------
'init-pki' complete; you may now create a CA or requests.

Your newly created PKI dir is:
* /etc/openvpn/easyRsa/pki

Using Easy-RSA configuration:
* /etc/openvpn/easyRsa/vars

IMPORTANT:
  The preferred location for 'vars' is within the PKI folder.
  To silence this message move your 'vars' file to your PKI
  or declare your 'vars' file with option: --vars=<FILE>

新しい認証局(CA)を生成します。

ここでは、nopassを指定しパスフレーズなしで生成するようにしています。

「Common Name」を聞かれますので「aws.client.vpn」(任意値)をタイプし、Enterキーを押し先に進みます。

# ./easyrsa build-ca nopass

Using Easy-RSA 'vars' configuration:
* /etc/openvpn/easyRsa/vars
・
・「中略」
・
Common Name (eg: your user, host, or server name)[Easy-RSA CA]:aws.client.vpn

Notice
------
CA creation complete. Your new CA certificate is at:
* /etc/openvpn/easyRsa/pki/ca.crt

サーバ証明書の作成

サーバ証明書をパスワードなしで、sanおよびコモンネームを指定し作成します。

# ./easyrsa --san=DNS:aws.client.vpn build-server-full aws.client.vpn nopass

※例:./easyrsa --san=DNS:{san名} build-server-full {コモンネーム名} nopass

Using Easy-RSA 'vars' configuration:
* /etc/openvpn/easyRsa/vars
・
・「中略」
・
Notice
------
Private-Key and Public-Certificate-Request files created.
Your files are:
* req: /etc/openvpn/easyRsa/pki/reqs/server.req
* key: /etc/openvpn/easyRsa/pki/private/server.key

You are about to sign the following certificate:
Request subject, to be signed as a server certificate
for '36500' days:

subject=
    commonName                = aws.client.vpn

X509v3 Subject Alternative Name:
    DNS:aws.client.vpn

Type the word 'yes' to continue, or any other input to abort.
  Confirm request details: yes

Using configuration from /etc/openvpn/easyRsa/pki/84b3a1ff/temp.1.1
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'server'
Certificate is to be certified until Aug  2 12:54:47 2124 GMT (36500 days)

Write out database with 1 new entries
Data Base Updated

Notice
------
Certificate created at:
* /etc/openvpn/easyRsa/pki/issued/server.crt

Notice
------
Inline file created:
* /etc/openvpn/easyRsa/pki/inline/server.inline

クライアントサーバー証明書とキーを生成

クライアントから接続する為に必要な証明書を作成
次のコマンドで、クライアント証明書・秘密鍵(パスフレーズ認証なし)の作成します。

サーバ証明書の作成をした時、同様、途中、リクエスト内容の確認が求められますので「yes」をタイプし、Enterします。

# ./easyrsa build-client-full vpn_user nopass

Using Easy-RSA 'vars' configuration:
* /etc/openvpn/easyRsa/vars
・
・「中略」
・
Notice
------
Private-Key and Public-Certificate-Request files created.
Your files are:
* req: /etc/openvpn/easyRsa/pki/reqs/vpn_user.req
* key: /etc/openvpn/easyRsa/pki/private/vpn_user.key

You are about to sign the following certificate:
Request subject, to be signed as a client certificate
for '36500' days:

subject=
    commonName                = vpn_user

Type the word 'yes' to continue, or any other input to abort.
  Confirm request details: yes

Using configuration from /etc/openvpn/easyRsa/pki/openssl-easyrsa.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'vpn_user'
Certificate is to be certified until Aug  2 12:56:55 2124 GMT (36500 days)

Write out database with 1 new entries
Data Base Updated

Notice
------
Certificate created at:
* /etc/openvpn/easyRsa/pki/issued/vpn_user.crt

Notice
------
Inline file created:
* /etc/openvpn/easyRsa/pki/inline/vpn_user.inline

ここまで作成した各種証明書を確認します。

# find / -name vpn_user.crt -or -name vpn_user.key -or -name ca.crt -or -name server.crt -or -name server.key | sort

/etc/openvpn/easyRsa/pki/ca.crt
/etc/openvpn/easyRsa/pki/issued/server.crt
/etc/openvpn/easyRsa/pki/issued/vpn_user.crt
/etc/openvpn/easyRsa/pki/private/server.key
/etc/openvpn/easyRsa/pki/private/vpn_user.key

証明書一式のコピー

ここまでで以下証明書類ができあがります。

ファイル 意味
ca.crt CA証明書
server.crt サーバー証明書
vpn_user.crt クライアント証明書
server.key サーバー証明書鍵
vpn_user.key クライアント証明書鍵

各種証明書を一式を証明書管理ディレクトリを作成し、コピーします。

# mkdir ~/certificate_manage

# cp -p /etc/openvpn/easyRsa/pki/ca.crt ~/certificate_manage/

# cp -p /etc/openvpn/easyRsa/pki/issued/server.crt ~/certificate_manage/

# cp -p /etc/openvpn/easyRsa/pki/issued/vpn_user.crt ~/certificate_manage/

# cp -p /etc/openvpn/easyRsa/pki/private/server.key ~/certificate_manage/

# cp -p /etc/openvpn/easyRsa/pki/private/vpn_user.key ~/certificate_manage/

コピー後、次の通りになっていることを確認します。

# ls -la ~/certificate_manage

total 40
drwxr-xr-x 2 root root 4096 Aug  4 13:06 .
drwxr-xr-x 1 root root 4096 Aug  4 13:06 ..
-rw------- 1 root root 1216 Aug  4 12:52 ca.crt
-rw------- 1 root root 4643 Aug  4 12:54 server.crt
-rw------- 1 root root 1704 Aug  4 12:54 server.key
-rw------- 1 root root 4509 Aug  4 12:56 vpn_user.crt
-rw------- 1 root root 1704 Aug  4 12:56 vpn_user.key

Terrafomを利用した環境一式展開

Terraformに主眼を置いていませんのでコードの子細説明はしません。

コード中にコメントを付与していますので参考にしてください。

種証明書一式をダウンロード

WinSCP等を利用し、先ほど作成したcertificate_manage配下のファイルを持ってきます。

Terraformから持ってきたファイルを読み込めるよう後ほど設定します。

server.crt、vpn_user.crtを開き、「-----BEGIN CERTIFICATE-----」~「-----END CERTIFICATE-----」の記載箇所部分のみ残し保存します。
 →※証明書部分に不要な記載があるため証明書部分のみ残す必要があります。

Terraformコード抜粋

今回、使用するTerraformコードは次からダウンロード可能です。

コード中にある、次の箇所で持ってきた各種証明書を読み込んでACM上にアップロードする内容です。

読み込むパスは各自環境に合わせてください。

# サーバー証明書のインポート
resource "aws_acm_certificate" "server_cert" {
  private_key       = file("certificate_manage/server.key")
  certificate_body  = file("certificate_manage/server.crt")
  certificate_chain = file("certificate_manage/ca.crt")

  tags = {
    Name = "server-cert"
  }
}

# クライアントルート証明書のインポート
resource "aws_acm_certificate" "client_root_cert" {
  private_key       = file("certificate_manage/vpn_user.key")
  certificate_body  = file("certificate_manage/vpn_user.crt")
  certificate_chain = file("certificate_manage/ca.crt")

  tags = {
    Name = "client-root-cert"
  }
}

キーペアについて

EC2インスタンスへssh接続する際に必要な公開鍵を準備し、Terraformから読み込めるようにします。

秘密鍵、公開鍵については各自用意してください。

ファイルパスは各自環境に合わせてください。

resource "aws_key_pair" "aws_key_pair_client-vpn-keypair" {
  key_name   = "client-vpn-keypair"
  public_key = file("keypair/id_rsa.pub")
}

準備が完了したらTerraformからAWS環境へ展開します。

Client VPN、EC2、各種VPC、VPN用ログCloudWatchロググループ、VPCピアリング等ができあがります。

展開には時間を要しますので注意ください。

Client VPN OpenVPN設定ファイルダウンロード

展開先AWSアカウントマネージメントコンソールからVPCサービスページにいきます。

「仮想プライベートネットワーク (VPN)」タブにある「クライアントVPNエンドポイント」を開きます。

次のリンクから直接飛ぶことが可能です。

main-client-vpnというエンドポイントがありますので、クリックし、「クライアント設定をダウンロード」を押します。

downloaded-client-config.ovpn がダウンロードされますので開き、クライアント証明書とクライアント鍵を記載し保存します。

記載例を次の通り示します。

client
dev tun
proto udp
remote cvpn-endpoint-***.prod.clientvpn.ap-northeast-1.amazonaws.com 443
remote-random-hostname
resolv-retry infinite
nobind
remote-cert-tls server
cipher AES-256-GCM
verb 3
<ca>
-----BEGIN CERTIFICATE-----
ここにca.crtの内容が記載済み。
-----END CERTIFICATE-----

</ca>

<key>
-----BEGIN PRIVATE KEY-----
ここにvpn_user.key ( クライアントの秘密鍵 ) の内容をコピペ
-----END PRIVATE KEY-----

</key>

<cert>
-----BEGIN CERTIFICATE-----
ここにvpn_user.crt ( クライアント証明書 ) に内容をコピペ
-----END CERTIFICATE-----

</cert>

reneg-sec 0

verify-x509-name server name

動作確認

次のリンクからOpenVPNクライアントをダウンロードし、インストールします。

インストール後、downloaded-client-config.ovpn をインポートし、AWS Client VPNに接続します。

EC2への接続

接続完了後、展開先のAWSマネージメントコンソールからEC2サービスページにいきます。

production-ec2-instance、staging-ec2-instanceというEC2インスタンスがありますので、それぞれのEC2インスタンスの「プライベートIPv4アドレス」を指定しssh接続できればokです。

接続の際に、秘密鍵を指定する必要がありますので、キーペアの秘密鍵を指定します。

インターネット向け通信確認

ブラウザからIPアドレス確認ページにいき、IPアドレスの確認をおこないます。

自ネットワークのグローバルIPアドレスになっていることを確認できればokです。

まとめ

実際にAWS Client VPNからプライベートにあるEC2インスタンスに対して接続することを確認できました。

VPCを跨いだ接続は、VPCピアリングよって接続でき、インターネット向けの通信はAWSを介さないことが確認できました。

返信を残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA