Compare commits

..

44 Commits
1.6.3 ... 1.6.6

Author SHA1 Message Date
ChsBuffer
d805a4fccd bump version to 1.6.6 2020-10-31 22:18:40 +08:00
ChsBuffer
902f78b563 fix: SSDLL flag
fix: let Trojan don't use AutoresolveHostname setting
2020-10-29 16:30:21 +08:00
ChsBuffer
159fbdd58d feat: ServerForm set the color of the control to red If the value is wrong 2020-10-29 14:56:26 +08:00
ChsBuffer
0c5464f833 refactor: extract RegisterNetchStartupItem() method 2020-10-29 14:47:45 +08:00
ChsBuffer
b019362f5f refactor: Check STUN Server setting 2020-10-29 14:46:39 +08:00
ChsBuffer
241371c6f7 feat: SettingForm set the color of the control to red If the value is wrong 2020-10-29 14:14:50 +08:00
ChsBuffer
9b3f5f456f refactor: Bandwidth.NetTraffic 2020-10-29 13:44:30 +08:00
ChsBuffer
c04b8f6ffd refactor: Check NF driver version 2020-10-29 13:27:33 +08:00
ChsBuffer
9d6b6d15d7 refactor: set StatusPortInfoText.ShareLan 2020-10-29 12:07:12 +08:00
ChsBuffer
39081c0a6f refactor: StatusPortInfoText.Value 2020-10-28 01:43:33 +08:00
ChsBuffer
812fab6322 fix: ModifiedDNS Setting init Enabled state 2020-10-27 18:42:41 +08:00
ChsBuffer
bfadb181c4 fix: SettingForm TUNTAPDNS value init
fix: show starting tun2socks after setup route table
fix: a typo
2020-10-27 12:14:10 +08:00
ChsBuffer
52ac05ee17 feat: add ChildProcessTracker 2020-10-26 17:36:50 +08:00
ChsBuffer
c774122fdb fix: Disable update ACL after startup 2020-10-26 16:58:45 +08:00
ChsBuffer
8e223faa71 fix: v2ray will proxy multicast address causing loop 2020-10-25 21:35:07 +08:00
ChsBuffer
7b0f0f35cc fix: SettingForm load RedriectorTCP value wrong
fix: Start Profile ModeComboBox.Text and ProfileNameText.Text wrong
2020-10-25 21:01:21 +08:00
ChsBuffer
89ce721d4c fix: language setting not saved 2020-10-25 00:24:40 +08:00
ChsBuffer
2247a75269 bump version to 1.6.5 2020-10-24 16:06:13 +08:00
ChsBuffer
c1e9856e92 refactor: check and build dns string 2020-10-23 18:32:06 +08:00
ChsBuffer
41e74e0794 feat: Add setting ”Modified DNS“ for Process Mode 2020-10-23 17:46:31 +08:00
ChsBuffer
6f8214951a fix: update subscription async warning 2020-10-23 17:20:58 +08:00
ChsBuffer
0fc5b77004 refactor: Regenerate SettingForm designer code 2020-10-23 16:35:49 +08:00
ChsBuffer
34cbcbfb0f fix: SettingForm Control Order 2020-10-23 16:30:21 +08:00
ChsBuffer
1ad4a08a85 fix: Edit subscription link shows "Remark Name Duplicate!" 2020-10-23 14:46:16 +08:00
ChsBuffer
8e0bc8e260 feat: Notification update subscription exception status code 2020-10-23 14:45:30 +08:00
ChsBuffer
bae9ecfe88 fix: ImportServerFromClipboard parse twice 2020-10-23 14:36:43 +08:00
ChsBuffer
3ca3e45ce2 feat: Add AioDNS Setting 2020-10-23 13:48:33 +08:00
ChsBuffer
bcb220bc4b Revert "refactor: MainForm change Enabled to change State"
This reverts commit abfae4a9a0.
2020-10-23 12:36:46 +08:00
AmazingDM
c50eb32828 Update README.md 2020-10-23 10:19:53 +08:00
ChsBuffer
b96f171b47 fix: V2RayConfigUtils direct outbound config
refactor: rename VMessController Name V2Ray to VMess
2020-10-22 21:31:20 +08:00
ChsBuffer
4fbbd1dbd4 feat: update progress check hash 2020-10-22 15:17:26 +08:00
ChsBuffer
2ad394dfde refactor: builder dns string and Mode FileString 2020-10-22 15:17:26 +08:00
ChsBuffer
421b35a797 fix: SettingForm UseCustomDNSCheckBox click event is not bound 2020-10-22 15:17:26 +08:00
Connection Refused
25612df086 Update v2ray-core 4.31.2 2020-10-22 13:24:43 +08:00
ChsBuffer
4ac5065ce4 feat: add UseMux Setting 2020-10-21 22:18:11 +08:00
ChsBuffer
d4b97a99e0 feat: V2Ray AllowInsecure Setting 2020-10-21 22:09:53 +08:00
ChsBuffer
3d49fe0338 Revert "feat: V2Ray TLS AllowInsecure Setting"
This reverts commit 591f8e5a5c.
2020-10-21 22:07:58 +08:00
ChsBuffer
af5100fe73 bump version to 1.6.4 2020-10-21 21:48:23 +08:00
ChsBuffer
f8bcef7ac9 fix: Updater parse multiple space path 2020-10-21 21:40:55 +08:00
ChsBuffer
591f8e5a5c feat: V2Ray TLS AllowInsecure Setting 2020-10-21 21:34:28 +08:00
ChsBuffer
00047a5030 refactor: SettingForm
feat: KCPSettings
2020-10-21 21:25:07 +08:00
ChsBuffer
6d4dab573e feat: split SettingForm settings 2020-10-21 17:50:22 +08:00
ChsBuffer
141fc58df4 fix: #415 Mode 4 start failed 2020-10-21 16:38:30 +08:00
ChsBuffer
4210f36814 fix: VLESSForm UseMux CheckBox 2020-10-20 17:52:17 +08:00
34 changed files with 1739 additions and 914 deletions

View File

@@ -15,9 +15,9 @@ namespace Netch.Controllers
/// <returns></returns>
public bool Start()
{
if (!aiodns_dial(Encoding.UTF8.GetBytes(Path.GetFullPath("bin\\china_site_list")),
Encoding.UTF8.GetBytes("223.5.5.5:53"),
Encoding.UTF8.GetBytes("1.1.1.1:53"))
if (!aiodns_dial(Encoding.UTF8.GetBytes(Path.GetFullPath(Global.Settings.AioDNS.RulePath)),
Encoding.UTF8.GetBytes($"{Global.Settings.AioDNS.ChinaDNS}:53"),
Encoding.UTF8.GetBytes($"{Global.Settings.AioDNS.OtherDNS}:53"))
)
return false;
return

View File

@@ -31,7 +31,10 @@ namespace Netch.Controllers
try
{
pPrivoxyController.Start(MainController.ServerController.Server, mode);
if (pPrivoxyController.Start(MainController.ServerController.Server, mode))
{
ChildProcessTracker.AddProcess(pPrivoxyController.Instance);
}
if (mode.Type == 3) NativeMethods.SetGlobal($"127.0.0.1:{Global.Settings.HTTPLocalPort}", IEProxyExceptions);
}

View File

@@ -69,6 +69,8 @@ namespace Netch.Controllers
throw new StartFailedException();
}
StatusPortInfoText.UpdateShareLan();
if (!await StartMode(server, mode))
{
throw new StartFailedException();
@@ -122,8 +124,23 @@ namespace Netch.Controllers
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", controller.Name));
if (controller.Start(in server, mode))
{
UsingPorts.Add(StatusPortInfoText.Socks5Port = controller.Socks5LocalPort());
StatusPortInfoText.ShareLan = controller.LocalAddress == "0.0.0.0";
if (controller is Guard guard)
{
if (guard.Instance != null)
{
ChildProcessTracker.AddProcess(guard.Instance);
}
}
if (server is Socks5 socks5)
{
if (socks5.Auth() && !mode.SupportSocks5Auth)
UsingPorts.Add(StatusPortInfoText.Socks5Port = controller.Socks5LocalPort());
}
else
{
UsingPorts.Add(StatusPortInfoText.Socks5Port = controller.Socks5LocalPort());
}
return true;
}
@@ -134,19 +151,33 @@ namespace Netch.Controllers
private static async Task<bool> StartMode(Server server, Mode mode)
{
ModeController = ModeHelper.GetModeControllerByType(mode.Type, out var port, out var portName, out var portType);
if (ModeController == null)
{
return true;
}
if (port != null)
{
PortCheckAndShowMessageBox((ushort) port, portName, portType);
UsingPorts.Add((ushort) port);
}
if (ModeController != null)
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ModeController.Name));
if (await Task.Run(() => ModeController.Start(mode)))
{
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ModeController.Name));
return await Task.Run(() => ModeController.Start(mode));
if (ModeController is Guard guard)
{
if (guard.Instance != null)
{
ChildProcessTracker.AddProcess(guard.Instance);
}
}
return true;
}
return true;
return false;
}
/// <summary>

