WindowsServer2016でfail2banっぽいことをする

#はじめに
[WindowsServerへのリモートデスクトップ接続を国内IPアドレスのみに限定する](https://qiita.com/Tsukeyakiber/items/640507af9b6bff2ca958)の続きっぽい記事です。
WANから接続可能なリモートデスクトップサーバーへのブルートフォースアタックを抑制したいと思い、fail2banにたどり着いたのですが、Windows上で動作させる方法が見つかりませんでした。
ですのでfail2banを実際に使ったことのない者がこの記事を書いています。すみません；

#概要
リモートデスクトップ接続に失敗すると、イベントビューアーにログオンタイプ3で失敗の監査が記録されます。
WindowsServer2012R2までは、イベントにIPアドレスが記録されませんでした。（仕様？）
WindowsServer2016では記録されるようになったので、PowerShellとタスクスケジューラを使って次の動作をさせたいと思います。

-  20分以内に10回ログインに失敗したIPアドレスを拒否する。
 -  拒否の解除は自動で行わない。

今回は該当IPアドレスからのすべてのアクセスを拒否します。
リモートでしかアクセスできないサーバーにはおすすめしません。

#環境
- OS
 - WindowsServer2016 Standard
- ファイアウォール
  - Windowsファイアウォール
- PowerShell
  - version5

#作業手順
###Windowsファイアウォールルールの追加

![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524270/77d52279-e7ed-c1c9-a817-fd81b20e412d.png)
セキュリティが強化されたWindowsファイアウォールを開き、
【受信の規則】をクリック。
![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524270/a4b9d8b0-6428-e93d-e740-1b5c80159dbb.png)
【新しい規則】をクリック。
![003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524270/920107bb-989c-5b6d-f691-0b58c8b12c1a.png)
【カスタム】にチェックして次へ。
![004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524270/a52787e7-3967-1135-b50f-abc9b278d492.png)
【すべてのプログラム】にチェック（デフォルト）を確認して次へ。
![005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524270/f4d45577-b2f1-0213-d823-f5cf912f98cc.png)
デフォルトのまま次へ。
![006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524270/d3189011-1ec4-2813-dafe-0d1747421686.png)
下段、「**この規則を適用するリモートIPアドレスを選択してください。**」の
【これらのIPアドレス】にチェック、【追加】ボタンをクリック。
![007.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524270/8e82018d-60b1-736d-1c3e-8075a9bfd488.png)
「このIPアドレスまたはサブネット」に、拒否していいIPアドレスを1つ以上入力。
（私は過去にアタックしてきたIPを入れていますが、1.1.1.1とかでも良さそう。）
【OK】をクリック。
![008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524270/9c124033-8d1a-98e9-e45a-3df42bd7fe18.png)
IPアドレスが追加されたことを確認して次へ。
![009.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524270/8a23c2a3-80ba-1064-539a-4186595c3305.png)
【接続をブロック】にチェックして次へ。
![010.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524270/1a2f7454-05de-f891-640d-c0620e315195.png)
デフォルトのまま次へ。
![011.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524270/406abe82-95ae-2724-ca11-1adc0fa3df9a.png)
ルールの名前は「MyBanRule」にします。
![012.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524270/3ef774f2-8bf1-d36e-17d2-60659c95b720.png)
ルールが追加されました。

###PowerShellスクリプト
- Windowsファイアウォールのルール「MyBanRule」にスコープを追加します。
- 結果を次のファイル名で、スクリプトと同じディレクトリに出力します。
  - MyBanRule.log

```FWDeny.ps1
$scriptPath = $MyInvocation.MyCommand.Path
$scriptPath = Split-Path -Parent $scriptPath
$logFile = $scriptPath  + "\MyBanRule.log"

#最新のログイン失敗イベントを抽出
$events = Get-WinEvent -LogName security -FilterXPath "Event[System[Provider[@Name='Microsoft-Windows-Security-Auditing']]] and Event[System[EventID='4625'] and EventData[Data[(@Name='Logontype')] = '3']]" -MaxEvents 1
#イベントをXMLに変換
$eventsXML = [xml]$events.toXML()
#XMLからIPアドレスを抽出
$FaleIpAddress = ($eventsXML.Event.EventData.Data | ? {$_.Name -eq "IpAddress"}).'#text'
Write-Output (Get-Date) >>$logFile
Write-Output ("IPアドレス" + $FaleIpAddress + "がログインに失敗しました。")>>$logFile

#IPが記録されなかったり、ループバックアドレスだった場合はスキップ
if(($FaleIpAddress -ne "-") -and ($FaleIpAddress -notlike "127*")){
    #過去20分のイベントを抽出
    $pastEvents = Get-WinEvent -LogName security -FilterXPath "Event[System[Provider[@Name='Microsoft-Windows-Security-Auditing']]] and Event[System[EventID='4625'] and EventData[Data[(@Name='Logontype')] = '3']] and Event[System[TimeCreated[timediff(@SystemTime) <= 1200000]]]"
    #テキストに変換
    $txtpastEvents = $pastEvents.toXML()
    #調べたIPが何回失敗しているかカウント
    $IpCount = ($txtpastEvents | Select-String $FaleIpAddress).Count
    Write-Output ($IpCount.toString() + "回失敗しています。")>>$logFile

    #10回以上失敗していたら事前に作成したファイアウォールルールのスコープにIPアドレスを追加
    if($IpCount -ge 10){
        $fwDeny = New-object -comObject HNetCfg.FwPolicy2
        $myDenyRule = $fwDeny.Rules | where {$_.Name -eq 'MyBanRule'}
        $myDenyRule.RemoteAddresses += (","+ $FaleIpAddress)

        Write-Output ("IPアドレス" + $FaleIpAddress + "のログイン失敗回数が10回を超えました。")>>$logFile
        Write-Output "接続拒否リストに追加します。">>$logFile


    }

}

Write-Output "--------------------------------------------------------------------">>$logFile
```

####説明
```
#過去20分のイベントを抽出
$pastEvents = Get-WinEvent -LogName security -FilterXPath "Event[System[Provider[@Name='Microsoft-Windows-Security-Auditing']]] and Event[System[EventID='4625'] and EventData[Data[(@Name='Logontype')] = '3']] and Event[System[TimeCreated[timediff(@SystemTime) <= 1200000]]]"
```
過去20分をミリ秒で指定しています。
時間を変える場合は`1200000`を変更してください。
時間ではなく、過去500件のイベントを抽出したい場合は↓

```
$pastEvents = Get-WinEvent -LogName security -FilterXPath "Event[System[Provider[@Name='Microsoft-Windows-Security-Auditing']]] and Event[System[EventID='4625'] and EventData[Data[(@Name='Logontype')] = '3']]" -MaxEvents 500
```
件数を変更したい場合は`MaxEvents 500`の`500`を変更してください。

```
 #10回以上失敗していたら事前に作成したファイアウォールルールのスコープにIPアドレスを追加
 if($IpCount -ge 10){
```
何回失敗で拒否するかはこちらの数字で変更してください。

####実行バッチファイル

PowerShellスクリプトを実行するバッチファイルを作っておきます。

```PSexe.bat
powershell -ExecutionPolicy RemoteSigned -File ＜スクリプトファイルのフルパス＞
```
スクリプトファイルのパスが`C:\fail2ban_win\FWDeny.ps1`の場合、次のようになります。

```PSexe.bat
powershell -ExecutionPolicy RemoteSigned -File "C:\fail2ban_win\FWDeny.ps1"
```
###タスクスケジューラの設定
失敗の監査イベントが発生したときにバッチファイルを実行するように設定します。

![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524270/db384e69-7f7a-12ee-aa9b-65fc81db3c1c.png)
タスクスケジューラを開き、【タスクスケジューラライブラリ】をクリック。
![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524270/705485e3-e9b3-5573-ea4b-8a0a3337a982.png)
【タスクの作成】をクリック。
![003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524270/f590cef6-fde9-79d7-bcdd-c169b0e6c7c4.png)
任意の名前をつけます。
【ユーザーがログオンしているかどうかにかかわらず実行する】にチェック。
![004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524270/493b4c41-d74b-565a-81e2-b280be6deae9.png)
【トリガー】タブをクリック。
【新規】ボタンをクリック。
![005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524270/3c4662d2-5a72-8293-2c77-29febf47e697.png)
「タスクの開始」で【イベント時】を選択。
![006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524270/75c52bfd-9432-f632-023f-33dd5b9bf71d.png)
【カスタム】にチェックし、【新しいイベントフィルター】ボタンをクリック。
![007.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524270/14605cf4-d523-b606-835e-d46f113a9228.png)
【ログごと】にチェック。
「イベントログ」で「Windowsログ」を展開し、【セキュリティ】にチェック。
![008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524270/f8ca67a3-b876-f1be-1cd1-68a7cf5ef317.png)
「イベントID」に【4625】と入力。
OKをクリック。
![009.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524270/13e790a4-c87c-9d8e-611a-f0f1f7f0c7a8.png)
OKをクリック。
![011.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524270/86523c3c-cfab-c3bd-9fe9-abb7fc6a76fb.png)
【操作】タブをクリック。
【新規】ボタンをクリック。
![012.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524270/fd5db954-5eae-da89-c321-39d3ee034291.png)
【参照】ボタンをクリック。
![013.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524270/046c92ac-cdc3-460b-2345-94f9277877d5.png)
バッチファイル「PSexe.bat」を選択。
【開く】ボタンをクリック。
![014.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524270/7fcb943f-4e30-c79a-6dbb-9311da1dab79.png)
【開始オプション】にバッチファイルのあるディレクトリを入力。
OKをクリック。

タスクの作成ウィンドウを閉じるときにパスワードを訊かれたら入力して終了です。

![015.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524270/8f51222f-9104-a177-118f-37045d06f926.png)
タスクが作成されました。

拒否の解除は今回作ったWindowsファイアウォールのルールを開いて、スコープタブから削除します。

#おわりに
スコープに何件まで登録できるのかわからないので、あまりにアタックが多いとどうなるかわかりません。

#参考記事
- [イベントログを抽出する　FilterXPath](http://mtgpowershell.blogspot.com/2012/09/filterxpath.html)
- [セキュリティログから PowerShell でログオン履歴を抽出する](http://www.vwnet.jp/windows/PowerShell/2017102401/GetLogonHistry.htm)
- [指定期間のイベントログを取得する](http://diarywind.com/blog/e/g13_182__powershell_3.html)
- [Get-WinEvent(PowerShellのヘルプ)](https://forsenergy.com/ja-jp/windowspowershellhelp/html/62e7642c-51d4-47d1-97fe-62b08197896a.htm)
- [WindowsServerへのリモートデスクトップ接続を国内IPアドレスのみに限定する（前回の記事）](https://qiita.com/Tsukeyakiber/items/640507af9b6bff2ca958)