Merge pull request #297 from chsbuffer/master

Netch 自动加入防火墙规则 &  NAT指示灯
This commit is contained in:
Connection Refused
2020-07-09 04:10:58 +08:00
committed by GitHub
8 changed files with 273 additions and 36 deletions

View File

@@ -36,6 +36,8 @@ namespace Netch.Forms
//MenuStrip.Enabled = ConfigurationGroupBox.Enabled = ControlButton.Enabled = SettingsButton.Enabled = false;
UpdateStatus(State.Starting);
Firewall.AddNetchFwRules();
Task.Run(() =>
{

View File

@@ -78,7 +78,9 @@ namespace Netch.Forms
this.UsedBandwidthLabel = new System.Windows.Forms.ToolStripStatusLabel();
this.DownloadSpeedLabel = new System.Windows.Forms.ToolStripStatusLabel();
this.UploadSpeedLabel = new System.Windows.Forms.ToolStripStatusLabel();
this.blankToolStripStatusLabel = new System.Windows.Forms.ToolStripStatusLabel();
this.NatTypeStatusLabel = new System.Windows.Forms.ToolStripStatusLabel();
this.NatTypeStatusLightLabel = new System.Windows.Forms.ToolStripStatusLabel();
this.ControlButton = new System.Windows.Forms.Button();
this.NotifyIcon = new System.Windows.Forms.NotifyIcon(this.components);
this.NotifyMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
@@ -309,7 +311,7 @@ namespace Netch.Forms
this.exitToolStripMenuItem.Name = "exitToolStripMenuItem";
this.exitToolStripMenuItem.Size = new System.Drawing.Size(40, 22);
this.exitToolStripMenuItem.Text = "Exit";
this.exitToolStripMenuItem.Click += new System.EventHandler(this.ExitToolStripButton_Click);
this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click);
//
// RelyToolStripMenuItem
//
@@ -528,7 +530,9 @@ namespace Netch.Forms
this.UsedBandwidthLabel,
this.DownloadSpeedLabel,
this.UploadSpeedLabel,
this.NatTypeStatusLabel});
this.blankToolStripStatusLabel,
this.NatTypeStatusLabel,
this.NatTypeStatusLightLabel});
this.StatusStrip.Location = new System.Drawing.Point(0, 250);
this.StatusStrip.Name = "StatusStrip";
this.StatusStrip.Size = new System.Drawing.Size(733, 22);
@@ -563,11 +567,29 @@ namespace Netch.Forms
this.UploadSpeedLabel.Text = "↑: 0 KB/s";
this.UploadSpeedLabel.Visible = false;
//
// blankToolStripStatusLabel
//
this.blankToolStripStatusLabel.Name = "blankToolStripStatusLabel";
this.blankToolStripStatusLabel.Size = new System.Drawing.Size(268, 17);
this.blankToolStripStatusLabel.Spring = true;
//
// NatTypeStatusLabel
//
this.NatTypeStatusLabel.Name = "NatTypeStatusLabel";
this.NatTypeStatusLabel.Size = new System.Drawing.Size(36, 17);
this.NatTypeStatusLabel.Text = "NAT:";
this.NatTypeStatusLabel.TextAlign = System.Drawing.ContentAlignment.BottomLeft;
//
// NatTypeStatusLightLabel
//
this.NatTypeStatusLightLabel.ActiveLinkColor = System.Drawing.Color.Red;
this.NatTypeStatusLightLabel.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
this.NatTypeStatusLightLabel.ForeColor = System.Drawing.Color.Red;
this.NatTypeStatusLightLabel.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1);
this.NatTypeStatusLightLabel.Name = "NatTypeStatusLightLabel";
this.NatTypeStatusLightLabel.Size = new System.Drawing.Size(18, 21);
this.NatTypeStatusLightLabel.Text = "⬤";
this.NatTypeStatusLightLabel.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
//
// ControlButton
//
@@ -751,5 +773,8 @@ namespace Netch.Forms
private System.Windows.Forms.ToolStripLabel VersionLabel;
#endregion
private System.Windows.Forms.ToolStripStatusLabel NatTypeStatusLightLabel;
private System.Windows.Forms.ToolStripStatusLabel blankToolStripStatusLabel;
}
}

