AWS Client VPN の OpenVPN 設定ファイルの内訳を確認してみた

VPN クライアント設定ファイルを「クライアント証明書の情報を追記する」くらいの用途でしか触ったことがなかったので、中身を理解してみました。

コンバンハ、千葉(幸)です。

AWS Client VPN では、OpenVPN ベースのクライアントを使用できます。

クライアントのセットアップの一環として「プロファイル」を作成する際には、VPN クライアント設定ファイルを読み込ませます。この設定ファイルは、AWS マネジメントコンソールからダウンロードしたものを使用するのが一般的です。この設定ファイルも OpenVPN ベースです。

特に OpenVPN に詳しくなくても AWS Client VPN のセットアップに困ることはないのですが、ふとしたときに設定ファイルを眺めることがありました。

それぞれの設定値の意味を確認したいとき、AWS ドキュメントではなく OpenVPN 関連のマニュアルを参照する必要があります。

せっかくなので調べた内容をこのブログにまとめておきます。

OpenVPN 設定ファイルのマニュアル

設定項目の意味を調べたいとき、まずは OpenVPN の公式のマニュアルを確認すると良いでしょう。

↑ここでは2023/8時点で最新の OpenVPN 2.6 マニュアルを参照しています。ページ内のリンクから他のバージョンのリファレンスに遷移できます。

OpenVPN をコマンドラインで実行する際の--付きの形式で書かれていますが、設定ファイルに記述する際は--を除去できる、と記載があります。

Though all command line options are preceded by a double-leading-dash ("--"), this prefix can be removed when an option is placed in a configuration file.

また、OpenVPN のクライアント側の設定ファイルのサンプルは以下にあります。コメント付きで記述されているので参考になります。

今回のブログでは、上記2つのソースを参考に内容を記述しています。

OpenVPN 設定ファイルのベーシックな設定項目

AWS Client VPN エンドポイントの設定値等によって細かい部分は変わりますが、AWS マネジメントコンソールからダウンロードした VPN 設定ファイルのサンプルは以下です。

cvpn-endpoint-xxxxxx.ovpn

client
dev tun
proto udp
remote cvpn-endpoint-xxxxxxxxxxxxx.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-----
(ACMにインポートされたサーバー証明書の中身)
-----END CERTIFICATE-----

</ca>
auth-user-pass

reneg-sec 0

verify-x509-name server name

まずはこれらの内容について簡単に押さえます。

以降、表で「サーバー」という時には AWS Client VPN エンドポイントのことを指します。

項目名 引数例 概要
client なし クライアント側の設定ファイルであることの宣言
dev tun デバイスの設定(TUN or TAP)
proto udp サーバーとの接続に用いるプロトコル(UDP or TCP)
remote cvpn-endpoint-xxxxxxxxxxxxx.prod.clientvpn.ap-northeast-1.amazonaws.com 443 サーバーのDNS名、ポート
remote-random-hostname なし DNSキャッシュを防ぐためリモートホスト名にランダムな文字列を付与する
resolv-retry infinite サーバーのDNS名の名前解決に失敗した際のリトライする秒数
nobind なし 指定するとローカルポート番号をバインドしない(動的割り当て)
remote-cert-tls server サーバー証明書がRFC3280 TLS に基づいて署名されていることを要求
cipher AES-256-CBC 暗号方式の選択
verb 3 ログレベルを0~11で指定。verbosity。
ca なし(証明書の内容が<ca></ca>に挟まれて記述されている) サーバー証明書
auth-user-pass なし サーバーでユーザー名とパスワードでの認証を実施
reneg-sec 0 データチャネルキーの再ネゴシエーションまでの秒数
verify-x509-name server name サーバー証明書のコモンネームなどを検証

設定項目について補足

いくつかピックアップして補足説明します。

dev

TUN/TAPのいずれかを選択します。

TUN/TAPは仮想ネットワークデバイス及びそのデバイスドライバの実装およびデバイス名で、主にUnix系システムで利用できる。実ハードウェアであるネットワークカードと対応しているデバイスドライバと同様にネットワーク通信ができるが、データはハードウェアではなく、ネットワーク通信を仮想化したソフトウェアのプロセスに送られ、そこで処理される(例えば、VPNの相手方への通信として、改めて実ハードから送信される)。

TUN はネットワーク層、TAP はデータリンク層をシミュレートします。

AWS Client VPN の機能を考えると、 TUN のみがサポートされていると考えるのが自然です。

cipher

OpneVPN 2.4.0 より前はこのオプションが有効でしたが、2.4.0 以降は無視され、AES-256-GCM が使用されるとのことです。

