--- tags: batch, regedit, windows firewall --- # 如何透過指令實現阻擋指定IP以外的連出連入 今天有個需求需要透過指令碼封鎖所有進出入連線, 僅放行特定IP與服務可連線 依據這篇文章[Windows 防火牆設定:阻擋指定 IP 以外的電腦連入](https://kheresy.wordpress.com/2019/01/10/windows-firewall-setting-only-aloow-some-ip-connect/)提到如下 1. 沒有例外條件功能 2. 先處理封鎖、再處理允許 >但是,Windows Firewall 在建立規則的時候,並沒有「例外條件」的功能可以設定,而根據官方的文件,防火牆內部的處理順序,又是先處理封鎖、再處理允許(參考);所以要滿足這邊的需求,也不能靠兩個條件的組合來達成。 ## 規則設計 我需要的規則如下 1. 阻擋所有連入但有兩個例外 2. 阻擋所有連出 3. 例外1: IP: 192.168.66.253 服務: RDP、SMB(為了遠端桌面的檔案傳輸)、SSH、FTP PORT: 無(天曉得人家有無變更RDP PORT) 方向: 外對內 4. 例外2: IP: 211.20.177.238 PORT: 443, 80 協定: TCP 方向: 雙向 因此調整如下 1. 封鎖 0.0.0.0-192.168.66.252 1. 封鎖 192.168.66.254-211.20.177.237 1. 封鎖 211.20.177.239-255.255.255.255 細節設定的部分暫時沒想法, 目前變成對這兩個IP完全開放 192.168.66.253、211.20.177.238 ## 指令研究 ### :heavy_check_mark:防火牆狀態檢視與變更 之後打算用備份還原的方式,所以這個就用不到了~ **檢視** ```bash= > netsh advfirewall show currentprofile state 私人設定檔 設定: ---------------------------------------------------------------------- 狀態 開啟 公用設定檔 設定: ---------------------------------------------------------------------- 狀態 開啟 確定。 ``` 恩...看來會因為不同語系而有不同版本, 那能否固定英文? 網路上幾乎是從系統語系調整,目前google不到相關文章 **編輯** ```bash= netsh advfirewall set currentprofile state on/off ``` 這個指令會一口氣啟動/關閉全部使用中的設定檔 以我為例會一次變動privateprofile、publicprofile, 而沒使用的domainprofile就不受影響 ### :heavy_check_mark:批次檔語系調整 可透過chcp 來解決 參考如下 https://blog.typeart.cc/windows-cmd-change-encoding/ ```bash= REM 常見的utf-8 REM chcp 65001 REM 這是我要的英文(美國) chcp 437 ``` ### :X:確認防火牆服務有啟動 *權限不夠無法操作* 這篇文章提到[電腦系統防火牆無法開啟的解決辦法2](https://zaitiyu.com/basketball/69098.html) 相關服務如下 系統名稱|顯示名稱 ---|--- mpssvc|Windows Firewall 查詢語法如下 ```bash= # 查詢狀態 > sc query mpssvc | find "STATE" STATE : 4 RUNNING # 執行服務(確認執行成功) net start "mpssvc" # 執行服務(只送出執行服務指令,不會確保正在執行成功) sc start "mpssvc" ``` 如果嘗試暫停的話會出現... 恩,系統管理員身分都沒權限.. ```bash= C:\Users\ma2g0> sc stop mpssvc [SC] OpenService FAILED 5: Access is denied. C:\Users\ma2g0>net stop mpssvc The requested pause, continue, or stop is not valid for this service. More help is available by typing NET HELPMSG 2191. ``` ### ~~確認防火牆當前設定檔有啟用~~ 管他有沒有啟用,直接透過`netsh advfirewall set currentprofile state on`解決 ### :heavy_check_mark:新增防火牆規則語法 ```bash= 使用方式: netsh advfirewall firewall add rule name=<string> dir=in|out action=allow|block|bypass [program=<program path>] [service=<service short name>|any] [description=<string>] [enable=yes|no (default=yes)] [profile=public|private|domain|any[,...]] [localip=any|<IPv4 address>|<IPv6 address>|<subnet>|<range>|<list>] [remoteip=any|localsubnet|dns|dhcp|wins|defaultgateway| <IPv4 address>|<IPv6 address>|<subnet>|<range>|<list>] [localport=0-65535|<port range>[,...]|RPC|RPC-EPMap|IPHTTPS|any (default=any)] [remoteport=0-65535|<port range>[,...]|any (default=any)] [protocol=0-255|icmpv4|icmpv6|icmpv4:type,code|icmpv6:type,code| tcp|udp|any (default=any)] [interfacetype=wireless|lan|ras|any] [rmtcomputergrp=<SDDL string>] [rmtusrgrp=<SDDL string>] [edge=yes|deferapp|deferuser|no (default=no)] [security=authenticate|authenc|authdynenc|authnoencap|notrequired (default=notrequired)] ``` ### :heavy_check_mark:刪除防火牆規則語法 ```bash= 使用方式: netsh advfirewall firewall delete rule name=<string> [dir=in|out] [profile=public|private|domain|any[,...]] [program=<program path>] [service=<service short name>|any] [localip=any|<IPv4 address>|<IPv6 address>|<subnet>|<range>|<list>] [remoteip=any|localsubnet|dns|dhcp|wins|defaultgateway| <IPv4 address>|<IPv6 address>|<subnet>|<range>|<list>] [localport=0-65535|<port range>[,...]|RPC|RPC-EPMap|any] [remoteport=0-65535|<port range>[,...]|any] [protocol=0-255|icmpv4|icmpv6|icmpv4:type,code|icmpv6:type,code| tcp|udp|any] 備註: - 刪除由名稱或選擇性地由端點、連接埠、通訊協定以及類型來 識別的規則。 - 若找到多個符合的項目,則會刪除所有符合的規則。 - 若指定 name=all,則會從指定的類型與設定檔刪除所有規則。 ``` ### :heavy_check_mark:防火牆設定備份與還原 我們變更設定後,當使用完畢就要還原 原本想說將防火牆狀態儲存到我新增的臨時規則的備註中, 要刪掉臨時規則前再依照備註的內容一一還原, 但感覺有點麻煩XDD 網路上看到這篇文章[透過註冊表開啟或關閉防火牆](https://ithelp.ithome.com.tw/articles/10023771) 防火牆設定會記錄再登入檔中, 那我直接對相關登入檔進行備份與還原應該會比較簡單 登入檔位置如下,只是不知道有沒有漏掉的 >[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SharedAccess] >[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\SharedAccess] 目前在論壇問問其他前輩們有沒有更好的做法 https://ithelp.ithome.com.tw/questions/10208741 網友告知還有一個實現方法 ```bash= REM 備份 netsh advfirewall export "D:\fw-rules.wfw" REM return Ok. REM 還原 netsh advfirewall import "D:\fw-rules.wfw" REM return Ok. ``` ## 最終批次檔 ### 登入限制 ```bash= REM 備份設定 netsh advfirewall export "C:\TainanMDRFwRules.wfw" REM 啟用防火牆 netsh advfirewall set currentprofile state on REM 新增阻擋規則 REM out: deny all exclude FireEye netsh advfirewall firewall add rule name="TainanMDRBlock" dir=out action=block enable=yes remoteip=0.0.0.0-211.20.177.237 protocol=any netsh advfirewall firewall add rule name="TainanMDRBlock" dir=out action=block enable=yes remoteip=211.20.177.239-255.255.255.255 protocol=any REM in: deny all exclude FireEye and 192.168.66.253 netsh advfirewall firewall add rule name="TainanMDRBlock" dir=in action=block enable=yes remoteip=0.0.0.0-192.168.66.252 protocol=any netsh advfirewall firewall add rule name="TainanMDRBlock" dir=in action=block enable=yes remoteip=192.168.66.254-211.20.177.237 protocol=any netsh advfirewall firewall add rule name="TainanMDRBlock" dir=in action=block enable=yes remoteip=211.20.177.239-255.255.255.255 protocol=any ``` ### 解除限制 ```bash= REM 刪除規則 netsh advfirewall firewall delete rule name="TainanMDRBlock" REM 還原設定 netsh advfirewall import "C:\TainanMDRFwRules.wfw" ```