refactor: 枚举移入Models目录,命名空间更新为Rainbow.Entity.Models
大石头 authored at 2026-07-02 12:54:58
3.49 KiB
RainbowBridge
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;
    }
}