using System;
using System.Diagnostics;
using System.Threading.Tasks;
namespace Rainbow.Services;
/// <summary>Windows 防火墙适配器。通过 netsh advfirewall 实现 IFirewallAdapter</summary>
public class WindowsFirewallAdapter : IFirewallAdapter
{
/// <summary>适配器名称</summary>
public String Name => "windows-fw";
/// <summary>添加防火墙规则</summary>
/// <param name="chain">规则方向(in/out),对应 dir=in/dir=out</param>
/// <param name="rule">规则描述,格式:protocol=tcp localport=80 name=xxx</param>
public async Task<Boolean> AddRuleAsync(String chain, String rule)
{
try
{
var dir = chain?.ToLower() == "out" ? "out" : "in";
var cmd = $"advfirewall firewall add rule {rule} dir={dir}";
var result = await RunNetshAsync(cmd);
return result;
}
catch
{
return false;
}
}
/// <summary>删除防火墙规则</summary>
public async Task<Boolean> DeleteRuleAsync(String chain, String rule)
{
try
{
var dir = chain?.ToLower() == "out" ? "out" : "in";
var cmd = $"advfirewall firewall delete rule {rule} dir={dir}";
var result = await RunNetshAsync(cmd);
return result;
}
catch
{
return false;
}
}
/// <summary>列出防火墙规则</summary>
public async Task<String> ListRulesAsync(String? chain = null)
{
try
{
var dir = chain?.ToLower() == "out" ? "dir=out" : "";
var cmd = $"advfirewall firewall show rule {dir}";
var psi = new ProcessStartInfo("netsh", cmd)
{
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true,
};
using var proc = Process.Start(psi);
if (proc == null) return "";
var output = await proc.StandardOutput.ReadToEndAsync();
await proc.WaitForExitAsync().WaitAsync(TimeSpan.FromSeconds(10));
return output ?? "";
}
catch
{
return "";
}
}
/// <summary>保存防火墙规则(Windows 自动持久化,export 作为备份)</summary>
public async Task<Boolean> SaveAsync()
{
try
{
var path = System.IO.Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
"Rainbow", "firewall-backup.wfw");
var dir = System.IO.Path.GetDirectoryName(path);
if (!String.IsNullOrEmpty(dir) && !System.IO.Directory.Exists(dir))
System.IO.Directory.CreateDirectory(dir);
var cmd = $"advfirewall export \"{path}\"";
var result = await RunNetshAsync(cmd);
return result;
}
catch
{
return false;
}
}
private static async Task<Boolean> RunNetshAsync(String arguments)
{
var psi = new ProcessStartInfo("netsh", arguments)
{
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true,
};
using var proc = Process.Start(psi);
if (proc == null) return false;
await proc.WaitForExitAsync().WaitAsync(TimeSpan.FromSeconds(15));
return proc.ExitCode == 0;
}
}
|