Windows PowerShellスクリプトでファイアウォールルール追加

Windows UpdateフィルタWindows Privacyフィルタで提供しているWindowsファイアウォール設定用PowerShellスクリプトの使い方。
WindowsのPowerShellは馴染みが薄いという人も多いだろうけど最も基本的な部分の使い方自体はコマンドプロンプトとそれほど大きく違わない。ただし、コマンドプロンプト用のバッチファイル(拡張子: bat)はエクスプローラー上でファイルをダブルクリックで実行できるのに対し、PowerShellのスクリプトファイル(拡張子: ps1)はダブルクリックでは実行できないので使おうと思ったら嫌でも黒画面(PowerShellは紺画面だけど)でコマンドを打たなければならない。そして、コマンドプロンプトと同じく文字の選択やコピー貼り付けは使いにくい。
コマンド入力は面倒だけどWindowsのファイアウォールを手動で設定するのはもっと面倒なので少しだけガマン。

スクリプトのダウンロード

まずはWindows UpdateフィルタWindows PrivacyフィルタからWindowsファイアウォール設定用PowerShellスクリプトをダウンロードする。ブラウザによってはリンクをクリックした際に「開く」と「ダウンロード」を選択する画面が出るけど開くではなくダウンロードを選択。
通常はオペレーション中のユーザーの「ダウンロード」フォルダにダウンロードされる筈(という前提で以下の説明に続く)。

Windows PowerShell画面を開く

Windows10 Firewall設定1
スタートボタンを「左クリック」し、最下部の「全てのアプリ」を「左クリック」。
Wまでスクロールして「Windows PowerShell」を「左クリック」する。ネストされたメニュー内の「Windows PowerShell」を「右クリック」し、ポップアップしたメニューで「管理者として実行する」を「左クリック」する。

Windows10 Firewall設定2
一見コマンドプロンプトに似た風なPowerShellの画面。

現在のスクリプトの実行ポリシーを確認する

Windowsの初期状態ではPowerShellのスクリプトが実行不可になっている筈だが、一応確認する。(必須ではない)

PS C:\WINDOWS/system32> Get-ExecutionPolicy
Restricted

Get-ExecutionPolicy(全部小文字でも構わない。以下入力時は同じ)と入力して[Enter]でRestrictedと表示されたらスクリプトは実行できない状態。Unrestrictedなら制限が解除された状態。AllSigned やRemoteSignedなら既に何らかでPowerShellを触っていて理由があって変更している筈。

スクリプトの実行ポリシーの変更