AWS Client VPN が OpenVPN のどのバージョンに対応しているのか、の情報は見つけられませんでした。

ca

AWS Client VPN においては、VPN エンドポイントに関連づけた ACM のサーバー証明書の内容が埋め込まれています。

以下のようにファイルパスを指定する書き方もできます。

ca ca.crt

クライアント証明書を用いる際には、同じように以下の書き方ができます。

cert client.crt #クライアント証明書
key client.key #クライアント証明書のプライベートキー

逆に、certkeyともに以下のように書くこともできます。

<cert>
-----BEGIN CERTIFICATE-----
(クライアント証明書の中身)
-----END CERTIFICATE-----
</cert>

<key>
-----BEGIN PRIVATE KEY-----
(プライベートキーの中身)
-----END PRIVATE KEY-----
</key>

reneg-sec

VPN 接続においてデータチャネルは定期的にローテーションされる一時的な暗号化キーを使用します。

reneg-ssecは再ネゴシエートするまでの秒数を定義する項目ですが、0の場合は対向(ここではサーバー=VPNエンドポイント)の設定に依存します。

verify-x509-name

verify-x509-name 名称 タイプの構文で指定します。今回の例ではサーバー証明書のコモンネームがserverです。タイプがnameの場合、デフォルトでコモンネームの検証を行います。

AWS VPN クライアントでサポートされている OpenVPN ディレクティブ

AWS 製の VPN クライアントツール(以降は AWS VPN クライアントと呼称)では、サポートされている OpenVPN ディレクティブがドキュメントに記載されています。

  • auth-user-pass
  • ca
  • cert
  • cipher
  • client
  • connect-retry
  • cryptoapicert (Windows のみ)
  • dev
  • key
  • nobind
  • persist-key
  • persist-tun
  • proto
  • remote
  • remote-cert-tls
  • remote-random-hostname
  • reneg-sec
  • resolv-retry
  • static-challenge
  • tun-mtu
  • tun-mtu-extra
  • verb

先ほどの表で取り上げていないものがあるため、補足します。

項目名 引数例 概要
cert client.crt クライアント証明書
connect-retry 3 接続試行の間隔の秒数
cryptoapicert (Windows のみ) "SUBJ:client1.domain.tld" Windows 証明書システム ストアから証明書と秘密キーをロード
key client.key クライアント証明書用プライベートキー
persist-key なし SIGUSR1による再起動時にキーファイルを読み込み直さない
persist-tun なし SIGUSR1による再起動時にTUN/TAPデバイスをクローズしない
static-challenge "Please enter token PIN" 1 static challenge/response protocolを有効にする
tun-mtu 1500 TUNデバイスのMTU(最大伝送単位)
tun-mtu-extra 32 tun-mtuを超えて返すサイズの想定

設定項目について補足

一部を補足説明します。

persist-key

SIGUSR1による OpenVPN プロセス再起動時にキーファイルを読み込み直さないためのオプションです。

SIGUSR1とは OpenVPN に送られるシグナルの一つで、 root権限なしでプロセスを再起動する条件付き再起動を指します。--ping-restartによってトリガーされることもあります。(一定期間Pingの応答がなかったら再起動)

static-challenge

静的な Challenge/Response Protocol を使用するためのオプションです。例えば接続するユーザーにPINコードを入力させるようなことができます。

以下の構文がサポートされています。

static-challenge text echo

textにはユーザーに表示したいメッセージを、echoでは入力した内容を表示する(1)かしない(0)かを定義します。

AWS VPN クライアントでサポートされている OpenVPN フラグ

上記の「サポートされている OpenVPN ディレクティブ」に記述がないものでも、いくつかの機能は AWS VPN クライアントで対応しています。それはリリースノートで確認できます。

例えば Windows 向けクライアントのリリースノートは以下です。

多くは「OpenVPN フラグ」という表現がされています。(route-ipv6は OpenVPN ディレクティブであるものの、リリースノートにしか記述がない。)

リリースノートで確認できる項目のうち、ここまで取り上げなかったものをまとめます。

項目名 引数例 概要
route-ipv6 2001:db8:0:abc::/64 IPv6のルートをプッシュ
inactive 30 指定した秒数 非アクティブな時にVPNを終了
pull-filter ignore "route" サーバー側からの設定のプッシュをフィルタリングする
route 10.0.0.0 255.0.0.0 IPv4のルートをプッシュ
dhcp-option DNS 8.8.8.8 DHCP関連の設定をプッシュ
connect-retry-max 3 接続リトライの試行回数
dev-type tun デバイスタイプ(TUN or TAP)
keepalive 10 60 pingオプションのインターバルとタイムアウト
ping 10 指定した秒数パケットが送信されない場合pingを実行
ping-restart 120 指定した秒数パケットやpingが送信されない場合SIGUSR1による再起動
pull なし サーバーからのプッシュを受け入れる
rcvbuf 0 TCP/UDP ソケットの受信バッファサイズ
server-poll-timeout 120 サーバーからの応答を待つ最大秒数

