はじめに
複数のお客さん環境を担当していると、拠点ごとに VPN をつなぎ直す機会が多くなります。毎回タスクバーから接続を選ぶのが面倒なので、接続用のバッチファイルを用意している方は多いと思います。
ただ、そのバッチが次のような形になっているケースはよくあります。
rasdial "本社VPN" user01 P@ssw0rd
動くには動きますが、パスワードがファイルに平文で残ります。端末に置きっぱなしになるファイルなので、できれば避けたいところです。
この記事では、rasphone.pbk の PreviewUserPw を書き換えることで、パスワードをどこにも書かずに VPN 接続を自動化した手順をまとめます。切り分けの過程で rasdial と rasphone の挙動の違いや、資格情報がどこに保存されるかも整理できたので、そのあたりも残しておきます。
環境
- Windows 11
- VPN 接続は「設定」アプリの「ネットワークとインターネット」→「VPN」から作成
- 接続先は複数(拠点ごとに接続エントリを分けている)
- 認証はユーザー名とパスワード
結論
先に結論だけ書いておきます。
- VPN 接続 UI で「サインイン情報を保存する」にチェックを入れて一度手動接続する
-
%APPDATA%\Microsoft\Network\Connections\Pbk\rasphone.pbkを開く - 対象エントリの
PreviewUserPw=1をPreviewUserPw=0に変更する - バッチからは接続名だけで呼ぶ
@echo off
rasphone.exe -d "本社VPN"
これでダイアログを出さずに接続まで通ります。バッチにもファイルにも平文のパスワードは出てきません。
切り分けの経緯
同じところで詰まる人もいると思うので、試したことを順に残しておきます。
引数なしの rasdial はエラー 691
まず考えたのが、Windows に資格情報を覚えさせて、バッチからは接続名だけ渡す方法です。
rasdial "本社VPN"
結果はエラー 691(ユーザー名またはパスワードが無効)。「サインイン情報を保存する」にチェックを入れて手動接続した後でも同じでした。
資格情報マネージャーにエントリがない
691 の原因を探るため、資格情報マネージャーを確認しました。
control /name Microsoft.CredentialManager
Windows 資格情報を見ても、該当する接続名のエントリはありませんでした。
つまり、GUI で保存した資格情報は資格情報マネージャーではなく rasphone.pbk 側に持たれていて、rasdial からは参照できない状態だったということです。設定アプリ経由で作成した VPN だと、この紐づけがうまくいかないことが多いようです。
なお、「サインイン情報を保存する」のチェックボックスは設定アプリの UI には出てこないことがあります。その場合は ncpa.cpl でネットワーク接続を開き、対象の接続を右クリック→プロパティ→オプションタブから設定できます。ただし Windows 11 では、この画面からダブルクリックで接続しようとすると設定アプリ側に飛ばされるので、接続自体はタスクバーのネットワークアイコンから行うことになります。
DPAPI での暗号化も検討したが見送り
rasdial を使う前提のまま、パスワードを PowerShell の ConvertFrom-SecureString で暗号化してファイルに置く方法も検討しました。
Read-Host -AsSecureString | ConvertFrom-SecureString | Set-Content vpn.txt
DPAPI で保護されるので、暗号化したユーザーアカウントと同じアカウントでしか復号できません。ファイルが持ち出されても他の端末では使えないため、平文よりはかなりマシです。
ただ、裏を返すと端末ごとに暗号化し直す必要があります。複数端末に展開する前提だと、各端末で初回セットアップを一回走らせる運用が必須になります。固定キーを渡して端末をまたいで復号できるようにする手もありますが、そのキーを配布した時点で守りたかったものが守れていないので、選択肢からは外しました。
rasphone に切り替えてエラー 623
次に rasphone を試しました。
rasphone -d "本社VPN"
今度はエラー 623(この接続のための電話帳エントリが見つかりませんでした)。rasdial は通っていたのでエントリ自体は存在するはずで、rasphone が見にいく pbk と実際にエントリがある pbk が違うパターンを疑いました。
pbk は二か所にあります。
| 種別 | パス |
|---|---|
| ユーザー個別 | %APPDATA%\Microsoft\Network\Connections\Pbk\rasphone.pbk |
| 全ユーザー共通 | %PROGRAMDATA%\Microsoft\Network\Connections\Pbk\rasphone.pbk |
-f オプションで pbk のパスを明示できるので、こちらで指定したところ 623 は解消しました。
rasphone -f "%APPDATA%\Microsoft\Network\Connections\Pbk\rasphone.pbk" -d "本社VPN"
同名エントリが両方にあると意図しない方を掴むことがあるので、展開を考えるならパスを明示しておいた方が安全です。
接続ダイアログが出るところで止まる
623 は消えましたが、今度は接続確認のダイアログが表示されたまま先に進まない状態になりました。無人実行が目的なので、ここで止まっては意味がありません。
ここで pbk の中身を眺めていて見つかったのが PreviewUserPw です。「接続前にユーザー名とパスワードの確認画面を出すかどうか」を決めている項目で、これが 1 になっていました。
0 に変更したところ、確認画面を飛ばして保存済みの資格情報でそのまま接続に進みました。
資格情報の保存自体は生きていたけれど、接続前に必ず確認ダイアログを出す設定になっていたために自動化できていなかった、というのが答えでした。691 が出ていた話とも辻褄が合います。
設定手順
1. 接続名を確認する
設定アプリの「ネットワークとインターネット」→「VPN」で、対象の接続が一覧にあることを確認します。ここに表示されている接続名がそのまま pbk のエントリ名になるので、正確にメモしておきます。
全角スペースが混ざっていると気づきにくいので、後で pbk 側と突き合わせるつもりで見ておくといいです。
2. 資格情報を保存させた状態で一度手動接続する
タスクバーのネットワークアイコンから VPN を選び、「サインイン情報を保存する」にチェックを入れた状態で接続します。
この操作で Windows がパスワードを覚えます。ここを飛ばすと後の手順が効きません。接続を確認したら、いったん切断しておきます。
3. pbk の場所を確認してバックアップする
pbk は保存先が二か所あります。VPN 接続を作成したときの設定によって、どちらに書かれるかが変わります。
| 種別 | パス | 該当するケース |
|---|---|---|
| ユーザー個別 | %APPDATA%\Microsoft\Network\Connections\Pbk\rasphone.pbk |
通常はこちら。設定アプリから作成した VPN |
| 全ユーザー共通 | %PROGRAMDATA%\Microsoft\Network\Connections\Pbk\rasphone.pbk |
「すべてのユーザーが使えるようにする」で作成した場合や、キッティング時に配布した場合 |
Windows + R に上記のフォルダパスを貼り付けて、両方とも開いて確認してください。エントリがどちらにあるか分からない状態で片方だけ直すと、書き換えたのに反映されない、という詰まり方をします。
rasphone.pbk が存在する側は、コピーして同じフォルダに貼り付けてバックアップを取っておきます。書き換えを間違えても戻せます。
なお、両方に同名のエントリが存在することもあります。その場合はどちらが使われるか読みづらいので、次の対応を取ってください。
- 両方の pbk を書き換える(どちらを掴んでも動く状態にする)
- または、片方に統一して不要なエントリを削除する
- そのうえで、バッチ側で
-fを使って pbk のパスを明示する
複数端末に展開する場合は、端末によって作成方法が違っていることがあるので、両方を見る前提で手順を組んでおいた方が安全です。
4. メモ帳で開いて PreviewUserPw を書き換える
rasphone.pbk を右クリック→「プログラムから開く」からメモ帳を選びます。ダブルクリックすると接続画面が開いてしまうので注意してください。
中身は接続ごとにブロックが分かれています。
[本社VPN]
Encoding=1
PBVersion=5
Type=2
...
PreviewUserPw=1
角かっこの行を目印に対象の接続を探し、そのブロック内の PreviewUserPw=1 を PreviewUserPw=0 に変更して上書き保存します。変更するのはこの 1 文字だけで、他の行は触りません。接続が複数ある環境では、別の接続のブロックを触らないよう気をつけてください。
両方の pbk に対象のエントリがある場合は、同じ書き換えをそれぞれに対して行います。片方だけ直して動かないときは、もう片方を掴んでいる可能性を疑ってください。
%PROGRAMDATA% 側を編集するには管理者権限が必要です。メモ帳を管理者として実行してから開くか、権限のあるエディタで開いてください。編集できたように見えて保存時に弾かれることがあるので、保存後にもう一度開いて反映を確認しておくと確実です。
5. バッチから呼ぶ
@echo off
rasphone.exe -d "本社VPN"
pbk のパスを明示する場合は -f を付けます。両方に同名エントリがある環境や、複数端末に展開する場合はこちらの形にしておくと、どちらを掴むかで挙動が変わる事故を防げます。
@echo off
rasphone.exe -f "%APPDATA%\Microsoft\Network\Connections\Pbk\rasphone.pbk" -d "本社VPN"
全ユーザー共通側を使う場合は、%APPDATA% を %PROGRAMDATA% に置き換えます。
接続名にスペースが入る可能性を考えて、ダブルクォートは常に付ける運用にしておくと事故が減ります。
結果
- バッチにもファイルにもパスワードが出てこなくなった
- 接続はバッチのダブルクリック一発、ダイアログなし
- 拠点ごとにバッチを分ければ複数の接続先にも対応できる
- 手動が必要なのは、端末ごとの初回セットアップ(資格情報の保存と pbk の書き換え)だけ
pbk はただのテキストファイルなので、PreviewUserPw の書き換えはスクリプト化できます。各端末で一度手動接続して資格情報を作ってもらい、そのあとスクリプトで pbk を書き換える、という流れなら手順を固定できます。
なお、資格情報は端末ごと・ユーザーごとに作られるため、pbk をそのままコピーして他端末に配っても使えません。展開の際は必ず各端末で初回セットアップが必要です。
補足:リダイヤル関連のパラメータ
pbk には再接続の挙動を決めるパラメータも同じ形式で入っています。VPN が切れたときの動作を調整したい場合はこのあたりが使えます。
RedialAttempts=3
RedialSeconds=60
IdleDisconnectSeconds=0
RedialOnLinkFailure=1
残課題
そのまま横展開する前に、確認しておいた方がよさそうなことです。
- Windows Update や VPN 設定の再作成で
PreviewUserPwが初期値に戻る可能性がある。pbk を作り直すと初期値に戻ることは十分あり得る - 今回うまくいったのが環境固有の条件による可能性もあるため、他の端末でも同じように効くか要確認
- 参考資料では、接続は確立するものの IP アドレスを拾えないケースが報告されている
台数が多い環境で恒久的に運用するなら、IKEv2 の証明書認証に切り替えてパスワード自体をなくすのが本来はきれいです。今回は認証方式を変更できない前提だったため、手持ちの範囲での対応になりました。
参考
-
20220215: Windows10 - VPN の自動接続 - PIB
今回最も参考にさせていただきました。PreviewUserPw=0による自動接続のほか、rasdialとrasphoneのコマンドライン仕様の違い、リダイヤル関連パラメータ、PowerShell の VpnClient モジュールについても触れられています。 - Single click to connect to VPN on Windows 10 - Super User
- How to Save Password in rasdial? - Stack Overflow