Windows firewall, netsh, block all ips from a text file

firewallipnetshwindows

am using the following scrip to block ip's from a text file into the windows firewall.

I'm using windows 2008 R2

    @echo off
if "%1"=="list" (
  netsh advfirewall firewall show rule Blockit | findstr RemoteIP
  exit/b
)

:: Deleting existing block on ips
netsh advfirewall firewall delete rule name="Blockit"

:: Block new ips (while reading them from blockit.txt)
for /f %%i in (blockit.txt) do (
  netsh advfirewall firewall add rule name="Blockit" protocol=any dir=in action=block remoteip=%%i
  netsh advfirewall firewall add rule name="Blockit" protocol=any dir=out action=block remoteip=%%i
)

:: call this batch again with list to show the blocked IPs
call %0 list

The problem is, this script is creating 1 separate rule for each blocked IP.

Is there any way to create less rules with multiple ips banned on the same rule? As far as I remember each rule has a maximum of 200 allowed banned ips. So when ip number 201 is found it should create a new rule. This way if we have 1000 ips to block it will create just 5 rules x 200 ip per rule instead of 1000 rules.

Hopefully someone can help me. Thank you

Best Answer

For the simple case of < 200 IPs you first need to iterate through the file and get all the IP addresses into a single string. Then you can call the netsh command twice outside the loop (once for inbound traffic and once for outbound).

In order to allow it to cope with more than 200 IPs I've added a counter into the for loop. Once you exceed 200 IPs it will call the netsh command and reset the IP counter before continuing to loop through the file. The end result should be that you end up with a series of rules in the format "Blockitn", where n is a number.

The one section I'm unsure on is the list and delete directives at the top. In order to get these to work properly the script needs to know how many relevant 'Blockit' rules exist. The best I could come up with is to list these and pass the results through a findstr in a for loop. I'm not sure that it's working quite right though. I'll keep working on it, but thought I would post this now as it's almost there - and hopefully you might be able to figure the last bit out :)

Note the addition of the enabledelayedexpansion directive near the top - this lets us use !VAR! style variables which won't be expanded during initialisation; only on execution. Otherwise the final IPADDR variable will just contain the last IP in the text file.

@echo off
setlocal enabledelayedexpansion
if "%1"=="list" (
  SET /A RULECOUNT=0
  for /f %%i in ('netsh advfirewall firewall show rule name^=all ^| findstr Blockit') do (
    SET /A RULECOUNT+=1
    netsh advfirewall firewall show rule Blockit!RULECOUNT! | findstr RemoteIP
  )
  SET "RULECOUNT="
  exit/b
)

REM Deleting existing block on ips
SET /A RULECOUNT=0
for /f %%i in ('netsh advfirewall firewall show rule name^=all ^| findstr Blockit') do (
  SET /A RULECOUNT+=1
  netsh advfirewall firewall delete rule name="Blockit!RULECOUNT!"
)
SET "RULECOUNT="

REM Block new ips (while reading them from blockit.txt)
SET /A IPCOUNT=0
SET /A BLOCKCOUNT=1
for /f %%i in (blockit.txt) do (
  SET /A IPCOUNT+=1
  if !IPCOUNT! == 201 (
    netsh advfirewall firewall add rule name="Blockit!BLOCKCOUNT!" protocol=any dir=in action=block remoteip=!IPADDR!
    netsh advfirewall firewall add rule name="Blockit!BLOCKCOUNT!" protocol=any dir=out action=block remoteip=!IPADDR!
    SET /A BLOCKCOUNT+=1
    SET /A IPCOUNT=1
    set IPADDR=%%i
  ) else (
    if not "!IPADDR!" == "" (  
      set IPADDR=!IPADDR!,%%i
    ) else (
      set IPADDR=%%i
    )
  )
)

REM add the final block of IPs of length less than 200
netsh advfirewall firewall add rule name="Blockit!BLOCKCOUNT!" protocol=any dir=in action=block remoteip=!IPADDR!
netsh advfirewall firewall add rule name="Blockit!BLOCKCOUNT!" protocol=any dir=out action=block remoteip=!IPADDR!

SET "IPCOUNT="
SET "BLOCKCOUNT="
SET "IPADDR="

REM call this batch again with list to show the blocked IPs
call %0 list

As an aside, if it were me I would probably look to learn Powershell for this sort of thing (or indeed any scripting on a semi-modern Microsoft platform). Once you get the hang of it you'll find it's far far more intuitive than batch files.

(P.S. - For any batch file experts reading this, feel free to suggest a better alternative - I'm no expert myself!)