前言
网络位置类型
区别:防火墙的域、专用、公用的网络位置类型不同。
域:Windows可以验证对计算机所联接域的域控制器的访问。
公共:除域网络之外,其他所有网络最初都归为公共网络一类。直接连到Internet的网络或者位于公共场所(如机场和咖啡店)的网络应保留为公共网络。
专用:由用户或应用程序标识为专用的网络。只应将可信网络标识为专用网络。用户很可能希望将家庭网络或小型企业网络标识为专用网络。
操作系统使用防火墙配置文件按照连接性、连接数和类别来识别并记住与它们连接的每个网络。
在高级安全Windows防火墙中有三种网络位置类型:域、公共、专用。
出入站规则
Windows 系统默认的规则
默认阻止入站连接,默认允许出站连接。也就是说,凡是入站连接,任何程序和端口都要在防火墙上配置入站规则,否则都会被禁止。
入站规则
入站规则是用来限制远程主机访问本机的服务的,本机接收的请求中如果被请求的程序或具体端口是被限制的,则该请求会被拦截。
出站规则
出站规则是用来限制对外访问的,从本机发出的请求中,如果请求的对象是被禁止的,该请求会被拦截,表现方式就是断网。
两种方式
注意
端口方式,开发过程和最终安装时都是一样的规则。推荐使用。
入站规则不生效
HttpListener启动的用户是由操作系统决定的。
如果您在Windows上使用HttpListener,则默认情况下,它将使用系统用户启动。
但是:
系统用户启动的服务,设置的防火墙入站规则程序方式不生效。
只能使用端口方式
推荐方式
运行Bat方式添加端口规则
查看端口信息
1 2 3
| netstat -ano
netstat -ano | findstr 10088
|
查看入站规则
键盘点击Ctrl+R打开运行,输入Firewall.cpl回车打开防火墙页面。
点击高级设置=>入站规则
里面就可以看到添加的配置,就代表成功了。
代码添加
添加COM引用
在引用=>添加引用=>选择COM 页=> 找到NetFwTypeLib, 确定即可
添加命名空间
程序方式添加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| using System;
using NetFwTypeLib;
namespace ZUtils { public class ZNetFwManger { private static void NetFwDelApps(string ruleName) { INetFwPolicy2 policy2 = (INetFwPolicy2)Activator .CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwPolicy2")); try { policy2.Rules.Remove(ruleName); } catch (Exception) { } }
public static void NetFwAllowApps(string name, string executablePath) { try { NetFwDelApps(name); INetFwRule rule = (INetFwRule)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FWRule")); rule.Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW; rule.Description = "Allow all for " + name; rule.ApplicationName = executablePath; rule.Enabled = true; rule.InterfaceTypes = "All"; rule.Name = name; INetFwPolicy2 policy2 = (INetFwPolicy2)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwPolicy2")); policy2.Rules.Add(rule); } catch (Exception) { } } } }
|
调用
1 2 3 4 5
| var processModule = Process.GetCurrentProcess().MainModule; if (processModule != null) { ZNetFwManger.NetFwAllowApps("Z_星火云鸽智慧课堂", processModule.FileName); }
|
名称不要用@开头,会导致规则无法删除。
端口方式添加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| using NetFwTypeLib; using System;
namespace ZUtils { public class ZFirewallManager { private static string GetName(int port, string protocol) { return "z-allow-port-" + protocol + "-" + port; }
public static void AllowPort(int port, string protocol) { DelPort(port, protocol); Type type = Type.GetTypeFromProgID("HNetCfg.FwRule"); INetFwRule rule = (INetFwRule)Activator.CreateInstance(type);
rule.Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW; rule.Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN; rule.Enabled = true; rule.InterfaceTypes = "All"; rule.Name = GetName(port, protocol); if (protocol.ToLower() == "tcp") { rule.Protocol = (int)NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP; } else { rule.Protocol = (int)NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_UDP; }
rule.LocalPorts = "" + port;
Type policyType = Type.GetTypeFromProgID("HNetCfg.FwPolicy2"); INetFwPolicy2 policy = (INetFwPolicy2)Activator.CreateInstance(policyType);
policy.Rules.Add(rule); }
public static void DelPort(int port, string protocol) { Type policyType = Type.GetTypeFromProgID("HNetCfg.FwPolicy2"); INetFwPolicy2 policy = (INetFwPolicy2)Activator.CreateInstance(policyType);
INetFwRules rules = policy.Rules;
foreach (INetFwRule rule in rules) { if (rule.Name == GetName(port, protocol)) { rules.Remove(rule.Name); Console.WriteLine(@"Firewall rule deleted successfully."); break; } } } } }
|
调用
1 2 3 4
| ZFirewallManager.AllowPort(10077, "tcp"); ZFirewallManager.AllowPort(10088, "tcp"); ZFirewallManager.AllowPort(55666, "udp");
|
命令行添加(推荐)
添加程序规则
添加规则
1
| netsh advfirewall firewall add rule name="MyApp" dir=in action=allow program="C:\MyApp.exe"
|
删除规则
1
| netsh advfirewall firewall delete rule name="MyApp" program="C:\MyApp.exe"
|
使用批处理将当前目录下的*.exe都加入到白名单中:
addfirewall.bat
1 2 3 4 5 6 7 8 9 10 11 12 13
| @echo off
set INPUT_RULE_NAME=Z-XHSCHOOL-IN for %%a in (*.exe) do ( netsh advfirewall firewall show rule name=%INPUT_RULE_NAME% >nul if not ERRORLEVEL 1 ( echo del %INPUT_RULE_NAME% netsh advfirewall firewall delete rule name=%INPUT_RULE_NAME% program="%cd%\%%a" >null ) echo add %INPUT_RULE_NAME% netsh advfirewall firewall add rule name=%INPUT_RULE_NAME% dir=in action=allow program="%cd%\%%a" >null ) pause
|
根据系统版本添加防火墙规则:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @echo off cd "%CD%" for /f "tokens=4,5 delims=. " %%a in ('ver') do if %%a%%b geq 60 goto new
:old cmd /c netsh firewall delete allowedprogram program="%CD%\ZClient.exe" profile=ALL cmd /c netsh firewall add allowedprogram program="%CD%\ZClient.exe" name="ZClient" ENABLE cmd /c netsh firewall add allowedprogram program="%CD%\ZClient.exe" name="ZClient" ENABLE profile=ALL goto end :new cmd /c netsh advfirewall firewall delete rule name="ZClient" cmd /c netsh advfirewall firewall add rule name="ZClient" dir=in action=allow program="%CD%\ZClient.exe" protocol=tcp enable=yes profile=public cmd /c netsh advfirewall firewall add rule name="ZClient" dir=in action=allow program="%CD%\ZClient.exe" protocol=udp enable=yes profile=public cmd /c netsh advfirewall firewall add rule name="ZClient" dir=out action=allow program="%CD%\ZClient.exe" protocol=tcp enable=yes profile=public cmd /c netsh advfirewall firewall add rule name="ZClient" dir=out action=allow program="%CD%\ZClient.exe" protocol=udp enable=yes profile=public cmd /c netsh advfirewall firewall add rule name="ZClient" dir=in action=allow program="%CD%\ZClient.exe" protocol=tcp enable=yes profile=domain cmd /c netsh advfirewall firewall add rule name="ZClient" dir=in action=allow program="%CD%\ZClient.exe" protocol=udp enable=yes profile=domain cmd /c netsh advfirewall firewall add rule name="ZClient" dir=out action=allow program="%CD%\ZClient.exe" protocol=tcp enable=yes profile=domain cmd /c netsh advfirewall firewall add rule name="ZClient" dir=out action=allow program="%CD%\ZClient.exe" protocol=udp enable=yes profile=domain cmd /c netsh advfirewall firewall add rule name="ZClient" dir=in action=allow program="%CD%\ZClient.exe" protocol=tcp enable=yes profile=private cmd /c netsh advfirewall firewall add rule name="ZClient" dir=in action=allow program="%CD%\ZClient.exe" protocol=udp enable=yes profile=private cmd /c netsh advfirewall firewall add rule name="ZClient" dir=out action=allow program="%CD%\ZClient.exe" protocol=tcp enable=yes profile=private cmd /c netsh advfirewall firewall add rule name="ZClient" dir=out action=allow program="%CD%\ZClient.exe" protocol=udp enable=yes profile=private :end
|
添加端口规则
注意
添加这个文件的时候文件编码不能是UTF-8,会导致命令执行失败,要设置为ANSI编码。
addfirewall.bat
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| @echo off
rem 设置指定端口变量和出入站规则名称 set INPUT_RULE_NAME=Z-XHSCHOOL-IN set OUT_RULE_NAME=Z-XHSCHOOL-OUT set PORT=10066,10077,10088,55666
rem 创建入站规则 echo Input Rule netsh advfirewall firewall show rule name=%INPUT_RULE_NAME% >nul rem 如果已经存在则先删除 if not ERRORLEVEL 1 ( netsh advfirewall firewall delete rule name=%INPUT_RULE_NAME% >nul echo %INPUT_RULE_NAME% Del Successed! ) netsh advfirewall firewall add rule name=%INPUT_RULE_NAME% dir=in action=allow protocol=TCP localport=%PORT% >nul netsh advfirewall firewall add rule name=%INPUT_RULE_NAME% dir=in action=allow protocol=UDP localport=%PORT% >nul echo %INPUT_RULE_NAME% Create Successed!
rem 创建出站规则 echo -------------------------------- echo Output Rule netsh advfirewall firewall show rule name=%OUT_RULE_NAME% >nul rem 如果已经存在则先删除 if not ERRORLEVEL 1 ( netsh advfirewall firewall delete rule name=%OUT_RULE_NAME% >nul echo %OUT_RULE_NAME% Del Successed! ) netsh advfirewall firewall add rule name=%OUT_RULE_NAME% dir=out action=allow protocol=TCP localport=%PORT% >nul netsh advfirewall firewall add rule name=%OUT_RULE_NAME% dir=out action=allow protocol=UDP localport=%PORT% >nul echo %OUT_RULE_NAME% Create Successed!
|
运行Bat
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| private void AddFirewallRule() { try { Process process = new Process(); string appPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); process.StartInfo.FileName = $@"{appPath}\addfirewall.bat"; process.StartInfo.UseShellExecute = false; process.StartInfo.CreateNoWindow = true; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.Verb = "runas"; process.Start(); string output = process.StandardOutput.ReadToEnd(); process.WaitForExit(); Console.WriteLine(@"================================"); Console.WriteLine(@"添加防火墙规则:"); Console.WriteLine(output); Console.ReadLine(); Console.WriteLine(@"================================"); } catch (Exception) { } }
|
系统版本判断
系统版本判断
1 2 3 4 5 6 7 8 9 10
| @echo off cd "%CD%" for /f "tokens=4,5 delims=. " %%a in ('ver') do if %%a%%b geq 60 goto new :old echo "old" goto end :new echo "new" :end pause
|
其中:
for /f "tokens=4,5 delims=. " %%a in ('ver') :使用for命令读取ver命令的输出,并将版本信息按照.和空格分隔,分别存储在变量%%a和%%b中。
if %%a%%b geq 60 goto new :判断版本号是否大于等于60(即Windows Vista及以上版本),如果是则跳转到标签new执行相关操作。
整体解析:
- 使用ver命令获取Windows版本号,格式为
主版本号.次版本号。例如10.0.17134。
- 使用for语句解析版本号,提取主版本号到
%%a,次版本号到%%b。
- 判断如果主版本号
%%a加次版本号%%b大于等于60,则跳转到:new标签。否则跳转到:old标签。
:old标签处打印"old",然后跳转到:end结束。
:new标签处打印"new",然后跳转到:end结束。
:end处暂停等待用户输入。
总结起来,
这个bat脚本的作用是判断Windows版本号是否>= 6.0(也就是Windows Vista及以上版本),如果是则打印"new",否则打印"old"。
举个例子:
在Windows 10下运行这个bat,会输出:
在Windows XP下运行,会输出: