Batch Scripts: Opening Windows XP Firewall Ports using Multiple Parallel Processes and Thread Counting

The goal of this article is to explain my method of Batch Parallel Processing to open Windows XP firewall ports which can only be opened via commandline one at a time, but this can be adapted to any application needing parallel processing in a batch script where a thread count must be maintained.

While writing a batch script, I recently found myself needing to run a command over and over again to open ports on a Window XP firewall.  Unfortunately, they have to be opened one at a time (one port per call to the firewall at command-line) and if you want to open a large number of ports, this can take a while since each call takes almost a second.

The simple script to do this can be found on any number of forums:

for /L %%i in (9000,1,9600) do netsh firewall add portopening TCP %%i "Port-range %%i"
where in this case 9000 is the start port, 9600 is the end port and TCP is the protocol (we could just as easily have put UDP in there).  Also keep in mind that from the command-line, we would only use one % in variable i, whereas in the batch script, we use two.

But like I already said, the line above takes a LONG TIME.  What can we do to speed this up?  How about run the calls in parallel!  The calls don’t rely on the calls before them, so there is no reason not to.  A simple way to do parallel calls would be:

for /L %%i in (9000,1,9600) do start netsh firewall add portopening TCP %%i "Port-range %%i"

adding the keyword “start” above will simply kick the process off and move to the next iteration of the for loop.  However, this is probably a bad idea since before you know it, there will be far too many threads open than your machine can keep up with, and you will probably overload netsh, causing a DLL error.

So how can we combat this problem?  We need to keep a thread count to make sure that we only have a certain number of instances running at one time, and if there are more, we need to slow the script down and wait for some to finish!

The first step is figuring out how many processes are running at a given time.  After much thought and Googling, my solution is below:

tasklist /svc /fi "imagename eq netsh.exe">temp.swap 2>NUL
for /f "tokens=3" %%f in ('find /c /i "netsh.exe" "temp.swap"') do set instances=%%f
del temp.swap

Above we call the Windows tasklist, store the results to a temp file (which will be located in the running directory), run a find on the temp file for the number of lines containing the process we care about (netsh), store that number in a variable called instances, and delete the temp file.  Not the most elegant, but it works.

So, we now know how to figure out how many instances are running at a given time, and we know the command to kick off a thread, reminder: start /b netsh firewall add portopening TCP %i% "Port-range %i%">NUL

The command is slightly different than before.  The /b prevents a new command line window from opening each time the command is called, and i is wrapped with % instead of being preceded by two %’s.  This is because I chose to forgo a standard for loop in favor of a configuration that allowed tighter control over whether new threads are created.  This includes if-statements to check the value of instances and i (i a dual purpose variable, serving as the counter until program completion, and the port to be opened, as seen in the netsh commands).  Instances can be checked against a variable I define to be the maximum number of threads allowed at one time, and i is checked against variable defined as the maximum port.

Another note is that the code to generate instances should NOT be run at every iteration of the custom loop, because it is a blocking statement and wastes valuable time.  I recommend checking it once out of a certain number of iterations, maybe using the value of the maximum number of threads.  Within a batch script, this can be done by:

set /A test=i %% %numthreads%

Keep in mind that in the batch script, two % are needed to represent modulus, and /A means that batch should evaluate the expression and assign test to the answer.  After this, the program would branch where it goes next based on if test==0.  If it does equal 0, the program should check the number of running instances and wait for things to settle down a little (the number of instances to go below 25, which we learned how to check before with the find command).

At some point I might post the complete code, but the diatribe above should provide some good tips.  If you want to encourage me, feel free to post a comment!

NOTE: It’s not a good idea to use this method to try to open 10′s of thousands of ports since the firewall will have to check each rule for each packet that comes in.  This will result in HIGH CPU usage.

© 2012, Electronsrock. All rights reserved.

Share and Enjoy:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Twitter
  • Google Bookmarks
  • email
  • LinkedIn
  • Slashdot
  • Add to favorites