VPN との終わりなき戦い 〜Cloud Journey 編〜

by Junya Taniguchi | September 24, 2021
infrastructure | #infrastructure

あれから1年

こんにちは、IT 基盤部第三グループのジュンヤと申します。
前回は、新型コロナウイルス感染症の広がりによって、急遽始まったテレワークを支える VPN サービスを運用する側の苦労話を書きました。 早いものであれから1年以上が経過しました。しかし感染症は未だ終息せず、予断を許さない状況が続いています。そしてテレワークは完全に日常のものとなり、ワークスタイルも大きく様変わりしました。

そのようなワークスタイルの変化に合わせて DeNA は、大部分の座席をフリーアドレスとした新社屋への移転を決定し、本年8月に移転を完了させました。7月の平均出社率は14%と引き続き低い数字が続いており、それをささえる VPN は社内システムの中でも重要なサービスとなっています。

粛々と行われていた「3カ年計画」がついに完了

既報ではありますが、DeNA では2018年から始まったクラウド移行が本年4月に無事に完了しました。

 【ノーカット掲載】3年に及ぶクラウド移行。「創造的な仕事へのフォーカス」がついに始まる -フルスイングより-

私が担当する「社内システム」も例外なくオンプレミスからクラウドへ移行しましたが、システムの種類で言うと単純な blog サーバもあれば、比較的大規模な Github:e や 社内システムの根幹でもある Active Directory など、多岐にわたりました。 そこで今回は(も)、 VPN サービスのクラウド移行においての顛末をお送りしたいと思います。

- 移行検討 -

IaaS vs マネージドサービス

VPN に限らずですが、クラウド移行をする際に以下の観点で確認と検討を行いました。

  • そもそも移行が必要か?(撤廃が可能なサービス、他システムとの相乗りができないか?)
  • トータルコストの観点で SaaS やマネージドサービスは利用できないか?

1点目については、VPN という手段を使わないのであれば、何らかの方法で社内システムへの安全なアクセス手段を準備する必要があります。 VPN の代替になるものといえば、最近はやりの「ゼロトラスト」が挙げられますが、これはソリューションというより概念になるので、おいそれと置き換えることができないものです。 DeNA においては、IDaaS を中心とした SSO + MFA を採用した WEB アプリケーションを基本としており、すでに VPN 不要で利用できる社内サービスは多数あります。ただし、例えばエンジニアにとっては必須の SSH アクセスなどは VPN を張ることが前提となっており、ここを置き換えるとなるとセキュリティの境界線をエンドポイントまで下げることになり、実現するためにはクライアント端末のセキュリティ強化など検討すべきことが多く、今回のタイミングでは見送っています。

2点目については、IaaS で運用している以上、どうしても運用コストがある程度かかります。SaaS やマネージドサービスを利用することで運用コストを少なくし、トータルコストでみたときに有利にならないかを検討しました。 残念ながら、DeNA の利用規模では現時点において IaaS の圧勝という結果となり、最終的には IaaS でのクラウド移行を選択することになりました。

IaaS でのシステム構成

社内システムの IaaS での移行は、オンプレミスのロードバランサが ELB に置き換わることや、OS やミドルウェアのバージョン差分を考慮する必要はありますが、それほど難しいことではありません。ただし、VPN サーバにおいては状況は異なりました。

事前検証を行った結果、AWS のインターネットゲートウェイの仕様のため、オンプレミスと同じ構成でクラウドリフトすることができないことがわかりました。 AWS のインターネットゲートウェイは EC2 インスタンスがインターネットと通信を行う際、対象インスタンスの持つプライベート IP アドレスをグローバル IP アドレスに NAT する必要があります。インターネットゲートウェイにプライベート IP アドレスとして認識されるのは VPC とサブネットで定義された IP アドレス範囲のみとなりますが、VPN クライアントにはルーティングのために VPN サーバが配置されたサブネットに属さない IP アドレスの範囲を割り当てている為、VPN クライアントはインターネットにでることができません。
インターネットにでるためには、別途、プロキシサーバを準備し、それを利用させるための pac ファイルを全端末に配布する必要があることや、そもそもこの方式はブラウザアクセスのみを考慮したものであり、それ以外の通信は救えないため別の方法を準備する必要があるなど、運用が複雑になることが考えられたので、同じ構成で移行することは断念しました。

