Compare commits

...

66 Commits
1.6.3 ... 1.6.7

Author SHA1 Message Date
AmazingDM
1eebb61d04 bump version to 1.6.7 2020-11-24 17:52:48 +08:00
AmazingDM
a2a66675c2 Update v2ray 4.33.0 2020-11-24 17:50:04 +08:00
ChsBuffer
850393ab71 refactor: TestFakeDNS 2020-11-15 00:38:29 +08:00
ChsBuffer
ea0dd3cd4a fix: Test project 2020-11-14 23:19:21 +08:00
ChsBuffer
c2afc1b014 fix: load config check if Server node is null 2020-11-14 19:52:44 +08:00
Bruce Wayne
7b9d9a6d57 Update CI 2020-11-14 16:51:18 +08:00
Bruce Wayne
860482402a More accurate TCPing 2020-11-14 16:51:13 +08:00
Bruce Wayne
a58f7c7b98 Use Safehandle job api
No handle leak
2020-11-14 16:51:08 +08:00
Bruce Wayne
6afc5e5e4d Update Nuget packages 2020-11-14 16:08:49 +08:00
ChsBuffer
98a5e91dd2 fix: Visual Studio warn solution contains incorrect configurations mappings 2020-11-11 23:27:27 +08:00
ChsBuffer
9581a41007 refactor: SettingForm AutoScaleMode,Disable Maximize SettingForm 2020-11-11 23:24:51 +08:00
ChsBuffer
d85b478868 doc: update bug report issue template 2020-11-10 23:44:08 +08:00
ChsBuffer
628dd6963a refactor: upgrade NetchLib.csproj to new format 2020-11-10 23:26:05 +08:00
ChsBuffer
5ae6f73062 fix: Netch GSF V2Ray TLSSecure 2020-11-05 23:59:39 +08:00
ChsBuffer
50b07ebabb refactor: GenerateClientConfig 2020-11-05 23:12:45 +08:00
ChsBuffer
21f2f8da5e refactor: extract Netch.Utils.Subscription 2020-11-05 16:13:30 +08:00
ChsBuffer
cfc070b1ef fix: clear DNS Cache wont clean system dns cache 2020-11-05 15:41:05 +08:00
ChsBuffer
a4f024df69 refactor: clean temp config file when exit 2020-11-05 15:04:54 +08:00
ChsBuffer
6754268714 feat: setting saving ignore null value 2020-11-05 14:31:45 +08:00
ChsBuffer
642cd57b71 fix: V2ray ServerForm Use Mux value 2020-11-05 14:31:37 +08:00
ChsBuffer
39ea679298 fix: VMess GetShareLink 2020-11-04 21:52:40 +08:00
ChsBuffer
1091486877 feat: #431 2020-11-04 21:50:18 +08:00
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
48 changed files with 1934 additions and 1293 deletions

View File