View File

@@ -403,7 +403,6 @@ namespace Netch.Forms
}
finally
{
UpdateStatus(State.Waiting);
MainController.Stop();
}
@@ -413,28 +412,12 @@ namespace Netch.Forms
#endregion
private void ExitToolStripButton_Click(object sender, EventArgs e)
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
// 已启动
if (State != State.Waiting && State != State.Stopped)
{
// 未开启自动停止
if (!Global.Settings.StopWhenExited)
{
MessageBoxX.Show(i18N.Translate("Please press Stop button first"));
Visible = true;
ShowInTaskbar = true; // 显示在系统任务栏
WindowState = FormWindowState.Normal; // 还原窗体
NotifyIcon.Visible = true; // 托盘图标隐藏
return;
}
// 自动停止
ControlButton_Click(sender, e);
}
SaveConfigs();
UpdateStatus(State.Terminating);
@@ -490,6 +473,5 @@ namespace Netch.Forms
}
#endregion
}
}

View File

@@ -1,5 +1,8 @@
using Netch.Models;
using System;
using System.Windows.Media;
using Netch.Models;
using Netch.Utils;
using Color = System.Drawing.Color;
namespace Netch.Forms
{
@@ -19,15 +22,57 @@ namespace Netch.Forms
if (State != State.Started)
{
NatTypeStatusLabel.Text = "";
NatTypeStatusLabel.Visible = true;
NatTypeStatusLabel.Visible = false;
NatTypeStatusLightLabel.Visible = false;
return;
}
if (!string.IsNullOrEmpty(text))
{
NatTypeStatusLabel.Text = "NAT" + i18N.Translate(": ") + text.Trim();
}
else
{
NatTypeStatusLabel.Text = "NAT" + i18N.Translate(": ") + i18N.Translate("Test failed");
}
NatTypeStatusLabel.Text = "NAT" + i18N.Translate(": ") +
(!string.IsNullOrEmpty(text) ? text.Trim() : i18N.Translate("Test failed"));
if (Enum.TryParse(text,false,out STUN_Client.NatType natType))
{
UpdateNatTypeLight(natType);
NatTypeStatusLightLabel.Visible = true;
}
else
{
NatTypeStatusLightLabel.Visible = false;
}
NatTypeStatusLabel.Visible = true;
}
private void UpdateNatTypeLight(STUN_Client.NatType natType)
{
Color c;
switch (natType)
{
case STUN_Client.NatType.UdpBlocked:
case STUN_Client.NatType.SymmetricUdpFirewall:
case STUN_Client.NatType.Symmetric:
c = Color.Red;
break;
case STUN_Client.NatType.RestrictedCone:
case STUN_Client.NatType.PortRestrictedCone:
c = Color.Yellow;
break;
case STUN_Client.NatType.OpenInternet:
case STUN_Client.NatType.FullCone:
c = Color.LimeGreen;
break;
default:
c=Color.Red;
break;
}
NatTypeStatusLightLabel.ForeColor=c;
}
public void StatusText(string text)
{
StatusLabel.Text = i18N.Translate("Status", ": ") + text;
@@ -45,17 +90,17 @@ namespace Netch.Forms
switch (state)
{
case State.Waiting:
ControlButton.Text = i18N.Translate("Start");
ControlButton.Enabled = true;
ControlButton.Text = i18N.Translate("Start");
MenuStrip.Enabled = ConfigurationGroupBox.Enabled = ControlButton.Enabled = SettingsButton.Enabled = true;
updateACLWithProxyToolStripMenuItem.Enabled = true;
NatTypeStatusText();
break;
case State.Starting:
ControlButton.Text = "...";
ControlButton.Enabled = false;
ControlButton.Text = "...";
ServerComboBox.Enabled = false;
ModeComboBox.Enabled = false;
@@ -66,22 +111,22 @@ namespace Netch.Forms
reinstallTapDriverToolStripMenuItem.Enabled = false;
break;
case State.Started:
ControlButton.Text = i18N.Translate("Stop");
ControlButton.Enabled = true;
ControlButton.Text = i18N.Translate("Stop");
break;
case State.Stopping:
ControlButton.Enabled = false;
ControlButton.Text = "...";
ProfileGroupBox.Enabled = false;
MenuStrip.Enabled = ConfigurationGroupBox.Enabled = SettingsButton.Enabled = true;
UsedBandwidthLabel.Visible = UploadSpeedLabel.Visible = DownloadSpeedLabel.Visible = false;
NatTypeStatusText();
break;
case State.Stopped:
ControlButton.Text = i18N.Translate("Start");
ControlButton.Enabled = true;
ControlButton.Text = i18N.Translate("Start");
LastUploadBandwidth = 0;
LastDownloadBandwidth = 0;

View File

@@ -72,7 +72,7 @@ namespace Netch.Forms
// 加载翻译
InitText();
//
NatTypeStatusText();
@@ -85,7 +85,7 @@ namespace Netch.Forms
// 为 ComboBox绘制 收集宽度数据
_eWidth = ServerComboBox.Width / 10;
// 自动检测延迟
Task.Run(() =>
{
@@ -414,6 +414,37 @@ namespace Netch.Forms
Activate();
}
private void ExitToolStripButton_Click(object sender, EventArgs e)
{
// 已启动
if (State != State.Waiting && State != State.Stopped)
{
// 未开启自动停止
if (!Global.Settings.StopWhenExited)
{
MessageBoxX.Show(i18N.Translate("Please press Stop button first"));
Visible = true;
ShowInTaskbar = true; // 显示在系统任务栏
WindowState = FormWindowState.Normal; // 还原窗体
NotifyIcon.Visible = true; // 托盘图标隐藏
return;
}
// 自动停止
ControlButton_Click(sender, e);
}
SaveConfigs();
UpdateStatus(State.Terminating);
NotifyIcon.Visible = false;
Close();
Dispose();
Environment.Exit(Environment.ExitCode);
}
private void NotifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
{
if (WindowState == FormWindowState.Minimized)
@@ -428,7 +459,7 @@ namespace Netch.Forms
}
#endregion
#endregion
}
}

View File

@@ -0,0 +1,16 @@
namespace Netch.Models
{
public class STUN_Client
{
public enum NatType
{
UdpBlocked,
OpenInternet,
SymmetricUdpFirewall,
FullCone,
RestrictedCone,
PortRestrictedCone,
Symmetric
}
}
}

View File

@@ -46,6 +46,14 @@
<Isolated>false</Isolated>
<EmbedInteropTypes>false</EmbedInteropTypes>
</COMReference>
<COMReference Include="NetFwTypeLib.dll">
<Guid>58fbcf7c-e7a9-467c-80b3-fc65e8fcca08</Guid>
<VersionMajor>1</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>tlbimp</WrapperTool>
<Isolated>false</Isolated>
</COMReference>
</ItemGroup>
<ItemGroup>

128
Netch/Utils/Firewall.cs Normal file
View File

@@ -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";
/// <summary>
/// 添加防火墙规则 (非 Netch 自带程序)
/// </summary>
/// <param name="exeFullPath"></param>
public static void AddFwRule(string exeFullPath)
{
AddFwRule(_netchAutoRule, exeFullPath);
}
/// <summary>
/// 清除防火墙规则 (非 Netch 自带程序)
/// </summary>
public static void RemoveFwRules()
{
RemoveFwRules(_netchAutoRule);
}
/// <summary>
/// Netch 自带程序添加防火墙
/// </summary>
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);
}
}
}
/// <summary>
/// 清除防火墙规则 (Netch 自带程序)
/// </summary>
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<INetFwRule>().Count(rule => rule.Name == ruleName);
}
#endregion
}
}