構成が変わることで予期しない問題が発生する可能性が高くなるため、なるべく構成は変えたくなかったものの、上記の理由により検討した結果、 VPN サーバ自体で NAT する構成を選択しました。

採用したシステム構成

採用したシステム構成

新システムへの切り替え、そしてあの時が蘇る

新 VPN サーバの構築が一通り完了し、関連部署の数人をアサインしてフィールドテストを実施、ACL など細かい確認をしながら切り替えに備えました。 あとは、IaaS に移行した際に必要になるであろう台数の試算です。VPN クライアント数、及び、トータルのセッション数、クライアント通信のスループットに比例して、CPU リソースを消費することがこれまでの運用経験でわかっています。このため、基本的には CPU リソースを基に台数を決めますが、IaaS であればインスタンスタイプを即時に増強できますし、スケールアウトも容易です。また、1年前の「NAT テーブル枯渇」による障害も記憶に新しく、想定より多めの台数を並べて新システムへの切り替えを実施しました。 切り替え方法として、DNS による一斉切り替えではなく、あらかじめ新しい VPN サーバ用の設定ファイルを Jamf & LanScope Cat により全端末に配布し、ユーザの都合のよいタイミング で新 VPN サーバに切り替えてもらうようにしました。これは、新 VPN サーバのグローバル IP を対向システムの許可リストに追加する必要があるためです。新旧 VPN サーバを並行運用することにより、「VPN サーバが移行したためシステムにアクセスできない」という問題や問い合わせを軽減する役割を果たしました。

事象

上記の並行運用期間を約1ヶ月とし、切り替えの推移を見守っていましたが、完全切り替え日が間近に迫るある日、多数の問い合わせが寄せられるようになってきました。

「VPN が遅い」「名前解決に時間がかかる」「Zoom に接続できない」

2020年4月の苦い記憶が蘇ります。

調査、原因箇所の特定

並行運用期間を十分に設定したとはいえ、結局のところ、多くのユーザが新サーバに切り替えたのは期日の約1週間前からでした。そのため、それまでは顕在化していない問題も接続するクライアント数が多くになるにつれて障害となって表面化した、というものでした。
報告された不具合の中で、前回の NAT テーブル枯渇問題のときと異なった点は「名前解決が遅い」というものでした。実際に、手元の VPN 接続した端末上で パケットキャプチャをとってみると、確かに DNS へのパケットが詰まる状況が確認できました。 「Windows Server の NAT テーブルが枯渇しているのではないか?」との予測はたちましたが、Windows Server の各種ログを確認しても関連しそうなイベント ID は出力されておらず、NAT テーブルが溢れていることを確認する術がありません。さらに、今回のクラウド移行においては、DNS サーバである Active Directory も同時期に移行していたため、問題が VPN サーバ以外にある可能性もありました。
そのため、通信経路の各ポイントでパケットキャプチャを取得し、どこがボトルネックになっているかを調査することにしました。

各ポイントにwiresharkを仕込む

各ポイントにwiresharkを仕込む

調査の結果、VPN サーバで NAT した通信のみにおいてパケットロスが発生していることが判明し、状況的に前回同様 NAT テーブルが枯渇していることがほぼ確定的になりました。 とはいえ、NAT テーブルが本当に枯渇しているかはサーバ上で確認することができません。
下記の通り、NAT テーブル(マッピングテーブル)を眺めることはできます。また、このテーブル情報は PowerShell で取得することができない情報のようで、全 VPN サーバに RDP 接続し、一つ一つ画面を確認するしかありません。
なにかヒントはないか根気強く見ていると、あることに気づきました。パブリックポート( NAT 後の IP の Port)の最小値と最大値こそ VPN サーバによって違えど、その差が「1976」で共通していることが判明しました。NAT Port が1976個では少なすぎます。枯渇していることに間違いない状況でしたが、これを拡張する方法がすぐには見つからなかったのです。

