C# 增删查防火墙例外

C# 增删查防火墙例外

当我们的程序涉及到网络通讯时,通常需要添加防火墙例外,否则程序会被防火墙拦截,导致通讯失败。在 .NET/C# 中,可以通过如下三种方式来对 防火墙例外 进行增、删、查:

  • 执行 netsh advfirewall firewall 命令
  • 使用 NetFwTypeLib COM 组件
  • 调用 PowerShell 脚本

其中,前两种方案较为常用,本文将详细展示其实现方法。对 PowerShell 方案感兴趣的,可访问 Windows PowerShell - NetSecurity 来了解相关脚本。

执行 netsh advfirewall firewall 命令

Windows 提供了防火墙相关的命令,后台调起 命令行工具(cmd.exe) ,通过运行 netsh advfirewall firewall 的相关命令来实现对防火墙规则的操作。

private static string FirewallCmd { get; } = "netsh advfirewall firewall";

/// <summary>
/// Adds firewall exception for the specified program file.
/// </summary>
/// <param name="fileName">The full path of the specified program file.</param>
public static void AddException(string fileName)
{
    AddRule(fileName, Path.GetFileName(fileName));
    AddRule(fileName, Path.GetFileNameWithoutExtension(fileName));
}

/// <summary>
/// Removes the firewall exception of the specified program file.
/// </summary>
/// <param name="fileName">The full path of the specified program file.</param>
public static void RemoveException(string fileName)
{
    RemoveRule(fileName, Path.GetFileName(fileName));
    RemoveRule(fileName, Path.GetFileNameWithoutExtension(fileName));
}

/// <summary>
/// Determines whether the firewall exception of the specified program file exists.
/// </summary>
/// <param name="fileName">The full path of the specified program file.</param>
/// <returns></returns>
public static bool ExceptionExists(string fileName)
{
    var nameWithEx = Path.GetFileName(fileName);

    var cmd = $"{FirewallCmd} show rule name ={nameWithEx} verbose";
    var output = CmdRunner.ExecuteWithOutput(cmd);

    if (!string.IsNullOrEmpty(output))
    {
        if (output.Contains(fileName))
        {
            return true;
        }
    }

    return false;
}

private static void AddRule(string appName, string ruleName)
{
    var commandIn = $"{FirewallCmd} add rule name=\"{ruleName}\" dir=in action=allow program=\"{appName}\"";
    var commandOut = $"{FirewallCmd} add rule name=\"{ruleName}\" dir=out action=allow program=\"{appName}\"";

    CmdRunner.Execute(commandIn);
    CmdRunner.Execute(commandOut);
}

private static void RemoveRule(string appName, string ruleName)
{
    var commandIn = $"{FirewallCmd} delete rule name=\"{ruleName}\" dir=in program=\"{appName}\"";
    var commandOut = $"{FirewallCmd} delete rule name=\"{ruleName}\" dir=out program=\"{appName}\"";

    CmdRunner.Execute(commandIn);
    CmdRunner.Execute(commandOut);
}

使用 NetFwTypeLib COM 组件

NetFwTypeLib 是系统提供的 COM 组件,该组件定义了防火墙的相关接口。首先,在项目中添加对 NetFwTypeLib 的引用,然后通过 INetFwPolicy2 实例和 INetFwRule 实例来实现对防火墙规则的操作。

private const string FwMgr = "HNetCfg.FwMgr";
private const string FwApp = "HNetCfg.FwAuthorizedApplication";
private const string FwPolicy = "HNetCfg.FwPolicy2";
private const string FwRule = "HNetCfg.FWRule";

/// <summary>
/// Adds firewall exception for the specified program file through `NetFwTypeLib` COM.
/// </summary>
/// <param name="fileName">The full path of the specified program file.</param>
public static void AddExceptionByCom(string fileName)
{
    AddRuleByCom(fileName, Path.GetFileName(fileName));
    AddRuleByCom(fileName, Path.GetFileNameWithoutExtension(fileName));
}

/// <summary>
/// Removes the firewall exception of the specified program file through `NetFwTypeLib` COM.
/// </summary>
/// <param name="fileName">The full path of the specified program file.</param>
public static void RemoveExceptionByCom(string fileName)
{
    RemoveRuleByCom(fileName, Path.GetFileName(fileName));
    RemoveRuleByCom(fileName, Path.GetFileNameWithoutExtension(fileName));
}

private static void AddRuleByCom(string appName, string ruleName)
{
    var policy = (INetFwPolicy2) Activator.CreateInstance(Type.GetTypeFromProgID(FwPolicy));

    // Inbound Rule
    var ruleIn = (INetFwRule) Activator.CreateInstance(Type.GetTypeFromProgID(FwRule));

    ruleIn.Name = ruleName;
    ruleIn.ApplicationName = appName;
    ruleIn.Enabled = true;

    policy.Rules.Add(ruleIn);

    // Outbound Rule
    var ruleOut = (INetFwRule) Activator.CreateInstance(Type.GetTypeFromProgID(FwRule));

    ruleOut.Name = ruleName;
    ruleOut.ApplicationName = appName;
    ruleOut.Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_OUT;
    ruleOut.Enabled = true;

    policy.Rules.Add(ruleOut);
}

private static void RemoveRuleByCom(string appName, string ruleName)
{
    var policy = (INetFwPolicy2) Activator.CreateInstance(Type.GetTypeFromProgID(FwPolicy));
    var rules = policy.Rules.OfType<INetFwRule>();

    foreach (var rule in rules.Where(x => x.Name == ruleName && x.ApplicationName == appName))
    {
        policy.Rules.Remove(rule.Name);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ironyho

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值