設定項目の補足

ここでもいくつか取り上げます。

inactive

inactvie 秒数 バイトのように書くこともできます。

その場合、「指定した秒数内のトラフィック量が指定したバイト数未満の場合に VPN 接続を終了」という挙動になります。

pull-filter

以下の構文がサポートされています。

pull-filter accept text
pull-filter ignore text
pull-filter reject text

textにはサーバー側からプッシュされるオプション名が入ります。例えばroutedhcp-optionです。

  • accept:受け入れる
  • ignore:受け入れない
  • reject:受け入れず、SIGUSR1による再起動を実施

AWS Client VPN エンドポイントで指定した DNS サーバーや Client VPN ルートテーブルの内容は VPN 接続時にクライアントにプッシュされてきますが、このオプションを使うことでフィルタリングできそうです。

route

以下の構文がサポートされています。

route network/IP
route network/IP netmask
route network/IP netmask gateway
route network/IP netmask gateway metric

クライアント側で制御するよりはサーバーからプッシュされたルートをそのまま受け入れた方が複雑にならなくていいとは思います。

dhcp-options

dhcp-options タイプ パラメーターの構文で指定します。

タイプは、DNSだけでなくNTPDOMAINWINなど多くのものが対応しています。

dev-type

devで指定するデバイス名がtunもしくはtapで始まらない場合のみこのオプションで指定します。

AWS Client VPN で使う機会はあまりなさそうです。

ping

一定期間パケットが送信されなかった場合に、TCP/UDP 制御チャネル経由でリモート(ここではサーバー)に ping を送信します。(IP Ping パケットではない。)

定期的な ping により、OpenVPN 接続のための UDP パケットを許可するステートフルファイアウォールのタイムアウトを避けられます。

pull

サーバーからのオプションのプッシュを受け入れることを示すオプションです。

clientディレクティブによって暗黙的にpull相当の指定がなされているはずなので、あえて書く場面がわかっていません。

AWS VPN クライアントでサポートされていない設定項目

ここまでいくつか AWS VPN クライアントに焦点を絞って確認してきましたが、「AWS VPN クライアントではサポートされていないが AWS Client VPN で使用できる」項目もあります。

例えば以下エントリではhttp-proxyOpneVPN ディレクティブを使用しています。

使いたい機能がある場合は、OpenVPN のマニュアルから探してみるのもよいでしょう。

なお、AWS VPN クライアントでサポートされていない機能を用いる場合は、「OpneVPN クライアント」など、別のクライアントツールを用いる必要があります。

サポートされていないディレクティブが含まれる設定ファイルを読み込ませると?

AWS VPN クライアントでサポートされていないディレクティブを含む VPN 設定ファイルを用いてプロファイルを作成しようとすると、以下のようなエラーが出ます。(Windows向けの場合の例。)

OpenVPN 設定の行「xxxx」には、サポートされていないディレクティブが含まれています。それを OpneVPN 設定から削除します。

全部が全部ダメなわけじゃない?

以下の設定項目を持つ VPN 設定ファイルを用いて AWS VPN クライアントでプロファイルを作成したところ、問題なく成功しました。

auth-federate
auth-retry interact
auth-nocache

上記の項目(ディレクティブ)は、「サポートされているディレクティブ」の一覧に載っていません。この状況をどう捉えるのがよいのか分かりませんが、ドキュメントでの確認に留めず実機で検証するのが一番確実そうです。

終わりに

AWS Client VPN のクライアントに用いる OpenVPN 設定ファイルの内訳を確認してみました。

改めて考えると、AWS Client VPN とは「マネージドな OpenVPN サーバー」であると感じました。

例えば EC2 インスタンスを立ててそこで OpenVPN サーバーを起動させる、でも AWS Client VPN と近しいことはできるはずです。(あるいはもっと細やかな制御ができる。)

とはいえそこの OS 管理をするのは大変ですし、設定項目もだいぶ複雑です。AWS Client VPN を利用することでマネージドになり、設定も抽象化された形で取り扱えます。

AWS Client VPN を活用しつつ、細かい部分でカスタマイズが必要な場合は OpenVPN のマニュアルを確認してみてください。

以上、 チバユキ (@batchicchi) がお送りしました。

参考