@@ -2,15 +2,13 @@
name: 'Bug report'
about: 'Create a report to help us improve'
title: ''
labels: 'Status: Review Needed'
labels: '需要核实'
assignees: ''
---
**Make sure you have read the readme, searched and read the issues related to yours. Otherwise it will be considered as a duplicate which will be closed immediately.**
**All issues about `bin/Redirector.exe` should be discussed at [issue #152](https://github.com/NetchX/Netch/issues/152).**
**Describe the bug**
A clear and concise description of what the bug is.

View File

@@ -2,15 +2,13 @@
name: '错误报告'
about: '创建错误报告以帮助我们改进'
title: ''
labels: 'Status: Review Needed'
labels: '需要核实'
assignees: ''
---
**确保你已经看过 readme也搜索并阅读过和你遇到的情况相关的问题。否则会被认为是重复的并被立刻关闭。**
**所有关于 `bin/Redirector.exe` 的问题,请在 [issue #152](https://github.com/NetchX/Netch/issues/152) 中讨论**
**错误描述**
对错误的清晰简洁描述

View File

@@ -14,26 +14,32 @@ jobs:
submodules: true
- name: Build Solution
shell: pwsh
run: .\BUILD.ps1
- name: Upload Artifact
continue-on-error: true
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
uses: actions/upload-artifact@v2
with:
name: Netch
path: Netch\bin\x64\Release
- name: Package
if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') }}
shell: pwsh
run: |
.\BUILD.ps1
New-Item -ItemType Directory -Path C:\builtfiles -Force > $null
7z a -mx9 C:\builtfiles\Netch.7z .\Netch\bin\x64\Release\
7z rn C:\builtfiles\Netch.7z Release Netch
echo "Netch_SHA256=$(.\GetSHA256.ps1 C:\builtfiles\Netch.7z)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
echo "Netch_EXE_SHA256=$(.\GetSHA256.ps1 Netch\bin\x64\Release\Netch.exe)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
- name: Upload Artifact
uses: actions/upload-artifact@v2
with:
name: Netch
path: Netch\bin\x64\Release
- name: Release
uses: softprops/action-gh-release@v1
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
if: startsWith(github.ref, 'refs/tags/')
if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') }}
with:
name: ${{ env.GITHUB_TAG_NAME }}
prerelease: true
@@ -49,23 +55,4 @@ jobs:
## 校验和
| 文件名 | SHA256 |
| :- | :- |
| Netch.7z | ${{ env.Netch_SHA256 }} |
# Deploy:
# needs: [build]
# runs-on: ubuntu-latest
# steps:
# - name: Download Artifacts
# uses: actions/download-artifact@v1
# with:
# name: Netch
# - name: Pushes to another repository
# uses: peaceiris/actions-gh-pages@v3
# with:
# personal_token: ${{ secrets.ACCESS_TOKEN }}
# publish_branch: repo
# publish_dir: ./Netch
# external_repository: ${{ github.repository_owner }}/NetchReleases
# user_name: 'github-actions[bot]'
# user_email: 'github-actions[bot]@users.noreply.github.com'
| Netch.7z | ${{ env.Netch_SHA256 }} |

View File

@@ -5,11 +5,11 @@ VisualStudioVersion = 16.0.29009.5
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Netch", "Netch\Netch.csproj", "{4B041B91-5790-4571-8C58-C63FFE4BC9F8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetchLib", "NetchLib\NetchLib.csproj", "{A8715AF4-ACC6-43F9-9381-4294C5360623}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetchLib", "NetchLib\NetchLib.csproj", "{A8715AF4-ACC6-43F9-9381-4294C5360623}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetchUpdater", "NetchUpdater\NetchUpdater.csproj", "{828318A8-9B90-4A5F-BD6B-E632CC9D8933}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetchUpdater", "NetchUpdater\NetchUpdater.csproj", "{828318A8-9B90-4A5F-BD6B-E632CC9D8933}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{53397641-35CA-4336-8E22-2CE12EF476AC}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "Test\Test.csproj", "{53397641-35CA-4336-8E22-2CE12EF476AC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -29,10 +29,9 @@ Global
{828318A8-9B90-4A5F-BD6B-E632CC9D8933}.Debug|x64.Build.0 = Debug|x64
{828318A8-9B90-4A5F-BD6B-E632CC9D8933}.Release|x64.ActiveCfg = Release|x64
{828318A8-9B90-4A5F-BD6B-E632CC9D8933}.Release|x64.Build.0 = Release|x64
{53397641-35CA-4336-8E22-2CE12EF476AC}.Debug|x64.ActiveCfg = Debug|Any CPU
{53397641-35CA-4336-8E22-2CE12EF476AC}.Debug|x64.Build.0 = Debug|Any CPU
{53397641-35CA-4336-8E22-2CE12EF476AC}.Release|x64.ActiveCfg = Release|Any CPU
{53397641-35CA-4336-8E22-2CE12EF476AC}.Release|x64.Build.0 = Release|Any CPU
{53397641-35CA-4336-8E22-2CE12EF476AC}.Debug|x64.ActiveCfg = Debug|x64
{53397641-35CA-4336-8E22-2CE12EF476AC}.Debug|x64.Build.0 = Debug|x64
{53397641-35CA-4336-8E22-2CE12EF476AC}.Release|x64.ActiveCfg = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

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

@@ -1,4 +1,4 @@
using System;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Windows.Forms;
@@ -31,7 +31,10 @@ namespace Netch.Controllers
try
{
pPrivoxyController.Start(MainController.ServerController.Server, mode);
if (pPrivoxyController.Start(MainController.ServerController.Server, mode))
{
Global.Job.AddProcess(pPrivoxyController.Instance);
}
if (mode.Type == 3) NativeMethods.SetGlobal($"127.0.0.1:{Global.Settings.HTTPLocalPort}", IEProxyExceptions);
}

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.IO;
using System.Net;
using System.Threading.Tasks;
@@ -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)
{
Global.Job.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)
{
Global.Job.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
{
@@ -226,33 +228,11 @@ namespace Netch.Controllers
public bool TestFakeDNS()
{
var exited = false;
var helpStr = new StringBuilder();
try
{
void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
{
if (e.Data == null)
{
exited = true;
return;
}
helpStr.Append(e.Data);
}
InitInstance("-h");
// Instance.OutputDataReceived += OnOutputDataReceived;
Instance.ErrorDataReceived += OnOutputDataReceived;
Instance.Start();
Instance.BeginOutputReadLine();
Instance.BeginErrorReadLine();
while (!exited)
{
Thread.Sleep(200);
}
return helpStr.ToString().Contains("-fakeDns");
return Instance.StandardError.ReadToEnd().Contains("-fakeDns");
}
catch
{

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.7";
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();
@@ -98,9 +100,7 @@ namespace Netch.Forms
}
private readonly object _serverLock = new object();
public async Task UpdateServersFromSubscribe()
private async Task UpdateServersFromSubscribe()
{
void DisableItems(bool v)
{
@@ -124,9 +124,11 @@ namespace Netch.Forms
StatusText(i18N.Translate("Starting update subscription"));
DisableItems(false);
var useProxyToUpdateSubscription = Global.Settings.UseProxyToUpdateSubscription;
try
{
if (Global.Settings.UseProxyToUpdateSubscription)
string proxyServer = null;
if (useProxyToUpdateSubscription)
{
var mode = new Models.Mode
{
@@ -134,40 +136,10 @@ namespace Netch.Forms
Type = 5
};
await MainController.Start(ServerComboBox.SelectedItem as Server, mode);
proxyServer = $"http://127.0.0.1:{Global.Settings.HTTPLocalPort}";
}
await Task.WhenAll(Global.Settings.SubscribeLink.Select(async item => await Task.Run(async () =>
{
try
{
var request = WebUtil.CreateRequest(item.Link);
if (!string.IsNullOrEmpty(item.UserAgent)) request.UserAgent = item.UserAgent;
if (Global.Settings.UseProxyToUpdateSubscription)
request.Proxy = new WebProxy($"http://127.0.0.1:{Global.Settings.HTTPLocalPort}");
var servers = ShareLink.ParseText(await WebUtil.DownloadStringAsync(request));
foreach (var server in servers)
{
server.Group = item.Remark;
}
lock (_serverLock)
{
Global.Settings.Server.RemoveAll(server => server.Group.Equals(item.Remark));
Global.Settings.Server.AddRange(servers);
}
NotifyTip(i18N.TranslateFormat("Update {1} server(s) from {0}", item.Remark, servers.Count));
}
catch (Exception e)
{
NotifyTip($"{i18N.TranslateFormat("Update servers error from {0}", item.Remark)}\n{e.Message}", info: false);
Logging.Error(e.ToString());
}
})).ToArray());
await Subscription.UpdateServersAsync(proxyServer);
InitServer();
Configuration.Save();
@@ -179,9 +151,16 @@ namespace Netch.Forms
}
finally
{
if (Global.Settings.UseProxyToUpdateSubscription)
if (useProxyToUpdateSubscription)
{
await MainController.Stop();
try
{
await MainController.Stop();
}
catch
{
// ignored
}
}
DisableItems(true);
@@ -223,7 +202,12 @@ namespace Netch.Forms
{
try
{
await Task.Run(() => DNS.Cache.Clear());
await Task.Run(() =>
{
NativeMethods.FlushDNSResolverCache();
DNS.Cache.Clear();
});
StatusText(i18N.Translate("DNS cache cleanup succeeded"));
}
catch (Exception)
@@ -244,19 +228,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 +270,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 +309,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

@@ -283,8 +283,11 @@ namespace Netch.Forms
Configuration.Save();
if (File.Exists("data\\last.json"))
File.Delete("data\\last.json");
foreach (var file in new[] {"data\\last.json", "data\\privoxy.conf"})
{
if (File.Exists(file))
File.Delete(file);
}
State = State.Terminating;
}
@@ -334,7 +337,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 +345,7 @@ namespace Netch.Forms
}
finally
{
State = State.Stopped;
Enabled = true;
StatusText(i18N.Translate("Test done"));
Refresh();
}
@@ -469,7 +472,7 @@ namespace Netch.Forms
Activate();
}
private void NotifyTip(string text, int timeout = 0, bool info = true)
public void NotifyTip(string text, int timeout = 0, bool info = true)
{
// 会阻塞线程 timeout 秒
NotifyIcon.ShowBalloonTip(timeout,

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

@@ -1,64 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
@@ -117,8 +57,8 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<assembly alias="System.Drawing.Common" name="System.Drawing.Common, Version=5.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing.Common" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAMAAAAAAAEAIAAoIAQANgAAAEBAAAABACAAKEIAAF4gBAAgIAAAAQAgAKgQAACGYgQAKAAAAAAB
AAAAAgAAAQAgAAAAAAAAIAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

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

@@ -1,14 +1,14 @@
using System;
using Netch.Controllers;
using Netch.Forms;
using Netch.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Threading.Tasks;
using System.Windows.Forms;
using Netch.Controllers;
using Netch.Forms;
using Netch.Models;
using WindowsJobAPI;
namespace Netch
{
@@ -87,5 +87,10 @@ namespace Netch
/// 用于存储模式
/// </summary>
public static readonly List<Mode> Modes = new List<Mode>();
/// <summary>
/// Windows Job API
/// </summary>
public static readonly JobObject Job = new JobObject();
}
}

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

@@ -4,7 +4,7 @@ using Netch.Utils;
namespace Netch.Models
{
public class Server
public class Server:ICloneable
{
/// <summary>
/// 备注
@@ -57,6 +57,11 @@ namespace Netch.Models
return $"[{ServerHelper.GetUtilByTypeName(Type)?.ShortName ?? "WTF"}][{Group}] {Remark}";
}
public object Clone()
{
return MemberwiseClone();
}
/// <summary>
/// 测试延迟
/// </summary>

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

@@ -67,11 +67,12 @@
<ItemGroup>
<PackageReference Include="ILMerge" Version="3.0.41" />
<PackageReference Include="MaxMind.GeoIP2" Version="3.3.0" />
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="2.0.61" />
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="2.0.62" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="System.Collections.Immutable" Version="5.0.0-rc.2.20475.5" />
<PackageReference Include="System.Reflection.Metadata" Version="5.0.0-rc.2.20475.5" />
<PackageReference Include="System.Collections.Immutable" Version="5.0.0" />
<PackageReference Include="System.Reflection.Metadata" Version="5.0.0" />
<PackageReference Include="WindowsAPICodePack-Shell" Version="1.1.1" />
<PackageReference Include="WindowsJobAPI" Version="5.0.0" />
</ItemGroup>
<ItemGroup>

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

@@ -34,7 +34,6 @@ namespace Netch.Servers.VLESS
public class VLESSGlobal
{
public static List<string> TransferProtocols => VMessGlobal.TransferProtocols;
public static readonly List<string> FakeTypes = new List<string>
@@ -42,5 +41,12 @@ namespace Netch.Servers.VLESS
"none",
"http"
};
public static readonly List<string> TLSSecure = new List<string>
{
"",
"tls",
"xtls"
};
}
}

View File

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

View File

@@ -15,7 +15,24 @@ namespace Netch.Servers.VLESS
public Server ParseJObject(in JObject j)
{
return j.ToObject<VLESS>();
var server = j.ToObject<VLESS>();
if (server == null)
return null;
if (server.TLSSecure != null)
{
if ((bool) server.TLSSecure)
{
server.TLSSecureType = "tls";
server.TLSSecure = null;
}
else
{
server.TLSSecure = null;
}
}
return server;
}
public void Edit(Server s)

View File

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

View File

@@ -1,8 +1,9 @@
using System.Collections.Generic;
using Netch.Controllers;
using System.Linq;
using Netch.Models;
using Netch.Servers.VMess.Models;
using Newtonsoft.Json;
using V2rayConfig = Netch.Servers.VMess.Models.V2rayConfig;
namespace Netch.Servers.VMess.Utils
{
@@ -18,9 +19,9 @@ namespace Netch.Servers.VMess.Utils
routing(server, mode, ref v2rayConfig);
outbound(server, ref v2rayConfig);
outbound(server, mode, ref v2rayConfig);
return JsonConvert.SerializeObject(v2rayConfig);
return JsonConvert.SerializeObject(v2rayConfig, Formatting.Indented, new JsonSerializerSettings {NullValueHandling = NullValueHandling.Ignore});
}
catch
{
@@ -58,44 +59,68 @@ namespace Netch.Servers.VMess.Utils
{
try
{
RulesItem rulesItem;
var directRuleObject = new RulesItem
{
type = "field",
ip = new List<string>(),
domain = new List<string>(),
outboundTag = "direct"
};
var blockRuleObject = new RulesItem
{
type = "field",
ip = new List<string>(),
domain = new List<string>(),
outboundTag = "block"
};
if (mode.BypassChina)
{
rulesItem = new RulesItem
if (mode.Type > 2)
{
type = "field",
ip = new List<string>
{
"geoip:cn",
"geoip:private"
},
domain = new List<string>
{
"geosite:cn"
},
outboundTag = "direct"
};
directRuleObject.domain.Add("geosite:cn");
}
if (mode.Type == 1 || mode.Type == 2)
{
if (Global.Flags.SupportFakeDns && Global.Settings.TUNTAP.UseFakeDNS)
directRuleObject.domain.Add("geosite:cn");
else
directRuleObject.ip.Add("geoip:cn");
}
}
else
if (mode.Type <= 2)
{
rulesItem = new RulesItem
{
type = "field",
ip = new List<string>
{
"geoip:private"
},
outboundTag = "direct"
};
blockRuleObject.ip.Add("geoip:private");
}
v2rayConfig.routing = new Routing
{
rules = new List<RulesItem>
{
rulesItem
}
rules = new List<RulesItem>()
};
static bool CheckRuleItem(ref RulesItem rulesItem)
{
bool ipResult, domainResult;
if (!(ipResult = rulesItem.ip.Any()))
{
rulesItem.ip = null;
}
if (!(domainResult = rulesItem.domain.Any()))
{
rulesItem.domain = null;
}
return ipResult || domainResult;
}
if (CheckRuleItem(ref directRuleObject))
v2rayConfig.routing.rules.Add(directRuleObject);
if (CheckRuleItem(ref blockRuleObject))
v2rayConfig.routing.rules.Add(blockRuleObject);
}
catch
{
@@ -103,7 +128,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
{
@@ -121,31 +146,25 @@ namespace Netch.Servers.VMess.Utils
{
case Socks5.Socks5 socks5:
{
var serversItem = new ServersItem
{
users = new List<SocksUsersItem>()
};
outbound.settings.servers = new List<ServersItem>
{
serversItem
};
serversItem.address = server.AutoResolveHostname();
serversItem.port = server.Port;
serversItem.method = null;
serversItem.password = null;
if (socks5.Auth())
{
var socksUsersItem = new SocksUsersItem
new ServersItem
{
user = socks5.Username,
pass = socks5.Password,
level = 1
};
serversItem.users.Add(socksUsersItem);
}
users = socks5.Auth()
? new List<SocksUsersItem>
{
new SocksUsersItem
{
user = socks5.Username,
pass = socks5.Password,
level = 1
}
}
: null,
address = server.AutoResolveHostname(),
port = server.Port
}
};
outbound.mux.enabled = false;
outbound.mux.concurrency = -1;
@@ -156,37 +175,36 @@ namespace Netch.Servers.VMess.Utils
{
var vnextItem = new VnextItem
{
users = new List<UsersItem>()
users = new List<UsersItem>(),
address = server.AutoResolveHostname(),
port = server.Port
};
outbound.settings.vnext = new List<VnextItem>
outbound.settings.vnext = new List<VnextItem> {vnextItem};
var usersItem = new UsersItem
{
vnextItem
id = vless.UserID,
alterId = 0,
flow = string.Empty,
encryption = vless.EncryptMethod
};
vnextItem.address = server.AutoResolveHostname();
vnextItem.port = server.Port;
var usersItem = new UsersItem();
vnextItem.users.Add(usersItem);
usersItem.id = vless.UserID;
usersItem.alterId = 0;
usersItem.flow = string.Empty;
usersItem.encryption = vless.EncryptMethod;
outbound.mux.enabled = vless.UseMux;
outbound.mux.concurrency = vless.UseMux ? 8 : -1;
var streamSettings = outbound.streamSettings;
boundStreamSettings(vless, ref streamSettings);
if (vless.TransferProtocol == "xtls")
if (vless.TLSSecureType == "xtls")
{
usersItem.flow = string.IsNullOrEmpty(vless.Flow) ? "xtls-rprx-origin" : vless.Flow;
outbound.mux.enabled = false;
outbound.mux.concurrency = -1;
}
else
{
outbound.mux.enabled = vless.UseMux ?? Global.Settings.V2RayConfig.UseMux;
outbound.mux.concurrency = vless.UseMux ?? Global.Settings.V2RayConfig.UseMux ? 8 : -1;
}
outbound.protocol = "vless";
outbound.settings.servers = null;
@@ -196,35 +214,42 @@ namespace Netch.Servers.VMess.Utils
{
var vnextItem = new VnextItem
{
users = new List<UsersItem>()
users = new List<UsersItem>(),
address = server.AutoResolveHostname(),
port = server.Port
};
outbound.settings.vnext = new List<VnextItem>
outbound.settings.vnext = new List<VnextItem> {vnextItem};
var usersItem = new UsersItem
{
vnextItem
id = vmess.UserID,
alterId = vmess.AlterID,
security = vmess.EncryptMethod
};
vnextItem.address = server.AutoResolveHostname();
vnextItem.port = server.Port;
var usersItem = new UsersItem();
vnextItem.users.Add(usersItem);
usersItem.id = vmess.UserID;
usersItem.alterId = vmess.AlterID;
usersItem.security = vmess.EncryptMethod;
outbound.mux.enabled = vmess.UseMux;
outbound.mux.concurrency = vmess.UseMux ? 8 : -1;
var streamSettings = outbound.streamSettings;
boundStreamSettings(vmess, ref streamSettings);
outbound.mux.enabled = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux;
outbound.mux.concurrency = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux ? 8 : -1;
outbound.protocol = "vmess";
break;
}
}
v2rayConfig.outbounds = new List<Outbounds> {outbound};
v2rayConfig.outbounds = new List<Outbounds>
{
outbound,
new Outbounds
{
tag = "direct", protocol = "freedom"
},
new Outbounds
{
tag = "block", protocol = "blackhole"
}
};
}
catch
{
@@ -237,25 +262,24 @@ namespace Netch.Servers.VMess.Utils
try
{
streamSettings.network = server.TransferProtocol;
var host = server.Host;
if (server.TLSSecure)
{
streamSettings.security = "tls";
if ((streamSettings.security = server.TLSSecureType) != "")
{
var tlsSettings = new TlsSettings
{
allowInsecure = true
allowInsecure = Global.Settings.V2RayConfig.AllowInsecure,
serverName = !string.IsNullOrWhiteSpace(server.Host) ? server.Host : null
};
if (!string.IsNullOrWhiteSpace(host))
{
tlsSettings.serverName = host;
}
streamSettings.tlsSettings = tlsSettings;
}
else
{
streamSettings.security = "";
switch (server.TLSSecureType)
{
case "tls":
streamSettings.tlsSettings = tlsSettings;
break;
case "xtls":
streamSettings.xtlsSettings = tlsSettings;
break;
}
}
switch (server.TransferProtocol)
@@ -263,14 +287,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
@@ -278,21 +301,16 @@ namespace Netch.Servers.VMess.Utils
seed = !string.IsNullOrWhiteSpace(server.Path) ? server.Path : null
};
streamSettings.kcpSettings = kcpSettings;
break;
case "ws":
var path = server.Path;
var wsSettings = new WsSettings
{
connectionReuse = true,
headers = !string.IsNullOrWhiteSpace(host)
? new Headers
{
Host = host
}
headers = !string.IsNullOrWhiteSpace(server.Host)
? new Headers {Host = server.Host}
: null,
path = !string.IsNullOrWhiteSpace(path) ? path : null
path = !string.IsNullOrWhiteSpace(server.Path) ? server.Path : null
};
streamSettings.wsSettings = wsSettings;
@@ -312,34 +330,22 @@ namespace Netch.Servers.VMess.Utils
case "quic":
var quicSettings = new QuicSettings
{
security = host,
security = server.Host,
key = server.Path,
header = new Header
{
type = server.FakeType
}
};
if (server.TLSSecure)
if (server.TLSSecureType != "")
{
// tls or xtls
streamSettings.tlsSettings.serverName = server.Hostname;
}
streamSettings.quicSettings = quicSettings;
break;
case "xtls":
streamSettings.security = server.TransferProtocol;
var xtlsSettings = new TlsSettings
{
allowInsecure = true
};
if (!string.IsNullOrWhiteSpace(host))
{
xtlsSettings.serverName = host;
}
streamSettings.xtlsSettings = xtlsSettings;
break;
default:
if (server.FakeType == "http")
{

View File

@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using Netch.Models;
@@ -64,12 +65,18 @@ namespace Netch.Servers.VMess
/// <summary>
/// TLS 底层传输安全
/// </summary>
public bool TLSSecure { get; set; } = false;
[Obsolete]
public bool? TLSSecure { get; set; }
/// <summary>
/// TLS 底层传输安全
/// </summary>
public string TLSSecureType { get; set; } = VMessGlobal.TLSSecure[0];
/// <summary>
/// Mux 多路复用
/// </summary>
public bool UseMux { get; set; } = true;
public bool? UseMux { get; set; } = true;
}
public class VMessGlobal
@@ -114,5 +121,14 @@ namespace Netch.Servers.VMess
"dtls",
"wireguard"
};
/// <summary>
/// TLS 安全类型
/// </summary>
public static readonly List<string> TLSSecure = new List<string>
{
"",
"tls"
};
}
}

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

@@ -20,7 +20,24 @@ namespace Netch.Servers.VMess
public Server ParseJObject(in JObject j)
{
return j.ToObject<VMess>();
var server = j.ToObject<VMess>();
if (server == null)
return null;
if (server.TLSSecure != null)
{
if ((bool) server.TLSSecure)
{
server.TLSSecureType = "tls";
server.TLSSecure = null;
}
else
{
server.TLSSecure = null;
}
}
return server;
}
public void Edit(Server s)
@@ -49,7 +66,7 @@ namespace Netch.Servers.VMess
type = server.FakeType,
host = server.Host,
path = server.Path,
tls = server.TLSSecure ? "tls" : ""
tls = server.TLSSecureType
});
return "vmess://" + ShareLink.URLSafeBase64Encode(vmessJson);
}
@@ -97,7 +114,7 @@ namespace Netch.Servers.VMess
data.Path = vmess.path;
}
data.TLSSecure = vmess.tls == "tls";
data.TLSSecureType = vmess.tls;
data.EncryptMethod = "auto"; // V2Ray 加密方式不包括在链接中,主动添加一个
return CheckServer(data) ? new[] {data} : null;

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

@@ -30,14 +30,14 @@ namespace Netch.Utils
Global.Settings = settingJObject?.ToObject<Setting>() ?? new Setting();
Global.Settings.Server.Clear();
foreach (JObject server in settingJObject["Server"])
{
var serverResult = ServerHelper.ParseJObject(server);
if (serverResult != null)
Global.Settings.Server.Add(serverResult);
}
if (settingJObject?["Server"] != null)
foreach (JObject server in settingJObject["Server"])
{
var serverResult = ServerHelper.ParseJObject(server);
if (serverResult != null)
Global.Settings.Server.Add(serverResult);
}
}
catch (JsonException)
{
}
@@ -62,7 +62,15 @@ namespace Netch.Utils
Directory.CreateDirectory(DATA_DIR);
}
File.WriteAllText(SETTINGS_JSON, JsonConvert.SerializeObject(Global.Settings, Formatting.Indented));
File.WriteAllText(SETTINGS_JSON,
JsonConvert.SerializeObject(
Global.Settings,
Formatting.Indented,
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
}
));
}
}
}

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