VPN サーバのマッピングテーブルの様子

VPN サーバのマッピングテーブルの様子

緩和策の実行

調査を続けながらも、完全切り替え日が迫ります。VPN サーバのスケールアウトを実施し、1台あたりの収容クライアント数を減らせば NAT テーブルのレコード数も減少し、パケットロスを緩和させることができます。ユーザへの影響も大きいことから、IaaS のコストが一時的に膨らむことを許容し、予定の倍の台数を構築してサービスインさせました。

探し求めていたもの

原因箇所は特定したものの、標準のパラメータでは変更できるものはありません。もちろん、様々なキーワードで検索を行ったり、周辺のメンバーに知見を求めるも、なかなか有益な情報を得ることができない状況が続きました。解決できなければ、さらにスケールアウトし、1台あたりの VPN コネクション数を減らすことで緩和するしかありません。IaaS コストも余計にかかりますし、到底、根治とは言えない状態です。

slack で情報を求める一コマ

slack で情報を求める一コマ

そんな根本解決が暗礁に乗り上げようとしていた時です。あるエンジニアが以下の情報にたどり着きました。

ルーティングとリモートアクセス環境下において、1976個以上の NAT コネクションを作ることができない

解決

「1976」という数値、説明されている症状から探していた情報はまさにこれです。 情報では、Routing and Remote Access での NAT Port はデフォルトで1976個(少なすぎる!)で、レジストリを変更することで解決するとのこと。早速、検証環境で適用してみます。 修正箇所は以下のレジストリです。

HKLM\System\CurrentContolSet\Services\IPNAT\Parameters

この設定を反映するには VPN サービスの再起動、または、OS の再起動が必要です。
検証環境で問題が解決されていること(設定した Port range を使っていること)を確認、ansible で設定を全 VPN サーバに適用し、NAT Port 枯渇問題を解決することができました。

- name: Configure for IPNAT
  win_regedit:
    name: ReservedPorts
    path: HKLM:\SYSTEM\CurrentControlSet\Services\IPNAT\Parameters
    type: String
    data: 30000-60000
    state: present

Ansible の task 例

運用負荷軽減

IaaS で運用している以上はどうしても運用コストがかかると前述しましたが、主なものとして定期的な Windows Update による再起動があげられます。一つの FQDN に対して複数の IP アドレスが紐づく DNS ラウンドロビンの構成のため、再起動する前に対象の A レコードから再起動を実施するサーバを外す必要があり、ここは手動でやらざるを得ませんでした。クラウド移行したタイミングにあわせてこの部分を自動化できないか検討し、現在では GPO による Windows Update 適用スケジュールとそれに連動した Route53 への DNS レコード修正スクリプトを準備し、人の手を介することなく適用する運用になっています。

VPN サーバの Windows Update 運用の自動化

VPN サーバの Windows Update 運用の自動化

おわりに

小規模な利用では問題がなくても、大規模な利用形態では想定していない問題が発生することは珍しくはありません。WEB アプリケーションなどではベンチマークをしておくなど、比較的予測がしやすいですが、今回のように仮想的に多数のクライアントを準備することが難しいシステムについては、想像力を働かせてボトルネックになりそうな箇所とその対応策を事前に考えておくことが大切です。

それにしても、「検索力」も立派なスキルの一つだとあらためて感じた出来事でした。精進したいと思います。


この記事を読んで「面白かった」「学びがあった」と思っていただけた方、よろしければ Twitter や facebook、はてなブックマークにてコメントをお願いします!

また DeNA 公式 Twitter アカウント @DeNAxTech では、 Blog記事だけでなく色々な勉強会での登壇資料も発信してます。ぜひフォローして下さい!