mirror of
https://github.com/netchx/netch.git
synced 2026-05-11 23:45:06 +08:00
Compare commits
44 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d805a4fccd | ||
|
|
902f78b563 | ||
|
|
159fbdd58d | ||
|
|
0c5464f833 | ||
|
|
b019362f5f | ||
|
|
241371c6f7 | ||
|
|
9b3f5f456f | ||
|
|
c04b8f6ffd | ||
|
|
9d6b6d15d7 | ||
|
|
39081c0a6f | ||
|
|
812fab6322 | ||
|
|
bfadb181c4 | ||
|
|
52ac05ee17 | ||
|
|
c774122fdb | ||
|
|
8e223faa71 | ||
|
|
7b0f0f35cc | ||
|
|
89ce721d4c | ||
|
|
2247a75269 | ||
|
|
c1e9856e92 | ||
|
|
41e74e0794 | ||
|
|
6f8214951a | ||
|
|
0fc5b77004 | ||
|
|
34cbcbfb0f | ||
|
|
1ad4a08a85 | ||
|
|
8e0bc8e260 | ||
|
|
bae9ecfe88 | ||
|
|
3ca3e45ce2 | ||
|
|
bcb220bc4b | ||
|
|
c50eb32828 | ||
|
|
b96f171b47 | ||
|
|
4fbbd1dbd4 | ||
|
|
2ad394dfde | ||
|
|
421b35a797 | ||
|
|
25612df086 | ||
|
|
4ac5065ce4 | ||
|
|
d4b97a99e0 | ||
|
|
3d49fe0338 | ||
|
|
af5100fe73 | ||
|
|
f8bcef7ac9 | ||
|
|
591f8e5a5c | ||
|
|
00047a5030 | ||
|
|
6d4dab573e | ||
|
|
141fc58df4 | ||
|
|
4210f36814 |
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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}")}";
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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}\""
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
1323
Netch/Forms/SettingForm.Designer.cs
generated
1323
Netch/Forms/SettingForm.Designer.cs
generated
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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)]
|
||||
|
||||
@@ -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>
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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;
|
||||
|
||||
145
Netch/Utils/ChildProcessTracker.cs
Normal file
145
Netch/Utils/ChildProcessTracker.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace System.Windows.Forms
|
||||
|
||||
private bool IsOriginalItems => Items.Count == AutoFillTag.Length;
|
||||
|
||||
private void ResetCompletionList()
|
||||
public void ResetCompletionList()
|
||||
{
|
||||
Keyword = null;
|
||||
try
|
||||
|
||||
@@ -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
|
||||
});
|
||||
|
||||
@@ -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/)
|
||||
|
||||
[](https://starchart.cc/NetchX/Netch)
|
||||
|
||||
2
binaries
2
binaries
Submodule binaries updated: f081890f60...d80fcdead2
Reference in New Issue
Block a user