工作中负责维护公司的安装包脚本(NSIS),公司产品属于windows操作系统的PC服务程序,涉及到跨PC的通信,不可避免的要添加防火墙规则,否则一旦遇到默认启用防火墙的用户计算机,就会出现服务之间无法通信的情况,虽然问题排查起来简单,但在实际的产品维护中占有比较大的比重,而且属于无意义的重复性工作。
最简单的实现方式莫过于调用CMD指令(netsh firewall)指令,对于NSIS来说,调用执行指令是非常简单的。
本文不详细列举 netsh firewall
的详细用法和参数说明,详细教程可以执行 cmd>netsh firewall
或者 cmd>netsh advfirewall
查看。
假如服务进程名称为 msmsgs.exe
需要发送和接收网络数据,添加防火墙规则如下:
添加规则
入站规则:
:: 以下指令来自 netsh advfirewall 的示例代码(删减不需要的参数)
C:\Users\Desktop>netsh advfirewall firewall add rule name="allow messenger" dir=in program="c:\programfiles\messenger\msmsgs.exe" action=allow
- name:表示添加规则名称。
- dir:[in,out]分别表示入站和出站。
- program:允许通过防火墙的进程。
- action:允许(也可以是拒绝)
出站规则:只需要将代码片中的 dir=in
改为 dir=out
即可。
删除规则
安装包卸载时会删除所有“痕迹”,包括创建的防火墙。
删除规则:
C:\Users\Desktop>netsh advfirewall firewall delete rule name="allow messenger"
按照名称删除已创建的防火墙规则,虽然在前面分别创建了入站和出站两项规则,但是删除的时候只需要执行以上一条指令即可。
直接添加以进程的形式建立防火墙规则的好处,所有进程占用的端口都可与外部通信,不需要逐个添加端口号,此方式适用于单一进程占用多个端口的情况。
坑(windows兼容性)
如果你觉得执行完上面的规则就完事了,那就被坑了。实际上在编写NSIS脚本的时候,都会遇到各种各样的坑,其中最普遍的就是版本兼容性,如果要编写产品级的安装包脚本,必须考虑产品安装用户计算机的各种环境,其中最为普遍的就是操作系统版本。
在MSDN中搜索得到如下提示:
Netsh AdvFirewall Firewall Commands
Updated: August 6, 2009
Applies To: Windows 7, Windows Server 2008, Windows Server 2008 R2, Windows Vista
也就是说 Netsh AdvFirewall
只适用于 Vista 及以上版本的操作系统。
Windows XP, 2003
是无法使用命令创建防火墙规则,既然如此,就改用 netsh firewall
指令在 xp 环境下查看创建规则。
既然 netsh firewall
指令 windows 操作系统一直都支持,能不能用它来作为通用指令来创建防火墙规则?
经过测试的测试验证的结论是不行。
因为 xp 和 2003 的防火墙规则不区分“入站”和“出站”。
windows 从 Vista
开始,防火墙变成双向控制(分为入站和出站)。
netsh firewall
在 Vista
及以上系统创建规则时,只会创建入站规则,不会创建出站规则,一旦遇到进程需要双向通信时,就会出现能够接收到其他计算机发送的数据,但无法给其他计算机回复数据的“尴尬”境地。
小结
编写NSIS脚本调用CMD指令 netsh
创建防火墙规则时要考虑windows操作系统版本兼容性问题,必须通过判断版本号来区分对待,Vista
及以上操作系统使用 netsh advfirewall
创建规则,XP和2003 使用 netsh firewall
创建规则。