PS C:\WINDOWS/system32> Set-ExecutionPolicy Unrestricted
実行ポリシーの変更
実行ポリシーは、信頼されていないスクリプトからの保護に役立ちます。実行ポリシーを
変更すると、about_Execution_Policiesのヘルプ トピック
(http://go.microsoft.com/fwlink/?LinkID=135170)
で説明されているセキュリティ上の危険にさらされる可能性があります。実行ポリシーを
変更しますか?
[Y] はい(Y)  [A] すべて続行(A)  [N] いいえ(N)  [L] すべて無視(L)  [S] 中断(S)
[?] ヘルプ (既定値は "N"): y
PS C:\WINDOWS/system32>

ポリシーがUnrestrictedでない場合(通常)はPowerShellスクリプトを実行できるように制限を解除する。Set-ExecutionPolicy Unrestricted と入力して[Enter]。
ポリシー変更の確認メッセージと選択が表示されるので[y]を押して[Enter]。
エラーにならなければ解除完了。または1つ前の手順で状態を確認。

ダウンロードしたスクリプトの実行

ダウンロードしたスクリプト(この記事の趣旨ではwinfirewall_windows_update.ps1またはwinfirewall_windows_privacy.ps1)を実行する。この記事でやりたいメインはこれ。

PS C:\WINDOWS/system32> ~\downloads\winfirewall_windows_update.ps1
または
PS C:\WINDOWS/system32> ~\downloads\winfirewall_windows_privacy.ps1

セキュリティ警告
信頼するスクリプトのみを実行してください。インターネットから入手したスクリプトは
便利ですが、コンピューターに危害を及ぼす可能性があります。このスクリプトを信頼
する場合は、この警告メッセージが表示されないように、Unblock-Fileコマンドレットを
使用して、スクリプトの実行を許可してください。
C:\User\Foobar\downloads\winfirewall_windows_update.ps1を実行しますか?
[D] 実行しない(D)  [R] 一度だけ実行する(R)  [S] 中断(S)  [?] ヘルプ (既定値は "D"): r

~\downloads\winfirewall_windows_update.ps1 と入力して[Enter]
または
~\downloads\winfirewall_windows_privacy.ps1 と入力して[Enter]

コマンドのどちらかを実行する。(2つダウンロードして両方のコマンド実行もモチロンあり)
~\downloadは実行中のユーザーの「ダウンロード」フォルダのこと。「~」であって「^」ではないので注意。「\」(バックスラッシュ)は日本語環境では¥(半角の円マーク)。
セキュリティ警告が出るので「一度だけ実行する」の「r」を押して[Enter]。

備考: PowerShellではコマンドプロンプトと違いカレントディレクトリ(カレントフォルダ)要するに現在のフォルダにあるスクリプトファイル名を指定しても実行できないのでその点だけ注意。コマンドプロンプトならc:\example\file.batを実行したい場合は cd \example[enter]でc:\exampleに移動してファイル名直指定 file.bat[enter] で実行できるけどPowerShellだと必ずスクリプトファイルのパスを指定しなければダメ。だからc:\example\file.ps1を実行したくてcd \example[enter]でc:\exampleに移動したとしても \example\file.ps1みたいにフルパスで指定するか.\file.ps1のように相対パスで指定するなどが必要。
ちなみにファイル名リストを表示したいときはコマンドプロンプトと同じく dir コマンドが使えるが Unix系と同じく ls も使える。 いろんな部分でUnix系シェルの作法に近い。

スクリプトの実行結果

Name                  : {68f4d025-50ab-4a30-a843-2642af4595a8}
DisplayName           : Windows10Privacy_inbound
Description           : https://gato.intaa.net/net/windows_update_filter
DisplayGroup          :
Group                 :
Enabled               : True
Profile               : Any
Platform              : {}
Direction             : Inbound
Action                : Allow
EdgeTraversalPolicy   : Block
LooseSourceMapping    : False
LocalOnlyMapping      : False
Owner                 :
PrimaryStatus         : OK
Status                : 規則は、ストアから正常に解析されました。 (65536)
EnforcementStatus     : NotApplicable
PolicyStoreSource     : PersistentStore
PolicyStoreSourceType : Local

Name                  : {5c5a97a3-ccf9-4958-856f-0ca832c81322}
DisplayName           : Windows10Privacy_outbound
Description           : https://gato.intaa.net/net/windows_privacy_filter
DisplayGroup          :
Group                 :
Enabled               : True
Profile               : Any
Platform              : {}
Direction             : Inbound
Action                : Allow
EdgeTraversalPolicy   : Block
LooseSourceMapping    : False
LocalOnlyMapping      : False
Owner                 :
PrimaryStatus         : OK
Status                : 規則は、ストアから正常に解析されました。 (65536)
EnforcementStatus     : NotApplicable
PolicyStoreSource     : PersistentStore
PolicyStoreSourceType : Local

こんな感じに2つのルールが読み込まれて「規則は、ストアから正常に解析されました。 (65536)」が2回表示されれば成功。Name行の {ホニャララ} の部分は固有の値になるので気にしない。

スクリプトの実行ポリシーを戻す

PS C:\WINDOWS/system32> Set-ExecutionPolicy Restricted
実行ポリシーの変更
実行ポリシーは、信頼されていないスクリプトからの保護に役立ちます。実行ポリシーを
変更すると、about_Execution_Policiesのヘルプ トピック
(http://go.microsoft.com/fwlink/?LinkID=135170)
で説明されているセキュリティ上の危険にさらされる可能性があります。実行ポリシーを
変更しますか?
[Y] はい(Y)  [A] すべて続行(A)  [N] いいえ(N)  [L] すべて無視(L)  [S] 中断(S)
[?] ヘルプ (既定値は "N"): y
PS C:\WINDOWS/system32>

スクリプトの実行ポリシーがUnrestrictedのままで放置するのは危険。このポリシーは手動で変更するまでPowerShellを終了してもPCを再起動してもそのままなのでRestricted (または正当な理由があればAllSigned, RemoteSigned)に戻すことを忘れないよう十分に注意。
Set-ExecutionPolicy Restricted と入力して[Enter]。 ポリシー変更の確認メッセージと選択が表示されるので[y]を押して[Enter]。 エラーにならなければ戻し完了。

ここまで問題なければ exit [Enter]でPowerShell画面を終了する。

まとめ

以上、ごちゃごちゃ書いたけどやったことはこんだけ。

  • スクリプトのダウンロード
  • Windows PowerShellの画面を開く
  • スクリプトの実行ポリシー変更
  • ダウンロードしたスクリプトを実行
  • スクリプトの実行ポリシーを戻す

この記事の目的であるMicrosoftの更新系や情報収集系サーバへの接続停止はこの時点で実現している筈。
フィルタを更新をしたい場合もここまでの手順を再度実行するだけ。この記事で実行したファイアウォールの設定スクリプトは設定を上書きする仕様なので先に古い設定を消すなどの必要ない。
以下はこの記事で追加したファイアウォールのルールの存在確認と停止/削除方法。

Windows10 Firewall設定3
スタートボタンを「右クリック」し、「コントロールパネル」を「左クリック」。

Windows10 Firewall設定4
コントロールパネルで「Windows ファイアウォール」を「左クリック」。

Windows10 Firewall設定5
Windows ファイアウォールで左メニューから「詳細設定」を「左クリック」。

Windows10 Firewall設定6
左ペインの「受信の規則」を選択。中央のペインをスクロールし「Windows10Update_Inbound」または「Windows10Privacy_Inbound」(または両方)を探し、左に道路標識の「駐車禁止」に似たマークが付いていれば「ブロック」ルールとして機能していることがわかる。
左ペインの「送信の規則」を選択。中央のペインをスクロールし「Windows10Update_Outbound」または「Windows10Privacy_Outbound」(または両方)を探し、左に道路標識の「駐車禁止」に似たマークが付いていれば「ブロック」ルールとして機能していることがわかる。

ルールを一時的に無効化したい場合は中央のペインで無効化したいルールを選択した状態で右ペインの「規則の無効化」を「左クリック」。「駐車禁止」に似たマークが消えればルールが無効化されている。
ルールを削除したい場合は中央のペインで削除したいルールを選択した状態で右ペインの「削除」を「左クリック」。中央ペインからそのルールが消えれば完了。

FAQ

Q: Hostsファイルを触れば簡単じゃない?
A: Microsoftの幾つかのホストへはHostsファイルの設定を無視して強制的に名前解決して接続するのでHostsファイルの変更では通信を阻止できない。

Q. これは何がしたいの?
A. Windows10の更新不具合を避ける或いはWindows10が勝手にPCや個人の情報をMicrosoftに送信するのを防ぐためにMicrosoftの一部のサーバに接続させない(通信をブロックする)ことが主目的。「がとらぼ」ではこれまでFreeBSD/OpenBSDあるいはLinuxなどをファイアウォールとして利用している所謂「ものずきな人」向けに通信ブロック用IPアドレスリストを提供してきたが、家庭用ブロードバンドルーターなどを利用している普通の人は使えなかった。Windowsに標準で備わっているファイアウォールを簡単に設定できれば多くの人が利用できるんじゃね?と考えて作ったのがこれ。

Q. 効果ある?
A. わからん、けどパケットキャプチャしてみた限りでは意図通り機能してる。

Q. ファイアウォールのルールは更新しなくて良い?
A.ブロック対象ホスト数やIPアドレスの追加変更は意外と少ないようなので頻繁な更新は要らないと思われる。

関連記事:


WordPressの一括変換用Search Regexプラグイン

WordPressで記事が増えてきたころに一括で修正したいようなことってよくあると思うんだけど、Wordpress自体はそういう一括修正のようなものは機能として持っていないので手作業となるとどえらく苦労することに。まぁ事実上無理。
そこでSearch Regexプラグインの登場になるわけだけどググっても単純な文字列の置換についての紹介しか見かけないので書いてみた。

Search Regex 1
画像1;
管理画面のツールから「Search Regex」を選ぶ。このツールは管理者画面では1項目だけ。ツールの操作画面も1つだけ。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<p></p>

<a href="http://example.com/page1.html">リンク1</a>

<a href="http://example.com/page2.html">
リンク2
</a>

<a href="http://example.com/"><br />リンク3</a><br /><a href="http://example.net/"><br />リンク4</a>

大小HijK

0123456789

<img src="http://example.com/dir/abc.webp" />
<img src="http://example.com/dir/def.webp" />
<img src="http://example.org/dir/abc.webp" />
<img src="http://example.org/dir/def.webp" />

信号機の色は赤です

16/05/04
2016/05/04

上のような投稿があったとして、以下はこの内容を置換するものとする。
この記事では投稿1つだけのテストサイトでやってるので検索結果や置換結果が少ないけど、実際には全ての投稿や固定記事(など)を対象とするので置換対象が膨大になる場合がある。なお、膨大といっても数万程度ならこのプラグインはサクッと処理できるので大丈夫。大変なのは確認かな。

Search Regex 2
画像2;
まずは単純な文字列の置換。Windowsの低機能な「メモ帳」にすら実装されている普通の置換機能と同等なので難しいことはない。
Source(WordPressのどの部分を対象とするか)はPost content (投稿と固定記事の本文のこと)を指定。 Search patternには置換対象(マッチさせる文字列)、Replace patternには置換文字列を指定する。
[Search]を押すとSourceからマッチするパターンを探して表示するだけで置換後の表示は無い。データベースは書き換えない(保存されない)ので何度でも試行錯誤できる。
[Replace]を押すとSourceから置換対象を探してマッチするものを表示すると共に置換したらどうなるかも表示する。これもデータベースを書き換えないので何度でも試行錯誤できる。
[Replace & Save]を押すと置換対象を探し置換してデータベースを書き換える。実行してしまうと戻せないような事態もあるので置換対象や置換したらどうなるかもしっかり確認するまではこのボタンは押さない。
上の画像は「桜」というのを「さくら」に変えたいという場合。単純に置換対象と置換文字列を指定して[Replace]を押した。
下の方に結果が表示される。緑塗りになっているのが検索対象の前後を含む文字列でその中で赤い部分がマッチした検索対象文字列。
黄色塗りになっているのが置換後の状態で前後の文字列を含む。その中で赤い部分が置換文字列。

ここからがこのSearch Regexの本領部分。

たとえばexample.comへのリンクを全て消し去りたい場合は基本的には下のようなタグを探すことになる。

<a href="http://example.com/○○">□□□</a>

おそらくリンク毎に○○や□□□の部分がバラバラなのでワイルドカードや正規表現を必要とする。そこでSearch Regexの正規表現モードを使うために「Regex:」にチェック。
正規表現モードのときは「Regex:」にチェックするだけでなく置換対象の文字列(置換パターン)をデリミタ / で挟む。←この1行見ただけで正規表現を扱い慣れている人は後を読む必要は無いかも。 逆に正規表現に馴染みがないと扱いにくいと思うかもなので下を頭の片隅にでも。

使い方の基本ルール

  • 既に書いたが / で置換対象の文字列を挟む。 例: /置換対象/
  • 行頭をマッチさせたいならMultilineモードで置換対象に^を付ける。 例: /^置換対象/
  • 行末をマッチさせたいならMultilineモードで置換対象に$を付ける。 例: /置換対象$/
  • 幾つかの特殊文字 /  .  *  +  ^  $  [  ]  (  )  {  }  \  |  などはエスケープが必要。
  • ワイルドカードは .* として使う * だけでは機能しない。(何か変だが)
  • 最長一致と最短一致を意識する。 最短一致で使いたい場合は .*? のように使う。
  • コードは途中で改行されて複数行で記述されているかもしれないことを意識する。

エスケープの例
普通に考えて<a href.*example.com.*</a> とするところを
<a href.*example\.com.*<\/a> のように特殊文字の直前に \ を付ける。

なお、\ は日本語環境だと半角の円記号 ¥ を使う。(←の¥は半角の円記号ではないので注意)

Search Regex 3
画像3;
普通に考えて /<a href.*example\.com.*<\/a>/ を置換対象とした。Regexにチェックして検索ボタンを押したところが上の画像。
リンク1は思惑通りにマッチした。しかし、リンク2はマッチせず、リンク3はマッチしているもののリンク4の終わりの</a>まで繋がってマッチしているので正しくない。
これは複数行を探していないのとパターンマッチの規則が最長一致だから。

Search Regex 4
画像4;
最短一致で抽出したい。そこで置換対象を /<a href.*?example\.com.*?<\/a>/ にする。つまり「?」を追加した。
その結果が上の画像。こんどはリンク1はもちろんリンク3も正しくマッチして、リンク4は (example.netは対象外なので)マッチしていない(正しい動作)。ただしリンク2はマッチしていない。

Search Regex 5
画像5;
リンク2もマッチさせたいので複数行に対応させる。画像4の置換対象のワイルドカード部分に . を含んでいるので「改行も含むすべての文字にマッチ」するモード(perlの正規表現でいうSinglelineモード)でパターンマッチする。(複数行を1行としてパターンマッチさせるので普通に想像するシングルラインとは意味が逆になる)
Search Regexには「dot-all」モードがあるのでチェックすると上の画像。
こんどは複数行に分かれて書かれたリンク2も思惑通りマッチした。
なお、Search RegexのResult欄は改行は無しで表示されるので念の為。

Search Regex 6
画像6;
dot-allにチェックしないで画像5と同じ結果を得るなら直接パターンマッチ演算子の s を付けて /マッチさせる文字列に.を含む/s のようにする。パターンマッチ演算子を直接付けて機能するんだったらSearch RegexプラグインのチェックボックスはRegexだけで良いんじゃないかと思うんだけど・・どうせ正規表現知らなきゃ使えない部分だし。

ついでにMultilineモードだけど、例えば行頭から0123のような文字列で始まるものをマッチさせたい場合に検索対象を /^0123/ とする。789が行末のような文字列をマッチさせるには検索対象を /789$/ とする。これを使うときはSearch Regexの「Multiline:」にチェックする。またはチェックはしないでパターンマッチ演算子の m をつけて /^0123/m や/789$/m のようにする。
初稿は寝ぼけてSearch RegexのMultilineのチェックが機能してないとかウソ書いてた、スミマセン。

Search Regex 7
画像7;
アルファベットの大文字小文字を無視して検索する場合は「case-insensitive:」にチェックを付ける。またはRegexオプションとして(デリミタの後に)iを付ける。例: /置換対象/i
上の画像では全て小文字のhijkで検索すると大文字小文字混ざりのHijKが思惑通りマッチした。

Search Regex 8
画像8;
パターンの一部をグループとして取り出した置換もできる。
上の例では0123456789から34の部分と78の部分をワイルドカードを括弧で括った2つのグループとして抜き出した。
そのグループを置換文字列として出力する。出力先は$1 $2などなど置換文字列側の括弧で括った順番に対応して数字を付ける。逆に並べて $2 $1 のようにしたり $1 $1 などのように同じグループを複数回使用することも当然できる。

Search Regex 9
画像9;
括弧で括った部分が1グループなので上の画像のようにexample.comという文字列を含むURL部分を最短一致で抜き出したものをグループとして抜き置換した。
もちろんexample.orgにはマッチしていない。こういう使い方をすることは何気に多い筈。特に大量にある場合はこういうの出来ないと大変。

Search Regex 10
画像10;
いずれかの文字列(選択パターン)をグループとして抜き出すことも可能。上の例だと /信号機の色は(青|黄|赤)です/ で青、黄、赤のいずれかであればマッチして抜き出される。だから「信号機の色は緑です」だとマッチしない。

Search Regex 11
画像11;
対象文字を絞り込んだり文字数を指定した(文字集合)パターンも作れる。上の例だと /([0-9]{4}\/([0-9]{2}\/([0-9]{2})/ で数字4文字/数字2文字/数字2文字のパターン(例: 2016/05/05)にマッチした場合にその各要素を抜き出している。年月日の区切りの / はエスケープが必要なので \/ になっている。

Search Regexプラグインの使い方というより正規表現のことしか書いてない感じになってるのでこれで終わり。正規表現の方も触りだけだけど。

Up