View File

@@ -3,7 +3,6 @@ using System.IO;
using System.Runtime.InteropServices;
using System.ServiceProcess;
using System.Threading.Tasks;
using Netch.Forms;
using Netch.Models;
using Netch.Servers.Socks5;
using Netch.Utils;
@@ -47,23 +46,10 @@ namespace Netch.Controllers
public bool Start(in Mode mode)
{
var binFileVersion = Utils.Utils.GetFileVersion(BinDriver);
var systemFileVersion = Utils.Utils.GetFileVersion(SystemDriver);
if (!CheckDriver())
return false;
Logging.Info("内置驱动版本: " + binFileVersion);
Logging.Info("系统驱动版本: " + systemFileVersion);
if (!systemFileVersion.Equals(binFileVersion))
{
if (File.Exists(SystemDriver))
{
Logging.Info("更新驱动");
UninstallDriver();
}
if (!InstallDriver())
return false;
}
#region aio_dial
aio_dial((int) NameList.TYPE_FILTERLOOPBACK, "false");
aio_dial((int) NameList.TYPE_FILTERTCP, "true");
@@ -74,16 +60,80 @@ namespace Netch.Controllers
SetName(mode);
#endregion
if (Global.Settings.ModifySystemDNS)
{
// 备份并替换系统 DNS
_sysDns = DNS.OutboundDNS;
DNS.OutboundDNS = "1.1.1.1,8.8.8.8";
if (string.IsNullOrWhiteSpace(Global.Settings.ModifiedDNS))
Global.Settings.ModifiedDNS = "1.1.1.1,8.8.8.8";
DNS.OutboundDNS = Global.Settings.ModifiedDNS;
}
return aio_init();
}
private static bool CheckDriver()
{
var binFileVersion = Utils.Utils.GetFileVersion(BinDriver);
var systemFileVersion = Utils.Utils.GetFileVersion(SystemDriver);
Logging.Info("内置驱动版本: " + binFileVersion);
Logging.Info("系统驱动版本: " + systemFileVersion);
if (!File.Exists(BinDriver))
{
Logging.Warning("内置驱动不存在");
if (File.Exists(SystemDriver))
{
Logging.Warning("使用系统驱动");
return true;
}
Logging.Error("未安装驱动");
return false;
}
if (!File.Exists(SystemDriver))
{
return InstallDriver();
}
var updateFlag = false;
if (Version.TryParse(binFileVersion, out var binResult) && Version.TryParse(systemFileVersion, out var systemResult))
{
if (binResult.CompareTo(systemResult) > 0)
{
// Bin greater than Installed
updateFlag = true;
}
else
{
// Installed greater than Bin
if (systemResult.Major != binResult.Major)
{
// API breaking changes
updateFlag = true;
}
}
}
else
{
if (!systemFileVersion.Equals(binFileVersion))
{
updateFlag = true;
}
}
if (!updateFlag) return true;
Logging.Info("更新驱动");
UninstallDriver();
return InstallDriver();
}
private void SetServer(in IServerController controller, in PortType portType)
{
if (portType == PortType.Both)

View File

@@ -68,12 +68,14 @@ namespace Netch.Controllers
SetupRouteTable();
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", Name));
string dns;
if (Global.Settings.TUNTAP.UseCustomDNS)
{
if (Global.Settings.TUNTAP.DNS.Any())
{
dns = Global.Settings.TUNTAP.DNS.Aggregate((current, ip) => $"{current},{ip}");
dns = DNS.Join(Global.Settings.TUNTAP.DNS);
}
else
{

View File

@@ -15,7 +15,7 @@ namespace Netch.Controllers
public const string Name = @"Netch";
public const string Copyright = @"Copyright © 2019 - 2020";
public const string AssemblyVersion = @"1.6.3";
public const string AssemblyVersion = @"1.6.6";
private const string Suffix = @"";
public static readonly string Version = $"{AssemblyVersion}{(string.IsNullOrEmpty(Suffix) ? "" : $"-{Suffix}")}";

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
@@ -26,8 +27,9 @@ namespace Netch.Forms
var texts = Clipboard.GetText();
if (!string.IsNullOrWhiteSpace(texts))
{
Global.Settings.Server.AddRange(ShareLink.ParseText(texts));
NotifyTip(i18N.TranslateFormat("Import {0} server(s) form Clipboard", ShareLink.ParseText(texts).Count));
var servers = ShareLink.ParseText(texts);
Global.Settings.Server.AddRange(servers);
NotifyTip(i18N.TranslateFormat("Import {0} server(s) form Clipboard", servers.Count));
InitServer();
Configuration.Save();
@@ -136,7 +138,7 @@ namespace Netch.Forms
await MainController.Start(ServerComboBox.SelectedItem as Server, mode);
}
await Task.WhenAll(Global.Settings.SubscribeLink.Select(async item => await Task.Run(async () =>
await Task.WhenAll(Global.Settings.SubscribeLink.Select(async item => await Task.Run(() =>
{
try
{
@@ -146,7 +148,17 @@ namespace Netch.Forms
if (Global.Settings.UseProxyToUpdateSubscription)
request.Proxy = new WebProxy($"http://127.0.0.1:{Global.Settings.HTTPLocalPort}");
var servers = ShareLink.ParseText(await WebUtil.DownloadStringAsync(request));
List<Server> servers;
var result = WebUtil.DownloadString(request, out var rep);
if (rep.StatusCode == HttpStatusCode.OK)
{
servers = ShareLink.ParseText(result);
}
else
{
throw new Exception($"{item.Remark} Response Status Code: {rep.StatusCode}");
}
foreach (var server in servers)
{
@@ -244,19 +256,13 @@ namespace Netch.Forms
private async void UpdateACL(bool useProxy)
{
void DisableItems(bool v)
{
UpdateACLToolStripMenuItem.Enabled = updateACLWithProxyToolStripMenuItem.Enabled = v;
}
if (useProxy && ServerComboBox.SelectedIndex == -1)
{
MessageBoxX.Show(i18N.Translate("Please select a server first"));
return;
}
DisableItems(false);
Enabled = false;
NotifyTip(i18N.Translate("Updating in the background"));
try
@@ -292,42 +298,38 @@ namespace Netch.Forms
State = State.Stopped;
}
DisableItems(true);
Enabled = true;
}
}
private async void UninstallServiceToolStripMenuItem_Click(object sender, EventArgs e)
{
State = State.Starting;
Enabled = false;
StatusText(i18N.TranslateFormat("Uninstalling {0}", "NF Service"));
var result = false;
try
{
await Task.Run(() =>
{
if (NFController.UninstallDriver())
{
result = true;
StatusText(i18N.TranslateFormat("{0} has been uninstalled", "NF Service"));
}
});
}
finally
{
State = State.Stopped;
if (result)
StatusText(i18N.TranslateFormat("{0} has been uninstalled", "NF Service"));
Enabled = true;
}
}
private async void reinstallTapDriverToolStripMenuItem_Click(object sender, EventArgs e)
{
State = State.Starting;
StatusText(i18N.TranslateFormat("Uninstalling {0}", "TUN/TAP driver"));
var result = false;
Enabled = false;
try
{
await Task.Run(TUNTAP.deltapall);
result = true;
StatusText(i18N.TranslateFormat("{0} has been uninstalled", "TUN/TAP driver"));
}
catch (Exception exception)
{
@@ -335,9 +337,8 @@ namespace Netch.Forms
}
finally
{
State = State.Stopped;
if (result)
StatusText(i18N.TranslateFormat("{0} has been uninstalled", "TUN/TAP driver"));
State = State.Waiting;
Enabled = true;
}
}

View File

@@ -2,6 +2,7 @@
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using Netch.Controllers;
using Netch.Utils;
@@ -44,15 +45,37 @@ namespace Netch.Forms
if (MessageBoxX.Show(i18N.Translate("Download and install now?"), confirm: true) != DialogResult.OK)
return;
NotifyTip(i18N.Translate("Start downloading new version"));
var tagPage = await WebUtil.DownloadStringAsync(WebUtil.CreateRequest(_updater.LatestVersionUrl));
var match = Regex.Match(tagPage, @"<td .*>(?<sha256>.*)</td>", RegexOptions.Singleline);
// TODO Replace with regex get basename and sha256
var fileName = Path.GetFileName(new Uri(_updater.LatestVersionDownloadUrl).LocalPath);
fileName = fileName.Insert(fileName.LastIndexOf('.'), _updater.LatestVersionNumber);
var fileFullPath = Path.Combine(Global.NetchDir, "data", fileName);
var sha256 = match.Groups["sha256"].Value;
try
{
if (!File.Exists(fileFullPath))
if (File.Exists(fileFullPath))
{
await WebUtil.DownloadFileAsync(WebUtil.CreateRequest(_updater.LatestVersionDownloadUrl), fileFullPath);
if (Utils.Utils.SHA256CheckSum(fileFullPath) == sha256)
{
RunUpdater();
return;
}
File.Delete(fileFullPath);
}
// TODO Replace "New Version Found" to Progress bar
await WebUtil.DownloadFileAsync(WebUtil.CreateRequest(_updater.LatestVersionDownloadUrl), fileFullPath);
if (Utils.Utils.SHA256CheckSum(fileFullPath) != sha256)
{
MessageBoxX.Show("The downloaded file has the wrong hash");
return;
}
RunUpdater();
@@ -73,7 +96,7 @@ namespace Netch.Forms
{
FileName = Path.Combine(Global.NetchDir, "NetchUpdater.exe"),
Arguments =
$"{Global.Settings.UDPSocketPort}|{fileFullPath}|{Global.NetchDir}"
$"{Global.Settings.UDPSocketPort} \"{fileFullPath}\" \"{Global.NetchDir}\""
});
}
}

View File

@@ -79,7 +79,8 @@ namespace Netch.Forms
private void LoadProfile(int index)
{
var p = Global.Settings.Profiles[index];
ProfileNameText.Text = p.ModeRemark;
ProfileNameText.Text = p.ProfileName;
ModeComboBox.ResetCompletionList();
if (p.IsDummy)
throw new Exception("Profile not found.");
@@ -160,9 +161,6 @@ namespace Netch.Forms
return;
}
// Reset Mode ComboBox Items
ModeComboBox.Text = string.Empty;
try
{
LoadProfile(index);

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Linq;
using Netch.Models;
using Netch.Utils;
@@ -35,10 +36,11 @@ namespace Netch.Forms
// 启动需要禁用的控件
UninstallServiceToolStripMenuItem.Enabled =
updateACLWithProxyToolStripMenuItem.Enabled =
UpdateServersFromSubscribeLinksToolStripMenuItem.Enabled =
UninstallTapDriverToolStripMenuItem.Enabled =
ReloadModesToolStripMenuItem.Enabled = enabled;
UpdateACLToolStripMenuItem.Enabled =
updateACLWithProxyToolStripMenuItem.Enabled =
UpdateServersFromSubscribeLinksToolStripMenuItem.Enabled =
UninstallTapDriverToolStripMenuItem.Enabled =
ReloadModesToolStripMenuItem.Enabled = enabled;
}
_state = value;
@@ -185,12 +187,7 @@ namespace Netch.Forms
{
private static ushort? _socks5Port;
private static ushort? _httpPort;
private static bool? _shareLan;
public static bool ShareLan
{
set => _shareLan = value;
}
private static bool _shareLan;
public static ushort HttpPort
{
@@ -202,35 +199,34 @@ namespace Netch.Forms
set => _socks5Port = value;
}
public static void UpdateShareLan() => _shareLan = Global.Settings.LocalAddress != "127.0.0.1";
public static string Value
{
get
{
if (_socks5Port == null && _httpPort == null)
return string.Empty;
var text = new StringBuilder();
if (_shareLan == true)
text.Append(i18N.Translate("Allow other Devices to connect") + " ");
var strings = new List<string>();
if (_socks5Port != null)
text.Append($"Socks5 {i18N.Translate("Local Port", ": ")}{_socks5Port}");
{
strings.Add($"Socks5 {i18N.Translate("Local Port", ": ")}{_socks5Port}");
}
if (_httpPort != null)
{
if (_socks5Port != null)
text.Append(" | ");
text.Append($"HTTP {i18N.Translate("Local Port", ": ")}{_httpPort}");
strings.Add($"HTTP {i18N.Translate("Local Port", ": ")}{_httpPort}");
}
return $" ({text})";
if (!strings.Any())
return string.Empty;
return $" ({(_shareLan ? i18N.Translate("Allow other Devices to connect") + " " : "")}{string.Join(" | ", strings)})";
}
}
public static void Reset()
{
_httpPort = _socks5Port = null;
_shareLan = null;
}
}
}

View File

@@ -334,7 +334,7 @@ namespace Netch.Forms
private async void SpeedPictureBox_Click(object sender, EventArgs e)
{
State = State.Starting;
Enabled = false;
StatusText(i18N.Translate("Testing"));
try
{
@@ -342,7 +342,7 @@ namespace Netch.Forms
}
finally
{
State = State.Stopped;
Enabled = true;
StatusText(i18N.Translate("Test done"));
Refresh();
}

View File

@@ -168,28 +168,37 @@ namespace Netch.Forms
private void ControlButton_Click(object sender, EventArgs e)
{
if (_checkActions.All(pair => pair.Value.Invoke(pair.Key.Text)))
Utils.Utils.ComponentIterator(this, component => Utils.Utils.ChangeControlForeColor(component, Color.Black));
var flag = true;
foreach (var pair in _checkActions.Where(pair => !pair.Value.Invoke(pair.Key.Text)))
{
foreach (var pair in _saveActions)
{
switch (pair.Key)
{
case CheckBox c:
pair.Value.Invoke(c.Checked);
break;
default:
pair.Value.Invoke(pair.Key.Text);
break;
}
}
if (Global.Settings.Server.IndexOf(Server) == -1)
Global.Settings.Server.Add(Server);
MessageBoxX.Show(i18N.Translate("Saved"));
Utils.Utils.ChangeControlForeColor(pair.Key, Color.Red);
flag = false;
}
else
if (!flag)
{
return;
}
foreach (var pair in _saveActions)
{
switch (pair.Key)
{
case CheckBox c:
pair.Value.Invoke(c.Checked);
break;
default:
pair.Value.Invoke(pair.Key.Text);
break;
}
}
if (Global.Settings.Server.IndexOf(Server) == -1)
Global.Settings.Server.Add(Server);
MessageBoxX.Show(i18N.Translate("Saved"));
Close();
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,13 @@
using System;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Windows.Forms;
using Netch.Controllers;
using Netch.Utils;
using TaskScheduler;
namespace Netch.Forms
{
@@ -15,30 +16,119 @@ namespace Netch.Forms
public SettingForm()
{
InitializeComponent();
InitText();
i18N.TranslateForm(this);
InitValue();
}
private void SettingForm_Load(object sender, EventArgs e)
{
TUNTAPUseCustomDNSCheckBox_CheckedChanged(null, null);
Task.Run(() => BeginInvoke(new Action(() => UseFakeDNSCheckBox.Visible = Global.Flags.SupportFakeDns)));
}
private void InitValue()
{
// Local Port
Socks5PortTextBox.Text = Global.Settings.Socks5LocalPort.ToString();
HTTPPortTextBox.Text = Global.Settings.HTTPLocalPort.ToString();
RedirectorTextBox.Text = Global.Settings.RedirectorTCPPort.ToString();
AllowDevicesCheckBox.Checked = Global.Settings.LocalAddress switch
{
"127.0.0.1" => false,
"0.0.0.0" => true,
_ => false
};
#region General
// TUN/TAP
TUNTAPAddressTextBox.Text = Global.Settings.TUNTAP.Address;
TUNTAPNetmaskTextBox.Text = Global.Settings.TUNTAP.Netmask;
TUNTAPGatewayTextBox.Text = Global.Settings.TUNTAP.Gateway;
UseCustomDNSCheckBox.Checked = Global.Settings.TUNTAP.UseCustomDNS;
BindTextBox<ushort>(Socks5PortTextBox,
p => p.ToString() != HTTPPortTextBox.Text && p.ToString() != RedirectorTextBox.Text,
p => Global.Settings.Socks5LocalPort = p,
Global.Settings.Socks5LocalPort);
BindTextBox<ushort>(HTTPPortTextBox,
p => p.ToString() != Socks5PortTextBox.Text && p.ToString() != RedirectorTextBox.Text,
p => Global.Settings.HTTPLocalPort = p,
Global.Settings.HTTPLocalPort);
BindTextBox<ushort>(RedirectorTextBox,
p => p.ToString() != Socks5PortTextBox.Text && p.ToString() != HTTPPortTextBox.Text,
p => Global.Settings.RedirectorTCPPort = p,
Global.Settings.RedirectorTCPPort);
BindCheckBox(AllowDevicesCheckBox,
c => Global.Settings.LocalAddress = AllowDevicesCheckBox.Checked ? "0.0.0.0" : "127.0.0.1",
Global.Settings.LocalAddress switch
{
"127.0.0.1" => false,
"0.0.0.0" => true,
_ => false
});
BindCheckBox(BootShadowsocksFromDLLCheckBox,
c => Global.Settings.BootShadowsocksFromDLL = c,
Global.Settings.BootShadowsocksFromDLL);
BindCheckBox(ResolveServerHostnameCheckBox,
c => Global.Settings.ResolveServerHostname = c,
Global.Settings.ResolveServerHostname);
BindTextBox<int>(ProfileCountTextBox,
i => i > -1,
i => Global.Settings.ProfileCount = i,
Global.Settings.ProfileCount);
BindCheckBox(TcpingAtStartedCheckBox,
b => Global.Settings.StartedTcping = b,
Global.Settings.StartedTcping);
BindTextBox<int>(DetectionIntervalTextBox,
i => i >= 0,
i => Global.Settings.StartedTcping_Interval = i,
Global.Settings.StartedTcping_Interval);
InitSTUN();
BindTextBox<string>(AclAddrTextBox,
s => true,
s => Global.Settings.ACL = s,
Global.Settings.ACL);
AclAddrTextBox.Text = Global.Settings.ACL;
LanguageComboBox.Items.AddRange(i18N.GetTranslateList().ToArray());
LanguageComboBox.SelectedItem = Global.Settings.Language;
#endregion
#region Process Mode
BindCheckBox(ModifySystemDNSCheckBox,
b => Global.Settings.ModifySystemDNS = b,
Global.Settings.ModifySystemDNS);
ModifySystemDNSCheckBox_CheckedChanged(null, null);
BindTextBox(ModifiedDNSTextBox,
s => DNS.TrySplit(s, out _, 2),
s => Global.Settings.ModifiedDNS = s,
Global.Settings.ModifiedDNS);
#endregion
#region TUN/TAP
BindTextBox(TUNTAPAddressTextBox,
s => IPAddress.TryParse(s, out _),
s => Global.Settings.TUNTAP.Address = s,
Global.Settings.TUNTAP.Address);
BindTextBox(TUNTAPNetmaskTextBox,
s => IPAddress.TryParse(s, out _),
s => Global.Settings.TUNTAP.Netmask = s,
Global.Settings.TUNTAP.Netmask);
BindTextBox(TUNTAPGatewayTextBox,
s => IPAddress.TryParse(s, out _),
s => Global.Settings.TUNTAP.Gateway = s,
Global.Settings.TUNTAP.Gateway);
BindCheckBox(UseCustomDNSCheckBox,
b => { Global.Settings.TUNTAP.UseCustomDNS = b; },
Global.Settings.TUNTAP.UseCustomDNS);
TUNTAPUseCustomDNSCheckBox_CheckedChanged(null, null);
ProxyDNSCheckBox.Checked = Global.Settings.TUNTAP.ProxyDNS;
UseFakeDNSCheckBox.Checked = Global.Settings.TUNTAP.UseFakeDNS;
BindTextBox(TUNTAPDNSTextBox,
s => !UseCustomDNSCheckBox.Checked || DNS.TrySplit(s, out _, 2),
s => Global.Settings.TUNTAP.DNS = DNS.Split(s).ToList(),
DNS.Join(Global.Settings.TUNTAP.DNS));
BindCheckBox(ProxyDNSCheckBox,
b => Global.Settings.TUNTAP.ProxyDNS = b,
Global.Settings.TUNTAP.ProxyDNS);
BindCheckBox(UseFakeDNSCheckBox,
b => Global.Settings.TUNTAP.UseFakeDNS = b,
Global.Settings.TUNTAP.UseFakeDNS);
try
{
@@ -54,26 +144,101 @@ namespace Netch.Forms
// ignored
}
// Behavior
ExitWhenClosedCheckBox.Checked = Global.Settings.ExitWhenClosed;
StopWhenExitedCheckBox.Checked = Global.Settings.StopWhenExited;
StartWhenOpenedCheckBox.Checked = Global.Settings.StartWhenOpened;
MinimizeWhenStartedCheckBox.Checked = Global.Settings.MinimizeWhenStarted;
RunAtStartupCheckBox.Checked = Global.Settings.RunAtStartup;
CheckUpdateWhenOpenedCheckBox.Checked = Global.Settings.CheckUpdateWhenOpened;
BootShadowsocksFromDLLCheckBox.Checked = Global.Settings.BootShadowsocksFromDLL;
CheckBetaUpdateCheckBox.Checked = Global.Settings.CheckBetaUpdate;
ModifySystemDNSCheckBox.Checked = Global.Settings.ModifySystemDNS;
UpdateSubscribeatWhenOpenedCheckBox.Checked = Global.Settings.UpdateSubscribeatWhenOpened;
ResolveServerHostnameCheckBox.Checked = Global.Settings.ResolveServerHostname;
#endregion
ProfileCountTextBox.Text = Global.Settings.ProfileCount.ToString();
TcpingAtStartedCheckBox.Checked = Global.Settings.StartedTcping;
DetectionIntervalTextBox.Text = Global.Settings.StartedTcping_Interval.ToString();
InitSTUN();
AclAddrTextBox.Text = Global.Settings.ACL;
LanguageComboBox.Items.AddRange(i18N.GetTranslateList().ToArray());
LanguageComboBox.SelectedItem = Global.Settings.Language;
#region V2Ray
BindCheckBox(TLSAllowInsecureCheckBox,
b => Global.Settings.V2RayConfig.AllowInsecure = b,
Global.Settings.V2RayConfig.AllowInsecure);
BindCheckBox(UseMuxCheckBox,
b => Global.Settings.V2RayConfig.UseMux = b,
Global.Settings.V2RayConfig.UseMux);
BindTextBox<int>(mtuTextBox,
i => true,
i => Global.Settings.V2RayConfig.KcpConfig.mtu = i,
Global.Settings.V2RayConfig.KcpConfig.mtu);
BindTextBox<int>(ttiTextBox,
i => true,
i => Global.Settings.V2RayConfig.KcpConfig.tti = i,
Global.Settings.V2RayConfig.KcpConfig.tti);
BindTextBox<int>(uplinkCapacityTextBox,
i => true,
i => Global.Settings.V2RayConfig.KcpConfig.uplinkCapacity = i,
Global.Settings.V2RayConfig.KcpConfig.uplinkCapacity);
BindTextBox<int>(downlinkCapacityTextBox,
i => true,
i => Global.Settings.V2RayConfig.KcpConfig.downlinkCapacity = i,
Global.Settings.V2RayConfig.KcpConfig.downlinkCapacity);
BindTextBox<int>(readBufferSizeTextBox,
i => true,
i => Global.Settings.V2RayConfig.KcpConfig.readBufferSize = i,
Global.Settings.V2RayConfig.KcpConfig.readBufferSize);
BindTextBox<int>(writeBufferSizeTextBox,
i => true,
i => Global.Settings.V2RayConfig.KcpConfig.writeBufferSize = i,
Global.Settings.V2RayConfig.KcpConfig.writeBufferSize);
BindCheckBox(congestionCheckBox,
b => Global.Settings.V2RayConfig.KcpConfig.congestion = b,
Global.Settings.V2RayConfig.KcpConfig.congestion);
#endregion
#region Others
BindCheckBox(ExitWhenClosedCheckBox,
b => Global.Settings.ExitWhenClosed = b,
Global.Settings.ExitWhenClosed);
BindCheckBox(StopWhenExitedCheckBox,
b => Global.Settings.StopWhenExited = b,
Global.Settings.StopWhenExited);
BindCheckBox(StartWhenOpenedCheckBox,
b => Global.Settings.StartWhenOpened = b,
Global.Settings.StartWhenOpened);
BindCheckBox(MinimizeWhenStartedCheckBox,
b => Global.Settings.MinimizeWhenStarted = b,
Global.Settings.MinimizeWhenStarted);
BindCheckBox(RunAtStartupCheckBox,
b => Global.Settings.RunAtStartup = b,
Global.Settings.RunAtStartup);
BindCheckBox(CheckUpdateWhenOpenedCheckBox,
b => Global.Settings.CheckUpdateWhenOpened = b,
Global.Settings.CheckUpdateWhenOpened);
BindCheckBox(CheckBetaUpdateCheckBox,
b => Global.Settings.CheckBetaUpdate = b,
Global.Settings.CheckBetaUpdate);
BindCheckBox(UpdateSubscribeatWhenOpenedCheckBox,
b => Global.Settings.UpdateSubscribeatWhenOpened = b,
Global.Settings.UpdateSubscribeatWhenOpened);
#endregion
#region AioDNS
BindTextBox(AioDNSRulePathTextBox,
s => true,
s => Global.Settings.AioDNS.RulePath = s,
Global.Settings.AioDNS.RulePath);
BindTextBox(ChinaDNSTextBox,
s => IPAddress.TryParse(s, out _),
s => Global.Settings.AioDNS.ChinaDNS = s,
Global.Settings.AioDNS.ChinaDNS);
BindTextBox(OtherDNSTextBox,
s => IPAddress.TryParse(s, out _),
s => Global.Settings.AioDNS.OtherDNS = s,
Global.Settings.AioDNS.OtherDNS);
#endregion
}
private void TUNTAPUseCustomDNSCheckBox_CheckedChanged(object sender, EventArgs e)
@@ -83,19 +248,15 @@ namespace Netch.Forms
if (UseCustomDNSCheckBox.Checked)
{
TUNTAPDNSTextBox.Text = Global.Settings.TUNTAP.DNS.Any()
? Global.Settings.TUNTAP.DNS.Aggregate((current, ip) => $"{current},{ip}")
? DNS.Join(Global.Settings.TUNTAP.DNS)
: "1.1.1.1";
}
else
{
TUNTAPDNSTextBox.Text = "Local DNS";
TUNTAPDNSTextBox.Text = "AioDNS";
}
}
private void InitText()
{
i18N.TranslateForm(this);
}
private void InitSTUN()
{
@@ -104,7 +265,7 @@ namespace Netch.Forms
var stuns = File.ReadLines("bin\\stun.txt");
STUN_ServerComboBox.Items.AddRange(stuns.ToArray());
}
catch (Exception)
catch
{
// ignored
}
@@ -112,13 +273,6 @@ namespace Netch.Forms
STUN_ServerComboBox.Text = $"{Global.Settings.STUN_Server}:{Global.Settings.STUN_Server_Port}";
}
private void SettingForm_Load(object sender, EventArgs e)
{
InitValue();
Task.Run(() => BeginInvoke(new Action(() => UseFakeDNSCheckBox.Visible = Global.Flags.SupportFakeDns)));
}
private void GlobalBypassIPsButton_Click(object sender, EventArgs e)
{
Hide();
@@ -128,158 +282,48 @@ namespace Netch.Forms
private void ControlButton_Click(object sender, EventArgs e)
{
Utils.Utils.ComponentIterator(this, component => Utils.Utils.ChangeControlForeColor(component, Color.Black));
#region Check
#region Port
ushort socks5LocalPort;
ushort httpLocalPort;
ushort redirectorTCPPort;
try
var flag = true;
foreach (var pair in _checkActions.Where(pair => !pair.Value.Invoke(pair.Key.Text)))
{
socks5LocalPort = ushort.Parse(Socks5PortTextBox.Text);
httpLocalPort = ushort.Parse(HTTPPortTextBox.Text);
redirectorTCPPort = ushort.Parse(RedirectorTextBox.Text);
static void CheckPort(string portName, ushort port, ushort originPort, PortType portType = PortType.Both)
{
if (port == originPort)
return;
if (PortHelper.PortInUse(port, portType))
{
MessageBoxX.Show(i18N.TranslateFormat("The {0} port is in use.", portName));
throw new PortInUseException();
}
}
CheckPort("Socks5", socks5LocalPort, Global.Settings.Socks5LocalPort);
CheckPort("HTTP", httpLocalPort, Global.Settings.HTTPLocalPort);
CheckPort("RedirectorTCP", redirectorTCPPort, Global.Settings.RedirectorTCPPort);
Utils.Utils.ChangeControlForeColor(pair.Key, Color.Red);
flag = false;
}
catch (Exception exception)
{
switch (exception)
{
case FormatException _:
MessageBoxX.Show(i18N.Translate("Port value illegal. Try again."));
break;
case PortInUseException _:
break;
}
if (!flag)
{
return;
}
#endregion
#region TUNTAP
#region CheckSTUN
var dns = new string[0];
try
var stunFlag = true;
var stunServer = string.Empty;
ushort stunServerPort = 3478;
var stun = STUN_ServerComboBox.Text.Split(':');
if (stun.Any())
{
IPAddress.Parse(TUNTAPAddressTextBox.Text);
IPAddress.Parse(TUNTAPNetmaskTextBox.Text);
IPAddress.Parse(TUNTAPGatewayTextBox.Text);
if (UseCustomDNSCheckBox.Checked)
{
dns = TUNTAPDNSTextBox.Text.Split(',').Where(s => !string.IsNullOrEmpty(s)).Select(s => s.Trim())
.ToArray();
if (dns.Any())
{
foreach (var ip in dns)
IPAddress.Parse(ip);
}
else
{
MessageBoxX.Show("DNS can not be empty");
return;
}
}
}
catch (Exception exception)
{
if (exception is FormatException)
MessageBoxX.Show(i18N.Translate("IP address format illegal. Try again."));
TUNTAPAddressTextBox.Text = Global.Settings.TUNTAP.Address;
TUNTAPNetmaskTextBox.Text = Global.Settings.TUNTAP.Netmask;
TUNTAPGatewayTextBox.Text = Global.Settings.TUNTAP.Gateway;
UseCustomDNSCheckBox.Checked = Global.Settings.TUNTAP.UseCustomDNS;
if (UseCustomDNSCheckBox.Checked)
{
TUNTAPDNSTextBox.Text = Global.Settings.TUNTAP.DNS.Aggregate((current, ip) => $"{current},{ip}");
}
return;
}
#endregion
#region Behavior
// Profile
int profileCount;
try
{
profileCount = int.Parse(ProfileCountTextBox.Text);
if (profileCount <= -1)
{
throw new FormatException();
}
}
catch (FormatException)
{
ProfileCountTextBox.Text = Global.Settings.ProfileCount.ToString();
MessageBoxX.Show(i18N.Translate("ProfileCount value illegal. Try again."));
return;
}
// Started TCPing Interval
int detectionInterval;
try
{
detectionInterval = int.Parse(DetectionIntervalTextBox.Text);
if (detectionInterval <= 0)
{
throw new FormatException();
}
}
catch (FormatException)
{
ProfileCountTextBox.Text = Global.Settings.ProfileCount.ToString();
MessageBoxX.Show(i18N.Translate("Detection interval value illegal. Try again."));
return;
}
// STUN
string stunServer;
int stunServerPort;
try
{
var stun = STUN_ServerComboBox.Text.Split(':');
stunServer = stun[0];
stunServerPort = 3478;
if (stun.Length > 1)
stunServerPort = int.Parse(stun[1]);
if (stunServerPort <= 0)
{
throw new FormatException();
}
if (!ushort.TryParse(stun[1], out stunServerPort))
{
stunFlag = false;
}
}
catch (FormatException)
else
{
ProfileCountTextBox.Text = Global.Settings.ProfileCount.ToString();
MessageBoxX.Show(i18N.Translate("STUN_ServerPort value illegal. Try again."));
stunFlag = false;
}
if (!stunFlag)
{
Utils.Utils.ChangeControlForeColor(STUN_ServerComboBox, Color.Red);
return;
}
@@ -289,104 +333,18 @@ namespace Netch.Forms
#region Save
#region Port
Global.Settings.Socks5LocalPort = socks5LocalPort;
Global.Settings.HTTPLocalPort = httpLocalPort;
Global.Settings.RedirectorTCPPort = redirectorTCPPort;
Global.Settings.LocalAddress = AllowDevicesCheckBox.Checked ? "0.0.0.0" : "127.0.0.1";
#endregion
#region TUNTAP
Global.Settings.TUNTAP.Address = TUNTAPAddressTextBox.Text;
Global.Settings.TUNTAP.Netmask = TUNTAPNetmaskTextBox.Text;
Global.Settings.TUNTAP.Gateway = TUNTAPGatewayTextBox.Text;
Global.Settings.TUNTAP.UseCustomDNS = UseCustomDNSCheckBox.Checked;
if (Global.Settings.TUNTAP.UseCustomDNS)
foreach (var pair in _saveActions)
{
Global.Settings.TUNTAP.DNS.Clear();
Global.Settings.TUNTAP.DNS.AddRange(dns);
pair.Value.Invoke(pair.Key);
}
Global.Settings.TUNTAP.ProxyDNS = ProxyDNSCheckBox.Checked;
Global.Settings.TUNTAP.UseFakeDNS = UseFakeDNSCheckBox.Checked;
#endregion
#region Behavior
Global.Settings.ExitWhenClosed = ExitWhenClosedCheckBox.Checked;
Global.Settings.StopWhenExited = StopWhenExitedCheckBox.Checked;
Global.Settings.StartWhenOpened = StartWhenOpenedCheckBox.Checked;
Global.Settings.MinimizeWhenStarted = MinimizeWhenStartedCheckBox.Checked;
Global.Settings.RunAtStartup = RunAtStartupCheckBox.Checked;
Global.Settings.CheckUpdateWhenOpened = CheckUpdateWhenOpenedCheckBox.Checked;
Global.Settings.BootShadowsocksFromDLL = BootShadowsocksFromDLLCheckBox.Checked;
Global.Settings.CheckBetaUpdate = CheckBetaUpdateCheckBox.Checked;
Global.Settings.ModifySystemDNS = ModifySystemDNSCheckBox.Checked;
Global.Settings.UpdateSubscribeatWhenOpened = UpdateSubscribeatWhenOpenedCheckBox.Checked;
Global.Settings.ResolveServerHostname = ResolveServerHostnameCheckBox.Checked;
Global.Settings.ProfileCount = profileCount;
Global.Settings.StartedTcping = TcpingAtStartedCheckBox.Checked;
Global.Settings.StartedTcping_Interval = detectionInterval;
Global.Settings.STUN_Server = stunServer;
Global.Settings.STUN_Server_Port = stunServerPort;
Global.Settings.ACL = AclAddrTextBox.Text;
Global.Settings.Language = LanguageComboBox.SelectedItem.ToString();
Global.Settings.Language = LanguageComboBox.Text;
#endregion
#endregion
#region Register Startup Item
var scheduler = new TaskSchedulerClass();
scheduler.Connect();
var folder = scheduler.GetFolder("\\");
var taskIsExists = false;
try
{
folder.GetTask("Netch Startup");
taskIsExists = true;
}
catch (Exception)
{
// ignored
}
if (Global.Settings.RunAtStartup)
{
if (taskIsExists)
folder.DeleteTask("Netch Startup", 0);
var task = scheduler.NewTask(0);
task.RegistrationInfo.Author = "Netch";
task.RegistrationInfo.Description = "Netch run at startup.";
task.Principal.RunLevel = _TASK_RUNLEVEL.TASK_RUNLEVEL_HIGHEST;
task.Triggers.Create(_TASK_TRIGGER_TYPE2.TASK_TRIGGER_LOGON);
var action = (IExecAction) task.Actions.Create(_TASK_ACTION_TYPE.TASK_ACTION_EXEC);
action.Path = Application.ExecutablePath;
task.Settings.ExecutionTimeLimit = "PT0S";
task.Settings.DisallowStartIfOnBatteries = false;
task.Settings.RunOnlyIfIdle = false;
folder.RegisterTaskDefinition("Netch Startup", task, (int) _TASK_CREATION.TASK_CREATE, null, null,
_TASK_LOGON_TYPE.TASK_LOGON_INTERACTIVE_TOKEN, "");
}
else
{
if (taskIsExists)
folder.DeleteTask("Netch Startup", 0);
}
#endregion
Utils.Utils.RegisterNetchStartupItem();
Configuration.Save();
MessageBoxX.Show(i18N.Translate("Saved"));
@@ -421,5 +379,43 @@ namespace Netch.Forms
ICSCheckBox.Enabled = true;
}
}
private void BindTextBox(TextBox control, Func<string, bool> check, Action<string> save, object value)
{
BindTextBox<string>(control, check, save, value);
}
private void BindTextBox<T>(TextBox control, Func<T, bool> check, Action<T> save, object value)
{
control.Text = value.ToString();
_checkActions.Add(control, s =>
{
try
{
return check.Invoke((T) Convert.ChangeType(s, typeof(T)));
}
catch
{
return false;
}
});
_saveActions.Add(control, c => save.Invoke((T) Convert.ChangeType(((TextBox) c).Text, typeof(T))));
}
private void BindCheckBox(CheckBox control, Action<bool> save, bool value)
{
control.Checked = value;
_checkActions.Add(control, s => true);
_saveActions.Add(control, c => save.Invoke(((CheckBox) c).Checked));
}
private readonly Dictionary<Control, Func<string, bool>> _checkActions = new Dictionary<Control, Func<string, bool>>();
private readonly Dictionary<Control, Action<Control>> _saveActions = new Dictionary<Control, Action<Control>>();
private void ModifySystemDNSCheckBox_CheckedChanged(object sender, EventArgs e)
{
ModifiedDNSTextBox.Enabled = ModifySystemDNSCheckBox.Checked;
}
}
}

View File

@@ -109,14 +109,14 @@ namespace Netch.Forms
return;
}
if (Global.Settings.SubscribeLink.Any(link => link.Remark.Equals(RemarkTextBox.Text)))
{
MessageBoxX.Show("Remark Name Duplicate!");
return;
}
if (_editingIndex == -1)
{
if (Global.Settings.SubscribeLink.Any(link => link.Remark.Equals(RemarkTextBox.Text)))
{
MessageBoxX.Show("Remark Name Duplicate!");
return;
}
Global.Settings.SubscribeLink.Add(new SubscribeLink
{
Remark = RemarkTextBox.Text,

View File

@@ -131,30 +131,30 @@ namespace Netch.Models
/// <returns>模式文件字符串</returns>
public string ToFileString()
{
string fileString;
StringBuilder fileString = new StringBuilder();
switch (Type)
{
case 0:
// 进程模式
fileString = $"# {Remark}";
fileString.Append($"# {Remark}");
break;
case 1:
// TUN/TAP 规则内 IP CIDR无 Bypass China 设置
fileString = $"# {Remark}, {Type}, 0";
fileString.Append($"# {Remark}, {Type}, 0");
break;
default:
fileString = $"# {Remark}, {Type}, {(BypassChina ? 1 : 0)}";
fileString.Append($"# {Remark}, {Type}, {(BypassChina ? 1 : 0)}");
break;
}
fileString += Global.EOF;
if (Rule.Any())
{
fileString.Append(Global.EOF);
fileString.Append(string.Join(Global.EOF, Rule));
}
fileString = Rule.Aggregate(fileString, (current, item) => $"{current}{item}{Global.EOF}");
// 去除最后的行尾符
fileString = fileString.Substring(0, fileString.Length - 2);
return fileString;
return fileString.ToString();
}
public string TypeToString()

View File

@@ -1,4 +1,6 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Netch.Models
{
@@ -43,6 +45,41 @@ namespace Netch.Models
public bool UseFakeDNS = false;
}
public class KcpConfig
{
public int mtu = 1350;
public int tti = 50;
public int uplinkCapacity = 12;
public int downlinkCapacity = 100;
public bool congestion = false;
public int readBufferSize = 2;
public int writeBufferSize = 2;
}
public class V2rayConfig
{
public bool AllowInsecure = true;
public KcpConfig KcpConfig = new KcpConfig();
public bool UseMux = true;
}
public class AioDNSConfig
{
public string RulePath = "bin\\china_site_list";
public string ChinaDNS = "223.5.5.5";
public string OtherDNS = "1.1.1.1";
}
/// <summary>
/// 用于读取和写入的配置的类
/// </summary>
@@ -103,6 +140,11 @@ namespace Netch.Models
/// </summary>
public bool ModifySystemDNS = false;
/// <summary>
/// 要修改为的系统 DNS
/// </summary>
public string ModifiedDNS = "1.1.1.1,8.8.8.8";
/// <summary>
/// 解析服务器主机名
/// </summary>
@@ -207,5 +249,9 @@ namespace Netch.Models
/// 语言设置
/// </summary>
public string Language = "System";
public V2rayConfig V2RayConfig = new V2rayConfig();
public AioDNSConfig AioDNS = new AioDNSConfig();
}
}

View File

@@ -16,13 +16,15 @@ namespace Netch.Servers.Shadowsocks
public string LocalAddress { get; set; }
private Mode _savedMode;
public bool DllFlag => Global.Settings.BootShadowsocksFromDLL && (_savedMode.Type == 0 || _savedMode.Type == 1 || _savedMode.Type == 2);
public bool DllFlag;
public bool Start(in Server s, in Mode mode)
{
_savedMode = mode;
Server = s;
var server = (Shadowsocks) s;
DllFlag = Global.Settings.BootShadowsocksFromDLL && (_savedMode.Type == 0 || _savedMode.Type == 1 || _savedMode.Type == 2);
//从DLL启动Shaowsocks
if (DllFlag)
{
@@ -76,14 +78,13 @@ namespace Netch.Servers.Shadowsocks
public override void Stop()
{
if (Instance == null)
if (DllFlag)
ShadowsocksDLL.Stop();
else
StopInstance();
_savedMode = null;
}
private class ShadowsocksDLL
{
[DllImport("shadowsocks-windows-dynamic", CallingConvention = CallingConvention.Cdecl)]

View File

@@ -31,7 +31,7 @@ namespace Netch.Servers.Trojan
{
local_addr = this.LocalAddress(),
local_port = this.Socks5LocalPort(),
remote_addr = server.AutoResolveHostname(),
remote_addr = server.Hostname,
remote_port = server.Port,
password = new List<string>
{

View File

@@ -1,3 +1,4 @@
using System.Collections.Generic;
using Netch.Forms;
namespace Netch.Servers.VLESS.VLESSForm
@@ -38,6 +39,16 @@ namespace Netch.Servers.VLESS.VLESSForm
s => true,
s => server.Path = s,
server.Path);
CreateComboBox("UseMux", "Use Mux",
new List<string> {"", "true", "false"},
s => server.UseMux = s switch
{
"" => null,
"true" => true,
"false" => false,
_ => null
},
server.UseMux?.ToString() ?? "");
CreateCheckBox("TLSSecure", "TLS Secure",
b => server.TLSSecure = b,
server.TLSSecure);

View File

@@ -1,4 +1,5 @@
using Netch.Forms;
using System.Collections.Generic;
using Netch.Forms;
namespace Netch.Servers.VMess.Form
{
@@ -47,9 +48,16 @@ namespace Netch.Servers.VMess.Form
s => true,
s => server.QUICSecret = s,
server.QUICSecret);
CreateCheckBox("UseMux", "Use Mux",
s => server.UseMux = s,
server.UseMux);
CreateComboBox("UseMux", "Use Mux",
new List<string> {"", "true", "false"},
s => server.UseMux = s switch
{
"" => null,
"true" => true,
"false" => false,
_ => null
},
server.UseMux?.ToString() ?? "");
CreateCheckBox("TLSSecure", "TLS Secure",
s => server.TLSSecure = s,
server.TLSSecure);

View File

@@ -1,8 +1,8 @@
using System.Collections.Generic;
using Netch.Controllers;
using Netch.Models;
using Netch.Servers.VMess.Models;
using Newtonsoft.Json;
using V2rayConfig = Netch.Servers.VMess.Models.V2rayConfig;
namespace Netch.Servers.VMess.Utils
{
@@ -18,7 +18,7 @@ namespace Netch.Servers.VMess.Utils
routing(server, mode, ref v2rayConfig);
outbound(server, ref v2rayConfig);
outbound(server, mode, ref v2rayConfig);
return JsonConvert.SerializeObject(v2rayConfig);
}
@@ -103,7 +103,7 @@ namespace Netch.Servers.VMess.Utils
}
}
private static void outbound(Server server, ref V2rayConfig v2rayConfig)
private static void outbound(Server server, Mode mode, ref V2rayConfig v2rayConfig)
{
try
{
@@ -174,8 +174,8 @@ namespace Netch.Servers.VMess.Utils
usersItem.flow = string.Empty;
usersItem.encryption = vless.EncryptMethod;
outbound.mux.enabled = vless.UseMux;
outbound.mux.concurrency = vless.UseMux ? 8 : -1;
outbound.mux.enabled = vless.UseMux ?? Global.Settings.V2RayConfig.UseMux;
outbound.mux.concurrency = vless.UseMux ?? Global.Settings.V2RayConfig.UseMux ? 8 : -1;
var streamSettings = outbound.streamSettings;
boundStreamSettings(vless, ref streamSettings);
@@ -213,8 +213,8 @@ namespace Netch.Servers.VMess.Utils
usersItem.alterId = vmess.AlterID;
usersItem.security = vmess.EncryptMethod;
outbound.mux.enabled = vmess.UseMux;
outbound.mux.concurrency = vmess.UseMux ? 8 : -1;
outbound.mux.enabled = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux;
outbound.mux.concurrency = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux ? 8 : -1;
var streamSettings = outbound.streamSettings;
boundStreamSettings(vmess, ref streamSettings);
@@ -225,6 +225,14 @@ namespace Netch.Servers.VMess.Utils
}
v2rayConfig.outbounds = new List<Outbounds> {outbound};
if (mode.Type <= 2)
return;
v2rayConfig.outbounds.Add(
new Outbounds
{
tag = "direct",
protocol = "freedom"
});
}
catch
{
@@ -244,7 +252,7 @@ namespace Netch.Servers.VMess.Utils
var tlsSettings = new TlsSettings
{
allowInsecure = true
allowInsecure = Global.Settings.V2RayConfig.AllowInsecure
};
if (!string.IsNullOrWhiteSpace(host))
{
@@ -263,14 +271,13 @@ namespace Netch.Servers.VMess.Utils
case "kcp":
var kcpSettings = new KcpSettings
{
/*TODO KCP Settings
mtu = Global.Settings.KcpSettings.mtu,
tti = Global.Settings.KcpSettings.tti,
uplinkCapacity = Global.Settings.KcpSettings.uplinkCapacity,
downlinkCapacity = Global.Settings.KcpSettings.downlinkCapacity,
congestion = Global.Settings.KcpSettings.congestion,
readBufferSize = Global.Settings.KcpSettings.readBufferSize,
writeBufferSize = Global.Settings.KcpSettings.writeBufferSize,*/
mtu = Global.Settings.V2RayConfig.KcpConfig.mtu,
tti = Global.Settings.V2RayConfig.KcpConfig.tti,
uplinkCapacity = Global.Settings.V2RayConfig.KcpConfig.uplinkCapacity,
downlinkCapacity = Global.Settings.V2RayConfig.KcpConfig.downlinkCapacity,
congestion = Global.Settings.V2RayConfig.KcpConfig.congestion,
readBufferSize = Global.Settings.V2RayConfig.KcpConfig.readBufferSize,
writeBufferSize = Global.Settings.V2RayConfig.KcpConfig.writeBufferSize,
header = new Header
{
type = server.FakeType
@@ -331,7 +338,7 @@ namespace Netch.Servers.VMess.Utils
var xtlsSettings = new TlsSettings
{
allowInsecure = true
allowInsecure = Global.Settings.V2RayConfig.AllowInsecure
};
if (!string.IsNullOrWhiteSpace(host))
{

View File

@@ -69,7 +69,7 @@ namespace Netch.Servers.VMess
/// <summary>
/// Mux 多路复用
/// </summary>
public bool UseMux { get; set; } = true;
public bool? UseMux { get; set; } = true;
}
public class VMessGlobal

View File

@@ -13,7 +13,7 @@ namespace Netch.Servers.VMess
StoppedKeywords.AddRange(new[] {"config file not readable", "failed to"});
}
public override string Name { get; protected set; } = "V2Ray";
public override string Name { get; protected set; } = "VMess";
public override string MainFile { get; protected set; } = "v2ray.exe";
public Server Server { get; set; }
public ushort? Socks5LocalPort { get; set; }

View File

@@ -8,6 +8,7 @@ using Microsoft.Diagnostics.Tracing.Session;
using Netch.Controllers;
using Netch.Models;
using Netch.Servers.Shadowsocks;
using Netch.Servers.Socks5;
namespace Netch.Utils
{
@@ -63,26 +64,28 @@ namespace Netch.Utils
//var processList = Process.GetProcessesByName(ProcessName).Select(p => p.Id).ToHashSet();
var instances = new List<Process>();
if (server.Type.Equals("Socks5") && MainController.ModeController.Name == "HTTP")
switch (MainController.ServerController)
{
instances.Add(((HTTPController) MainController.ModeController).pPrivoxyController.Instance);
}
else if (MainController.ServerController != null)
{
switch (MainController.ServerController)
{
case SSController ssController when ssController.DllFlag:
instances.Add(Process.GetCurrentProcess());
break;
case Guard instanceController:
case null:
break;
case SSController ssController when ssController.DllFlag:
instances.Add(Process.GetCurrentProcess());
break;
case Guard instanceController:
if (instanceController.Instance != null)
instances.Add(instanceController.Instance);
break;
}
break;
}
else if (MainController.ModeController != null)
if (!instances.Any())
{
switch (MainController.ModeController)
{
case null:
break;
case HTTPController httpController:
instances.Add(httpController.pPrivoxyController.Instance);
break;
case NFController _:
instances.Add(Process.GetCurrentProcess());
break;

View File

@@ -0,0 +1,145 @@
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Netch.Utils
{
/// <summary>
/// Allows processes to be automatically killed if this parent process unexpectedly quits.
/// This feature requires Windows 8 or greater. On Windows 7, nothing is done.</summary>
/// <remarks>References:
/// https://stackoverflow.com/a/4657392/386091
/// https://stackoverflow.com/a/9164742/386091 </remarks>
public static class ChildProcessTracker
{
/// <summary>
/// Add the process to be tracked. If our current process is killed, the child processes
/// that we are tracking will be automatically killed, too. If the child process terminates
/// first, that's fine, too.</summary>
/// <param name="process"></param>
public static void AddProcess(Process process)
{
if (s_jobHandle != IntPtr.Zero)
{
var success = AssignProcessToJobObject(s_jobHandle, process.Handle);
if (!success && !process.HasExited)
throw new Win32Exception();
}
}
static ChildProcessTracker()
{
// This feature requires Windows 8 or later. To support Windows 7 requires
// registry settings to be added if you are using Visual Studio plus an
// app.manifest change.
// https://stackoverflow.com/a/4232259/386091
// https://stackoverflow.com/a/9507862/386091
/*if (Environment.OSVersion.Version < new Version(6, 2))
return;*/
// The job name is optional (and can be null) but it helps with diagnostics.
// If it's not null, it has to be unique. Use SysInternals' Handle command-line
// utility: handle -a ChildProcessTracker
var jobName = "ChildProcessTracker" + Process.GetCurrentProcess().Id;
s_jobHandle = CreateJobObject(IntPtr.Zero, jobName);
var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION();
// This is the key flag. When our process is killed, Windows will automatically
// close the job handle, and when that happens, we want the child processes to
// be killed, too.
info.LimitFlags = JOBOBJECTLIMIT.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
{
BasicLimitInformation = info
};
var length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
var extendedInfoPtr = Marshal.AllocHGlobal(length);
try
{
Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);
if (!SetInformationJobObject(s_jobHandle, JobObjectInfoType.ExtendedLimitInformation,
extendedInfoPtr, (uint) length))
{
throw new Win32Exception();
}
}
finally
{
Marshal.FreeHGlobal(extendedInfoPtr);
}
}
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr CreateJobObject(IntPtr lpJobAttributes, string name);
[DllImport("kernel32.dll")]
private static extern bool SetInformationJobObject(IntPtr job, JobObjectInfoType infoType,
IntPtr lpJobObjectInfo, uint cbJobObjectInfoLength);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process);
// Windows will automatically close any open job handles when our process terminates.
// This can be verified by using SysInternals' Handle utility. When the job handle
// is closed, the child processes will be killed.
private static readonly IntPtr s_jobHandle;
}
public enum JobObjectInfoType
{
AssociateCompletionPortInformation = 7,
BasicLimitInformation = 2,
BasicUIRestrictions = 4,
EndOfJobTimeInformation = 6,
ExtendedLimitInformation = 9,
SecurityLimitInformation = 5,
GroupInformation = 11
}
[StructLayout(LayoutKind.Sequential)]
public struct JOBOBJECT_BASIC_LIMIT_INFORMATION
{
public Int64 PerProcessUserTimeLimit;
public Int64 PerJobUserTimeLimit;
public JOBOBJECTLIMIT LimitFlags;
public UIntPtr MinimumWorkingSetSize;
public UIntPtr MaximumWorkingSetSize;
public UInt32 ActiveProcessLimit;
public Int64 Affinity;
public UInt32 PriorityClass;
public UInt32 SchedulingClass;
}
[Flags]
public enum JOBOBJECTLIMIT : uint
{
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x2000
}
[StructLayout(LayoutKind.Sequential)]
public struct IO_COUNTERS
{
public UInt64 ReadOperationCount;
public UInt64 WriteOperationCount;
public UInt64 OtherOperationCount;
public UInt64 ReadTransferCount;
public UInt64 WriteTransferCount;
public UInt64 OtherTransferCount;
}
[StructLayout(LayoutKind.Sequential)]
public struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
{
public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
public IO_COUNTERS IoInfo;
public UIntPtr ProcessMemoryLimit;
public UIntPtr JobMemoryLimit;
public UIntPtr PeakProcessMemoryUsed;
public UIntPtr PeakJobMemoryUsed;
}
}

View File

@@ -1,5 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using Microsoft.Win32;
@@ -75,5 +77,24 @@ namespace Netch.Utils
}
set => AdapterRegistry(true).SetValue("NameServer", value, RegistryValueKind.String);
}
public static IEnumerable<string> Split(string dns)
{
return dns.Split(',').Where(ip => !string.IsNullOrWhiteSpace(ip)).Select(ip => ip.Trim());
}
public static bool TrySplit(string value, out IEnumerable<string> result, ushort maxCount = 0)
{
result = Split(value).ToArray();
return maxCount == 0 || result.Count() <= maxCount
&&
result.All(ip => IPAddress.TryParse(ip, out _));
}
public static string Join(IEnumerable<string> dns)
{
return string.Join(",", dns);
}
}
}

View File

@@ -159,6 +159,9 @@ namespace Netch.Utils
portName = "HTTP";
MainForm.StatusPortInfoText.HttpPort = (ushort) port;
break;
case 4:
modeController = null;
break;
default:
Logging.Error("未知模式类型");
throw new StartFailedException();

View File

@@ -7,10 +7,12 @@ using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using MaxMind.GeoIP2;
using TaskScheduler;
namespace Netch.Utils
{
@@ -96,7 +98,7 @@ namespace Netch.Utils
{
try
{
var sha256 = System.Security.Cryptography.SHA256.Create();
var sha256 = SHA256.Create();
var fileStream = File.OpenRead(filePath);
return sha256.ComputeHash(fileStream).Aggregate(string.Empty, (current, b) => current + b.ToString("x2"));
}
@@ -237,5 +239,62 @@ namespace Netch.Utils
break;
}
}
public static void RegisterNetchStartupItem()
{
var scheduler = new TaskSchedulerClass();
scheduler.Connect();
var folder = scheduler.GetFolder("\\");
var taskIsExists = false;
try
{
folder.GetTask("Netch Startup");
taskIsExists = true;
}
catch
{
// ignored
}
if (Global.Settings.RunAtStartup)
{
if (taskIsExists)
folder.DeleteTask("Netch Startup", 0);
var task = scheduler.NewTask(0);
task.RegistrationInfo.Author = "Netch";
task.RegistrationInfo.Description = "Netch run at startup.";
task.Principal.RunLevel = _TASK_RUNLEVEL.TASK_RUNLEVEL_HIGHEST;
task.Triggers.Create(_TASK_TRIGGER_TYPE2.TASK_TRIGGER_LOGON);
var action = (IExecAction) task.Actions.Create(_TASK_ACTION_TYPE.TASK_ACTION_EXEC);
action.Path = Application.ExecutablePath;
task.Settings.ExecutionTimeLimit = "PT0S";
task.Settings.DisallowStartIfOnBatteries = false;
task.Settings.RunOnlyIfIdle = false;
folder.RegisterTaskDefinition("Netch Startup", task, (int) _TASK_CREATION.TASK_CREATE, null, null,
_TASK_LOGON_TYPE.TASK_LOGON_INTERACTIVE_TOKEN, "");
}
else
{
if (taskIsExists)
folder.DeleteTask("Netch Startup", 0);
}
}
public static void ChangeControlForeColor(Component component, Color color)
{
switch (component)
{
case TextBox _:
case ComboBox _:
if (((Control) component).ForeColor != color) ((Control) component).ForeColor = color;
break;
}
}
}
}

View File

@@ -47,6 +47,22 @@ namespace Netch.Utils
return memoryStream.ToArray();
}
/// <summary>
/// 异步下载并编码为字符串
/// </summary>
/// <param name="req"></param>
/// <param name="rep"></param>
/// <param name="encoding">编码默认UTF-8</param>
/// <returns></returns>
public static string DownloadString(HttpWebRequest req, out HttpWebResponse rep, string encoding = "UTF-8")
{
rep = (HttpWebResponse) req.GetResponse();
using var responseStream = rep.GetResponseStream();
using var streamReader = new StreamReader(responseStream, Encoding.GetEncoding(encoding));
return streamReader.ReadToEnd();
}
/// <summary>
/// 异步下载并编码为字符串
/// </summary>

View File

@@ -75,7 +75,7 @@ namespace System.Windows.Forms
private bool IsOriginalItems => Items.Count == AutoFillTag.Length;
private void ResetCompletionList()
public void ResetCompletionList()
{
Keyword = null;
try

View File

@@ -25,11 +25,10 @@ namespace NetchUpdater
UpdaterFriendlyName = Path.GetFileName(UpdaterFullName);
}
public static void Main(string[] args1)
public static void Main(string[] args)
{
var result = false;
var args = args1.Aggregate((s, s1) => $"{s} {s1}").Split('|').Select(s => s.Trim()).ToArray();
try
{
#region Check Arguments
@@ -87,7 +86,7 @@ namespace NetchUpdater
Process.Start(new ProcessStartInfo
{
FileName = newUpdaterPath,
Arguments = $"{port}|{updatePath}|{targetPath}",
Arguments = $"{port} \"{updatePath}\" \"{targetPath}\"",
WorkingDirectory = tempPath,
UseShellExecute = false
});

View File

@@ -70,3 +70,5 @@ As well, Netch avoid the restricted NAT problem caused by SSTap. You can use an
- [Privoxy](https://www.privoxy.org/)
- [NatTypeTester](https://github.com/HMBSbige/NatTypeTester)
- [NetFilter SDK](https://netfiltersdk.com/)
[![Stargazers over time](https://starchart.cc/NetchX/Netch.svg)](https://starchart.cc/NetchX/Netch)