インターネットに閉じられたVPCにVPN接続
背景など
たまには、セキュアなVPCがしたいですよね。
とくにVPCへインターネットからの接続が不要な場合(データ処理系など)IGW・NATの用意が不要で面倒ですね。
でも接続ができないとVPC内の設定やテストなどが難しい。
じゃ、そのときにBASTIONサーバ・IGW・NATをやめて、VPNClientで接続すればいいじゃん。
VPNってなんだっけ?
VirtualPrivateNetwork (VPN)は、セキュアな接続が可能になります。
SSHも同様のものですが、SSHするために、EC2/NAT/IGWの導入が必要になります。
どっちがいいかといわれると、管理が楽、設置が簡単なものを優先します。
でも正直、この場合、どっちも一緒かな。
じゃ、コストみると、VPN Clientの方が高い印象です。
VPN Clientの場合、下記のものに対して下記されます:
- AWS Client VPN endpoint association (クライエントVPNエンドポイントアソシエーション)
- $0.15/h (ap-northeast-1 TOKYO)
- AWS Client VPN connection (クライエントVPN接続)
- $0.10/h/connection (ap-northeast-1 TOKYO)
Vs NAT/IGW/EIP/EC2:
- NAT Gateway
- $0.062 (ap-northeast-1 TOKYO)/h
- EIP
- $0.005 (ap-northeast-1 TOKYO)/h
- EC2 t2.micro:
- $0.0152/h
ということで、ケース バイ ケースにしましょう。
今回使うニーズは、DX(DirectConnect)と同様な接続したいので、VPN ClientがNAT/IGW経由より、DXに近いかなと思ってやってみました。
Prerequisites
- AWS Account
- Linux(like) System
- こちらでUBUNTU 18.04でやっています
- awscli
OpenVPN用の証明書とキーを用意
-
ローカルで作業DIRを作成:
mkdir ~/prepare-aws-vpn-client
-
OpenVPN/easy-rsaを取得:
OpenVPN/easy-rsa がRSAキーや証明書用意する作業を楽にしてくれるツール
cd ~/prepare-aws-vpn-client git clone https://github.com/OpenVPN/easy-rsa.git
-
Public Key Infrastructure (PKI) を作成
cd easy-rsa/easyrsa3 # run `easyrsa init-pki` to build the PublicKeyInfrastructure (PKI) ./easyrsa init-pki
-
証明書作成用のCertificate Authority (CA)を構築:
./easyrsa build-ca nopass # Enter, "rcs-vpn-ca" for Common Name. Common Name (eg: your user, host, or server name) [Easy-RSA CA]:rcs-vpn-ca CA creation complete and you may now import and sign cert requests. Your new CA certificate file for publishing is at: ~/prepare-aws-client-vpn/easy-rsa/easyrsa3/pki/ca.crt
-
サーバ用とクライエント用の証明書とキーを作成:
# create server private key for signing and certificate ./easyrsa build-server-full server nopass # create client private key for signing and certificate ./easyrsa build-client-full client1.vpn.tld nopass
-
作業が楽になるよう、サーバ・クライエントの証明書とキーを収集:
mkdir /tmp/aws-vpn/ # copy CA certificate cp pki/ca.crt /tmp/aws-vpn/ # collect server cert/key cp pki/issued/server.crt /tmp/aws-vpn/ cp pki/private/server.key /tmp/aws-vpn/ # collect cliet cert/key cp pki/issued/client1.vpn.tld.crt /tmp/aws-vpn/ cp pki/private/client1.vpn.tld.key /tmp/aws-vpn/ # check certs/keys were successfully copied ls -lrt /tmp/aws-vpn/
AWS ACMに作成したサーバ・クライエントの証明書とキーをインポート:
-
awscli用のプロファイル
AWS_PROFILE
を設定:export AWS_PROFILE={YOUR APPROPRIATE AWS PROFILE}
-
AWS ACMに作成したサーバの証明書とキーをインポート:
aws acm import-certificate --certificate file:///tmp/aws-vpn/server.crt --private-key file:///tmp/aws-vpn/server.key --certificate-chain file:///tmp/aws-vpn/ca.crt
-
AWS ACMに作成したクライエントの証明書とキーをインポート:
aws acm import-certificate --certificate file:///tmp/aws-vpn/client1.vpn.tld.crt --private-key file:///tmp/aws-vpn/client1.vpn.tld.key --certificate-chain file:///tmp/aws-vpn/ca.crt
-
AWS ACMに正しくインポートできたかを確認:
aws acm list-certificates # both server & client1.vpn.tld should be displayed in the output
-
VPN接続ログ用のCloudwatch LogGroup/LogStreamを作成:
aws logs create-log-group --log-group-name vpn-client-logs aws logs create-log-stream --log-group-name vpn-client-logs --log-stream-name connections
-
クライエントVPNエンドポイントを作成:
aws ec2 create-client-vpn-endpoint --client-cidr-block "10.0.208.0/22" \ --server-certificate-arn $(aws acm list-certificates --query 'CertificateSummaryList[?DomainName==`server`].CertificateArn' --output text) \ --authentication-options Type=certificate-authentication,MutualAuthentication={ClientRootCertificateChainArn=$(aws acm list-certificates --query 'CertificateSummaryList[?DomainName==`client1.vpn.tld`].CertificateArn' --output text)} \ --connection-log-options Enabled=true,CloudwatchLogGroup=vpn-client-logs,CloudwatchLogStream=connections
-
VPCにクライエントVPNエンドポイントをアソシエイト:
NOTE: 少なくともVPCに'public'のTagValueが存在すると想定
1 クライエントVPNエンドポイントのみが存在と想定export RCS_VPCID={YOUR TARGET VPC} aws ec2 associate-client-vpn-target-network \ --client-vpn-endpoint-id $(aws ec2 describe-client-vpn-endpoints --query 'ClientVpnEndpoints[0].ClientVpnEndpointId' --output text) \ --subnet-id $(aws ec2 describe-subnets --query 'Subnets[?VpcId==`'$RCS_VPCID'` && Tags[?Value==`public`]].SubnetId | [0]' --output text)
-
VPCのセグメント(10.0.0.0/16)にVPNエンドポイントの接続を許可:
NOTE: Defined CIDR here is specific to prepared VPC, may need to update in your case.
aws ec2 authorize-client-vpn-ingress \ --client-vpn-endpoint-id $(aws ec2 describe-client-vpn-endpoints --query 'ClientVpnEndpoints[0].ClientVpnEndpointId' --output text) \ --target-network-cidr "10.0.0.0/16" \ --authorize-all-groups
-
ローカルPCでクライエントVPNエンドポイント用のクライエント設定ファイルをダウンロード:
NOTE: 1 クライエントVPNエンドポイントのみが存在と想定
aws ec2 export-client-vpn-client-configuration --client-vpn-endpoint-id $(aws ec2 describe-client-vpn-endpoints --query 'ClientVpnEndpoints[0].ClientVpnEndpointId' --output text) \ --query 'ClientConfiguration' --output text > ~/client-configuration.ovpn
-
ローカルにあるクライエントの証明書とキー情報をクライエント設定ファイル(*.ovpn)に追加:
echo "cert /tmp/aws-vpn/client1.vpn.tld.crt" >> ~/client-configuration.ovpn echo "key /tmp/aws-vpn/client1.vpn.tld.key" >> ~/client-configuration.ovpn
VPN(openvpn)で接続
-
openvpn
をインストール (ubuntu):sudo apt install openvpn
-
クライエント設定ファイル(*.ovpn)を使って、VPNで接続:
sudo openvpn --config ~/client-configuration.ovpn