treedown’s Report

システム管理者に巻き起こる様々な事象を読者の貴方へ報告するブログです。会社でも家庭でも"システム"に携わるすべての方の共感を目指しています。

※https化しました。その影響でしばらくリンク切れなどがあるかもしれませんが徐々に修正していきます。 リンク切れなどのお気づきの点がございましたらコメントなどでご指摘いただけますと助かります。

バッチでネットワークカテゴリを判定してプライベートに変更

ネットワークカテゴリのプライベート/パブリック、同じ社内LAN(家庭内LAN)に接続されていても、ふとしたことで意外とパブリック化してしまうもの。
予期しないパブリックネットワーク適用に備えて自動化するためのバッチを作成してみましたのでご報告です。現在テスト中。

バッチファイルを管理者として実行が可能な環境があることが前提となります。
※ネットワークカテゴリの変更には管理者として実行したコマンドプロンプトが必要なため

ネットワークカテゴリ、パブリックとプライベート

Wi-FiのAPを交換した、ルータ(LAN内のデフォルトゲートウエイとなる機器)を交換した、といったネットワーク構成に変更が生じた際にWindowsで認識するネットワークカテゴリがプライベートネットワークだったものがパブリックネットワークに変わってしまうことがありました。

従来、コマンドで対処。

blog.treedown.net

バッチファイルで実行するために、

blog.treedown.net

ここで調べた、「PowerShell -command」を使う手法を学びました。

コマンドプロンプトで実行できるなら、バッチファイルで判定してパブリックネットワークの時だけ実行するようにできるんじゃないかと思って、今回バッチファイルを作成してみました。

判定条件を二つ考える

まず考えたのは、ネットワークカテゴリを判定して設定、変更の必要が無ければ何もせず終了、となるような判定条件です。
あと、持ち出した先での利用(モバイルWi-Fiが提供するDHCPとかで意図せず動作しないように)を想定して、IPアドレスをイントラネットに限定するようにしようかなと考えました。
※実際にはこれ以外にも制限事項はあるのですが、バッチファイルじゃないところで実施したので割愛。

こうなると、バッチファイルの作りとして、ネットワークカテゴリを変更する前に
1) パブリックネットワークになっているかどうか
2)IPアドレスのセグメントは予め指定したセグメントか
を判定して、条件に一致すればネットワークカテゴリをプライベートに変更するバッチファイル、ということになります。
判定するセグメントは二つ(デフォルト192.168.0.0/24と192.168.1.0/24)あります。

基本的にWindows10ではNICが複数搭載されていても、自動では一つしか有効にならない(参考:<NICが二つあると、片方が認識しない(ことがある) - treedown’s Report>)という仕様なので、ネットワークの判定条件はそれほど複雑にせず単一にしておくようにします。

バッチ内のコマンドを生成する

今のネットワークカテゴリがパブリックネットワークになっているかどうかは、PowerShellの「Get-NetConnectionProfile」コマンドを利用すれば画面に表示されます。
コマンドプロンプトで「powershell -Command」経由で実行したときにfindコマンドで抽出ができるかどうか不安だったのですが、試してみると、

f:id:treedown:20210723204618p:plain
試しにパブリックネットワークに変更したPCで状態が検出できました。これで判定できそうです。

次に、IPアドレスが予め決めていたネットワークセグメントに所属しているかを確認するために、ipconfigコマンドでIPの箇所を確認するようにします。

f:id:treedown:20210723204801p:plain
これはすんなりfindコマンドで抽出、あとはコレを組み合わせて判定条件にできれば、自動的に判定後に設定することができそうです。

バッチファイル

早速バッチファイルを。

--------------------------------------------------------------
@echo off

set IPseg=192.168.0.
set IPseg2=192.168.1.

REM パブリックネットワーク利用の判定
powershell -Command Get-NetConnectionProfile | find "Public"
if %ERRORLEVEL% == 0 goto IPdetermination
if %ERRORLEVEL% == 1 goto end

:IPdetermination
REM IPセグメントの判定
ipconfig | find "%IPseg%"
if %ERRORLEVEL% == 0 goto setNWCategory
if %ERRORLEVEL% == 1 goto NextIPdetermination
       :NextIPdetermination
       rem 副セグメントのIP判定
       ipconfig | find "%IPseg2%"
       if %ERRORLEVEL% == 0 goto setNWCategory
       if %ERRORLEVEL% == 1 goto end

:setNWCategory
rem ネットワークカテゴリをプライベートネットワークに設定
powershell -Command "Set-NetConnectionProfile -NetworkCategory Private"

:end
set IPseg=
set IPseg2=
--------------------------------------------------------------

ちょっとした解説

まずは

powershell -Command Get-NetConnectionProfile | find "Public"

でパブリックネットワークの判定をしています。パブリックネットワークなら前述のように表示されるので、条件を満たすためERRORLEVELは0となりで次の判定に飛ばします。条件外(=1)の場合にはプライベートネットワークと言う判断をして何もせずに終了させています。

この次の判定は、

ipconfig | find "%IPseg%"

で現在利用中のIPアドレスを表示させています。冒頭のsetコマンドで予め設定してある条件を満たせば(IPは「192.168.0.」なので192.168.0.xxなら)ERRORLEVELは0になりネットワークカテゴリをプライベートネットワークに変更するコマンド実行に処理を移します。
条件外の場合には(ERRORLEVEL=1)次の判定に飛ばしています。ネットワークセグメントが二つあるため、もう片方のネットワークセグメント(IPは「192.168.1.」なので192.168.1.xx)に所属しているかどうかの判定を同じように実行しています。
どちらでもなければ、何もせずに終了。

最終的に、ネットワークカテゴリがPublic、かつセグメントが「192.168.0.」または「192.168.1.」の時に

powershell -Command "Set-NetConnectionProfile -NetworkCategory Private"

を実行する、という処理をしています。

最後に

このバッチファイルを(管理者として実行するソリューションを使って)自動実行するようにして、何かしらイベントによりプライベートがパブリックに変化したら、すかさず自動実行からプライベートにネットワークカテゴリを戻す、という使い方。

ただ自動実行なので毎回実行されますが、普段は(プライベートネットワークにいる限りは)何もせず終了、持ち出したりして別ネットワークのIPを使っているときも何もせずに終了、と普段は動作しないけど、LAN内でパブリックになったときだけ動作するという意図で作成しました。

冒頭の「set IPseg=」や「set IPseg2=」を変更すれば、別のIPアドレスに対応可能。