diff --git a/Netch/Forms/MainForm.Control.cs b/Netch/Forms/MainForm.Control.cs index 619dfece..6389d78c 100644 --- a/Netch/Forms/MainForm.Control.cs +++ b/Netch/Forms/MainForm.Control.cs @@ -36,6 +36,8 @@ namespace Netch.Forms //MenuStrip.Enabled = ConfigurationGroupBox.Enabled = ControlButton.Enabled = SettingsButton.Enabled = false; UpdateStatus(State.Starting); + + Firewall.AddNetchFwRules(); Task.Run(() => { diff --git a/Netch/Netch.csproj b/Netch/Netch.csproj index 5689d44c..d8de9087 100644 --- a/Netch/Netch.csproj +++ b/Netch/Netch.csproj @@ -46,6 +46,14 @@ false false + + 58fbcf7c-e7a9-467c-80b3-fc65e8fcca08 + 1 + 0 + 0 + tlbimp + false + diff --git a/Netch/Utils/Firewall.cs b/Netch/Utils/Firewall.cs new file mode 100644 index 00000000..33adfd18 --- /dev/null +++ b/Netch/Utils/Firewall.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using NetFwTypeLib; + +namespace Netch.Utils +{ + public class Firewall + { + private static readonly string[] ProgramPath = + { + "bin/NTT.exe", + "bin/Privoxy.exe", + "bin/Redirector.exe", + "bin/Shadowsocks.exe", + "bin/ShadowsocksR.exe", + "bin/Trojan.exe", + "bin/tun2socks.exe", + "bin/unbound.exe", + "bin/v2ray.exe", + "Netch.exe" + }; + + private const string _netch = "Netch"; + private const string _netchAutoRule = "NetchAutoRule"; + + /// + /// 添加防火墙规则 (非 Netch 自带程序) + /// + /// + public static void AddFwRule(string exeFullPath) + { + AddFwRule(_netchAutoRule, exeFullPath); + } + + /// + /// 清除防火墙规则 (非 Netch 自带程序) + /// + public static void RemoveFwRules() + { + RemoveFwRules(_netchAutoRule); + } + + /// + /// Netch 自带程序添加防火墙 + /// + public static void AddNetchFwRules() + { + if (GetFwRulePath(_netch).StartsWith(AppDomain.CurrentDomain.BaseDirectory) && GetFwRulesNumber(_netch) >= ProgramPath.Length) return; + RemoveNetchFwRules(); + foreach (var p in ProgramPath) + { + var path = Path.GetFullPath(p); + if (File.Exists(path)) + { + AddFwRule("Netch", path); + } + } + } + + /// + /// 清除防火墙规则 (Netch 自带程序) + /// + public static void RemoveNetchFwRules() + { + RemoveFwRules(_netch); + } + + #region 封装 + + private static readonly INetFwPolicy2 FwPolicy = (INetFwPolicy2) Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwPolicy2")); + + private static void AddFwRule(string ruleName, string exeFullPath) + { + var rule = NewFwRule(); + + rule.Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW; + // ApplicationName 大小不敏感 + rule.ApplicationName = exeFullPath; + // rule.Description = "Used to block all internet access."; + rule.Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN; + rule.Enabled = true; + rule.InterfaceTypes = "All"; + rule.Name = ruleName; + + FwPolicy.Rules.Add(rule); + } + + private static void RemoveFwRules(string ruleName) + { + var c = GetFwRulesNumber(ruleName); + foreach (var _ in new bool[c]) + { + FwPolicy.Rules.Remove(ruleName); + } + } + + private static INetFwRule NewFwRule() + { + return (INetFwRule) Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FWRule")); + } + + + private static string GetFwRulePath(string ruleName) + { + try + { + var rule = (INetFwRule2)FwPolicy.Rules.Item(ruleName); + return rule.ApplicationName; + } + catch (Exception e) + { + return ""; + } + } + + private static int GetFwRulesNumber(string ruleName) + { + // https://stackoverflow.com/a/53601691 + return FwPolicy.Rules.Cast().Count(rule => rule.Name == ruleName); + } + + #endregion + } +} \ No newline at end of file