Game design, game programming and more

Installing firewall exception rules programmatically

Writing installers for applications requires a substantial effort, even when using tools like InstallShield. My challenge for today was to write as little code as possible (because I’m lazy) to configure Windows Firewall exception rules so that the game I’m working on wouldn’t “pop” a dialog box asking the user to configure firewall settings — this freaks out users and is generally considered a bad thing.

Of course I relied upon Google to find a solution, but boy did I have a tough time finding code to do the job. Many folks run external commands like “netsh” to configure firewall exceptions, but this sucks because the netsh.exe command has different syntax in different versions of Windows. Yuck!

Here’s my solution in visual basic (cscript.exe), which has the virtue of being installed on every modern (XP+) Windows computer in the world.

'configure-firewall.vbs
'Sets Windows firewall permissions for a specific application
'Grants full inbound/outbound access for TCP/UDP
'by Patrick Wyatt 12/22/2011
'MIT License - do with as you will; no warranty


option explicit


'**************************************
const NET_FW_IP_PROTOCOL_TCP  = 6
const NET_FW_IP_PROTOCOL_UDP  = 17

const NET_FW_RULE_DIR_IN  = 1
const NET_FW_RULE_DIR_OUT = 2


'**************************************
sub UpdateFirewallRule (addRules, policy, groupName, ruleName, exePath, netProtocol, direction)
  'Prettify the rule name
  dim name
  name = ruleName
  name = name & " - Allow"
  if netProtocol = NET_FW_IP_PROTOCOL_TCP then
    name = name & " TCP"
  elseif netProtocol = NET_FW_IP_PROTOCOL_UDP then
    name = name & " UDP"
  end if
  if direction = NET_FW_RULE_DIR_IN then
    name = name & " IN"
  elseif direction = NET_FW_RULE_DIR_OUT then
    name = name & " OUT"
  end if

  'Set rule parameters
  dim rule
  set rule              = CreateObject("HNetCfg.FwRule")
  rule.Enabled          = true
  rule.Grouping         = groupName
  rule.Name             = name
  rule.ApplicationName  = exePath
  rule.Protocol         = netProtocol
  rule.Direction        = direction

  'Remove old rule
  if addRules < 0 then
    Wscript.echo "  Removing rule '" & name
  end if
  
  'Always remove old rule to prevent duplicates
  policy.Rules.Remove rule.name
  
  if Err.Number <> 0 then
    Wscript.Echo "  Removing rule '" & name & "'failed with error '" & Err.Description & "' (" & Err.Number & ")"
    Wscript.Quit 1
  end if

  'Add new rule
  if addRules > 0 then
    Wscript.echo "  Adding rule '" & name
    policy.Rules.Add rule
    if Err.Number <> 0 then
      Wscript.Echo "  Adding rule '" & name & "'failed with error '" & Err.Description & "' (" & Err.Number & ")"
      Wscript.Echo "  did you remember to run this script as administrator?"
      Wscript.Quit 1
    end if
  end if

end sub


'**************************************
sub DisplayRules (policy, groupName)
  dim RulesObject
  set RulesObject = policy.Rules

  Wscript.echo "Displaying firewall rules"

  dim Rule
  for each Rule in RulesObject
    if Rule.Grouping = groupName then
      Wscript.Echo "  Rule: " & Rule.Name
    end if
  next

  Wscript.echo ""
  
end sub


'**************************************
'Main program
  dim command, groupName, ruleName, exePath
  command   = Wscript.Arguments.Named("Command")
  groupName = Wscript.Arguments.Named("GroupName")
  ruleName  = Wscript.Arguments.Named("RuleName")
  exePath   = Wscript.Arguments.Named("ExePath")

  Wscript.echo "Firewall rule update arguments:"
  Wscript.echo "  Command:  " & command
  Wscript.echo "  Grouping: " & groupName
  Wscript.echo "  RuleName: " & ruleName
  Wscript.echo "  ExePath:  " & exePath
  Wscript.echo ""

  'Parse command line
  dim addRules
  if command = "install" then
    Wscript.echo "Installing firewall rules"
    addRules = 1
  elseif command = "remove" then
    Wscript.echo "Removing firewall rules"
    addRules = -1
  elseif command = "display" then
    addRules = 0
  else
    Wscript.echo "Unknown command: " & command
    Wscript.Quit 1
  end if

  dim policy
  set policy = CreateObject("HNetCfg.FwPolicy2")

  if addRules <> 0 then
    UpdateFirewallRule addRules, policy, groupName, ruleName, exePath, NET_FW_IP_PROTOCOL_TCP, NET_FW_RULE_DIR_IN
    UpdateFirewallRule addRules, policy, groupName, ruleName, exePath, NET_FW_IP_PROTOCOL_TCP, NET_FW_RULE_DIR_OUT
    UpdateFirewallRule addRules, policy, groupName, ruleName, exePath, NET_FW_IP_PROTOCOL_UDP, NET_FW_RULE_DIR_IN
    UpdateFirewallRule addRules, policy, groupName, ruleName, exePath, NET_FW_IP_PROTOCOL_UDP, NET_FW_RULE_DIR_OUT
    Wscript.echo ""
  end if
  
  DisplayRules policy, groupName

  Wscript.echo "Success"
  Wscript.Quit 0

And here’s a batch file to call this script. Now in real life you wouldn’t use a batch file; you would call the configure-firewall.vbs script directly from your installer script. That’s one of the reasons that the command-line validation of my script doesn’t do much error checking — it’s not for end-users, it’s for you programmer-types.

::sample-firewall-configuration.bat
@echo off
SETLOCAL EnableExtensions

if "%1" == "" (
  echo Usage:
  echo   %0 display
  echo   %0 install
  echo   %0 remove
  exit /B 1
)

%SystemRoot%\System32\cscript.exe //nologo configure-firewall.vbs /GroupName:"!GroupNameHere" /RuleName:"!RuleNameHere" /ExePath:"C:\Windows\notepad.exe" /Command:%1

Use the code as you see fit!

About Patrick Wyatt

As a game developer with more than 22 years in the industry I have helped build small companies into big ones (VP of Blizzard, Founder of ArenaNet, COO of En Masse Entertainment); lead the design and development efforts for best-selling game series (Warcraft, Diablo, Starcraft, Guild Wars); written code for virtually every aspect of game development (networking, graphics, AI, pathing, sound, tools, installers, servers, databases, ecommerce, analytics, crypto, dev-ops, etc.); designed many aspects of the games I've shipped; run platform services teams (datacenter operations, customer support, billing/accounts, security, analytics); and developed state-of-the-art technologies required to compete in the AAA+ game publishing business.

Comments

  1. PatrickWyatt says

    Test message

  2. PatrickWyatt says

    Test

  3. Graeme Wicksted says
  4. Debbie Murray says

    Thank you! This helped me out tremendously!

  5. Thanks! This saved me a bunch of time and effort!

Speak Your Mind

*