@@ -5,6 +5,7 @@ using System.Linq;
using System.Text;
using Netch.Servers.Shadowsocks;
using Netch.Servers.Shadowsocks.Models;
using Netch.Servers.VMess;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Server = Netch.Models.Server;
@@ -233,7 +234,14 @@ namespace Netch.Utils
public static string GetNetchLink(Server s)
{
return "Netch://" + URLSafeBase64Encode(JsonConvert.SerializeObject(s));
var server = (Server) s.Clone();
if (server is VMess vmess)
{
vmess.TLSSecure = !string.IsNullOrEmpty(vmess.TLSSecureType);
vmess.TLSSecureType = null;
}
return "Netch://" + URLSafeBase64Encode(JsonConvert.SerializeObject(server, new JsonSerializerSettings {NullValueHandling = NullValueHandling.Ignore}));
}
}
}

View File

@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Netch.Models;
namespace Netch.Utils
{
public static class Subscription
{
private static readonly object ServerLock = new object();
public static async Task UpdateServersAsync(string proxyServer = default)
{
await Task.WhenAll(
Global.Settings.SubscribeLink.Select(item =>
Task.Run(() => UpdateServer(item, proxyServer))
).ToArray()
);
}
public static void UpdateServer(SubscribeLink item, string proxyServer)
{
try
{
var request = WebUtil.CreateRequest(item.Link);
if (!string.IsNullOrEmpty(item.UserAgent)) request.UserAgent = item.UserAgent;
if (!string.IsNullOrEmpty(proxyServer)) request.Proxy = new WebProxy(proxyServer);
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) server.Group = item.Remark;
lock (ServerLock)
{
Global.Settings.Server.RemoveAll(server => server.Group.Equals(item.Remark));
Global.Settings.Server.AddRange(servers);
}
Global.MainForm.NotifyTip(i18N.TranslateFormat("Update {1} server(s) from {0}", item.Remark, servers.Count));
}
catch (Exception e)
{
Global.MainForm.NotifyTip($"{i18N.TranslateFormat("Update servers error from {0}", item.Remark)}\n{e.Message}", info: false);
Logging.Error(e.ToString());
}
}
}
}

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
@@ -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
{
@@ -37,12 +39,12 @@ namespace Netch.Utils
public static async Task<int> TCPingAsync(IPAddress ip, int port, int timeout = 1000, CancellationToken ct = default)
{
using var client = new TcpClient(ip.AddressFamily);
var stopwatch = Stopwatch.StartNew();
var task = client.ConnectAsync(ip, port);
var stopwatch = new Stopwatch();
stopwatch.Start();
var resTask = await Task.WhenAny(Task.Delay(timeout, ct), task);
var resTask = await Task.WhenAny(task, Task.Delay(timeout, ct));
stopwatch.Stop();
if (resTask == task && client.Connected)
@@ -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

@@ -1,67 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Platforms>x86;x64</Platforms>
<ProjectGuid>{A8715AF4-ACC6-43F9-9381-4294C5360623}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>NetchLib</RootNamespace>
<AssemblyName>NetchLib</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningsAsErrors />
<NoWarn />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'">
<DefineConstants>DEBUG;TRACE</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<NoWarn />
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningsAsErrors />
<OutputPath>bin\x86\Debug\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<NoWarn />
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningsAsErrors />
<OutputPath>bin\x86\Release\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<NoWarn />
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningsAsErrors />
<OutputPath>bin\x64\Release\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SearchComboBox.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<TargetFramework>net48</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<Platforms>x64</Platforms>
<UseWindowsForms>true</UseWindowsForms>
<LangVersion>latest</LangVersion>
</PropertyGroup>
</Project>

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)