AWSのClient VPNを利用する
利用する機会があったので、触った時のメモです。AWSのClinet VPNサービスとは、Managed OpenVPNサービスと呼べるものです。参考ドキュメントはこちら。
構成
こんな感じです。VPNで接続するユーザーを、Simple ADのActiveDirectoryで管理する事になります。
認証の仕組み
Clinet VPNの認証処理は、下記2つの方法が用意されています。今回の例では、下記2つを併用します。
- ActiveDirectory認証
- 相互認証(Mutual TLS)
ActiveDirectory認証は、後述のSimpleADを利用します。
相互認証とは、一般のHTTPS認証と、クライアントTLS認証を合わせた仕組みです。
相互認証とは、認証方式の一つで、双方の当事者が互いに相手の正当性を認証する方式。サーバやサービス提供者と、クライアントやサービス利用者が、相互に相手が正当な相手かどうか検証すること。通常の認証(片方向認証、単方向認証)では、クライアントがサーバの正当な利用者であることを検証するが、相互認証はクライアントから見て接続しているサーバが信用できる相手かどうか確認できない可能性がある状況で利用される。
相互認証 【 mutual authentication 】 双方向認証 / two-way authentication
【図解】クライアント証明書の仕組み~シーケンス、クライアント認証、メリット 〜
そのため、サーバーとクライアント双方それぞれで利用される証明書と鍵を作成する事になります。
ActiveDirectory認証の設定(Simple ADの作成)
Simple ADと、Simple ADを管理用のWindowsサーバーを作成します。
Simple ADとは、機能を制限されたAWS ManagedなActive Directoryサービスです。
Simple AD では、AWS Managed Microsoft AD の機能のサブセットを使用できます。たとえば、ユーザーアカウントやグループメンバーシップの管理、グループポリシーの作成および適用、Amazon EC2 インスタンスへの安全な接続を行うことができるだけでなく、Kerberos ベースのシングルサインオン (SSO) を使用できます。ただし、Simple AD では、他ドメインとの信頼関係、Active Directory 管理センター、PowerShell サポート、Active Directory のごみ箱、グループが管理するサービスアカウント、POSIX および Microsoft アプリケーションのスキーマ拡張などの機能はサポートされていません。
Simple ADは、ユーザーアカウントを管理するためのコンソール画面が用意されておらず、通常のWindowsサーバー上にインストールされた リモートサーバー管理ツール
から操作することになります。そのためのWindowsサーバーも用意します。
作成
Simple ADと管理用Windowsサーバーを作成するCloudFormationテンプレートを置いておきます。
https://github.com/goodbyegangster/cloudformation/tree/master/simple-ad
今回の例では sample.com
というドメインを作成しています。
管理用Windowsサーバのドメイン参加
作成したWindowsサーバーを、Simple ADで作成したドメインに参加させます。今回はWindows2019のサーバーを作成しています。
ネットワーク接続設定画面を開いて、IPv4のプロパティ画面まで進みます。
> %SystemRoot%\system32\control.exe ncpa.cpl
参照するDNSサーバー先として、SimpleADが提供するDNSサーバーのIPアドレスを入力します。
システムプロパティの設定画面を開いて、参加ドメイン変更画面まで進みます。
> %SystemRoot%\system32\control.exe sysdm.cpl
参加するドメインを、SimpleADで作成したドメイン名に変更します。
設定を登録すると、ドメイン参加のための認証情報を求められるので、以下と入力します。
設定 | 値 |
---|---|
ユーザー名 | (ドメイン)\administrator ※今回の例では「example.com\administrator」 |
パスワード | SimpleAD作成時に指定したもの ※上記CloudFormationテンプレートでは「Passw0rd」 |
OSを再起動します。
ClinetVPN接続可能ユーザーの作成
管理可能となったSimpleADのドメイン内に、Clinet VPNで接続可能とするユーザーを追加します。まずドメインのadministratorユーザーで、Windowsサーバーにログインします。
管理者権限で、Powershellのプロンプトを開き、以下を実行します。リモートサーバー管理ツールたるRemote Server Access Tool(RSAT)は、Windowsのコンポーネントとして用意されているため、それら一式をインストールします。
> Install-WindowsFeature -name RSAT -IncludeAllSubFeature
インストール後はOSを再起動します。
再起動後に再度サーバーにドメインadminユーザーでログインすると、Windows管理ツール内に ActiveDirectory ユーザーとコンピューター
があるので、SimpleAD内のドメインを操作できるようなります。
ここより、ClinetVPNで利用するユーザーを作成します。なお、初期ログイン時にパスワード変更を求めるユーザー設定を実施すると、ClinetVPNへの接続をできなくなるので注意。
相互認証用の設定
各証明書と鍵の作成
相互認証で利用される各証明書と鍵を作成します。作成には easy-rsa
を利用します。
easy-rsa is a CLI utility to build and manage a PKI CA. In laymen's terms, this means to create a root certificate authority, and request and sign certificates, including sub-CAs and certificate revocation lists (CRL).
easy-rsa
実行用のモジュールをダウンロードしてきます。
$ git clone https://github.com/OpenVPN/easy-rsa.git
$ cd easy-rsa/easyrsa3
PKI(Public Key Infrastructure)環境の初期化を行います。
$ ./easyrsa init-pki
init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /home/zunda/openvpn/easy-rsa/easyrsa3/pki
証明書を発行するための認証局(Certification Authority)を作成します。作成途中で求められるCommon Nameは、ブランクで問題ありません。
$ ./easyrsa build-ca nopass Using SSL: openssl OpenSSL 1.1.0g 2 Nov 2017 Generating RSA private key, 2048 bit long modulus ..........................+++ ..................+++ e is 65537 (0x010001) You are about to be asked to enter information that will be incorporatedinto your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank for some fields there will be a default value, If you enter '.', the field will be left blank. ----- Common Name (eg: your user, host, or server name) [Easy-RSA CA]: CA creation complete and you may now import and sign cert requests. Your new CA certificate file for publishing is at: /home/zunda/openvpn/easy-rsa/easyrsa3/pki/ca.crt
サーバー向けの証明書と鍵を作成します。デフォルトでは有効期限が825日で作成されるため、 EASYRSA_CERT_EXPIRE
にて有効期限を365日に変更しています。また、AWS Clinet VPNで利用する証明書はパスワード不要で作成する必要があります。
$ export EASYRSA_CERT_EXPIRE=365 $ ./easyrsa build-server-full server nopass Using SSL: openssl OpenSSL 1.1.0g 2 Nov 2017 (Library: OpenSSL 1.1.1 11 Sep 2018) Generating a 2048 bit RSA private key .........+++++ .........................+++++ writing new private key to '/home/zunda/easy-rsa/easyrsa3/pki/easy-rsa-506.K4EXuV/tmp.qwMm7I' ----- Using configuration from /home/zunda/easy-rsa/easyrsa3/pki/easy-rsa-506.K4EXuV/tmp.Sy0ERj 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 Feb 8 01:28:14 2021 GMT (365 days) Write out database with 1 new entries Data Base Updated
続いて同様に、クライアント向けの証明書と鍵を作成します。
$ ./easyrsa build-client-full client nopass Using SSL: openssl OpenSSL 1.1.0g 2 Nov 2017 (Library: OpenSSL 1.1.1 11 Sep 2018) Generating a 2048 bit RSA private key ......+++++ ...............................+++++ writing new private key to '/home/zunda/easy-rsa/easyrsa3/pki/easy-rsa-581.vaGaDx/tmp.jBGMpb' ----- Using configuration from /home/zunda/easy-rsa/easyrsa3/pki/easy-rsa-581.vaGaDx/tmp.jNtfDm Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows commonName :ASN.1 12:'client' Certificate is to be certified until Feb 8 01:29:34 2021 GMT (365 days) Write out database with 1 new entries Data Base Update
作成された以下ファイルを、一時フォルダにコピーします。
$ mkdir /tmp/zunda
$ cp pki/ca.crt /tmp/zunda/
$ cp pki/issued/server.crt /tmp/zunda/
$ cp pki/private/server.key /tmp/zunda/
$ cp pki/issued/client.crt /tmp/zunda/
$ cp pki/private/client.key /tmp/zunda/
ACMへのインポート
作成されたCA証明書、およびサーバー用証明書と鍵をACMにインポートします。
$ aws acm import-certificate \ --certificate-chain file:///tmp/zunda/ca.crt \ --certificate file:///tmp/zunda/server.crt \ --private-key file:///tmp/zunda/server.key
今回は、クライアント用証明と鍵も、easy-rsaで作成した同じ認証局(CA)で作成しているため、クライアント用証明と鍵ファイルをACMにアップロードする必要はありません。
クライアント証明書が、サーバー証明書と同じ認証機関 (発行者) によって発行されている場合、そのクライアント証明書 ARN に対してサーバー証明書 ARN を使用することができます。
Client VPNの作成
Clinet VPNエンドポイントの作成
Clinet VPNエンドポイントを作成します。作成用CloudFormationのテンプレートはこちら。
AWSTemplateFormatVersion: 2010-09-09 Description: "CFn for Client VPN" Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: "CFn for Client VPN" Parameters: - ClinetVpnName - DirectoryId - CertArn - VpcCidr - Subnet - VpnCidr Parameters: ClinetVpnName: Type: "String" DirectoryId: Type: "String" CertArn: Type: "String" VpcCidr: Type: "String" Subnet: Type: "AWS::EC2::Subnet::Id" VpnCidr: Type: "String" Resources: CloudwatchLogGroup: Type: "AWS::Logs::LogGroup" # https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-logs-loggroup.html DeletionPolicy: "Delete" Properties: LogGroupName: !Sub /aws/clientvpn/${ClinetVpnName} RetentionInDays: 30 CloudwatchLogStream: Type: "AWS::Logs::LogStream" # https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-logs-logstream.html DeletionPolicy: "Delete" DependsOn: "CloudwatchLogGroup" Properties: LogGroupName: !Ref CloudwatchLogGroup LogStreamName: !Ref ClinetVpnName Endpoint: Type: "AWS::EC2::ClientVpnEndpoint" # https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-clientvpnendpoint.html DependsOn: "CloudwatchLogStream" DeletionPolicy: "Delete" Properties: AuthenticationOptions: - Type: "directory-service-authentication" ActiveDirectory: DirectoryId: !Ref DirectoryId - Type: "certificate-authentication" MutualAuthentication: ClientRootCertificateChainArn: !Ref CertArn ClientCidrBlock: !Ref VpnCidr ConnectionLogOptions: Enabled: True CloudwatchLogGroup: !Ref CloudwatchLogGroup CloudwatchLogStream: !Ref CloudwatchLogStream Description: "sample" # DnsServers: # - String ServerCertificateArn: !Ref CertArn SplitTunnel: False TagSpecifications: - ResourceType: "client-vpn-endpoint" Tags: - Key: "Name" Value: !Ref ClinetVpnName TransportProtocol: "udp" Association: Type: "AWS::EC2::ClientVpnTargetNetworkAssociation" # https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-clientvpntargetnetworkassociation.html DependsOn: "Endpoint" DeletionPolicy: "Delete" Properties: ClientVpnEndpointId: !Ref Endpoint SubnetId: !Ref Subnet Authorization1: Type: AWS::EC2::ClientVpnAuthorizationRule # https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-clientvpnauthorizationrule.html DependsOn: "Endpoint" DeletionPolicy: "Delete" Properties: # AccessGroupId: String AuthorizeAllGroups: true ClientVpnEndpointId: !Ref Endpoint Description: "for vpc" TargetNetworkCidr: !Ref VpcCidr Authorization2: Type: AWS::EC2::ClientVpnAuthorizationRule # https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-clientvpnauthorizationrule.html DependsOn: "Endpoint" DeletionPolicy: "Delete" Properties: # AccessGroupId: String AuthorizeAllGroups: true ClientVpnEndpointId: !Ref Endpoint Description: "for internet" TargetNetworkCidr: "0.0.0.0/0" VpnRoute: Type: "AWS::EC2::ClientVpnRoute" # https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-clientvpnroute.html DependsOn: "Association" DeletionPolicy: "Delete" Properties: ClientVpnEndpointId: !Ref Endpoint Description: "for internet" DestinationCidrBlock: "0.0.0.0/0" TargetVpcSubnetId: !Ref Subnet
設定上の注意点はこちら。
ClientCidrBlock
で指定するCIDRは、プレフィックスが/16から/22の間である必要あります。
ClientRootCertificateChainArn
と ServerCertificateArn
は、同じ認証局を利用しているため、ACMに登録した同じ設定情報を登録します。
ClientVpnAuthorizationRule
の設定で、アクセス先とするVPCのCIDR情報、およびVPN接続時にもInternetに接続可能とするため、 0.0.0.0/0
を登録します。合わせて、 ClientVpnRoute
にも、 0.0.0.0/0
をDestinationとする経路情報を登録しておきます。
接続してみる
ClientにあたるWindows10のPCから、接続してみます。
まず、OpenVPNのClientをインストールします。
OpenVPN GUI for Windows - インストール
作成されたClient VPNよりコンフィグファイルをダウンロードします。ダウンロードは、ClinentVPNのコンソール上より実施できます。
ダウンロードしたコンフィグファイルと、作成したクライアント向け証明書・鍵ファイルを、以下に配置します。
C:\Users\zunda\OpenVPN\config\sample ├── client.crt ├── client.key └── downloaded-client-config.ovpn
ダウンロードしたコンフィグファイルの末尾に、 cert client.crt
と key client.key
という設定を追加します。下記みたく。
... auth-user-pass reneg-sec 0 cert client.crt key client.key
以上で必要設定は完了です。VPNに接続可能となります。なお、VPN接続中にVPC内リソースにアクセスする場合、SourceとなるIPアドレスは、ClinetVPNで利用されているENIのIPアドレスとなっているので、その点は注意です。