mirror of
https://github.com/netchx/netch.git
synced 2026-05-11 23:45:06 +08:00
Compare commits
75 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af5100fe73 | ||
|
|
f8bcef7ac9 | ||
|
|
591f8e5a5c | ||
|
|
00047a5030 | ||
|
|
6d4dab573e | ||
|
|
141fc58df4 | ||
|
|
4210f36814 | ||
|
|
98adb01760 | ||
|
|
a2ae28d3ae | ||
|
|
30854deba6 | ||
|
|
ef8013c073 | ||
|
|
abfae4a9a0 | ||
|
|
4731e27d2e | ||
|
|
a993df7f2f | ||
|
|
3c6c2bde31 | ||
|
|
f8299fb7be | ||
|
|
b54bc6fa40 | ||
|
|
b2ac98b21f | ||
|
|
86a86a94d8 | ||
|
|
7bbffb002f | ||
|
|
1b6fe29085 | ||
|
|
918e260f3e | ||
|
|
508e77759c | ||
|
|
a21d7ff6fd | ||
|
|
b4050f2fa4 | ||
|
|
1b1a9fc05d | ||
|
|
985330f564 | ||
|
|
eb6b87e4aa | ||
|
|
5af2749760 | ||
|
|
be4a18d599 | ||
|
|
5d0bcbd6b0 | ||
|
|
ab6a2ecc30 | ||
|
|
ceb57dcc1a | ||
|
|
79b6e5da43 | ||
|
|
2d95d8b257 | ||
|
|
50eb07badf | ||
|
|
3f902a2d3d | ||
|
|
72b094e641 | ||
|
|
c7fb7e3959 | ||
|
|
9e249bc211 | ||
|
|
2332c9ec50 | ||
|
|
202fdfe5a0 | ||
|
|
18b905ed0c | ||
|
|
3f1b21c4e5 | ||
|
|
477c6e3fc1 | ||
|
|
5e58708895 | ||
|
|
c3eb07005e | ||
|
|
12b2989755 | ||
|
|
0222792361 | ||
|
|
3e5e3a7275 | ||
|
|
a49e280e03 | ||
|
|
45b6352553 | ||
|
|
406fbd8b7e | ||
|
|
454b03a69f | ||
|
|
98ab8864eb | ||
|
|
f3358f3da2 | ||
|
|
fa1593de49 | ||
|
|
f26d09bf9f | ||
|
|
35859a19f7 | ||
|
|
e3e595d469 | ||
|
|
36718e774c | ||
|
|
bf6d3aae95 | ||
|
|
477509b12f | ||
|
|
910f6818b0 | ||
|
|
ed3f4d1763 | ||
|
|
be53432a2e | ||
|
|
9d78de0f6c | ||
|
|
75bf753a65 | ||
|
|
3efbad5e5e | ||
|
|
020c2d7e67 | ||
|
|
adcc6a75c9 | ||
|
|
7e907eef6f | ||
|
|
d213872bde | ||
|
|
71687c1da6 | ||
|
|
2eb6b23ca7 |
26
.github/workflows/build.yml
vendored
26
.github/workflows/build.yml
vendored
@@ -5,43 +5,29 @@ jobs:
|
||||
name: Build
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Setup NuGet
|
||||
uses: nuget/setup-nuget@v1
|
||||
|
||||
- name: Setup MSBuild
|
||||
uses: microsoft/setup-msbuild@v1.0.1
|
||||
uses: microsoft/setup-msbuild@v1.0.2
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Restore NuGet Packages Cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.nuget/packages
|
||||
key: ${{ runner.os }}-nuget-${{ hashFiles('Netch/Netch.csproj') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-nuget-
|
||||
|
||||
- name: Restore NuGet Package
|
||||
run: nuget restore Netch.sln
|
||||
|
||||
- name: Build Solution
|
||||
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\win-x64\
|
||||
7z rn C:\builtfiles\Netch.7z win-x64 Netch
|
||||
echo "::set-env name=Netch_SHA256::$(.\GetSHA256.ps1 C:\builtfiles\Netch.7z)"
|
||||
echo "::set-env name=Netch_EXE_SHA256::$(.\GetSHA256.ps1 Netch\bin\x64\Release\win-x64\Netch.exe)"
|
||||
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\win-x64
|
||||
path: Netch\bin\x64\Release
|
||||
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
|
||||
39
BUILD.ps1
39
BUILD.ps1
@@ -1,33 +1,12 @@
|
||||
param([string]$buildtfm = 'all')
|
||||
Write-Host 'Building'
|
||||
|
||||
Write-Host 'DotNet SDK Version'
|
||||
dotnet --version
|
||||
msbuild -v:n -m:1 /p:Configuration="Release" `
|
||||
/p:Platform="x64" `
|
||||
/p:TargetFramework=net48 `
|
||||
/p:SolutionDir="..\" `
|
||||
/restore `
|
||||
Netch\Netch.csproj
|
||||
|
||||
$exe = 'Netch.exe'
|
||||
$mainDir = (Get-Item -Path ".\").FullName
|
||||
$net_baseoutput = "$mainDir\Netch\bin\$configuration"
|
||||
if ($LASTEXITCODE) { exit $LASTEXITCODE }
|
||||
|
||||
Write-Host $mainDir
|
||||
Write-Host $net_baseoutput
|
||||
|
||||
function Build-NetFrameworkx64
|
||||
{
|
||||
Write-Host 'Building .NET Framework x64'
|
||||
|
||||
$outdir = "$net_baseoutput\x64"
|
||||
|
||||
msbuild -v:n -m:1 /p:Configuration="Release" `
|
||||
/p:Platform="x64" `
|
||||
/p:TargetFramework=net48 `
|
||||
/p:Runtimeidentifier=win-x64 `
|
||||
/restore
|
||||
if ($LASTEXITCODE) { cd $mainDir ; exit $LASTEXITCODE }
|
||||
|
||||
Write-Host 'Build done'
|
||||
}
|
||||
|
||||
cd $mainDir
|
||||
Build-NetFrameworkx64
|
||||
cd $mainDir
|
||||
|
||||
exit 0
|
||||
Write-Host 'Build done'
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
param([string]$file)
|
||||
$hash = [Security.Cryptography.HashAlgorithm]::Create( "SHA256" )
|
||||
$stream = ([IO.StreamReader]$file).BaseStream
|
||||
-join ($hash.ComputeHash($stream) | ForEach { "{0:x2}" -f $_ })
|
||||
$stream.Close()
|
||||
$path = (Resolve-Path -Path $file).Path
|
||||
$stream = ([IO.StreamReader]$path).BaseStream
|
||||
-join ($hash.ComputeHash($stream) | ForEach-Object { "{0:x2}" -f $_ })
|
||||
$stream.Close()
|
||||
@@ -11,8 +11,6 @@ namespace Netch.Controllers
|
||||
{
|
||||
public class HTTPController : IModeController
|
||||
{
|
||||
public bool TestNatRequired { get; } = false;
|
||||
|
||||
public const string IEProxyExceptions = "localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*";
|
||||
|
||||
public PrivoxyController pPrivoxyController = new PrivoxyController();
|
||||
@@ -25,26 +23,15 @@ namespace Netch.Controllers
|
||||
/// <summary>
|
||||
/// 启动
|
||||
/// </summary>
|
||||
/// <param name="s">服务器</param>
|
||||
/// <param name="mode">模式</param>
|
||||
/// <returns>是否启动成功</returns>
|
||||
public bool Start(Server s, Mode mode)
|
||||
public bool Start(in Mode mode)
|
||||
{
|
||||
RecordPrevious();
|
||||
|
||||
try
|
||||
{
|
||||
if (s.IsSocks5())
|
||||
{
|
||||
var server = (Socks5) s;
|
||||
if (!string.IsNullOrWhiteSpace(server.Username) && !string.IsNullOrWhiteSpace(server.Password)) return false;
|
||||
|
||||
pPrivoxyController.Start(s, mode);
|
||||
}
|
||||
else
|
||||
{
|
||||
pPrivoxyController.Start(s, mode);
|
||||
}
|
||||
pPrivoxyController.Start(MainController.ServerController.Server, mode);
|
||||
|
||||
if (mode.Type == 3) NativeMethods.SetGlobal($"127.0.0.1:{Global.Settings.HTTPLocalPort}", IEProxyExceptions);
|
||||
}
|
||||
|
||||
@@ -7,11 +7,8 @@ namespace Netch.Controllers
|
||||
/// <summary>
|
||||
/// 启动
|
||||
/// </summary>
|
||||
/// <param name="s">服务器</param>
|
||||
/// <param name="mode">模式</param>
|
||||
/// <returns>是否成功</returns>
|
||||
public abstract bool Start(Server s, Mode mode);
|
||||
|
||||
public abstract bool TestNatRequired { get; }
|
||||
public abstract bool Start(in Mode mode);
|
||||
}
|
||||
}
|
||||
@@ -4,16 +4,31 @@ namespace Netch.Controllers
|
||||
{
|
||||
public interface IServerController : IController
|
||||
{
|
||||
public int? Socks5LocalPort { get; set; }
|
||||
public Server Server { get; set; }
|
||||
|
||||
public ushort? Socks5LocalPort { get; set; }
|
||||
|
||||
public string LocalAddress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 启动
|
||||
/// </summary>
|
||||
/// <param name="server">服务器</param>
|
||||
/// <param name="s">服务器</param>
|
||||
/// <param name="mode">模式</param>
|
||||
/// <returns>是否启动成功</returns>
|
||||
public abstract bool Start(Server server, Mode mode);
|
||||
public abstract bool Start(in Server s, in Mode mode);
|
||||
}
|
||||
|
||||
public static class ServerControllerExtension
|
||||
{
|
||||
public static ushort Socks5LocalPort(this IServerController controller)
|
||||
{
|
||||
return controller.Socks5LocalPort ?? Global.Settings.Socks5LocalPort;
|
||||
}
|
||||
|
||||
public static string LocalAddress(this IServerController controller)
|
||||
{
|
||||
return controller.LocalAddress ?? Global.Settings.LocalAddress;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ using System.IO;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.Socks5;
|
||||
using Netch.Utils;
|
||||
using static Netch.Forms.MainForm;
|
||||
using static Netch.Utils.PortHelper;
|
||||
@@ -11,12 +12,18 @@ namespace Netch.Controllers
|
||||
{
|
||||
public static class MainController
|
||||
{
|
||||
public static IServerController ServerController { get; private set; }
|
||||
public static IServerController ServerController
|
||||
{
|
||||
get => _serverController;
|
||||
private set => _serverController = value;
|
||||
}
|
||||
|
||||
public static IModeController ModeController { get; private set; }
|
||||
|
||||
public static bool NttTested;
|
||||
|
||||
private static readonly NTTController NTTController = new NTTController();
|
||||
private static IServerController _serverController;
|
||||
|
||||
/// <summary>
|
||||
/// 启动
|
||||
@@ -28,11 +35,12 @@ namespace Netch.Controllers
|
||||
{
|
||||
Logging.Info($"启动主控制器: {server.Type} [{mode.Type}]{mode.Remark}");
|
||||
|
||||
if (server.IsSocks5() && mode.Type == 4)
|
||||
if (server is Socks5 && mode.Type == 4)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 刷新DNS缓存
|
||||
NativeMethods.FlushDNSResolverCache();
|
||||
|
||||
try
|
||||
@@ -45,17 +53,18 @@ namespace Netch.Controllers
|
||||
return false;
|
||||
}
|
||||
|
||||
if (DNS.Lookup(server.Hostname) == null)
|
||||
if (Global.Settings.ResolveServerHostname && DNS.Lookup(server.Hostname) == null)
|
||||
{
|
||||
MessageBoxX.Show("Lookup Server hostname failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 添加Netch到防火墙
|
||||
_ = Task.Run(Firewall.AddNetchFwRules);
|
||||
|
||||
try
|
||||
{
|
||||
if (!await StartServer(server, mode))
|
||||
if (!await Task.Run(() => StartServer(server, mode, ref _serverController)))
|
||||
{
|
||||
throw new StartFailedException();
|
||||
}
|
||||
@@ -65,7 +74,7 @@ namespace Netch.Controllers
|
||||
throw new StartFailedException();
|
||||
}
|
||||
|
||||
if (ModeController?.TestNatRequired ?? false)
|
||||
if (mode.TestNatRequired)
|
||||
NatTest();
|
||||
|
||||
return true;
|
||||
@@ -99,27 +108,23 @@ namespace Netch.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<bool> StartServer(Server server, Mode mode)
|
||||
private static bool StartServer(Server server, Mode mode, ref IServerController controller)
|
||||
{
|
||||
if (server.IsSocks5())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
controller = ServerHelper.GetUtilByTypeName(server.Type).GetController();
|
||||
|
||||
ServerController = ServerHelper.GetUtilByTypeName(server.Type).GetController();
|
||||
|
||||
if (ServerController is Guard instanceController)
|
||||
if (controller is Guard instanceController)
|
||||
{
|
||||
Utils.Utils.KillProcessByName(instanceController.MainFile);
|
||||
}
|
||||
|
||||
PortCheckAndShowMessageBox(Global.Settings.Socks5LocalPort, "Socks5");
|
||||
PortCheckAndShowMessageBox(controller.Socks5LocalPort(), "Socks5");
|
||||
|
||||
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ServerController.Name));
|
||||
if (await Task.Run(() => ServerController.Start(server, mode)))
|
||||
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", controller.Name));
|
||||
if (controller.Start(in server, mode))
|
||||
{
|
||||
UsingPorts.Add(StatusPortInfoText.Socks5Port = Global.Settings.Socks5LocalPort);
|
||||
StatusPortInfoText.ShareLan = Global.Settings.LocalAddress == "0.0.0.0";
|
||||
UsingPorts.Add(StatusPortInfoText.Socks5Port = controller.Socks5LocalPort());
|
||||
StatusPortInfoText.ShareLan = controller.LocalAddress == "0.0.0.0";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -128,45 +133,20 @@ namespace Netch.Controllers
|
||||
|
||||
private static async Task<bool> StartMode(Server server, Mode mode)
|
||||
{
|
||||
var port = 0;
|
||||
switch (mode.Type)
|
||||
ModeController = ModeHelper.GetModeControllerByType(mode.Type, out var port, out var portName, out var portType);
|
||||
if (port != null)
|
||||
{
|
||||
case 0:
|
||||
ModeController = new NFController();
|
||||
PortCheckAndShowMessageBox(port = Global.Settings.RedirectorTCPPort, "Redirector TCP");
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
ModeController = new TUNTAPController();
|
||||
break;
|
||||
case 3:
|
||||
case 5:
|
||||
ModeController = new HTTPController();
|
||||
PortCheckAndShowMessageBox(port = Global.Settings.HTTPLocalPort, "HTTP");
|
||||
break;
|
||||
case 4:
|
||||
return true;
|
||||
default:
|
||||
Logging.Error("未知模式类型");
|
||||
return false;
|
||||
PortCheckAndShowMessageBox((ushort) port, portName, portType);
|
||||
UsingPorts.Add((ushort) port);
|
||||
}
|
||||
|
||||
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ModeController.Name));
|
||||
if (await Task.Run(() => ModeController.Start(server, mode)))
|
||||
if (ModeController != null)
|
||||
{
|
||||
switch (mode.Type)
|
||||
{
|
||||
case 3:
|
||||
case 5:
|
||||
StatusPortInfoText.HttpPort = port;
|
||||
break;
|
||||
}
|
||||
|
||||
UsingPorts.Add(port);
|
||||
return true;
|
||||
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ModeController.Name));
|
||||
return await Task.Run(() => ModeController.Start(mode));
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -175,6 +155,7 @@ namespace Netch.Controllers
|
||||
public static async Task Stop()
|
||||
{
|
||||
UsingPorts.Clear();
|
||||
StatusPortInfoText.Reset();
|
||||
|
||||
_ = Task.Run(() => NTTController.Stop());
|
||||
|
||||
@@ -184,6 +165,8 @@ namespace Netch.Controllers
|
||||
Task.Run(() => ModeController?.Stop()),
|
||||
};
|
||||
await Task.WhenAll(tasks);
|
||||
ModeController = null;
|
||||
ServerController = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -195,7 +178,7 @@ namespace Netch.Controllers
|
||||
/// <param name="portName">端口用途名称</param>
|
||||
/// <param name="portType"></param>
|
||||
/// <exception cref="PortInUseException"></exception>
|
||||
private static void PortCheckAndShowMessageBox(int port, string portName, PortType portType = PortType.Both)
|
||||
private static void PortCheckAndShowMessageBox(ushort port, string portName, PortType portType = PortType.Both)
|
||||
{
|
||||
if (PortInUse(port, portType))
|
||||
{
|
||||
|
||||
@@ -3,7 +3,9 @@ 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;
|
||||
using nfapinet;
|
||||
|
||||
@@ -11,8 +13,6 @@ namespace Netch.Controllers
|
||||
{
|
||||
public class NFController : IModeController
|
||||
{
|
||||
public bool TestNatRequired { get; } = true;
|
||||
|
||||
private static readonly ServiceController NFService = new ServiceController("netfilter2");
|
||||
|
||||
private static readonly string BinDriver = string.Empty;
|
||||
@@ -45,14 +45,18 @@ namespace Netch.Controllers
|
||||
BinDriver = "bin\\" + fileName;
|
||||
}
|
||||
|
||||
public bool Start(Server s, Mode mode)
|
||||
public bool Start(in Mode mode)
|
||||
{
|
||||
Logging.Info("内置驱动版本: " + Utils.Utils.GetFileVersion(BinDriver));
|
||||
if (Utils.Utils.GetFileVersion(SystemDriver) != Utils.Utils.GetFileVersion(BinDriver))
|
||||
var binFileVersion = Utils.Utils.GetFileVersion(BinDriver);
|
||||
var systemFileVersion = Utils.Utils.GetFileVersion(SystemDriver);
|
||||
|
||||
Logging.Info("内置驱动版本: " + binFileVersion);
|
||||
Logging.Info("系统驱动版本: " + systemFileVersion);
|
||||
|
||||
if (!systemFileVersion.Equals(binFileVersion))
|
||||
{
|
||||
if (File.Exists(SystemDriver))
|
||||
{
|
||||
Logging.Info("系统驱动版本: " + Utils.Utils.GetFileVersion(SystemDriver));
|
||||
Logging.Info("更新驱动");
|
||||
UninstallDriver();
|
||||
}
|
||||
@@ -61,31 +65,14 @@ namespace Netch.Controllers
|
||||
return false;
|
||||
}
|
||||
|
||||
aio_dial((int) NameList.TYPE_CLRNAME, "");
|
||||
foreach (var rule in mode.Rule)
|
||||
{
|
||||
aio_dial((int) NameList.TYPE_ADDNAME, rule);
|
||||
}
|
||||
aio_dial((int) NameList.TYPE_FILTERLOOPBACK, "false");
|
||||
aio_dial((int) NameList.TYPE_FILTERTCP, "true");
|
||||
aio_dial((int) NameList.TYPE_FILTERUDP, "true");
|
||||
aio_dial((int) NameList.TYPE_TCPLISN, Global.Settings.RedirectorTCPPort.ToString());
|
||||
|
||||
aio_dial((int) NameList.TYPE_ADDNAME, "NTT.exe");
|
||||
SetServer(MainController.ServerController, PortType.Both);
|
||||
|
||||
if (s.IsSocks5())
|
||||
{
|
||||
var result = DNS.Lookup(s.Hostname);
|
||||
if (result == null)
|
||||
{
|
||||
Logging.Info("无法解析服务器 IP 地址");
|
||||
return false;
|
||||
}
|
||||
|
||||
aio_dial((int) NameList.TYPE_TCPHOST, $"{result}:{s.Port}");
|
||||
aio_dial((int) NameList.TYPE_UDPHOST, $"{result}:{s.Port}");
|
||||
}
|
||||
else
|
||||
{
|
||||
aio_dial((int) NameList.TYPE_TCPHOST, $"127.0.0.1:{Global.Settings.Socks5LocalPort}");
|
||||
aio_dial((int) NameList.TYPE_UDPHOST, $"127.0.0.1:{Global.Settings.Socks5LocalPort}");
|
||||
}
|
||||
SetName(mode);
|
||||
|
||||
if (Global.Settings.ModifySystemDNS)
|
||||
{
|
||||
@@ -97,6 +84,46 @@ namespace Netch.Controllers
|
||||
return aio_init();
|
||||
}
|
||||
|
||||
private void SetServer(in IServerController controller, in PortType portType)
|
||||
{
|
||||
if (portType == PortType.Both)
|
||||
{
|
||||
SetServer(controller, PortType.TCP);
|
||||
SetServer(controller, PortType.UDP);
|
||||
return;
|
||||
}
|
||||
|
||||
var offset = portType == PortType.UDP ? UdpNameListOffset : 0;
|
||||
|
||||
aio_dial((int) NameList.TYPE_TCPTYPE + offset, "Socks5");
|
||||
|
||||
if (controller.Server is Socks5 socks5)
|
||||
{
|
||||
aio_dial((int) NameList.TYPE_TCPHOST + offset, $"{socks5.AutoResolveHostname()}:{socks5.Port}");
|
||||
aio_dial((int) NameList.TYPE_TCPUSER + offset, socks5.Username ?? string.Empty);
|
||||
aio_dial((int) NameList.TYPE_TCPPASS + offset, socks5.Password ?? string.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
aio_dial((int) NameList.TYPE_TCPHOST + offset, $"127.0.0.1:{controller.Socks5LocalPort()}");
|
||||
aio_dial((int) NameList.TYPE_TCPUSER + offset, string.Empty);
|
||||
aio_dial((int) NameList.TYPE_TCPPASS + offset, string.Empty);
|
||||
}
|
||||
|
||||
aio_dial((int) NameList.TYPE_TCPMETH + offset, string.Empty);
|
||||
}
|
||||
|
||||
private void SetName(Mode mode)
|
||||
{
|
||||
aio_dial((int) NameList.TYPE_CLRNAME, "");
|
||||
foreach (var rule in mode.FullRule)
|
||||
{
|
||||
aio_dial((int) NameList.TYPE_ADDNAME, rule);
|
||||
}
|
||||
|
||||
aio_dial((int) NameList.TYPE_ADDNAME, "NTT.exe");
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
Task.Run(() =>
|
||||
@@ -111,6 +138,8 @@ namespace Netch.Controllers
|
||||
|
||||
#region NativeMethods
|
||||
|
||||
private const int UdpNameListOffset = (int) NameList.TYPE_UDPTYPE - (int) NameList.TYPE_TCPTYPE;
|
||||
|
||||
[DllImport("Redirector.bin", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern bool aio_dial(int name, [MarshalAs(UnmanagedType.LPWStr)] string value);
|
||||
|
||||
@@ -126,6 +155,28 @@ namespace Netch.Controllers
|
||||
[DllImport("Redirector.bin", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern ulong aio_getDL();
|
||||
|
||||
|
||||
public enum NameList : int
|
||||
{
|
||||
TYPE_FILTERLOOPBACK,
|
||||
TYPE_FILTERTCP,
|
||||
TYPE_FILTERUDP,
|
||||
TYPE_TCPLISN,
|
||||
TYPE_TCPTYPE,
|
||||
TYPE_TCPHOST,
|
||||
TYPE_TCPUSER,
|
||||
TYPE_TCPPASS,
|
||||
TYPE_TCPMETH,
|
||||
TYPE_UDPTYPE,
|
||||
TYPE_UDPHOST,
|
||||
TYPE_UDPUSER,
|
||||
TYPE_UDPPASS,
|
||||
TYPE_UDPMETH,
|
||||
TYPE_ADDNAME,
|
||||
TYPE_BYPNAME,
|
||||
TYPE_CLRNAME
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Utils
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.Socks5;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
@@ -16,13 +18,21 @@ namespace Netch.Controllers
|
||||
|
||||
public bool Start(Server server, Mode mode)
|
||||
{
|
||||
var text = File.ReadAllText("bin\\default.conf")
|
||||
.Replace("_BIND_PORT_", Global.Settings.HTTPLocalPort.ToString())
|
||||
.Replace("_DEST_PORT_", (server.IsSocks5() ? server.Port : Global.Settings.Socks5LocalPort).ToString())
|
||||
.Replace("0.0.0.0", Global.Settings.LocalAddress);
|
||||
if (server.IsSocks5())
|
||||
text = text.Replace("/ 127.0.0.1", $"/ {server.Hostname}");
|
||||
File.WriteAllText("data\\privoxy.conf", text);
|
||||
var text = new StringBuilder(File.ReadAllText("bin\\default.conf"));
|
||||
|
||||
text.Replace("_BIND_PORT_", Global.Settings.HTTPLocalPort.ToString());
|
||||
text.Replace("0.0.0.0", Global.Settings.LocalAddress); /* BIND_HOST */
|
||||
|
||||
if (server is Socks5 socks5 && !socks5.Auth())
|
||||
{
|
||||
text.Replace("/ 127.0.0.1", $"/ {server.AutoResolveHostname()}"); /* DEST_HOST */
|
||||
text.Replace("_DEST_PORT_", socks5.Port.ToString());
|
||||
}
|
||||
|
||||
text.Replace("_DEST_PORT_", Global.Settings.Socks5LocalPort.ToString());
|
||||
|
||||
|
||||
File.WriteAllText("data\\privoxy.conf", text.ToString());
|
||||
|
||||
return StartInstanceAuto("..\\data\\privoxy.conf");
|
||||
}
|
||||
|
||||
@@ -10,18 +10,13 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.Socks5;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
public class TUNTAPController : Guard, IModeController
|
||||
{
|
||||
public bool TestNatRequired { get; } = true;
|
||||
|
||||
// ByPassLan IP
|
||||
private readonly List<string> _bypassLanIPs = new List<string>
|
||||
{"10.0.0.0/8", "172.16.0.0/16", "192.168.0.0/16"};
|
||||
|
||||
private Mode _savedMode = new Mode();
|
||||
private Server _savedServer = new Server();
|
||||
|
||||
@@ -44,10 +39,10 @@ namespace Netch.Controllers
|
||||
public override string Name { get; protected set; } = "tun2socks";
|
||||
public override string MainFile { get; protected set; } = "tun2socks.exe";
|
||||
|
||||
public bool Start(Server s, Mode mode)
|
||||
public bool Start(in Mode mode)
|
||||
{
|
||||
_savedMode = mode;
|
||||
_savedServer = s;
|
||||
_savedServer = MainController.ServerController.Server;
|
||||
|
||||
// 查询服务器 IP 地址
|
||||
_serverAddresses = DNS.Lookup(_savedServer.Hostname);
|
||||
@@ -59,12 +54,18 @@ namespace Netch.Controllers
|
||||
}
|
||||
|
||||
// 查找并安装 TAP 适配器
|
||||
if (!SearchTapAdapter() && !AddTap())
|
||||
if (!SearchTapAdapter())
|
||||
{
|
||||
Logging.Error("Tap 适配器安装失败");
|
||||
return false;
|
||||
if (!AddTap())
|
||||
{
|
||||
Logging.Error("Tap 适配器安装失败");
|
||||
return false;
|
||||
}
|
||||
|
||||
SearchTapAdapter();
|
||||
}
|
||||
|
||||
|
||||
SetupRouteTable();
|
||||
|
||||
string dns;
|
||||
@@ -87,8 +88,8 @@ namespace Netch.Controllers
|
||||
}
|
||||
|
||||
var argument = new StringBuilder();
|
||||
if (s.IsSocks5())
|
||||
argument.Append($"-proxyServer {_serverAddresses}:{s.Port} ");
|
||||
if (_savedServer is Socks5 socks5 && !socks5.Auth())
|
||||
argument.Append($"-proxyServer {_serverAddresses}:{_savedServer.Port} ");
|
||||
else
|
||||
argument.Append($"-proxyServer 127.0.0.1:{Global.Settings.Socks5LocalPort} ");
|
||||
|
||||
@@ -115,9 +116,9 @@ namespace Netch.Controllers
|
||||
Task.WaitAll(tasks);
|
||||
}
|
||||
|
||||
private readonly List<IPNetwork> _directIPs = new List<IPNetwork>();
|
||||
private readonly List<string> _directIPs = new List<string>();
|
||||
|
||||
private readonly List<IPNetwork> _proxyIPs = new List<IPNetwork>();
|
||||
private readonly List<string> _proxyIPs = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// 设置绕行规则
|
||||
@@ -126,83 +127,87 @@ namespace Netch.Controllers
|
||||
private void SetupRouteTable()
|
||||
{
|
||||
Global.MainForm.StatusText(i18N.Translate("SetupBypass"));
|
||||
Logging.Info("设置路由规则");
|
||||
|
||||
Logging.Info("绕行 → 全局绕过 IP");
|
||||
_directIPs.AddRange(Global.Settings.BypassIPs.Select(IPNetwork.Parse));
|
||||
#region Rule IPs
|
||||
|
||||
Logging.Info("绕行 → 服务器 IP");
|
||||
if (!IPAddress.IsLoopback(_serverAddresses))
|
||||
_directIPs.Add(IPNetwork.Parse(_serverAddresses.ToString(), 32));
|
||||
|
||||
Logging.Info("绕行 → 局域网 IP");
|
||||
_directIPs.AddRange(_bypassLanIPs.Select(IPNetwork.Parse));
|
||||
|
||||
switch (_savedMode.Type)
|
||||
if (_savedMode.Type == 1)
|
||||
{
|
||||
case 1:
|
||||
// 代理规则
|
||||
Logging.Info("代理 → 规则 IP");
|
||||
_proxyIPs.AddRange(_savedMode.Rule.Select(IPNetwork.Parse));
|
||||
// 代理规则
|
||||
Logging.Info("代理 → 规则 IP");
|
||||
RouteAction(Action.Create, _savedMode.FullRule, RouteType.TUNTAP);
|
||||
|
||||
//处理 NAT 类型检测,由于协议的原因,无法仅通过域名确定需要代理的 IP,自己记录解析了返回的 IP,仅支持默认检测服务器
|
||||
if (Global.Settings.STUN_Server == "stun.stunprotocol.org")
|
||||
try
|
||||
{
|
||||
Logging.Info("代理 → STUN 服务器 IP");
|
||||
_proxyIPs.AddRange(new[]
|
||||
//处理 NAT 类型检测,由于协议的原因,无法仅通过域名确定需要代理的 IP,自己记录解析了返回的 IP,仅支持默认检测服务器
|
||||
if (Global.Settings.STUN_Server == "stun.stunprotocol.org")
|
||||
{
|
||||
try
|
||||
{
|
||||
Logging.Info("代理 → STUN 服务器 IP");
|
||||
RouteAction(Action.Create,
|
||||
new[]
|
||||
{
|
||||
Dns.GetHostAddresses(Global.Settings.STUN_Server)[0],
|
||||
Dns.GetHostAddresses("stunresponse.coldthunder11.com")[0]
|
||||
}.Select(ip => IPNetwork.Parse(ip.ToString(), 32)));
|
||||
}
|
||||
catch
|
||||
{
|
||||
Logging.Info("NAT 类型测试域名解析失败,将不会被添加到代理列表");
|
||||
}
|
||||
|
||||
if (Global.Settings.TUNTAP.ProxyDNS)
|
||||
{
|
||||
Logging.Info("代理 → 自定义 DNS");
|
||||
if (Global.Settings.TUNTAP.UseCustomDNS)
|
||||
{
|
||||
_proxyIPs.AddRange(Global.Settings.TUNTAP.DNS.Select(ip => IPNetwork.Parse(ip, 32)));
|
||||
}
|
||||
else
|
||||
{
|
||||
_proxyIPs.AddRange(new[] {"1.1.1.1", "8.8.8.8", "9.9.9.9", "185.222.222.222"}.Select(ip => IPNetwork.Parse(ip, 32)));
|
||||
}
|
||||
}.Select(ip => $"{ip}/32"),
|
||||
RouteType.TUNTAP);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Logging.Info("NAT 类型测试域名解析失败,将不会被添加到代理列表");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case 2:
|
||||
// 绕过规则
|
||||
if (Global.Settings.TUNTAP.ProxyDNS)
|
||||
{
|
||||
Logging.Info("代理 → 自定义 DNS");
|
||||
if (Global.Settings.TUNTAP.UseCustomDNS)
|
||||
{
|
||||
RouteAction(Action.Create,
|
||||
Global.Settings.TUNTAP.DNS.Select(ip => $"{ip}/32"),
|
||||
RouteType.TUNTAP);
|
||||
}
|
||||
else
|
||||
{
|
||||
RouteAction(Action.Create,
|
||||
new[] {"1.1.1.1", "8.8.8.8", "9.9.9.9", "185.222.222.222"}.Select(ip => $"{ip}/32"),
|
||||
RouteType.TUNTAP);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (_savedMode.Type == 2)
|
||||
{
|
||||
// 绕过规则
|
||||
|
||||
// 将 TUN/TAP 网卡权重放到最高
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = "netsh",
|
||||
Arguments = $"interface ip set interface {Global.TUNTAP.Index} metric=0",
|
||||
WindowStyle = ProcessWindowStyle.Hidden,
|
||||
UseShellExecute = true,
|
||||
CreateNoWindow = true
|
||||
}
|
||||
);
|
||||
// 将 TUN/TAP 网卡权重放到最高
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = "netsh",
|
||||
Arguments = $"interface ip set interface {Global.TUNTAP.Index} metric=0",
|
||||
WindowStyle = ProcessWindowStyle.Hidden,
|
||||
UseShellExecute = true,
|
||||
CreateNoWindow = true
|
||||
}
|
||||
);
|
||||
|
||||
Logging.Info("绕行 → 规则 IP");
|
||||
_directIPs.AddRange(_savedMode.Rule.Select(IPNetwork.Parse));
|
||||
|
||||
Logging.Info("代理 → 全局");
|
||||
RouteAction(Action.Create, IPNetwork.Parse("0.0.0.0", 0), RouteType.TUNTAP);
|
||||
|
||||
Logging.Info("移除 → 出口网卡路由");
|
||||
RouteAction(Action.Delete, IPNetwork.Parse("0.0.0.0", 0), RouteType.Gateway);
|
||||
|
||||
break;
|
||||
Logging.Info("绕行 → 规则 IP");
|
||||
RouteAction(Action.Create, _savedMode.FullRule, RouteType.Outbound);
|
||||
}
|
||||
|
||||
Logging.Info("设置路由规则");
|
||||
RouteAction(Action.Create, _directIPs, RouteType.Gateway);
|
||||
RouteAction(Action.Create, _proxyIPs, RouteType.TUNTAP);
|
||||
#endregion
|
||||
|
||||
Logging.Info("绕行 → 服务器 IP");
|
||||
if (!IPAddress.IsLoopback(_serverAddresses))
|
||||
RouteAction(Action.Create, $"{_serverAddresses}/32", RouteType.Outbound);
|
||||
|
||||
Logging.Info("绕行 → 全局绕过 IP");
|
||||
RouteAction(Action.Create, Global.Settings.BypassIPs, RouteType.Outbound);
|
||||
|
||||
if (_savedMode.Type == 2)
|
||||
{
|
||||
// 绕过规则
|
||||
Logging.Info("代理 → 全局");
|
||||
RouteAction(Action.Create, "0.0.0.0/0", RouteType.TUNTAP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -211,17 +216,7 @@ namespace Netch.Controllers
|
||||
/// </summary>
|
||||
private bool ClearRouteTable()
|
||||
{
|
||||
switch (_savedMode.Type)
|
||||
{
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
RouteAction(Action.Delete, IPNetwork.Parse("0.0.0.0", 0), RouteType.TUNTAP);
|
||||
RouteAction(Action.Create, IPNetwork.Parse("0.0.0.0", 0), RouteType.Gateway);
|
||||
break;
|
||||
}
|
||||
|
||||
RouteAction(Action.Delete, _directIPs, RouteType.Gateway);
|
||||
RouteAction(Action.Delete, _directIPs, RouteType.Outbound);
|
||||
RouteAction(Action.Delete, _proxyIPs, RouteType.TUNTAP);
|
||||
_directIPs.Clear();
|
||||
_proxyIPs.Clear();
|
||||
@@ -321,7 +316,7 @@ namespace Netch.Controllers
|
||||
|
||||
private enum RouteType
|
||||
{
|
||||
Gateway,
|
||||
Outbound,
|
||||
TUNTAP
|
||||
}
|
||||
|
||||
@@ -331,7 +326,7 @@ namespace Netch.Controllers
|
||||
Delete
|
||||
}
|
||||
|
||||
private static void RouteAction(Action action, IEnumerable<IPNetwork> ipNetworks, RouteType routeType,
|
||||
private void RouteAction(Action action, in IEnumerable<string> ipNetworks, RouteType routeType,
|
||||
int metric = 0)
|
||||
{
|
||||
foreach (var address in ipNetworks)
|
||||
@@ -340,13 +335,13 @@ namespace Netch.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
private static bool RouteAction(Action action, IPNetwork ipNetwork, RouteType routeType, int metric = 0)
|
||||
private bool RouteAction(Action action, in string ipNetwork, RouteType routeType, int metric = 0)
|
||||
{
|
||||
string gateway;
|
||||
int index;
|
||||
switch (routeType)
|
||||
{
|
||||
case RouteType.Gateway:
|
||||
case RouteType.Outbound:
|
||||
gateway = Global.Outbound.Gateway.ToString();
|
||||
index = Global.Outbound.Index;
|
||||
break;
|
||||
@@ -358,18 +353,48 @@ namespace Netch.Controllers
|
||||
throw new ArgumentOutOfRangeException(nameof(routeType), routeType, null);
|
||||
}
|
||||
|
||||
var result = action switch
|
||||
string network;
|
||||
ushort cidr;
|
||||
try
|
||||
{
|
||||
Action.Create => NativeMethods.CreateRoute(ipNetwork.Network.ToString(), ipNetwork.Cidr, gateway, index,
|
||||
metric),
|
||||
Action.Delete => NativeMethods.DeleteRoute(ipNetwork.Network.ToString(), ipNetwork.Cidr, gateway, index,
|
||||
metric),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(action), action, null)
|
||||
};
|
||||
var s = ipNetwork.Split('/');
|
||||
network = s[0];
|
||||
cidr = ushort.Parse(s[1]);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Logging.Warning($"Failed to parse rule {ipNetwork}");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result;
|
||||
switch (action)
|
||||
{
|
||||
case Action.Create:
|
||||
{
|
||||
result = NativeMethods.CreateRoute(network, cidr, gateway, index, metric);
|
||||
switch (routeType)
|
||||
{
|
||||
case RouteType.Outbound:
|
||||
_directIPs.Add(ipNetwork);
|
||||
break;
|
||||
case RouteType.TUNTAP:
|
||||
_proxyIPs.Add(ipNetwork);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case Action.Delete:
|
||||
result = NativeMethods.DeleteRoute(network, cidr, gateway, index, metric);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(action), action, null);
|
||||
}
|
||||
|
||||
if (!result)
|
||||
{
|
||||
Logging.Warning($"Failed {action} Route on {routeType} Adapter: {ipNetwork} metric {metric}");
|
||||
Logging.Warning($"Failed to {action} Route on {routeType} Adapter: {ipNetwork} metric {metric}");
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -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.0";
|
||||
public const string AssemblyVersion = @"1.6.4";
|
||||
private const string Suffix = @"";
|
||||
|
||||
public static readonly string Version = $"{AssemblyVersion}{(string.IsNullOrEmpty(Suffix) ? "" : $"-{Suffix}")}";
|
||||
|
||||
92
Netch/Forms/MainForm.Designer.cs
generated
92
Netch/Forms/MainForm.Designer.cs
generated
@@ -85,6 +85,8 @@
|
||||
this.SettingsButton = new System.Windows.Forms.Button();
|
||||
this.ProfileGroupBox = new System.Windows.Forms.GroupBox();
|
||||
this.ProfileTable = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.ButtomControlContainerControl = new System.Windows.Forms.ContainerControl();
|
||||
this.MenuStrip.SuspendLayout();
|
||||
this.ConfigurationGroupBox.SuspendLayout();
|
||||
this.configLayoutPanel.SuspendLayout();
|
||||
@@ -99,6 +101,8 @@
|
||||
this.StatusStrip.SuspendLayout();
|
||||
this.NotifyMenu.SuspendLayout();
|
||||
this.ProfileGroupBox.SuspendLayout();
|
||||
this.flowLayoutPanel1.SuspendLayout();
|
||||
this.ButtomControlContainerControl.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// MenuStrip
|
||||
@@ -118,7 +122,7 @@
|
||||
this.MenuStrip.Location = new System.Drawing.Point(0, 0);
|
||||
this.MenuStrip.Name = "MenuStrip";
|
||||
this.MenuStrip.RenderMode = System.Windows.Forms.ToolStripRenderMode.Professional;
|
||||
this.MenuStrip.Size = new System.Drawing.Size(733, 26);
|
||||
this.MenuStrip.Size = new System.Drawing.Size(740, 26);
|
||||
this.MenuStrip.TabIndex = 0;
|
||||
//
|
||||
// ServerToolStripMenuItem
|
||||
@@ -202,42 +206,42 @@
|
||||
// OpenDirectoryToolStripMenuItem
|
||||
//
|
||||
this.OpenDirectoryToolStripMenuItem.Name = "OpenDirectoryToolStripMenuItem";
|
||||
this.OpenDirectoryToolStripMenuItem.Size = new System.Drawing.Size(219, 22);
|
||||
this.OpenDirectoryToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
|
||||
this.OpenDirectoryToolStripMenuItem.Text = "Open Directory";
|
||||
this.OpenDirectoryToolStripMenuItem.Click += new System.EventHandler(this.OpenDirectoryToolStripMenuItem_Click);
|
||||
//
|
||||
// CleanDNSCacheToolStripMenuItem
|
||||
//
|
||||
this.CleanDNSCacheToolStripMenuItem.Name = "CleanDNSCacheToolStripMenuItem";
|
||||
this.CleanDNSCacheToolStripMenuItem.Size = new System.Drawing.Size(219, 22);
|
||||
this.CleanDNSCacheToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
|
||||
this.CleanDNSCacheToolStripMenuItem.Text = "Clean DNS Cache";
|
||||
this.CleanDNSCacheToolStripMenuItem.Click += new System.EventHandler(this.CleanDNSCacheToolStripMenuItem_Click);
|
||||
//
|
||||
// UpdateACLToolStripMenuItem
|
||||
//
|
||||
this.UpdateACLToolStripMenuItem.Name = "UpdateACLToolStripMenuItem";
|
||||
this.UpdateACLToolStripMenuItem.Size = new System.Drawing.Size(219, 22);
|
||||
this.UpdateACLToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
|
||||
this.UpdateACLToolStripMenuItem.Text = "Update ACL";
|
||||
this.UpdateACLToolStripMenuItem.Click += new System.EventHandler(this.updateACLToolStripMenuItem_Click);
|
||||
//
|
||||
// updateACLWithProxyToolStripMenuItem
|
||||
//
|
||||
this.updateACLWithProxyToolStripMenuItem.Name = "updateACLWithProxyToolStripMenuItem";
|
||||
this.updateACLWithProxyToolStripMenuItem.Size = new System.Drawing.Size(219, 22);
|
||||
this.updateACLWithProxyToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
|
||||
this.updateACLWithProxyToolStripMenuItem.Text = "Update ACL with proxy";
|
||||
this.updateACLWithProxyToolStripMenuItem.Click += new System.EventHandler(this.updateACLWithProxyToolStripMenuItem_Click);
|
||||
//
|
||||
// UninstallServiceToolStripMenuItem
|
||||
//
|
||||
this.UninstallServiceToolStripMenuItem.Name = "UninstallServiceToolStripMenuItem";
|
||||
this.UninstallServiceToolStripMenuItem.Size = new System.Drawing.Size(219, 22);
|
||||
this.UninstallServiceToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
|
||||
this.UninstallServiceToolStripMenuItem.Text = "Uninstall NF Service";
|
||||
this.UninstallServiceToolStripMenuItem.Click += new System.EventHandler(this.UninstallServiceToolStripMenuItem_Click);
|
||||
//
|
||||
// UninstallTapDriverToolStripMenuItem
|
||||
//
|
||||
this.UninstallTapDriverToolStripMenuItem.Name = "UninstallTapDriverToolStripMenuItem";
|
||||
this.UninstallTapDriverToolStripMenuItem.Size = new System.Drawing.Size(219, 22);
|
||||
this.UninstallTapDriverToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
|
||||
this.UninstallTapDriverToolStripMenuItem.Text = "Uninstall TUN/TAP driver";
|
||||
this.UninstallTapDriverToolStripMenuItem.Click += new System.EventHandler(this.reinstallTapDriverToolStripMenuItem_Click);
|
||||
//
|
||||
@@ -311,7 +315,7 @@
|
||||
// ConfigurationGroupBox
|
||||
//
|
||||
this.ConfigurationGroupBox.Controls.Add(this.configLayoutPanel);
|
||||
this.ConfigurationGroupBox.Location = new System.Drawing.Point(12, 28);
|
||||
this.ConfigurationGroupBox.Location = new System.Drawing.Point(3, 3);
|
||||
this.ConfigurationGroupBox.Name = "ConfigurationGroupBox";
|
||||
this.ConfigurationGroupBox.Size = new System.Drawing.Size(709, 115);
|
||||
this.ConfigurationGroupBox.TabIndex = 1;
|
||||
@@ -320,6 +324,8 @@
|
||||
//
|
||||
// configLayoutPanel
|
||||
//
|
||||
this.configLayoutPanel.AutoSize = true;
|
||||
this.configLayoutPanel.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
this.configLayoutPanel.ColumnCount = 3;
|
||||
this.configLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.configLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
@@ -336,9 +342,9 @@
|
||||
this.configLayoutPanel.Location = new System.Drawing.Point(3, 19);
|
||||
this.configLayoutPanel.Name = "configLayoutPanel";
|
||||
this.configLayoutPanel.RowCount = 3;
|
||||
this.configLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
|
||||
this.configLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
|
||||
this.configLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
|
||||
this.configLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.configLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.configLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.configLayoutPanel.Size = new System.Drawing.Size(703, 93);
|
||||
this.configLayoutPanel.TabIndex = 15;
|
||||
//
|
||||
@@ -346,7 +352,7 @@
|
||||
//
|
||||
this.ProfileLabel.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.ProfileLabel.AutoSize = true;
|
||||
this.ProfileLabel.Location = new System.Drawing.Point(3, 69);
|
||||
this.ProfileLabel.Location = new System.Drawing.Point(3, 68);
|
||||
this.ProfileLabel.Name = "ProfileLabel";
|
||||
this.ProfileLabel.Size = new System.Drawing.Size(45, 17);
|
||||
this.ProfileLabel.TabIndex = 10;
|
||||
@@ -356,7 +362,7 @@
|
||||
//
|
||||
this.ModeLabel.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.ModeLabel.AutoSize = true;
|
||||
this.ModeLabel.Location = new System.Drawing.Point(3, 38);
|
||||
this.ModeLabel.Location = new System.Drawing.Point(3, 36);
|
||||
this.ModeLabel.Name = "ModeLabel";
|
||||
this.ModeLabel.Size = new System.Drawing.Size(43, 17);
|
||||
this.ModeLabel.TabIndex = 3;
|
||||
@@ -366,7 +372,7 @@
|
||||
//
|
||||
this.ServerLabel.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.ServerLabel.AutoSize = true;
|
||||
this.ServerLabel.Location = new System.Drawing.Point(3, 7);
|
||||
this.ServerLabel.Location = new System.Drawing.Point(3, 6);
|
||||
this.ServerLabel.Name = "ServerLabel";
|
||||
this.ServerLabel.Size = new System.Drawing.Size(45, 17);
|
||||
this.ServerLabel.TabIndex = 0;
|
||||
@@ -375,7 +381,7 @@
|
||||
// ProfileNameText
|
||||
//
|
||||
this.ProfileNameText.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.ProfileNameText.Location = new System.Drawing.Point(54, 65);
|
||||
this.ProfileNameText.Location = new System.Drawing.Point(54, 63);
|
||||
this.ProfileNameText.Name = "ProfileNameText";
|
||||
this.ProfileNameText.Size = new System.Drawing.Size(546, 23);
|
||||
this.ProfileNameText.TabIndex = 11;
|
||||
@@ -387,7 +393,7 @@
|
||||
this.ModeComboBox.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
|
||||
this.ModeComboBox.FormattingEnabled = true;
|
||||
this.ModeComboBox.IntegralHeight = false;
|
||||
this.ModeComboBox.Location = new System.Drawing.Point(54, 34);
|
||||
this.ModeComboBox.Location = new System.Drawing.Point(54, 33);
|
||||
this.ModeComboBox.Name = "ModeComboBox";
|
||||
this.ModeComboBox.Size = new System.Drawing.Size(546, 24);
|
||||
this.ModeComboBox.TabIndex = 2;
|
||||
@@ -481,7 +487,7 @@
|
||||
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F));
|
||||
this.tableLayoutPanel3.Controls.Add(this.EditModePictureBox, 0, 0);
|
||||
this.tableLayoutPanel3.Controls.Add(this.DeleteModePictureBox, 1, 0);
|
||||
this.tableLayoutPanel3.Location = new System.Drawing.Point(606, 34);
|
||||
this.tableLayoutPanel3.Location = new System.Drawing.Point(606, 33);
|
||||
this.tableLayoutPanel3.Name = "tableLayoutPanel3";
|
||||
this.tableLayoutPanel3.RowCount = 1;
|
||||
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
@@ -521,9 +527,9 @@
|
||||
this.blankToolStripStatusLabel,
|
||||
this.NatTypeStatusLabel,
|
||||
this.NatTypeStatusLightLabel});
|
||||
this.StatusStrip.Location = new System.Drawing.Point(0, 250);
|
||||
this.StatusStrip.Location = new System.Drawing.Point(0, 272);
|
||||
this.StatusStrip.Name = "StatusStrip";
|
||||
this.StatusStrip.Size = new System.Drawing.Size(733, 22);
|
||||
this.StatusStrip.Size = new System.Drawing.Size(740, 22);
|
||||
this.StatusStrip.SizingGrip = false;
|
||||
this.StatusStrip.TabIndex = 2;
|
||||
//
|
||||
@@ -558,7 +564,7 @@
|
||||
// blankToolStripStatusLabel
|
||||
//
|
||||
this.blankToolStripStatusLabel.Name = "blankToolStripStatusLabel";
|
||||
this.blankToolStripStatusLabel.Size = new System.Drawing.Size(487, 17);
|
||||
this.blankToolStripStatusLabel.Size = new System.Drawing.Size(494, 17);
|
||||
this.blankToolStripStatusLabel.Spring = true;
|
||||
//
|
||||
// NatTypeStatusLabel
|
||||
@@ -584,7 +590,7 @@
|
||||
// ControlButton
|
||||
//
|
||||
this.ControlButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.ControlButton.Location = new System.Drawing.Point(646, 214);
|
||||
this.ControlButton.Location = new System.Drawing.Point(631, 3);
|
||||
this.ControlButton.Name = "ControlButton";
|
||||
this.ControlButton.Size = new System.Drawing.Size(75, 27);
|
||||
this.ControlButton.TabIndex = 3;
|
||||
@@ -627,7 +633,7 @@
|
||||
// SettingsButton
|
||||
//
|
||||
this.SettingsButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.SettingsButton.Location = new System.Drawing.Point(12, 215);
|
||||
this.SettingsButton.Location = new System.Drawing.Point(1, 3);
|
||||
this.SettingsButton.Name = "SettingsButton";
|
||||
this.SettingsButton.Size = new System.Drawing.Size(72, 27);
|
||||
this.SettingsButton.TabIndex = 4;
|
||||
@@ -638,7 +644,7 @@
|
||||
// ProfileGroupBox
|
||||
//
|
||||
this.ProfileGroupBox.Controls.Add(this.ProfileTable);
|
||||
this.ProfileGroupBox.Location = new System.Drawing.Point(12, 146);
|
||||
this.ProfileGroupBox.Location = new System.Drawing.Point(3, 124);
|
||||
this.ProfileGroupBox.Name = "ProfileGroupBox";
|
||||
this.ProfileGroupBox.Size = new System.Drawing.Size(709, 65);
|
||||
this.ProfileGroupBox.TabIndex = 13;
|
||||
@@ -661,17 +667,40 @@
|
||||
this.ProfileTable.Size = new System.Drawing.Size(703, 43);
|
||||
this.ProfileTable.TabIndex = 0;
|
||||
//
|
||||
// flowLayoutPanel1
|
||||
//
|
||||
this.flowLayoutPanel1.AutoSize = true;
|
||||
this.flowLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
this.flowLayoutPanel1.Controls.Add(this.ConfigurationGroupBox);
|
||||
this.flowLayoutPanel1.Controls.Add(this.ProfileGroupBox);
|
||||
this.flowLayoutPanel1.Controls.Add(this.ButtomControlContainerControl);
|
||||
this.flowLayoutPanel1.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;
|
||||
this.flowLayoutPanel1.Location = new System.Drawing.Point(12, 29);
|
||||
this.flowLayoutPanel1.Name = "flowLayoutPanel1";
|
||||
this.flowLayoutPanel1.Size = new System.Drawing.Size(715, 256);
|
||||
this.flowLayoutPanel1.TabIndex = 14;
|
||||
//
|
||||
// ButtomControlContainerControl
|
||||
//
|
||||
this.ButtomControlContainerControl.Controls.Add(this.ControlButton);
|
||||
this.ButtomControlContainerControl.Controls.Add(this.SettingsButton);
|
||||
this.ButtomControlContainerControl.Location = new System.Drawing.Point(3, 195);
|
||||
this.ButtomControlContainerControl.Name = "ButtomControlContainerControl";
|
||||
this.ButtomControlContainerControl.Size = new System.Drawing.Size(706, 58);
|
||||
this.ButtomControlContainerControl.TabIndex = 14;
|
||||
this.ButtomControlContainerControl.TabStop = false;
|
||||
this.ButtomControlContainerControl.Text = "groupBox1";
|
||||
//
|
||||
// MainForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
|
||||
this.ClientSize = new System.Drawing.Size(733, 272);
|
||||
this.Controls.Add(this.ProfileGroupBox);
|
||||
this.Controls.Add(this.SettingsButton);
|
||||
this.Controls.Add(this.ControlButton);
|
||||
this.Controls.Add(this.StatusStrip);
|
||||
this.Controls.Add(this.ConfigurationGroupBox);
|
||||
this.AutoSize = true;
|
||||
this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
this.ClientSize = new System.Drawing.Size(740, 294);
|
||||
this.Controls.Add(this.MenuStrip);
|
||||
this.Controls.Add(this.StatusStrip);
|
||||
this.Controls.Add(this.flowLayoutPanel1);
|
||||
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
@@ -685,6 +714,7 @@
|
||||
this.MenuStrip.ResumeLayout(false);
|
||||
this.MenuStrip.PerformLayout();
|
||||
this.ConfigurationGroupBox.ResumeLayout(false);
|
||||
this.ConfigurationGroupBox.PerformLayout();
|
||||
this.configLayoutPanel.ResumeLayout(false);
|
||||
this.configLayoutPanel.PerformLayout();
|
||||
this.tableLayoutPanel2.ResumeLayout(false);
|
||||
@@ -700,6 +730,8 @@
|
||||
this.NotifyMenu.ResumeLayout(false);
|
||||
this.ProfileGroupBox.ResumeLayout(false);
|
||||
this.ProfileGroupBox.PerformLayout();
|
||||
this.flowLayoutPanel1.ResumeLayout(false);
|
||||
this.ButtomControlContainerControl.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
@@ -763,5 +795,7 @@
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
|
||||
private System.Windows.Forms.ContainerControl ButtomControlContainerControl;
|
||||
}
|
||||
}
|
||||
@@ -26,19 +26,8 @@ namespace Netch.Forms
|
||||
var texts = Clipboard.GetText();
|
||||
if (!string.IsNullOrWhiteSpace(texts))
|
||||
{
|
||||
var result = ShareLink.ParseText(texts);
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
foreach (var server in result)
|
||||
{
|
||||
Global.Settings.Server.Add(server);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("Import servers error!"), LogLevel.ERROR);
|
||||
}
|
||||
Global.Settings.Server.AddRange(ShareLink.ParseText(texts));
|
||||
NotifyTip(i18N.TranslateFormat("Import {0} server(s) form Clipboard", ShareLink.ParseText(texts).Count));
|
||||
|
||||
InitServer();
|
||||
Configuration.Save();
|
||||
@@ -108,6 +97,9 @@ namespace Netch.Forms
|
||||
await UpdateServersFromSubscribe();
|
||||
}
|
||||
|
||||
|
||||
private readonly object _serverLock = new object();
|
||||
|
||||
public async Task UpdateServersFromSubscribe()
|
||||
{
|
||||
void DisableItems(bool v)
|
||||
@@ -144,8 +136,6 @@ namespace Netch.Forms
|
||||
await MainController.Start(ServerComboBox.SelectedItem as Server, mode);
|
||||
}
|
||||
|
||||
var serverLock = new object();
|
||||
|
||||
await Task.WhenAll(Global.Settings.SubscribeLink.Select(async item => await Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
@@ -156,31 +146,25 @@ namespace Netch.Forms
|
||||
if (Global.Settings.UseProxyToUpdateSubscription)
|
||||
request.Proxy = new WebProxy($"http://127.0.0.1:{Global.Settings.HTTPLocalPort}");
|
||||
|
||||
var str = await WebUtil.DownloadStringAsync(request);
|
||||
var servers = ShareLink.ParseText(await WebUtil.DownloadStringAsync(request));
|
||||
|
||||
lock (serverLock)
|
||||
foreach (var server in servers)
|
||||
{
|
||||
Global.Settings.Server.RemoveAll(server => server.Group == item.Remark);
|
||||
|
||||
var result = ShareLink.ParseText(str);
|
||||
if (result != null)
|
||||
{
|
||||
foreach (var server in result)
|
||||
{
|
||||
server.Group = item.Remark;
|
||||
Global.Settings.Server.Add(server);
|
||||
}
|
||||
}
|
||||
|
||||
NotifyTip(i18N.TranslateFormat("Update {1} server(s) from {0}", item.Remark, result?.Count ?? 0));
|
||||
server.Group = item.Remark;
|
||||
}
|
||||
}
|
||||
catch (WebException e)
|
||||
{
|
||||
NotifyTip($"{i18N.TranslateFormat("Update servers error from {0}", item.Remark)}\n{e.Message}", info: false);
|
||||
|
||||
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());
|
||||
@@ -314,32 +298,36 @@ namespace Netch.Forms
|
||||
|
||||
private async void UninstallServiceToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Enabled = false;
|
||||
State = State.Starting;
|
||||
StatusText(i18N.TranslateFormat("Uninstalling {0}", "NF Service"));
|
||||
var result = false;
|
||||
try
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
if (NFController.UninstallDriver())
|
||||
{
|
||||
StatusText(i18N.TranslateFormat("{0} has been uninstalled", "NF Service"));
|
||||
result = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
finally
|
||||
{
|
||||
Enabled = true;
|
||||
State = State.Stopped;
|
||||
if (result)
|
||||
StatusText(i18N.TranslateFormat("{0} has been uninstalled", "NF Service"));
|
||||
}
|
||||
}
|
||||
|
||||
private async void reinstallTapDriverToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
State = State.Starting;
|
||||
StatusText(i18N.TranslateFormat("Uninstalling {0}", "TUN/TAP driver"));
|
||||
Enabled = false;
|
||||
var result = false;
|
||||
try
|
||||
{
|
||||
await Task.Run(TUNTAP.deltapall);
|
||||
StatusText(i18N.TranslateFormat("{0} has been uninstalled", "TUN/TAP driver"));
|
||||
result = true;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
@@ -347,8 +335,9 @@ namespace Netch.Forms
|
||||
}
|
||||
finally
|
||||
{
|
||||
State = State.Waiting;
|
||||
Enabled = true;
|
||||
State = State.Stopped;
|
||||
if (result)
|
||||
StatusText(i18N.TranslateFormat("{0} has been uninstalled", "TUN/TAP driver"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace Netch.Forms
|
||||
{
|
||||
FileName = Path.Combine(Global.NetchDir, "NetchUpdater.exe"),
|
||||
Arguments =
|
||||
$"{Global.Settings.UDPSocketPort} {fileFullPath} {Global.NetchDir}"
|
||||
$"{Global.Settings.UDPSocketPort} \"{fileFullPath}\" \"{Global.NetchDir}\""
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,12 +15,8 @@ namespace Netch.Forms
|
||||
|
||||
partial class MainForm
|
||||
{
|
||||
/// init at <see cref="MainForm_Load"/>
|
||||
private int _sizeHeight;
|
||||
|
||||
private int _profileConfigurationHeight;
|
||||
private int _profileGroupboxHeight;
|
||||
private int _configurationGroupBoxHeight;
|
||||
private int _profileConfigurationHeight;
|
||||
|
||||
private void InitProfile()
|
||||
{
|
||||
@@ -41,7 +37,6 @@ namespace Netch.Forms
|
||||
ProfileGroupBox.Visible = false;
|
||||
|
||||
ConfigurationGroupBox.Size = new Size(ConfigurationGroupBox.Size.Width, _configurationGroupBoxHeight - _profileConfigurationHeight);
|
||||
Size = new Size(Size.Width, _sizeHeight - (_profileConfigurationHeight + _profileGroupboxHeight));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -75,11 +70,9 @@ namespace Netch.Forms
|
||||
ProfileTable.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 1));
|
||||
}
|
||||
|
||||
if (Size.Height == _sizeHeight) return;
|
||||
configLayoutPanel.RowStyles[2].SizeType = SizeType.AutoSize;
|
||||
ProfileGroupBox.Visible = true;
|
||||
ConfigurationGroupBox.Size = new Size(ConfigurationGroupBox.Size.Width, _configurationGroupBoxHeight);
|
||||
Size = new Size(Size.Width, _sizeHeight);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -183,34 +183,55 @@ namespace Netch.Forms
|
||||
|
||||
public static class StatusPortInfoText
|
||||
{
|
||||
public static int Socks5Port = 0;
|
||||
public static int HttpPort = 0;
|
||||
public static bool ShareLan = false;
|
||||
private static ushort? _socks5Port;
|
||||
private static ushort? _httpPort;
|
||||
private static bool? _shareLan;
|
||||
|
||||
public static bool ShareLan
|
||||
{
|
||||
set => _shareLan = value;
|
||||
}
|
||||
|
||||
public static ushort HttpPort
|
||||
{
|
||||
set => _httpPort = value;
|
||||
}
|
||||
|
||||
public static ushort Socks5Port
|
||||
{
|
||||
set => _socks5Port = value;
|
||||
}
|
||||
|
||||
public static string Value
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Socks5Port == 0 && HttpPort == 0)
|
||||
if (_socks5Port == null && _httpPort == null)
|
||||
return string.Empty;
|
||||
|
||||
var text = new StringBuilder();
|
||||
if (ShareLan)
|
||||
if (_shareLan == true)
|
||||
text.Append(i18N.Translate("Allow other Devices to connect") + " ");
|
||||
|
||||
if (Socks5Port != 0)
|
||||
text.Append($"Socks5 {i18N.Translate("Local Port", ": ")}{Socks5Port}");
|
||||
if (_socks5Port != null)
|
||||
text.Append($"Socks5 {i18N.Translate("Local Port", ": ")}{_socks5Port}");
|
||||
|
||||
if (HttpPort != 0)
|
||||
if (_httpPort != null)
|
||||
{
|
||||
if (Socks5Port != 0)
|
||||
if (_socks5Port != null)
|
||||
text.Append(" | ");
|
||||
text.Append($"HTTP {i18N.Translate("Local Port", ": ")}{HttpPort}");
|
||||
text.Append($"HTTP {i18N.Translate("Local Port", ": ")}{_httpPort}");
|
||||
}
|
||||
|
||||
return $" ({text})";
|
||||
}
|
||||
}
|
||||
|
||||
public static void Reset()
|
||||
{
|
||||
_httpPort = _socks5Port = null;
|
||||
_shareLan = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -63,10 +64,8 @@ namespace Netch.Forms
|
||||
// 隐藏 NatTypeStatusLabel
|
||||
NatTypeStatusText();
|
||||
|
||||
_sizeHeight = Size.Height;
|
||||
_configurationGroupBoxHeight = ConfigurationGroupBox.Height;
|
||||
_profileConfigurationHeight = ConfigurationGroupBox.Controls[0].Height / 3; // 因为 AutoSize, 所以得到的是Controls的总高度
|
||||
_profileGroupboxHeight = ProfileGroupBox.Height;
|
||||
// 加载快速配置
|
||||
InitProfile();
|
||||
|
||||
@@ -234,11 +233,12 @@ namespace Netch.Forms
|
||||
case ListControl _:
|
||||
break;
|
||||
case Control c:
|
||||
|
||||
c.Text = ControlText(c.Name);
|
||||
if (_mainFormText.ContainsKey(c.Name))
|
||||
c.Text = ControlText(c.Name);
|
||||
break;
|
||||
case ToolStripItem c:
|
||||
c.Text = ControlText(c.Name);
|
||||
if (_mainFormText.ContainsKey(c.Name))
|
||||
c.Text = ControlText(c.Name);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -282,6 +282,10 @@ namespace Netch.Forms
|
||||
}
|
||||
|
||||
Configuration.Save();
|
||||
|
||||
if (File.Exists("data\\last.json"))
|
||||
File.Delete("data\\last.json");
|
||||
|
||||
State = State.Terminating;
|
||||
}
|
||||
|
||||
@@ -330,7 +334,7 @@ namespace Netch.Forms
|
||||
|
||||
private async void SpeedPictureBox_Click(object sender, EventArgs e)
|
||||
{
|
||||
Enabled = false;
|
||||
State = State.Starting;
|
||||
StatusText(i18N.Translate("Testing"));
|
||||
try
|
||||
{
|
||||
@@ -338,7 +342,7 @@ namespace Netch.Forms
|
||||
}
|
||||
finally
|
||||
{
|
||||
Enabled = true;
|
||||
State = State.Stopped;
|
||||
StatusText(i18N.Translate("Test done"));
|
||||
Refresh();
|
||||
}
|
||||
|
||||
19
Netch/Forms/Mode/Process.Designer.cs
generated
19
Netch/Forms/Mode/Process.Designer.cs
generated
@@ -47,19 +47,21 @@ namespace Netch.Forms.Mode
|
||||
this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||
this.ControlButton = new System.Windows.Forms.Button();
|
||||
this.DeleteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.containerControl1 = new System.Windows.Forms.ContainerControl();
|
||||
this.ConfigurationGroupBox.SuspendLayout();
|
||||
this.ProcessGroupBox.SuspendLayout();
|
||||
this.contextMenuStrip.SuspendLayout();
|
||||
this.containerControl1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// ConfigurationGroupBox
|
||||
//
|
||||
this.ConfigurationGroupBox.Controls.Add(this.containerControl1);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.UseCustomFilenameBox);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.FilenameLabel);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.FilenameTextBox);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.ScanButton);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.ProcessGroupBox);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.RuleListBox);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.RemarkTextBox);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.RemarkLabel);
|
||||
this.ConfigurationGroupBox.Location = new System.Drawing.Point(12, 12);
|
||||
@@ -136,8 +138,9 @@ namespace Netch.Forms.Mode
|
||||
// RuleListBox
|
||||
//
|
||||
this.RuleListBox.FormattingEnabled = true;
|
||||
this.RuleListBox.Dock = DockStyle.Fill;
|
||||
this.RuleListBox.ItemHeight = 17;
|
||||
this.RuleListBox.Location = new System.Drawing.Point(6, 100);
|
||||
this.RuleListBox.Location = new System.Drawing.Point(0, 0);
|
||||
this.RuleListBox.Name = "RuleListBox";
|
||||
this.RuleListBox.Size = new System.Drawing.Size(328, 157);
|
||||
this.RuleListBox.TabIndex = 2;
|
||||
@@ -183,6 +186,16 @@ namespace Netch.Forms.Mode
|
||||
this.DeleteToolStripMenuItem.Text = "Delete";
|
||||
this.DeleteToolStripMenuItem.Click += new System.EventHandler(this.deleteRule_Click);
|
||||
//
|
||||
// containerControl1
|
||||
//
|
||||
this.containerControl1.Controls.Add(this.RuleListBox);
|
||||
this.containerControl1.Location = new System.Drawing.Point(6, 100);
|
||||
this.containerControl1.Name = "containerControl1";
|
||||
this.containerControl1.Size = new System.Drawing.Size(328, 157);
|
||||
this.containerControl1.TabIndex = 10;
|
||||
this.containerControl1.Padding = new Padding(0);
|
||||
this.containerControl1.Text = "containerControl1";
|
||||
//
|
||||
// Process
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
|
||||
@@ -204,11 +217,13 @@ namespace Netch.Forms.Mode
|
||||
this.ProcessGroupBox.ResumeLayout(false);
|
||||
this.ProcessGroupBox.PerformLayout();
|
||||
this.contextMenuStrip.ResumeLayout(false);
|
||||
this.containerControl1.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.ContainerControl containerControl1;
|
||||
private System.Windows.Forms.ContextMenuStrip contextMenuStrip;
|
||||
private System.Windows.Forms.ToolStripMenuItem DeleteToolStripMenuItem;
|
||||
public System.Windows.Forms.GroupBox ConfigurationGroupBox;
|
||||
|
||||
@@ -142,10 +142,6 @@ namespace Netch.Forms.Mode
|
||||
if (!string.IsNullOrWhiteSpace(ProcessNameTextBox.Text))
|
||||
{
|
||||
var process = ProcessNameTextBox.Text;
|
||||
if (!process.EndsWith(".exe"))
|
||||
{
|
||||
process += ".exe";
|
||||
}
|
||||
|
||||
if (!RuleListBox.Items.Contains(process))
|
||||
{
|
||||
|
||||
144
Netch/Forms/ServerForm.Designer.cs
generated
144
Netch/Forms/ServerForm.Designer.cs
generated
@@ -1,144 +0,0 @@
|
||||
namespace Netch.Forms
|
||||
{
|
||||
partial class ServerForm
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ServerForm));
|
||||
this.ConfigurationGroupBox = new System.Windows.Forms.GroupBox();
|
||||
this.AddressLabel = new System.Windows.Forms.Label();
|
||||
this.PortTextBox = new System.Windows.Forms.TextBox();
|
||||
this.AddressTextBox = new System.Windows.Forms.TextBox();
|
||||
this.RemarkTextBox = new System.Windows.Forms.TextBox();
|
||||
this.RemarkLabel = new System.Windows.Forms.Label();
|
||||
this.PortLabel = new System.Windows.Forms.Label();
|
||||
this.ConfigurationGroupBox.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// ConfigurationGroupBox
|
||||
//
|
||||
this.ConfigurationGroupBox.AutoSize = true;
|
||||
this.ConfigurationGroupBox.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
this.ConfigurationGroupBox.Controls.Add(this.AddressLabel);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.PortTextBox);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.AddressTextBox);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.RemarkTextBox);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.RemarkLabel);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.PortLabel);
|
||||
this.ConfigurationGroupBox.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.ConfigurationGroupBox.Location = new System.Drawing.Point(5, 5);
|
||||
this.ConfigurationGroupBox.Name = "ConfigurationGroupBox";
|
||||
this.ConfigurationGroupBox.Size = new System.Drawing.Size(434, 127);
|
||||
this.ConfigurationGroupBox.TabIndex = 0;
|
||||
this.ConfigurationGroupBox.TabStop = false;
|
||||
this.ConfigurationGroupBox.Text = "Configuration";
|
||||
//
|
||||
// AddressLabel
|
||||
//
|
||||
this.AddressLabel.AutoSize = true;
|
||||
this.AddressLabel.Location = new System.Drawing.Point(10, ControlLineHeight*2);
|
||||
this.AddressLabel.Name = "AddressLabel";
|
||||
this.AddressLabel.Size = new System.Drawing.Size(56, 17);
|
||||
this.AddressLabel.TabIndex = 2;
|
||||
this.AddressLabel.Text = "Address";
|
||||
//
|
||||
// PortTextBox
|
||||
//
|
||||
this.PortTextBox.Location = new System.Drawing.Point(358, ControlLineHeight*2);
|
||||
this.PortTextBox.Name = "PortTextBox";
|
||||
this.PortTextBox.Size = new System.Drawing.Size(56, 23);
|
||||
this.PortTextBox.TabIndex = 5;
|
||||
this.PortTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
//
|
||||
// AddressTextBox
|
||||
//
|
||||
this.AddressTextBox.Location = new System.Drawing.Point(120, ControlLineHeight*2);
|
||||
this.AddressTextBox.Name = "AddressTextBox";
|
||||
this.AddressTextBox.Size = new System.Drawing.Size(232, 23);
|
||||
this.AddressTextBox.TabIndex = 3;
|
||||
this.AddressTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
//
|
||||
// RemarkTextBox
|
||||
//
|
||||
this.RemarkTextBox.Location = new System.Drawing.Point(120, ControlLineHeight);
|
||||
this.RemarkTextBox.Name = "RemarkTextBox";
|
||||
this.RemarkTextBox.Size = new System.Drawing.Size(294, 23);
|
||||
this.RemarkTextBox.TabIndex = 1;
|
||||
this.RemarkTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
//
|
||||
// RemarkLabel
|
||||
//
|
||||
this.RemarkLabel.AutoSize = true;
|
||||
this.RemarkLabel.Location = new System.Drawing.Point(10, ControlLineHeight);
|
||||
this.RemarkLabel.Name = "RemarkLabel";
|
||||
this.RemarkLabel.Size = new System.Drawing.Size(53, 17);
|
||||
this.RemarkLabel.TabIndex = 0;
|
||||
this.RemarkLabel.Text = "Remark";
|
||||
//
|
||||
// PortLabel
|
||||
//
|
||||
this.PortLabel.AutoSize = true;
|
||||
this.PortLabel.Location = new System.Drawing.Point(351, ControlLineHeight*2);
|
||||
this.PortLabel.Name = "PortLabel";
|
||||
this.PortLabel.Size = new System.Drawing.Size(11, 17);
|
||||
this.PortLabel.TabIndex = 4;
|
||||
this.PortLabel.Text = ":";
|
||||
//
|
||||
// ServerForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
|
||||
this.AutoSize = true;
|
||||
this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
this.ClientSize = new System.Drawing.Size(444, 137);
|
||||
this.Controls.Add(this.ConfigurationGroupBox);
|
||||
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) (134)));
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||
this.Icon = ((System.Drawing.Icon) (resources.GetObject("$this.Icon")));
|
||||
this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
this.MaximizeBox = false;
|
||||
this.Name = "ServerForm";
|
||||
this.Padding = new System.Windows.Forms.Padding(11, 5, 11, 4);
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Load += new System.EventHandler(this.ServerForm_Load);
|
||||
this.ConfigurationGroupBox.ResumeLayout(false);
|
||||
this.ConfigurationGroupBox.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.GroupBox ConfigurationGroupBox;
|
||||
private System.Windows.Forms.Label RemarkLabel;
|
||||
protected System.Windows.Forms.TextBox RemarkTextBox;
|
||||
private System.Windows.Forms.Label PortLabel;
|
||||
protected System.Windows.Forms.TextBox AddressTextBox;
|
||||
private System.Windows.Forms.TextBox PortTextBox;
|
||||
private System.Windows.Forms.Label AddressLabel;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,16 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Models;
|
||||
using Netch.Properties;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Forms
|
||||
{
|
||||
public abstract partial class ServerForm : Form
|
||||
public abstract class ServerForm : Form
|
||||
{
|
||||
protected abstract string TypeName { get; }
|
||||
protected Server Server { get; set; }
|
||||
@@ -32,6 +34,35 @@ namespace Netch.Forms
|
||||
_saveActions.Add(PortTextBox, s => Server.Port = ushort.Parse((string) s));
|
||||
}
|
||||
|
||||
public new void ShowDialog()
|
||||
{
|
||||
AfterFactor();
|
||||
base.ShowDialog();
|
||||
}
|
||||
|
||||
public new void Show()
|
||||
{
|
||||
AfterFactor();
|
||||
base.Show();
|
||||
}
|
||||
|
||||
private void AfterFactor()
|
||||
{
|
||||
Text = TypeName ?? string.Empty;
|
||||
|
||||
RemarkTextBox.Text = Server.Remark;
|
||||
AddressTextBox.Text = Server.Hostname;
|
||||
PortTextBox.Text = Server.Port.ToString();
|
||||
|
||||
AddSaveButton();
|
||||
i18N.TranslateForm(this);
|
||||
|
||||
ConfigurationGroupBox.ResumeLayout(false);
|
||||
ConfigurationGroupBox.PerformLayout();
|
||||
ResumeLayout(false);
|
||||
PerformLayout();
|
||||
}
|
||||
|
||||
protected void CreateTextBox(string name, string remark, Func<string, bool> check, Action<string> save, string value, int width = InputBoxWidth)
|
||||
{
|
||||
_controlLines++;
|
||||
@@ -120,18 +151,6 @@ namespace Netch.Forms
|
||||
|
||||
private readonly Dictionary<Control, Action<object>> _saveActions = new Dictionary<Control, Action<object>>();
|
||||
|
||||
private void ServerForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
Text = TypeName ?? string.Empty;
|
||||
|
||||
RemarkTextBox.Text = Server.Remark;
|
||||
AddressTextBox.Text = Server.Hostname;
|
||||
PortTextBox.Text = Server.Port.ToString();
|
||||
|
||||
AddSaveButton();
|
||||
i18N.TranslateForm(this);
|
||||
}
|
||||
|
||||
private void AddSaveButton()
|
||||
{
|
||||
_controlLines++;
|
||||
@@ -174,5 +193,124 @@ namespace Netch.Forms
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
private IContainer components = null;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
components?.Dispose();
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
ConfigurationGroupBox = new GroupBox();
|
||||
AddressLabel = new Label();
|
||||
PortTextBox = new TextBox();
|
||||
AddressTextBox = new TextBox();
|
||||
RemarkTextBox = new TextBox();
|
||||
RemarkLabel = new Label();
|
||||
PortLabel = new Label();
|
||||
ConfigurationGroupBox.SuspendLayout();
|
||||
SuspendLayout();
|
||||
//
|
||||
// ConfigurationGroupBox
|
||||
//
|
||||
ConfigurationGroupBox.AutoSize = true;
|
||||
ConfigurationGroupBox.AutoSizeMode = AutoSizeMode.GrowAndShrink;
|
||||
ConfigurationGroupBox.Controls.Add(AddressLabel);
|
||||
ConfigurationGroupBox.Controls.Add(PortTextBox);
|
||||
ConfigurationGroupBox.Controls.Add(AddressTextBox);
|
||||
ConfigurationGroupBox.Controls.Add(RemarkTextBox);
|
||||
ConfigurationGroupBox.Controls.Add(RemarkLabel);
|
||||
ConfigurationGroupBox.Controls.Add(PortLabel);
|
||||
ConfigurationGroupBox.Dock = DockStyle.Fill;
|
||||
ConfigurationGroupBox.Location = new Point(5, 5);
|
||||
ConfigurationGroupBox.Name = "ConfigurationGroupBox";
|
||||
ConfigurationGroupBox.Size = new Size(434, 127);
|
||||
ConfigurationGroupBox.TabIndex = 0;
|
||||
ConfigurationGroupBox.TabStop = false;
|
||||
ConfigurationGroupBox.Text = "Configuration";
|
||||
//
|
||||
// AddressLabel
|
||||
//
|
||||
AddressLabel.AutoSize = true;
|
||||
AddressLabel.Location = new Point(10, ControlLineHeight * 2);
|
||||
AddressLabel.Name = "AddressLabel";
|
||||
AddressLabel.Size = new Size(56, 17);
|
||||
AddressLabel.TabIndex = 2;
|
||||
AddressLabel.Text = "Address";
|
||||
//
|
||||
// PortTextBox
|
||||
//
|
||||
PortTextBox.Location = new Point(358, ControlLineHeight * 2);
|
||||
PortTextBox.Name = "PortTextBox";
|
||||
PortTextBox.Size = new Size(56, 23);
|
||||
PortTextBox.TabIndex = 5;
|
||||
PortTextBox.TextAlign = HorizontalAlignment.Center;
|
||||
//
|
||||
// AddressTextBox
|
||||
//
|
||||
AddressTextBox.Location = new Point(120, ControlLineHeight * 2);
|
||||
AddressTextBox.Name = "AddressTextBox";
|
||||
AddressTextBox.Size = new Size(232, 23);
|
||||
AddressTextBox.TabIndex = 3;
|
||||
AddressTextBox.TextAlign = HorizontalAlignment.Center;
|
||||
//
|
||||
// RemarkTextBox
|
||||
//
|
||||
RemarkTextBox.Location = new Point(120, ControlLineHeight);
|
||||
RemarkTextBox.Name = "RemarkTextBox";
|
||||
RemarkTextBox.Size = new Size(294, 23);
|
||||
RemarkTextBox.TabIndex = 1;
|
||||
RemarkTextBox.TextAlign = HorizontalAlignment.Center;
|
||||
//
|
||||
// RemarkLabel
|
||||
//
|
||||
RemarkLabel.AutoSize = true;
|
||||
RemarkLabel.Location = new Point(10, ControlLineHeight);
|
||||
RemarkLabel.Name = "RemarkLabel";
|
||||
RemarkLabel.Size = new Size(53, 17);
|
||||
RemarkLabel.TabIndex = 0;
|
||||
RemarkLabel.Text = "Remark";
|
||||
//
|
||||
// PortLabel
|
||||
//
|
||||
PortLabel.AutoSize = true;
|
||||
PortLabel.Location = new Point(351, ControlLineHeight * 2);
|
||||
PortLabel.Name = "PortLabel";
|
||||
PortLabel.Size = new Size(11, 17);
|
||||
PortLabel.TabIndex = 4;
|
||||
PortLabel.Text = ":";
|
||||
//
|
||||
// ServerForm
|
||||
//
|
||||
AutoScaleDimensions = new SizeF(96F, 96F);
|
||||
AutoScaleMode = AutoScaleMode.Dpi;
|
||||
AutoSize = true;
|
||||
AutoSizeMode = AutoSizeMode.GrowAndShrink;
|
||||
ClientSize = new Size(444, 137);
|
||||
Controls.Add(ConfigurationGroupBox);
|
||||
Font = new Font("微软雅黑", 9F, FontStyle.Regular, GraphicsUnit.Point, (byte) 134);
|
||||
FormBorderStyle = FormBorderStyle.FixedSingle;
|
||||
Icon = Icon.FromHandle(Resources.Netch.GetHicon());
|
||||
Margin = new Padding(3, 4, 3, 4);
|
||||
MaximizeBox = false;
|
||||
Name = "ServerForm";
|
||||
Padding = new Padding(11, 5, 11, 4);
|
||||
StartPosition = FormStartPosition.CenterScreen;
|
||||
}
|
||||
|
||||
private GroupBox ConfigurationGroupBox;
|
||||
private Label RemarkLabel;
|
||||
protected TextBox RemarkTextBox;
|
||||
private Label PortLabel;
|
||||
protected TextBox AddressTextBox;
|
||||
private TextBox PortTextBox;
|
||||
private Label AddressLabel;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
829
Netch/Forms/SettingForm.Designer.cs
generated
829
Netch/Forms/SettingForm.Designer.cs
generated
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,11 @@
|
||||
using System;
|
||||
using Netch.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
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,55 +15,196 @@ namespace Netch.Forms
|
||||
public SettingForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
i18N.TranslateForm(this);
|
||||
InitValue();
|
||||
}
|
||||
|
||||
|
||||
private void SettingForm2_Load(object sender, EventArgs e)
|
||||
{
|
||||
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;
|
||||
TUNTAPUseCustomDNSCheckBox_CheckedChanged(null, null);
|
||||
ProxyDNSCheckBox.Checked = Global.Settings.TUNTAP.ProxyDNS;
|
||||
UseFakeDNSCheckBox.Checked = Global.Settings.TUNTAP.UseFakeDNS;
|
||||
BindTextBox<ushort>(Socks5PortTextBox,
|
||||
p => CheckPort("Socks5", p, Global.Settings.Socks5LocalPort),
|
||||
p => Global.Settings.Socks5LocalPort = p,
|
||||
Global.Settings.Socks5LocalPort);
|
||||
BindTextBox<ushort>(HTTPPortTextBox,
|
||||
p => CheckPort("HTTP", p, Global.Settings.HTTPLocalPort),
|
||||
p => Global.Settings.HTTPLocalPort = p,
|
||||
Global.Settings.HTTPLocalPort);
|
||||
BindTextBox<ushort>(RedirectorTextBox,
|
||||
s => CheckPort("RedirectorTCP", s, Global.Settings.RedirectorTCPPort),
|
||||
s => Global.Settings.RedirectorTCPPort = s,
|
||||
Global.Settings.HTTPLocalPort);
|
||||
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
|
||||
});
|
||||
|
||||
if (TUNTAPController.SearchTapAdapter())
|
||||
{
|
||||
ICSCheckBox.Enabled = true;
|
||||
ICSCheckBox.Checked = ICSHelper.Enabled;
|
||||
}
|
||||
|
||||
// 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;
|
||||
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);
|
||||
|
||||
ProfileCountTextBox.Text = Global.Settings.ProfileCount.ToString();
|
||||
TcpingAtStartedCheckBox.Checked = Global.Settings.StartedTcping;
|
||||
DetectionIntervalTextBox.Text = Global.Settings.StartedTcping_Interval.ToString();
|
||||
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);
|
||||
|
||||
#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);
|
||||
|
||||
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
|
||||
{
|
||||
var icsHelperEnabled = ICSHelper.Enabled;
|
||||
if (icsHelperEnabled != null)
|
||||
{
|
||||
ICSCheckBox.Enabled = true;
|
||||
ICSCheckBox.Checked = (bool) icsHelperEnabled;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region V2Ray
|
||||
|
||||
BindCheckBox(TLSAllowInsecureCheckBox,
|
||||
b => Global.Settings.V2RayConfig.AllowInsecure = b,
|
||||
Global.Settings.V2RayConfig.AllowInsecure);
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
private void TUNTAPUseCustomDNSCheckBox_CheckedChanged(object sender, EventArgs e)
|
||||
@@ -82,10 +223,6 @@ namespace Netch.Forms
|
||||
}
|
||||
}
|
||||
|
||||
private void InitText()
|
||||
{
|
||||
i18N.TranslateForm(this);
|
||||
}
|
||||
|
||||
private void InitSTUN()
|
||||
{
|
||||
@@ -94,7 +231,7 @@ namespace Netch.Forms
|
||||
var stuns = File.ReadLines("bin\\stun.txt");
|
||||
STUN_ServerComboBox.Items.AddRange(stuns.ToArray());
|
||||
}
|
||||
catch (Exception)
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
@@ -102,13 +239,6 @@ namespace Netch.Forms
|
||||
STUN_ServerComboBox.Text = $"{Global.Settings.STUN_Server}:{Global.Settings.STUN_Server_Port}";
|
||||
}
|
||||
|
||||
private void SettingForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
UseFakeDNSCheckBox.Visible = Global.Flags.SupportFakeDns;
|
||||
InitText();
|
||||
InitValue();
|
||||
}
|
||||
|
||||
private void GlobalBypassIPsButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
Hide();
|
||||
@@ -118,63 +248,16 @@ namespace Netch.Forms
|
||||
|
||||
private void ControlButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
#region Check
|
||||
|
||||
#region Port
|
||||
|
||||
int socks5LocalPort;
|
||||
int httpLocalPort;
|
||||
int redirectorTCPPort;
|
||||
try
|
||||
{
|
||||
socks5LocalPort = int.Parse(Socks5PortTextBox.Text);
|
||||
httpLocalPort = int.Parse(HTTPPortTextBox.Text);
|
||||
redirectorTCPPort = int.Parse(RedirectorTextBox.Text);
|
||||
|
||||
static void CheckPort(string portName, int port, int originPort, PortType portType = PortType.Both)
|
||||
{
|
||||
if (port <= 0 || port > 65536)
|
||||
throw new FormatException();
|
||||
|
||||
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);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
switch (exception)
|
||||
{
|
||||
case FormatException _:
|
||||
MessageBoxX.Show(i18N.Translate("Port value illegal. Try again."));
|
||||
break;
|
||||
case PortInUseException _:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!_checkActions.All(pair => pair.Value.Invoke(pair.Key.Text)))
|
||||
return;
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region Check
|
||||
|
||||
#region TUNTAP
|
||||
|
||||
var dns = new string[0];
|
||||
try
|
||||
{
|
||||
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())
|
||||
@@ -196,11 +279,6 @@ namespace Netch.Forms
|
||||
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}");
|
||||
@@ -213,44 +291,6 @@ namespace Netch.Forms
|
||||
|
||||
#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;
|
||||
@@ -270,7 +310,6 @@ namespace Netch.Forms
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
ProfileCountTextBox.Text = Global.Settings.ProfileCount.ToString();
|
||||
MessageBoxX.Show(i18N.Translate("STUN_ServerPort value illegal. Try again."));
|
||||
|
||||
return;
|
||||
@@ -282,54 +321,14 @@ 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.ProfileCount = profileCount;
|
||||
Global.Settings.StartedTcping = TcpingAtStartedCheckBox.Checked;
|
||||
Global.Settings.StartedTcping_Interval = detectionInterval;
|
||||
Global.Settings.TUNTAP.DNS = dns.ToList();
|
||||
Global.Settings.STUN_Server = stunServer;
|
||||
Global.Settings.STUN_Server_Port = stunServerPort;
|
||||
Global.Settings.ACL = AclAddrTextBox.Text;
|
||||
Global.Settings.Language = LanguageComboBox.SelectedItem.ToString();
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -385,22 +384,75 @@ namespace Netch.Forms
|
||||
Close();
|
||||
}
|
||||
|
||||
private bool CheckPort(string portName, ushort port, ushort originPort, PortType portType = PortType.Both)
|
||||
{
|
||||
if (port == originPort) return true;
|
||||
if (!PortHelper.PortInUse(port, portType)) return true;
|
||||
|
||||
MessageBoxX.Show(i18N.TranslateFormat("The {0} port is in use.", portName));
|
||||
return false;
|
||||
}
|
||||
|
||||
private async void ICSCheckBox_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
ICSCheckBox.Enabled = false;
|
||||
await Task.Run(() =>
|
||||
try
|
||||
{
|
||||
if (ICSCheckBox.Checked)
|
||||
ICSCheckBox.Enabled = false;
|
||||
await Task.Run(() =>
|
||||
{
|
||||
if (!ICSHelper.Enabled)
|
||||
ICSCheckBox.Checked = ICSHelper.Enable();
|
||||
if (ICSCheckBox.Checked)
|
||||
{
|
||||
if (!(ICSHelper.Enabled ?? true))
|
||||
ICSCheckBox.Checked = ICSHelper.Enable();
|
||||
}
|
||||
else
|
||||
{
|
||||
ICSHelper.Disable();
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
ICSCheckBox.Checked = false;
|
||||
Logging.Error(exception.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
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)));
|
||||
}
|
||||
else
|
||||
catch
|
||||
{
|
||||
ICSHelper.Disable();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
ICSCheckBox.Enabled = true;
|
||||
_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>>();
|
||||
}
|
||||
}
|
||||
7
Netch/Forms/SubscribeForm.Designer.cs
generated
7
Netch/Forms/SubscribeForm.Designer.cs
generated
@@ -81,11 +81,11 @@
|
||||
//
|
||||
// ClearButton
|
||||
//
|
||||
this.ClearButton.Location = new System.Drawing.Point(477, 103);
|
||||
this.ClearButton.Location = new System.Drawing.Point(448, 103);
|
||||
this.ClearButton.Name = "ClearButton";
|
||||
this.ClearButton.Size = new System.Drawing.Size(58, 26);
|
||||
this.ClearButton.Size = new System.Drawing.Size(87, 26);
|
||||
this.ClearButton.TabIndex = 7;
|
||||
this.ClearButton.Text = "Clear";
|
||||
this.ClearButton.Text = "Unselect";
|
||||
this.ClearButton.UseVisualStyleBackColor = true;
|
||||
this.ClearButton.Click += new System.EventHandler(this.ClearButton_Click);
|
||||
//
|
||||
@@ -114,7 +114,6 @@
|
||||
this.LinkTextBox.Name = "LinkTextBox";
|
||||
this.LinkTextBox.Size = new System.Drawing.Size(545, 23);
|
||||
this.LinkTextBox.TabIndex = 4;
|
||||
this.LinkTextBox.TextChanged += new System.EventHandler(this.ListTextBox_TextChanged);
|
||||
//
|
||||
// LinkLabel
|
||||
//
|
||||
|
||||
@@ -109,39 +109,23 @@ namespace Netch.Forms
|
||||
return;
|
||||
}
|
||||
|
||||
// 备注重复的订阅项
|
||||
var duplicateRemarkItems = Global.Settings.SubscribeLink.Where(link => link.Remark.Equals(RemarkLabel.Text));
|
||||
|
||||
// 链接重复的订阅项
|
||||
SubscribeLink duplicateLinkItem = null;
|
||||
try
|
||||
{
|
||||
duplicateLinkItem = Global.Settings.SubscribeLink.First(link => link.Link.Equals(LinkTextBox.Text));
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
if (duplicateRemarkItems.Any())
|
||||
if (Global.Settings.SubscribeLink.Any(link => link.Remark.Equals(RemarkTextBox.Text)))
|
||||
{
|
||||
MessageBoxX.Show("Remark Name Duplicate!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (duplicateLinkItem != null)
|
||||
if (_editingIndex == -1)
|
||||
{
|
||||
if (duplicateLinkItem.Remark != RemarkTextBox.Text)
|
||||
Global.Settings.SubscribeLink.Add(new SubscribeLink
|
||||
{
|
||||
RenameServersGroup(duplicateLinkItem.Remark, RemarkTextBox.Text);
|
||||
}
|
||||
|
||||
duplicateLinkItem.Remark = RemarkTextBox.Text;
|
||||
duplicateLinkItem.UserAgent = UserAgentTextBox.Text;
|
||||
Remark = RemarkTextBox.Text,
|
||||
Link = LinkTextBox.Text,
|
||||
UserAgent = UserAgentTextBox.Text
|
||||
});
|
||||
}
|
||||
else if (_editingIndex != -1)
|
||||
else
|
||||
{
|
||||
// 只修改备注/未修改被上面处理
|
||||
var target = Global.Settings.SubscribeLink[_editingIndex];
|
||||
if (MessageBox.Show(i18N.Translate("Delete the corresponding group of items in the server list?"), i18N.Translate("Confirm"), MessageBoxButtons.YesNo) == DialogResult.Yes)
|
||||
{
|
||||
@@ -156,15 +140,6 @@ namespace Netch.Forms
|
||||
target.Remark = RemarkTextBox.Text;
|
||||
target.UserAgent = UserAgentTextBox.Text;
|
||||
}
|
||||
else
|
||||
{
|
||||
Global.Settings.SubscribeLink.Add(new SubscribeLink
|
||||
{
|
||||
Remark = RemarkTextBox.Text,
|
||||
Link = LinkTextBox.Text,
|
||||
UserAgent = UserAgentTextBox.Text
|
||||
});
|
||||
}
|
||||
|
||||
Configuration.Save();
|
||||
Global.Settings.UseProxyToUpdateSubscription = UseSelectedServerCheckBox.Checked;
|
||||
@@ -260,17 +235,5 @@ namespace Netch.Forms
|
||||
{
|
||||
ResetEditingGroup();
|
||||
}
|
||||
|
||||
private void ListTextBox_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
for (var i = 0; i < SubscribeLinkListView.Items.Count; i++)
|
||||
{
|
||||
if (((TextBox) sender).Text == SubscribeLinkListView.Items[i].SubItems[1].Text)
|
||||
{
|
||||
_editingIndex = i;
|
||||
AddSubscriptionBox.Text = SubscribeLinkListView.Items[i].SubItems[0].Text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,13 +28,13 @@ namespace Netch.Models
|
||||
/// </summary>
|
||||
string[] UriScheme { get; }
|
||||
|
||||
Server ParseJObject(JObject j);
|
||||
Server ParseJObject(in JObject j);
|
||||
|
||||
public void Edit(Server s);
|
||||
|
||||
public void Create();
|
||||
|
||||
string GetShareLink(Server server);
|
||||
string GetShareLink(Server s);
|
||||
|
||||
public abstract IServerController GetController();
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Models
|
||||
@@ -32,6 +33,20 @@ namespace Netch.Models
|
||||
/// </summary>
|
||||
public int Type = 0;
|
||||
|
||||
public bool SupportSocks5Auth => Type switch
|
||||
{
|
||||
0 => true,
|
||||
_ => false
|
||||
};
|
||||
|
||||
public bool TestNatRequired => Type switch
|
||||
{
|
||||
0 => true,
|
||||
1 => true,
|
||||
2 => true,
|
||||
_ => false
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 绕过中国(0. 不绕过 1. 绕过)
|
||||
/// </summary>
|
||||
@@ -42,6 +57,65 @@ namespace Netch.Models
|
||||
/// </summary>
|
||||
public readonly List<string> Rule = new List<string>();
|
||||
|
||||
public List<string> FullRule
|
||||
{
|
||||
get
|
||||
{
|
||||
var result = new List<string>();
|
||||
foreach (var s in Rule)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(s))
|
||||
continue;
|
||||
if (s.StartsWith("//"))
|
||||
continue;
|
||||
|
||||
if (s.StartsWith("#include"))
|
||||
{
|
||||
var relativePath = new StringBuilder(s.Substring(8).Trim());
|
||||
relativePath.Replace("<", "");
|
||||
relativePath.Replace(">", "");
|
||||
relativePath.Replace(".h", ".txt");
|
||||
|
||||
var mode = Global.Modes.FirstOrDefault(m => m.RelativePath.Equals(relativePath.ToString()));
|
||||
|
||||
if (mode == null)
|
||||
{
|
||||
Logging.Warning($"{relativePath} file included in {Remark} not found");
|
||||
}
|
||||
else if (mode == this)
|
||||
{
|
||||
Logging.Warning("Can't self-reference");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mode.Type != Type)
|
||||
{
|
||||
Logging.Warning($"{mode.Remark}'s mode is not as same as {Remark}'s mode");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mode.Rule.Any(rule => rule.StartsWith("#include")))
|
||||
{
|
||||
Logging.Warning("Cannot reference mode that reference other mode");
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AddRange(mode.FullRule);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Add(s);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取备注
|
||||
/// </summary>
|
||||
|
||||
@@ -34,15 +34,13 @@ namespace Netch.Models
|
||||
/// <summary>
|
||||
/// 端口
|
||||
/// </summary>
|
||||
public int Port;
|
||||
public ushort Port;
|
||||
|
||||
/// <summary>
|
||||
/// 延迟
|
||||
/// </summary>
|
||||
public int Delay = -1;
|
||||
|
||||
public bool IsSocks5() => Type == "Socks5";
|
||||
|
||||
/// <summary>
|
||||
/// 获取备注
|
||||
/// </summary>
|
||||
@@ -101,4 +99,12 @@ namespace Netch.Models
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class ServerExtension
|
||||
{
|
||||
public static string AutoResolveHostname(this Server server)
|
||||
{
|
||||
return Global.Settings.ResolveServerHostname ? DNS.Lookup(server.Hostname).ToString() : server.Hostname;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,30 @@ 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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用于读取和写入的配置的类
|
||||
/// </summary>
|
||||
@@ -103,6 +127,11 @@ namespace Netch.Models
|
||||
/// </summary>
|
||||
public bool ModifySystemDNS = false;
|
||||
|
||||
/// <summary>
|
||||
/// 解析服务器主机名
|
||||
/// </summary>
|
||||
public bool ResolveServerHostname = false;
|
||||
|
||||
/// <summary>
|
||||
/// 网页请求超时 毫秒
|
||||
/// </summary>
|
||||
@@ -111,22 +140,22 @@ namespace Netch.Models
|
||||
/// <summary>
|
||||
/// HTTP 本地端口
|
||||
/// </summary>
|
||||
public int HTTPLocalPort = 2802;
|
||||
public ushort HTTPLocalPort = 2802;
|
||||
|
||||
/// <summary>
|
||||
/// Socks5 本地端口
|
||||
/// </summary>
|
||||
public int Socks5LocalPort = 2801;
|
||||
public ushort Socks5LocalPort = 2801;
|
||||
|
||||
/// <summary>
|
||||
/// Redirector TCP 占用端口
|
||||
/// </summary>
|
||||
public int RedirectorTCPPort = 3901;
|
||||
public ushort RedirectorTCPPort = 3901;
|
||||
|
||||
/// <summary>
|
||||
/// UDP Socket 占用端口
|
||||
/// </summary>
|
||||
public int UDPSocketPort = 18291;
|
||||
public ushort UDPSocketPort = 18291;
|
||||
|
||||
/// <summary>
|
||||
/// HTTP 和 Socks5 本地代理地址
|
||||
@@ -196,11 +225,13 @@ namespace Netch.Models
|
||||
/// <summary>
|
||||
/// 是否使用DLL启动Shadowsocks
|
||||
/// </summary>
|
||||
public bool BootShadowsocksFromDLL = false;
|
||||
public bool BootShadowsocksFromDLL = true;
|
||||
|
||||
/// <summary>
|
||||
/// 语言设置
|
||||
/// </summary>
|
||||
public string Language = "System";
|
||||
|
||||
public V2rayConfig V2RayConfig = new V2rayConfig();
|
||||
}
|
||||
}
|
||||
@@ -2,18 +2,6 @@
|
||||
|
||||
namespace Netch
|
||||
{
|
||||
public enum NameList : int
|
||||
{
|
||||
TYPE_FILTERLOOPBACK,
|
||||
TYPE_FILTERTCP,
|
||||
TYPE_FILTERUDP,
|
||||
TYPE_TCPHOST,
|
||||
TYPE_UDPHOST,
|
||||
TYPE_ADDNAME,
|
||||
TYPE_BYPNAME,
|
||||
TYPE_CLRNAME
|
||||
}
|
||||
|
||||
public static class NativeMethods
|
||||
{
|
||||
/// <summary>
|
||||
@@ -66,5 +54,11 @@ namespace Netch
|
||||
|
||||
[DllImport("dnsapi", EntryPoint = "DnsFlushResolverCache")]
|
||||
public static extern uint FlushDNSResolverCache();
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool AllocConsole();
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool AttachConsole(int dwProcessId);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
@@ -17,6 +18,12 @@ namespace Netch
|
||||
[STAThread]
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
if (args.Contains("-console"))
|
||||
{
|
||||
NativeMethods.AllocConsole();
|
||||
NativeMethods.AttachConsole(-1);
|
||||
}
|
||||
|
||||
// 创建互斥体防止多次运行
|
||||
using (var mutex = new Mutex(false, "Global\\Netch"))
|
||||
{
|
||||
|
||||
@@ -66,12 +66,11 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ILMerge" Version="3.0.41" />
|
||||
<PackageReference Include="IPNetwork2" Version="2.5.211" />
|
||||
<PackageReference Include="MaxMind.GeoIP2" Version="3.2.0" />
|
||||
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="2.0.58" />
|
||||
<PackageReference Include="MaxMind.GeoIP2" Version="3.3.0" />
|
||||
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="2.0.61" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="System.Collections.Immutable" Version="5.0.0-preview.8.20407.11" />
|
||||
<PackageReference Include="System.Reflection.Metadata" Version="5.0.0-preview.8.20407.11" />
|
||||
<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="WindowsAPICodePack-Shell" Version="1.1.1" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@
|
||||
"Check update when opened": "打开软件时检查更新",
|
||||
"Check Beta update": "检查 Beta 更新",
|
||||
"Update subscribeat when opened": "自动更新订阅",
|
||||
"SS DLL(No ACL support)": "SS DLL(不支持 ACL)",
|
||||
"SS DLL": "SS DLL",
|
||||
"Modify System DNS": "修改系统 DNS",
|
||||
"ProfileCount": "快捷配置数量",
|
||||
"ProfileCount value illegal. Try again.": "快捷配置数值非法。请重试。",
|
||||
@@ -169,6 +169,7 @@
|
||||
"Custom ACL": "自定义 ACL 规则",
|
||||
"Language": "语言",
|
||||
"Tap Network Sharing": "Tap 网络共享",
|
||||
"Resolve Server Hostname": "解析服务器主机名",
|
||||
|
||||
"Profile": "配置名",
|
||||
"Profiles": "配置",
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Netch.Servers.Shadowsocks.Models.SSD
|
||||
/// <summary>
|
||||
/// 端口
|
||||
/// </summary>
|
||||
public int port;
|
||||
public ushort port;
|
||||
|
||||
/// <summary>
|
||||
/// 加密方式
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
/// <summary>
|
||||
/// 端口
|
||||
/// </summary>
|
||||
public int port;
|
||||
public ushort port;
|
||||
|
||||
/// <summary>
|
||||
/// 加密方式
|
||||
|
||||
@@ -3,7 +3,7 @@ namespace Netch.Servers.Shadowsocks.Models
|
||||
public class ShadowsocksConfig
|
||||
{
|
||||
public string server { get; set; }
|
||||
public int server_port { get; set; }
|
||||
public ushort server_port { get; set; }
|
||||
public string password { get; set; }
|
||||
public string method { get; set; }
|
||||
public string remarks { get; set; }
|
||||
|
||||
@@ -11,23 +11,24 @@ namespace Netch.Servers.Shadowsocks
|
||||
public override string Name { get; protected set; } = "Shadowsocks";
|
||||
public override string MainFile { get; protected set; } = "Shadowsocks.exe";
|
||||
|
||||
public int? Socks5LocalPort { get; set; }
|
||||
public Server Server { get; set; }
|
||||
public ushort? Socks5LocalPort { get; set; }
|
||||
public string LocalAddress { get; set; }
|
||||
|
||||
public bool Start(Server s, Mode mode)
|
||||
{
|
||||
bool DllFlag()
|
||||
{
|
||||
return Global.Settings.BootShadowsocksFromDLL && (mode.Type == 0 || mode.Type == 1 || mode.Type == 2);
|
||||
}
|
||||
private Mode _savedMode;
|
||||
public bool DllFlag => Global.Settings.BootShadowsocksFromDLL && (_savedMode.Type == 0 || _savedMode.Type == 1 || _savedMode.Type == 2);
|
||||
|
||||
public bool Start(in Server s, in Mode mode)
|
||||
{
|
||||
_savedMode = mode;
|
||||
Server = s;
|
||||
var server = (Shadowsocks) s;
|
||||
//从DLL启动Shaowsocks
|
||||
if (DllFlag())
|
||||
if (DllFlag)
|
||||
{
|
||||
State = State.Starting;
|
||||
var client = Encoding.UTF8.GetBytes($"{LocalAddress}:{Socks5LocalPort}");
|
||||
var remote = Encoding.UTF8.GetBytes($"{DNS.Lookup(server.Hostname)}:{server.Port}");
|
||||
var client = Encoding.UTF8.GetBytes($"{this.LocalAddress()}:{this.Socks5LocalPort()}");
|
||||
var remote = Encoding.UTF8.GetBytes($"{server.AutoResolveHostname()}:{server.Port}");
|
||||
var passwd = Encoding.UTF8.GetBytes($"{server.Password}");
|
||||
var method = Encoding.UTF8.GetBytes($"{server.EncryptMethod}");
|
||||
if (!ShadowsocksDLL.Info(client, remote, passwd, method))
|
||||
@@ -55,10 +56,10 @@ namespace Netch.Servers.Shadowsocks
|
||||
|
||||
var argument = new StringBuilder();
|
||||
argument.Append(
|
||||
$"-s {DNS.Lookup(server.Hostname)} " +
|
||||
$"-s {server.AutoResolveHostname()} " +
|
||||
$"-p {server.Port} " +
|
||||
$"-b {LocalAddress ?? Global.Settings.LocalAddress} " +
|
||||
$"-l {Socks5LocalPort ?? Global.Settings.Socks5LocalPort} " +
|
||||
$"-b {this.LocalAddress()} " +
|
||||
$"-l {this.Socks5LocalPort()} " +
|
||||
$"-m {server.EncryptMethod} " +
|
||||
$"-k \"{server.Password}\" " +
|
||||
"-u ");
|
||||
@@ -79,6 +80,7 @@ namespace Netch.Servers.Shadowsocks
|
||||
ShadowsocksDLL.Stop();
|
||||
else
|
||||
StopInstance();
|
||||
_savedMode = null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Netch.Servers.Shadowsocks
|
||||
public string ShortName { get; } = "SS";
|
||||
public string[] UriScheme { get; } = {"ss", "ssd"};
|
||||
|
||||
public Server ParseJObject(JObject j)
|
||||
public Server ParseJObject(in JObject j)
|
||||
{
|
||||
return j.ToObject<Shadowsocks>();
|
||||
}
|
||||
@@ -140,7 +140,7 @@ namespace Netch.Servers.Shadowsocks
|
||||
if (!match.Success) throw new FormatException();
|
||||
|
||||
data.Hostname = match.Groups["server"].Value;
|
||||
data.Port = int.Parse(match.Groups["port"].Value);
|
||||
data.Port = ushort.Parse(match.Groups["port"].Value);
|
||||
|
||||
var base64 = ShareLink.URLSafeBase64Decode(match.Groups["base64"].Value);
|
||||
match = parser.Match(base64);
|
||||
@@ -156,7 +156,7 @@ namespace Netch.Servers.Shadowsocks
|
||||
if (!match.Success) throw new FormatException();
|
||||
|
||||
data.Hostname = match.Groups["server"].Value;
|
||||
data.Port = int.Parse(match.Groups["port"].Value);
|
||||
data.Port = ushort.Parse(match.Groups["port"].Value);
|
||||
data.EncryptMethod = match.Groups["method"].Value;
|
||||
data.Password = match.Groups["password"].Value;
|
||||
}
|
||||
|
||||
@@ -11,17 +11,19 @@ namespace Netch.Servers.ShadowsocksR
|
||||
|
||||
public override string Name { get; protected set; } = "ShadowsocksR";
|
||||
|
||||
public int? Socks5LocalPort { get; set; }
|
||||
public Server Server { get; set; }
|
||||
public ushort? Socks5LocalPort { get; set; }
|
||||
public string LocalAddress { get; set; }
|
||||
|
||||
public bool Start(Server s, Mode mode)
|
||||
public bool Start(in Server s, in Mode mode)
|
||||
{
|
||||
Server = s;
|
||||
var server = (ShadowsocksR) s;
|
||||
|
||||
#region Argument
|
||||
|
||||
var argument = new StringBuilder();
|
||||
argument.Append($"-s {DNS.Lookup(server.Hostname)} -p {server.Port} -k \"{server.Password}\" -m {server.EncryptMethod} -t 120");
|
||||
argument.Append($"-s {server.AutoResolveHostname()} -p {server.Port} -k \"{server.Password}\" -m {server.EncryptMethod} -t 120");
|
||||
if (!string.IsNullOrEmpty(server.Protocol))
|
||||
{
|
||||
argument.Append($" -O {server.Protocol}");
|
||||
@@ -34,7 +36,7 @@ namespace Netch.Servers.ShadowsocksR
|
||||
if (!string.IsNullOrEmpty(server.OBFSParam)) argument.Append($" -g \"{server.OBFSParam}\"");
|
||||
}
|
||||
|
||||
argument.Append($" -b {LocalAddress ?? Global.Settings.LocalAddress} -l {Socks5LocalPort ?? Global.Settings.Socks5LocalPort} -u");
|
||||
argument.Append($" -b {this.LocalAddress()} -l {this.Socks5LocalPort()} -u");
|
||||
if (mode.BypassChina) argument.Append(" --acl default.acl");
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Netch.Servers.ShadowsocksR
|
||||
public string ShortName { get; } = "SR";
|
||||
public string[] UriScheme { get; } = {"ssr"};
|
||||
|
||||
public Server ParseJObject(JObject j)
|
||||
public Server ParseJObject(in JObject j)
|
||||
{
|
||||
return j.ToObject<ShadowsocksR>();
|
||||
}
|
||||
|
||||
@@ -10,6 +10,14 @@ namespace Netch.Servers.Socks5.Form
|
||||
{
|
||||
server ??= new Socks5();
|
||||
Server = server;
|
||||
CreateTextBox("Username", "Username",
|
||||
s => true,
|
||||
s => server.Username = s,
|
||||
server.Username);
|
||||
CreateTextBox("Password", "Password",
|
||||
s => true,
|
||||
s => server.Password = s,
|
||||
server.Password);
|
||||
}
|
||||
}
|
||||
}
|
||||
42
Netch/Servers/Socks5/S5Controller.cs
Normal file
42
Netch/Servers/Socks5/S5Controller.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using System.IO;
|
||||
using Netch.Controllers;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.VMess.Utils;
|
||||
|
||||
namespace Netch.Servers.Socks5
|
||||
{
|
||||
public class S5Controller : Guard, IServerController
|
||||
{
|
||||
public override string Name { get; protected set; } = "Socks5";
|
||||
public override string MainFile { get; protected set; } = "v2ray.exe";
|
||||
|
||||
public bool Start(in Server s, in Mode mode)
|
||||
{
|
||||
Server = s;
|
||||
var server = (Socks5) s;
|
||||
if (server.Auth() && !mode.SupportSocks5Auth)
|
||||
{
|
||||
File.WriteAllText("data\\last.json", V2rayConfigUtils.GenerateClientConfig(s, mode));
|
||||
if (StartInstanceAuto("-config ..\\data\\last.json"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
if (Instance != null)
|
||||
StopInstance();
|
||||
}
|
||||
|
||||
public Server Server { get; set; }
|
||||
public ushort? Socks5LocalPort { get; set; }
|
||||
|
||||
public string LocalAddress { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ namespace Netch.Servers.Socks5
|
||||
public string ShortName { get; } = "S5";
|
||||
public string[] UriScheme { get; } = { };
|
||||
|
||||
public Server ParseJObject(JObject j)
|
||||
public Server ParseJObject(in JObject j)
|
||||
{
|
||||
return j.ToObject<Socks5>();
|
||||
}
|
||||
@@ -30,15 +30,18 @@ namespace Netch.Servers.Socks5
|
||||
new Socks5Form().ShowDialog();
|
||||
}
|
||||
|
||||
public string GetShareLink(Server server)
|
||||
public string GetShareLink(Server s)
|
||||
{
|
||||
var server = (Socks5) s;
|
||||
// https://t.me/socks?server=1.1.1.1&port=443
|
||||
return $"https://t.me/socks?server={server.Hostname}&port={server.Port}";
|
||||
return $"https://t.me/socks?server={server.Hostname}&port={server.Port}" +
|
||||
$"{(!string.IsNullOrWhiteSpace(server.Username) ? $"&user={server.Username}" : "")}" +
|
||||
$"{(server.Auth() ? $"&user={server.Password}" : "")}";
|
||||
}
|
||||
|
||||
public IServerController GetController()
|
||||
{
|
||||
return null;
|
||||
return new S5Controller();
|
||||
}
|
||||
|
||||
public IEnumerable<Server> ParseUri(string text)
|
||||
@@ -58,7 +61,7 @@ namespace Netch.Servers.Socks5
|
||||
var data = new Socks5
|
||||
{
|
||||
Hostname = dict["server"],
|
||||
Port = int.Parse(dict["port"])
|
||||
Port = ushort.Parse(dict["port"])
|
||||
};
|
||||
|
||||
if (dict.ContainsKey("user") && !string.IsNullOrWhiteSpace(dict["user"]))
|
||||
|
||||
@@ -18,5 +18,7 @@ namespace Netch.Servers.Socks5
|
||||
{
|
||||
Type = "Socks5";
|
||||
}
|
||||
|
||||
public bool Auth() => !string.IsNullOrWhiteSpace(Username) && !string.IsNullOrWhiteSpace(Password);
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,14 @@ namespace Netch.Servers.Trojan.Form
|
||||
{
|
||||
server ??= new Trojan();
|
||||
Server = server;
|
||||
CreateTextBox("Password", "Password",
|
||||
s => true,
|
||||
s => server.Password = s,
|
||||
server.Password);
|
||||
CreateTextBox("Host", "Host",
|
||||
s => true,
|
||||
s => server.Host = s,
|
||||
server.Host);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,18 +18,20 @@ namespace Netch.Servers.Trojan
|
||||
|
||||
public override string MainFile { get; protected set; } = "Trojan.exe";
|
||||
public override string Name { get; protected set; } = "Trojan";
|
||||
public int? Socks5LocalPort { get; set; }
|
||||
public Server Server { get; set; }
|
||||
public ushort? Socks5LocalPort { get; set; }
|
||||
public string LocalAddress { get; set; }
|
||||
|
||||
|
||||
public bool Start(Server s, Mode mode)
|
||||
public bool Start(in Server s, in Mode mode)
|
||||
{
|
||||
Server = s;
|
||||
var server = (Trojan) s;
|
||||
File.WriteAllText("data\\last.json", JsonConvert.SerializeObject(new TrojanConfig
|
||||
{
|
||||
local_addr = LocalAddress ?? Global.Settings.LocalAddress,
|
||||
local_port = Socks5LocalPort ?? Global.Settings.Socks5LocalPort,
|
||||
remote_addr = DNS.Lookup(server.Hostname).ToString(),
|
||||
local_addr = this.LocalAddress(),
|
||||
local_port = this.Socks5LocalPort(),
|
||||
remote_addr = server.AutoResolveHostname(),
|
||||
remote_port = server.Port,
|
||||
password = new List<string>
|
||||
{
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Netch.Servers.Trojan
|
||||
public string ShortName { get; } = "TR";
|
||||
public string[] UriScheme { get; } = {"trojan"};
|
||||
|
||||
public Server ParseJObject(JObject j)
|
||||
public Server ParseJObject(in JObject j)
|
||||
{
|
||||
return j.ToObject<Trojan>();
|
||||
}
|
||||
@@ -32,10 +32,10 @@ namespace Netch.Servers.Trojan
|
||||
new TrojanForm().ShowDialog();
|
||||
}
|
||||
|
||||
public string GetShareLink(Server server)
|
||||
public string GetShareLink(Server s)
|
||||
{
|
||||
// TODO
|
||||
return "";
|
||||
var server = (Trojan) s;
|
||||
return $"trojan://{HttpUtility.UrlEncode(server.Password)}@{server.Hostname}:{server.Port}#{server.Remark}";
|
||||
}
|
||||
|
||||
public IServerController GetController()
|
||||
@@ -85,7 +85,7 @@ namespace Netch.Servers.Trojan
|
||||
|
||||
data.Password = match.Groups["psk"].Value;
|
||||
data.Hostname = match.Groups["server"].Value;
|
||||
data.Port = int.Parse(match.Groups["port"].Value);
|
||||
data.Port = ushort.Parse(match.Groups["port"].Value);
|
||||
|
||||
return new[] {data};
|
||||
}
|
||||
|
||||
46
Netch/Servers/VLESS/VLESS.cs
Normal file
46
Netch/Servers/VLESS/VLESS.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using System.Collections.Generic;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.VMess;
|
||||
|
||||
namespace Netch.Servers.VLESS
|
||||
{
|
||||
public class VLESS : VMess.VMess
|
||||
{
|
||||
public VLESS()
|
||||
{
|
||||
Type = "VLESS";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加密方式
|
||||
/// </summary>
|
||||
public new string EncryptMethod { get; set; } = "none";
|
||||
|
||||
/// <summary>
|
||||
/// 传输协议
|
||||
/// </summary>
|
||||
public new string TransferProtocol { get; set; } = VLESSGlobal.TransferProtocols[0];
|
||||
|
||||
/// <summary>
|
||||
/// 伪装类型
|
||||
/// </summary>
|
||||
public new string FakeType { get; set; } = VLESSGlobal.FakeTypes[0];
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Flow { get; set; }
|
||||
}
|
||||
|
||||
public class VLESSGlobal
|
||||
{
|
||||
|
||||
public static List<string> TransferProtocols => VMessGlobal.TransferProtocols;
|
||||
|
||||
public static readonly List<string> FakeTypes = new List<string>
|
||||
{
|
||||
"none",
|
||||
"http"
|
||||
};
|
||||
}
|
||||
}
|
||||
30
Netch/Servers/VLESS/VLESSController.cs
Normal file
30
Netch/Servers/VLESS/VLESSController.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System.IO;
|
||||
using Netch.Controllers;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.VMess.Utils;
|
||||
|
||||
namespace Netch.Servers.VLESS
|
||||
{
|
||||
public class VLESSController : Guard, IServerController
|
||||
{
|
||||
public override string Name { get; protected set; } = "VLESS";
|
||||
public override string MainFile { get; protected set; } = "v2ray.exe";
|
||||
|
||||
public Server Server { get; set; }
|
||||
public ushort? Socks5LocalPort { get; set; }
|
||||
|
||||
public string LocalAddress { get; set; }
|
||||
|
||||
public bool Start(in Server s,in Mode mode)
|
||||
{
|
||||
Server = s;
|
||||
File.WriteAllText("data\\last.json", V2rayConfigUtils.GenerateClientConfig(s, mode));
|
||||
return StartInstanceAuto("-config ..\\data\\last.json");
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
StopInstance();
|
||||
}
|
||||
}
|
||||
}
|
||||
60
Netch/Servers/VLESS/VLESSForm/VLESSForm.cs
Normal file
60
Netch/Servers/VLESS/VLESSForm/VLESSForm.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
using System.Collections.Generic;
|
||||
using Netch.Forms;
|
||||
|
||||
namespace Netch.Servers.VLESS.VLESSForm
|
||||
{
|
||||
class VLESSForm : ServerForm
|
||||
{
|
||||
protected override string TypeName { get; } = "VLESS";
|
||||
|
||||
public VLESSForm(VLESS server = default)
|
||||
{
|
||||
server ??= new VLESS();
|
||||
Server = server;
|
||||
CreateTextBox("UUID", "UUID",
|
||||
s => true,
|
||||
s => server.UserID = s,
|
||||
server.UserID);
|
||||
CreateTextBox("EncryptMethod", "Encrypt Method",
|
||||
s => true,
|
||||
s => server.EncryptMethod = !string.IsNullOrWhiteSpace(s) ? s : "none",
|
||||
server.EncryptMethod);
|
||||
CreateTextBox("Flow", "Flow",
|
||||
s => true,
|
||||
s => server.Flow = s,
|
||||
server.Flow);
|
||||
CreateComboBox("TransferProtocol", "Transfer Protocol",
|
||||
VLESSGlobal.TransferProtocols,
|
||||
s => server.TransferProtocol = s,
|
||||
server.TransferProtocol);
|
||||
CreateComboBox("FakeType", "Fake Type",
|
||||
VLESSGlobal.FakeTypes,
|
||||
s => server.FakeType = s,
|
||||
server.FakeType);
|
||||
CreateTextBox("Host", "Host",
|
||||
s => true,
|
||||
s => server.Host = s,
|
||||
server.Host);
|
||||
CreateTextBox("Path", "Path",
|
||||
s => true,
|
||||
s => server.Path = s,
|
||||
server.Path);
|
||||
CreateComboBox("TLSSecure", "TLS Secure",
|
||||
new List<string> {"", "true", "false"},
|
||||
s =>
|
||||
{
|
||||
server.TLSSecure = s switch
|
||||
{
|
||||
"" => null,
|
||||
"true" => true,
|
||||
"false" => false,
|
||||
_ => null
|
||||
};
|
||||
},
|
||||
server.TLSSecure?.ToString() ?? string.Empty);
|
||||
CreateCheckBox("UseMux", "Use Mux",
|
||||
b => server.UseMux = b,
|
||||
server.UseMux);
|
||||
}
|
||||
}
|
||||
}
|
||||
53
Netch/Servers/VLESS/VLESSUtil.cs
Normal file
53
Netch/Servers/VLESS/VLESSUtil.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using System.Collections.Generic;
|
||||
using Netch.Controllers;
|
||||
using Netch.Models;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Netch.Servers.VLESS
|
||||
{
|
||||
public class VLESSUtil : IServerUtil
|
||||
{
|
||||
public ushort Priority { get; } = 2;
|
||||
public string TypeName { get; } = "VLESS";
|
||||
public string FullName { get; } = "VLESS";
|
||||
public string ShortName { get; } = "VL";
|
||||
public string[] UriScheme { get; } = { };
|
||||
|
||||
public Server ParseJObject(in JObject j)
|
||||
{
|
||||
return j.ToObject<VLESS>();
|
||||
}
|
||||
|
||||
public void Edit(Server s)
|
||||
{
|
||||
new VLESSForm.VLESSForm((VLESS) s).ShowDialog();
|
||||
}
|
||||
|
||||
public void Create()
|
||||
{
|
||||
new VLESSForm.VLESSForm().ShowDialog();
|
||||
}
|
||||
|
||||
public string GetShareLink(Server server)
|
||||
{
|
||||
// TODO
|
||||
return "";
|
||||
}
|
||||
|
||||
public IServerController GetController()
|
||||
{
|
||||
return new VLESSController();
|
||||
}
|
||||
|
||||
public IEnumerable<Server> ParseUri(string text)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public bool CheckServer(Server s)
|
||||
{
|
||||
// TODO
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Netch.Forms;
|
||||
using System.Collections.Generic;
|
||||
using Netch.Forms;
|
||||
|
||||
namespace Netch.Servers.VMess.Form
|
||||
{
|
||||
@@ -47,12 +48,22 @@ namespace Netch.Servers.VMess.Form
|
||||
s => true,
|
||||
s => server.QUICSecret = s,
|
||||
server.QUICSecret);
|
||||
CreateComboBox("TLSSecure", "TLS Secure",
|
||||
new List<string> {"", "true", "false"},
|
||||
s =>
|
||||
{
|
||||
server.TLSSecure = s switch
|
||||
{
|
||||
"" => null,
|
||||
"true" => true,
|
||||
"false" => false,
|
||||
_ => null
|
||||
};
|
||||
},
|
||||
server.TLSSecure?.ToString() ?? string.Empty);
|
||||
CreateCheckBox("UseMux", "Use Mux",
|
||||
s => server.UseMux = s,
|
||||
server.UseMux);
|
||||
CreateCheckBox("TLSSecure", "TLS Secure",
|
||||
s => server.TLSSecure = s,
|
||||
server.TLSSecure);
|
||||
}
|
||||
}
|
||||
}
|
||||
287
Netch/Servers/VMess/Models/V2rayConfig.cs
Normal file
287
Netch/Servers/VMess/Models/V2rayConfig.cs
Normal file
@@ -0,0 +1,287 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Netch.Servers.VMess.Models
|
||||
{
|
||||
public class V2rayConfig
|
||||
{
|
||||
public List<Inbounds> inbounds { get; set; }
|
||||
|
||||
public List<Outbounds> outbounds { get; set; }
|
||||
|
||||
public Routing routing { get; set; }
|
||||
}
|
||||
|
||||
public class Inbounds
|
||||
{
|
||||
public string tag { get; set; }
|
||||
|
||||
public ushort port { get; set; }
|
||||
|
||||
public string listen { get; set; }
|
||||
|
||||
public string protocol { get; set; }
|
||||
|
||||
public Sniffing sniffing { get; set; }
|
||||
|
||||
public Inboundsettings settings { get; set; }
|
||||
|
||||
public StreamSettings streamSettings { get; set; }
|
||||
}
|
||||
|
||||
public class Inboundsettings
|
||||
{
|
||||
public string auth { get; set; }
|
||||
|
||||
public bool udp { get; set; }
|
||||
|
||||
public string ip { get; set; }
|
||||
|
||||
public string address { get; set; }
|
||||
|
||||
public List<UsersItem> clients { get; set; }
|
||||
|
||||
|
||||
public string decryption { get; set; }
|
||||
}
|
||||
|
||||
public class UsersItem
|
||||
{
|
||||
public string id { get; set; }
|
||||
|
||||
public int alterId { get; set; }
|
||||
|
||||
public string email { get; set; }
|
||||
|
||||
public string security { get; set; }
|
||||
|
||||
public string encryption { get; set; }
|
||||
|
||||
public string flow { get; set; }
|
||||
}
|
||||
|
||||
public class Sniffing
|
||||
{
|
||||
public bool enabled { get; set; }
|
||||
|
||||
public List<string> destOverride { get; set; }
|
||||
}
|
||||
|
||||
public class Outbounds
|
||||
{
|
||||
public string tag { get; set; }
|
||||
|
||||
public string protocol { get; set; }
|
||||
|
||||
public Outboundsettings settings { get; set; }
|
||||
|
||||
public StreamSettings streamSettings { get; set; }
|
||||
|
||||
public Mux mux { get; set; }
|
||||
}
|
||||
|
||||
public class Outboundsettings
|
||||
{
|
||||
public List<VnextItem> vnext { get; set; }
|
||||
|
||||
public List<ServersItem> servers { get; set; }
|
||||
|
||||
public Response response { get; set; }
|
||||
}
|
||||
|
||||
public class VnextItem
|
||||
{
|
||||
public string address { get; set; }
|
||||
|
||||
public ushort port { get; set; }
|
||||
|
||||
public List<UsersItem> users { get; set; }
|
||||
}
|
||||
|
||||
public class ServersItem
|
||||
{
|
||||
public string email { get; set; }
|
||||
|
||||
public string address { get; set; }
|
||||
|
||||
public string method { get; set; }
|
||||
|
||||
public bool ota { get; set; }
|
||||
|
||||
public string password { get; set; }
|
||||
|
||||
public ushort port { get; set; }
|
||||
|
||||
public int level { get; set; }
|
||||
|
||||
public List<SocksUsersItem> users { get; set; }
|
||||
}
|
||||
|
||||
public class SocksUsersItem
|
||||
{
|
||||
public string user { get; set; }
|
||||
|
||||
public string pass { get; set; }
|
||||
|
||||
public int level { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class Mux
|
||||
{
|
||||
public bool enabled { get; set; }
|
||||
|
||||
public int concurrency { get; set; }
|
||||
}
|
||||
|
||||
public class Response
|
||||
{
|
||||
public string type { get; set; }
|
||||
}
|
||||
|
||||
public class Dns
|
||||
{
|
||||
public List<string> servers { get; set; }
|
||||
}
|
||||
|
||||
public class RulesItem
|
||||
{
|
||||
public string type { get; set; }
|
||||
|
||||
public string port { get; set; }
|
||||
|
||||
public List<string> inboundTag { get; set; }
|
||||
|
||||
public string outboundTag { get; set; }
|
||||
|
||||
public List<string> ip { get; set; }
|
||||
|
||||
public List<string> domain { get; set; }
|
||||
}
|
||||
|
||||
public class Routing
|
||||
{
|
||||
public string domainStrategy { get; set; }
|
||||
|
||||
public List<RulesItem> rules { get; set; }
|
||||
}
|
||||
|
||||
public class StreamSettings
|
||||
{
|
||||
public string network { get; set; }
|
||||
|
||||
public string security { get; set; }
|
||||
|
||||
public TlsSettings tlsSettings { get; set; }
|
||||
|
||||
public TcpSettings tcpSettings { get; set; }
|
||||
|
||||
public KcpSettings kcpSettings { get; set; }
|
||||
|
||||
public WsSettings wsSettings { get; set; }
|
||||
|
||||
public HttpSettings httpSettings { get; set; }
|
||||
|
||||
public QuicSettings quicSettings { get; set; }
|
||||
|
||||
public TlsSettings xtlsSettings { get; set; }
|
||||
}
|
||||
|
||||
public class TlsSettings
|
||||
{
|
||||
public bool allowInsecure { get; set; }
|
||||
|
||||
public string serverName { get; set; }
|
||||
}
|
||||
|
||||
public class TcpSettings
|
||||
{
|
||||
public bool connectionReuse { get; set; }
|
||||
|
||||
public Header header { get; set; }
|
||||
}
|
||||
|
||||
public class Header
|
||||
{
|
||||
public string type { get; set; }
|
||||
|
||||
public TCPRequest request { get; set; }
|
||||
|
||||
public object response { get; set; }
|
||||
}
|
||||
|
||||
public class TCPRequest
|
||||
{
|
||||
public string version = "1.1";
|
||||
|
||||
public string method = "GET";
|
||||
|
||||
public string path = "/";
|
||||
|
||||
public TCPRequestHeaders headers;
|
||||
}
|
||||
|
||||
|
||||
public class TCPRequestHeaders
|
||||
{
|
||||
public string Host;
|
||||
|
||||
//public string User_Agent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36";
|
||||
|
||||
public string Accept_Encoding = "gzip, deflate";
|
||||
|
||||
public string Connection = "keep-alive";
|
||||
|
||||
public string Pragma = "no-cache";
|
||||
}
|
||||
|
||||
public class KcpSettings
|
||||
{
|
||||
public int mtu { get; set; }
|
||||
|
||||
public int tti { get; set; }
|
||||
|
||||
public int uplinkCapacity { get; set; }
|
||||
|
||||
public int downlinkCapacity { get; set; }
|
||||
|
||||
public bool congestion { get; set; }
|
||||
|
||||
public int readBufferSize { get; set; }
|
||||
|
||||
public int writeBufferSize { get; set; }
|
||||
|
||||
public Header header { get; set; }
|
||||
|
||||
public string seed { get; set; }
|
||||
}
|
||||
|
||||
public class WsSettings
|
||||
{
|
||||
public bool connectionReuse { get; set; }
|
||||
|
||||
public string path { get; set; }
|
||||
|
||||
public Headers headers { get; set; }
|
||||
}
|
||||
|
||||
public class Headers
|
||||
{
|
||||
public string Host { get; set; }
|
||||
}
|
||||
|
||||
public class HttpSettings
|
||||
{
|
||||
public string path { get; set; }
|
||||
|
||||
public List<string> host { get; set; }
|
||||
}
|
||||
|
||||
public class QuicSettings
|
||||
{
|
||||
public string security { get; set; }
|
||||
|
||||
public string key { get; set; }
|
||||
|
||||
public Header header { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -3,74 +3,61 @@
|
||||
/// <summary>
|
||||
/// 使用 v2rayN 定义的 VMess 链接格式
|
||||
/// </summary>
|
||||
public class VMessJObject
|
||||
public class V2rayNSharing
|
||||
{
|
||||
/// <summary>
|
||||
/// Mux Class
|
||||
/// </summary>
|
||||
public class Mux
|
||||
{
|
||||
public object enabled;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 链接版本
|
||||
/// </summary>
|
||||
public string v;
|
||||
public string v = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string ps;
|
||||
public string ps = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 地址
|
||||
/// </summary>
|
||||
public string add;
|
||||
public string add = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 端口
|
||||
/// </summary>
|
||||
public int port;
|
||||
public string port = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 用户 ID
|
||||
/// </summary>
|
||||
public string id;
|
||||
public string id = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 额外 ID
|
||||
/// </summary>
|
||||
public int aid = 0;
|
||||
public string aid = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 传输协议
|
||||
/// </summary>
|
||||
public string net;
|
||||
public string net = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 伪装类型
|
||||
/// </summary>
|
||||
public string type;
|
||||
public string type = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 伪装域名(HTTP,WS)
|
||||
/// </summary>
|
||||
public string host;
|
||||
public string host = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 伪装路径
|
||||
/// </summary>
|
||||
public string path;
|
||||
public string path = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 是否使用 TLS
|
||||
/// </summary>
|
||||
public string tls;
|
||||
|
||||
/// <summary>
|
||||
/// Mux 多路复用
|
||||
/// </summary>
|
||||
public Mux mux;
|
||||
public string tls = string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -1,206 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Netch.Servers.VMess.Models
|
||||
{
|
||||
public class VMessConfig
|
||||
{
|
||||
public class InboundSettings
|
||||
{
|
||||
public bool udp = true;
|
||||
}
|
||||
|
||||
public class Inbounds
|
||||
{
|
||||
public string listen = "127.0.0.1";
|
||||
|
||||
public int port = 2801;
|
||||
|
||||
public string protocol = "socks";
|
||||
|
||||
public InboundSettings settings;
|
||||
}
|
||||
|
||||
public class User
|
||||
{
|
||||
public string id;
|
||||
|
||||
public int alterId;
|
||||
|
||||
public string security;
|
||||
}
|
||||
|
||||
public class VNext
|
||||
{
|
||||
public string address;
|
||||
|
||||
public int port;
|
||||
|
||||
public List<User> users;
|
||||
}
|
||||
|
||||
public class WSHeaders
|
||||
{
|
||||
public string Host;
|
||||
}
|
||||
|
||||
public class TCPRequestHeaders
|
||||
{
|
||||
public string Host;
|
||||
|
||||
//public string User_Agent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36";
|
||||
|
||||
public string Accept_Encoding = "gzip, deflate";
|
||||
|
||||
public string Connection = "keep-alive";
|
||||
|
||||
public string Pragma = "no-cache";
|
||||
}
|
||||
|
||||
public class TCPRequest
|
||||
{
|
||||
public string version = "1.1";
|
||||
|
||||
public string method = "GET";
|
||||
|
||||
public string path = "/";
|
||||
|
||||
public TCPRequestHeaders headers;
|
||||
}
|
||||
|
||||
public class TCPHeaders
|
||||
{
|
||||
public string type;
|
||||
|
||||
public TCPRequest request;
|
||||
}
|
||||
|
||||
public class WebSocketSettings
|
||||
{
|
||||
public bool connectionReuse = true;
|
||||
|
||||
public string path = "/";
|
||||
|
||||
public WSHeaders headers;
|
||||
}
|
||||
|
||||
public class TCPSettings
|
||||
{
|
||||
public bool connectionReuse = true;
|
||||
|
||||
public TCPHeaders header;
|
||||
}
|
||||
|
||||
public class QUICSettings
|
||||
{
|
||||
public string security;
|
||||
|
||||
public string key;
|
||||
|
||||
public TCPHeaders header;
|
||||
}
|
||||
|
||||
public class KCPSettings
|
||||
{
|
||||
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 TCPHeaders header;
|
||||
}
|
||||
|
||||
public class HTTPSettings
|
||||
{
|
||||
public string host;
|
||||
|
||||
public string path;
|
||||
}
|
||||
|
||||
public class TLSSettings
|
||||
{
|
||||
public bool allowInsecure = true;
|
||||
|
||||
public string serverName;
|
||||
}
|
||||
|
||||
public class OutboundSettings
|
||||
{
|
||||
public List<VNext> vnext;
|
||||
}
|
||||
|
||||
public class OutboundMux
|
||||
{
|
||||
public bool enabled = false;
|
||||
}
|
||||
|
||||
public class StreamSettings
|
||||
{
|
||||
public string network;
|
||||
|
||||
public string security;
|
||||
|
||||
public TCPSettings tcpSettings;
|
||||
|
||||
public WebSocketSettings wsSettings;
|
||||
|
||||
public KCPSettings kcpSettings;
|
||||
|
||||
public QUICSettings quicSettings;
|
||||
|
||||
public HTTPSettings httpSettings;
|
||||
|
||||
public TLSSettings tlsSettings;
|
||||
}
|
||||
|
||||
public class Outbounds
|
||||
{
|
||||
public string tag = "proxy";
|
||||
|
||||
public string protocol = "vmess";
|
||||
|
||||
public OutboundSettings settings;
|
||||
|
||||
public StreamSettings streamSettings;
|
||||
|
||||
public OutboundMux mux;
|
||||
}
|
||||
|
||||
public class RoutingRules
|
||||
{
|
||||
public string type = "field";
|
||||
|
||||
public List<string> port;
|
||||
|
||||
public string outboundTag;
|
||||
|
||||
public List<string> ip;
|
||||
|
||||
public List<string> domain;
|
||||
}
|
||||
|
||||
public class Routing
|
||||
{
|
||||
public string domainStrategy = "IPIfNonMatch";
|
||||
|
||||
public List<RoutingRules> rules;
|
||||
}
|
||||
|
||||
public class Config
|
||||
{
|
||||
public List<Inbounds> inbounds;
|
||||
|
||||
public List<Outbounds> outbounds;
|
||||
|
||||
public Routing routing;
|
||||
}
|
||||
}
|
||||
}
|
||||
374
Netch/Servers/VMess/Utils/V2rayConfigUtils.cs
Normal file
374
Netch/Servers/VMess/Utils/V2rayConfigUtils.cs
Normal file
@@ -0,0 +1,374 @@
|
||||
using System.Collections.Generic;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.VMess.Models;
|
||||
using Newtonsoft.Json;
|
||||
using V2rayConfig = Netch.Servers.VMess.Models.V2rayConfig;
|
||||
|
||||
namespace Netch.Servers.VMess.Utils
|
||||
{
|
||||
public static class V2rayConfigUtils
|
||||
{
|
||||
public static string GenerateClientConfig(Server server, Mode mode)
|
||||
{
|
||||
try
|
||||
{
|
||||
var v2rayConfig = new V2rayConfig();
|
||||
|
||||
inbound(server, ref v2rayConfig);
|
||||
|
||||
routing(server, mode, ref v2rayConfig);
|
||||
|
||||
outbound(server, ref v2rayConfig);
|
||||
|
||||
return JsonConvert.SerializeObject(v2rayConfig);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private static void inbound(Server server, ref V2rayConfig v2rayConfig)
|
||||
{
|
||||
try
|
||||
{
|
||||
var inbound = new Inbounds
|
||||
{
|
||||
port = Global.Settings.Socks5LocalPort,
|
||||
protocol = "socks",
|
||||
listen = Global.Settings.LocalAddress,
|
||||
settings = new Inboundsettings
|
||||
{
|
||||
udp = true
|
||||
}
|
||||
};
|
||||
|
||||
v2rayConfig.inbounds = new List<Inbounds>
|
||||
{
|
||||
inbound
|
||||
};
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
private static void routing(Server server, Mode mode, ref V2rayConfig v2rayConfig)
|
||||
{
|
||||
try
|
||||
{
|
||||
RulesItem rulesItem;
|
||||
if (mode.BypassChina)
|
||||
{
|
||||
rulesItem = new RulesItem
|
||||
{
|
||||
type = "field",
|
||||
ip = new List<string>
|
||||
{
|
||||
"geoip:cn",
|
||||
"geoip:private"
|
||||
},
|
||||
domain = new List<string>
|
||||
{
|
||||
"geosite:cn"
|
||||
},
|
||||
outboundTag = "direct"
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
rulesItem = new RulesItem
|
||||
{
|
||||
type = "field",
|
||||
ip = new List<string>
|
||||
{
|
||||
"geoip:private"
|
||||
},
|
||||
outboundTag = "direct"
|
||||
};
|
||||
}
|
||||
|
||||
v2rayConfig.routing = new Routing
|
||||
{
|
||||
rules = new List<RulesItem>
|
||||
{
|
||||
rulesItem
|
||||
}
|
||||
};
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
private static void outbound(Server server, ref V2rayConfig v2rayConfig)
|
||||
{
|
||||
try
|
||||
{
|
||||
var outbound = new Outbounds
|
||||
{
|
||||
settings = new Outboundsettings(),
|
||||
mux = new Mux(),
|
||||
streamSettings = new StreamSettings
|
||||
{
|
||||
network = "tcp"
|
||||
}
|
||||
};
|
||||
|
||||
switch (server)
|
||||
{
|
||||
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
|
||||
{
|
||||
user = socks5.Username,
|
||||
pass = socks5.Password,
|
||||
level = 1
|
||||
};
|
||||
|
||||
serversItem.users.Add(socksUsersItem);
|
||||
}
|
||||
|
||||
outbound.mux.enabled = false;
|
||||
outbound.mux.concurrency = -1;
|
||||
outbound.protocol = "socks";
|
||||
break;
|
||||
}
|
||||
case VLESS.VLESS vless:
|
||||
{
|
||||
var vnextItem = new VnextItem
|
||||
{
|
||||
users = new List<UsersItem>()
|
||||
};
|
||||
outbound.settings.vnext = new List<VnextItem>
|
||||
{
|
||||
vnextItem
|
||||
};
|
||||
|
||||
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")
|
||||
{
|
||||
usersItem.flow = string.IsNullOrEmpty(vless.Flow) ? "xtls-rprx-origin" : vless.Flow;
|
||||
|
||||
outbound.mux.enabled = false;
|
||||
outbound.mux.concurrency = -1;
|
||||
}
|
||||
|
||||
outbound.protocol = "vless";
|
||||
outbound.settings.servers = null;
|
||||
break;
|
||||
}
|
||||
case VMess vmess:
|
||||
{
|
||||
var vnextItem = new VnextItem
|
||||
{
|
||||
users = new List<UsersItem>()
|
||||
};
|
||||
outbound.settings.vnext = new List<VnextItem>
|
||||
{
|
||||
vnextItem
|
||||
};
|
||||
|
||||
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.protocol = "vmess";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
v2rayConfig.outbounds = new List<Outbounds> {outbound};
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
private static void boundStreamSettings(VMess server, ref StreamSettings streamSettings)
|
||||
{
|
||||
try
|
||||
{
|
||||
streamSettings.network = server.TransferProtocol;
|
||||
var host = server.Host;
|
||||
if (server.TLSSecure ?? Global.Settings.V2RayConfig.AllowInsecure)
|
||||
{
|
||||
streamSettings.security = "tls";
|
||||
|
||||
var tlsSettings = new TlsSettings
|
||||
{
|
||||
allowInsecure = true
|
||||
};
|
||||
if (!string.IsNullOrWhiteSpace(host))
|
||||
{
|
||||
tlsSettings.serverName = host;
|
||||
}
|
||||
|
||||
streamSettings.tlsSettings = tlsSettings;
|
||||
}
|
||||
else
|
||||
{
|
||||
streamSettings.security = "";
|
||||
}
|
||||
|
||||
switch (server.TransferProtocol)
|
||||
{
|
||||
case "kcp":
|
||||
var kcpSettings = new KcpSettings
|
||||
{
|
||||
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
|
||||
},
|
||||
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
|
||||
}
|
||||
: null,
|
||||
path = !string.IsNullOrWhiteSpace(path) ? path : null
|
||||
};
|
||||
|
||||
streamSettings.wsSettings = wsSettings;
|
||||
break;
|
||||
case "h2":
|
||||
var httpSettings = new HttpSettings
|
||||
{
|
||||
host = new List<string>
|
||||
{
|
||||
string.IsNullOrWhiteSpace(server.Host) ? server.Hostname : server.Host
|
||||
},
|
||||
path = server.Path
|
||||
};
|
||||
|
||||
streamSettings.httpSettings = httpSettings;
|
||||
break;
|
||||
case "quic":
|
||||
var quicSettings = new QuicSettings
|
||||
{
|
||||
security = host,
|
||||
key = server.Path,
|
||||
header = new Header
|
||||
{
|
||||
type = server.FakeType
|
||||
}
|
||||
};
|
||||
if (server.TLSSecure ?? Global.Settings.V2RayConfig.AllowInsecure)
|
||||
{
|
||||
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")
|
||||
{
|
||||
var tcpSettings = new TcpSettings
|
||||
{
|
||||
connectionReuse = true,
|
||||
header = new Header
|
||||
{
|
||||
type = server.FakeType,
|
||||
request = new TCPRequest
|
||||
{
|
||||
path = string.IsNullOrWhiteSpace(server.Path) ? "/" : server.Path,
|
||||
headers = new TCPRequestHeaders
|
||||
{
|
||||
Host = string.IsNullOrWhiteSpace(server.Host) ? server.Hostname : server.Host
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
streamSettings.tcpSettings = tcpSettings;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,7 @@ namespace Netch.Servers.VMess
|
||||
/// <summary>
|
||||
/// TLS 底层传输安全
|
||||
/// </summary>
|
||||
public bool TLSSecure { get; set; } = false;
|
||||
public bool? TLSSecure { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Mux 多路复用
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO;
|
||||
using Netch.Controllers;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.VMess.Models;
|
||||
using Netch.Utils;
|
||||
using Newtonsoft.Json;
|
||||
using Netch.Servers.VMess.Utils;
|
||||
|
||||
namespace Netch.Servers.VMess
|
||||
{
|
||||
@@ -16,171 +13,18 @@ namespace Netch.Servers.VMess
|
||||
StoppedKeywords.AddRange(new[] {"config file not readable", "failed to"});
|
||||
}
|
||||
|
||||
|
||||
public override string Name { get; protected set; } = "V2Ray";
|
||||
public override string MainFile { get; protected set; } = "v2ray.exe";
|
||||
public int? Socks5LocalPort { get; set; }
|
||||
public Server Server { get; set; }
|
||||
public ushort? Socks5LocalPort { get; set; }
|
||||
public string LocalAddress { get; set; }
|
||||
|
||||
|
||||
public bool Start(Server s, Mode mode)
|
||||
public bool Start(in Server s,in Mode mode)
|
||||
{
|
||||
var server = (VMess) s;
|
||||
File.WriteAllText("data\\last.json", JsonConvert.SerializeObject(new VMessConfig.Config()
|
||||
{
|
||||
inbounds = new List<VMessConfig.Inbounds>
|
||||
{
|
||||
new VMessConfig.Inbounds
|
||||
{
|
||||
settings = new VMessConfig.InboundSettings(),
|
||||
port = Socks5LocalPort ?? Global.Settings.Socks5LocalPort,
|
||||
listen = LocalAddress ?? Global.Settings.LocalAddress
|
||||
}
|
||||
},
|
||||
outbounds = new List<VMessConfig.Outbounds>
|
||||
{
|
||||
new VMessConfig.Outbounds
|
||||
{
|
||||
settings = new VMessConfig.OutboundSettings
|
||||
{
|
||||
vnext = new List<VMessConfig.VNext>
|
||||
{
|
||||
new VMessConfig.VNext
|
||||
{
|
||||
address = DNS.Lookup(server.Hostname).ToString(),
|
||||
port = server.Port,
|
||||
users = new List<VMessConfig.User>
|
||||
{
|
||||
new VMessConfig.User
|
||||
{
|
||||
id = server.UserID,
|
||||
alterId = server.AlterID,
|
||||
security = server.EncryptMethod
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
streamSettings = new VMessConfig.StreamSettings
|
||||
{
|
||||
network = server.TransferProtocol,
|
||||
security = server.TLSSecure ? "tls" : string.Empty,
|
||||
wsSettings = server.TransferProtocol == "ws"
|
||||
? new VMessConfig.WebSocketSettings
|
||||
{
|
||||
path = server.Path == string.Empty ? "/" : server.Path,
|
||||
headers = new VMessConfig.WSHeaders
|
||||
{
|
||||
Host = server.Host == string.Empty ? server.Hostname : server.Host
|
||||
}
|
||||
}
|
||||
: null,
|
||||
tcpSettings = server.FakeType == "http"
|
||||
? new VMessConfig.TCPSettings
|
||||
{
|
||||
header = new VMessConfig.TCPHeaders
|
||||
{
|
||||
type = server.FakeType,
|
||||
request = new VMessConfig.TCPRequest
|
||||
{
|
||||
path = server.Path == string.Empty ? "/" : server.Path,
|
||||
headers = new VMessConfig.TCPRequestHeaders
|
||||
{
|
||||
Host = server.Host == string.Empty ? server.Hostname : server.Host
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
: null,
|
||||
kcpSettings = server.TransferProtocol == "kcp"
|
||||
? new VMessConfig.KCPSettings
|
||||
{
|
||||
header = new VMessConfig.TCPHeaders
|
||||
{
|
||||
type = server.FakeType
|
||||
}
|
||||
}
|
||||
: null,
|
||||
quicSettings = server.TransferProtocol == "quic"
|
||||
? new VMessConfig.QUICSettings
|
||||
{
|
||||
security = server.QUICSecure,
|
||||
key = server.QUICSecret,
|
||||
header = new VMessConfig.TCPHeaders
|
||||
{
|
||||
type = server.FakeType
|
||||
}
|
||||
}
|
||||
: null,
|
||||
httpSettings = server.TransferProtocol == "h2"
|
||||
? new VMessConfig.HTTPSettings
|
||||
{
|
||||
host = server.Host == "" ? server.Hostname : server.Host,
|
||||
path = server.Path == "" ? "/" : server.Path
|
||||
}
|
||||
: null,
|
||||
tlsSettings = new VMessConfig.TLSSettings
|
||||
{
|
||||
allowInsecure = true,
|
||||
serverName = server.Host == "" ? server.Hostname : server.Host
|
||||
}
|
||||
},
|
||||
mux = new VMessConfig.OutboundMux
|
||||
{
|
||||
enabled = server.UseMux
|
||||
}
|
||||
},
|
||||
mode.Type == 0 || mode.Type == 1 || mode.Type == 2
|
||||
? new VMessConfig.Outbounds
|
||||
{
|
||||
tag = "TUNTAP",
|
||||
protocol = "freedom"
|
||||
}
|
||||
: new VMessConfig.Outbounds
|
||||
{
|
||||
tag = "direct",
|
||||
protocol = "freedom"
|
||||
}
|
||||
},
|
||||
routing = new VMessConfig.Routing
|
||||
{
|
||||
rules = new List<VMessConfig.RoutingRules>
|
||||
{
|
||||
mode.BypassChina
|
||||
? new VMessConfig.RoutingRules
|
||||
{
|
||||
type = "field",
|
||||
ip = new List<string>
|
||||
{
|
||||
"geoip:cn",
|
||||
"geoip:private"
|
||||
},
|
||||
domain = new List<string>
|
||||
{
|
||||
"geosite:cn"
|
||||
},
|
||||
outboundTag = "direct"
|
||||
}
|
||||
: new VMessConfig.RoutingRules
|
||||
{
|
||||
type = "field",
|
||||
ip = new List<string>
|
||||
{
|
||||
"geoip:private"
|
||||
},
|
||||
outboundTag = "direct"
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
if (StartInstanceAuto("-config ..\\data\\last.json"))
|
||||
{
|
||||
if (File.Exists("data\\last.json")) File.Delete("data\\last.json");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
Server = s;
|
||||
File.WriteAllText("data\\last.json", V2rayConfigUtils.GenerateClientConfig(s, mode));
|
||||
return StartInstanceAuto("-config ..\\data\\last.json");
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Netch.Controllers;
|
||||
using Netch.Models;
|
||||
@@ -17,7 +18,7 @@ namespace Netch.Servers.VMess
|
||||
public string ShortName { get; } = "V2";
|
||||
public string[] UriScheme { get; } = {"vmess"};
|
||||
|
||||
public Server ParseJObject(JObject j)
|
||||
public Server ParseJObject(in JObject j)
|
||||
{
|
||||
return j.ToObject<VMess>();
|
||||
}
|
||||
@@ -48,7 +49,7 @@ namespace Netch.Servers.VMess
|
||||
type = server.FakeType,
|
||||
host = server.Host,
|
||||
path = server.Path,
|
||||
tls = server.TLSSecure ? "tls" : ""
|
||||
tls = server.TLSSecure ?? Global.Settings.V2RayConfig.AllowInsecure ? "tls" : ""
|
||||
});
|
||||
return "vmess://" + ShareLink.URLSafeBase64Encode(vmessJson);
|
||||
}
|
||||
@@ -63,26 +64,25 @@ namespace Netch.Servers.VMess
|
||||
var data = new VMess();
|
||||
|
||||
text = text.Substring(8);
|
||||
var vmess = JsonConvert.DeserializeObject<VMessJObject>(ShareLink.URLSafeBase64Decode(text));
|
||||
V2rayNSharing vmess;
|
||||
try
|
||||
{
|
||||
vmess = JsonConvert.DeserializeObject<V2rayNSharing>(ShareLink.URLSafeBase64Decode(text));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Warning(e.ToString());
|
||||
return null;
|
||||
}
|
||||
|
||||
data.Remark = vmess.ps;
|
||||
data.Hostname = vmess.add;
|
||||
data.Port = vmess.port;
|
||||
data.Port = ushort.Parse(vmess.port);
|
||||
data.UserID = vmess.id;
|
||||
data.AlterID = vmess.aid;
|
||||
data.AlterID = int.Parse(vmess.aid);
|
||||
data.TransferProtocol = vmess.net;
|
||||
data.FakeType = vmess.type;
|
||||
|
||||
if (vmess.v == null || vmess.v == "1")
|
||||
{
|
||||
var info = vmess.host.Split(';');
|
||||
if (info.Length == 2)
|
||||
{
|
||||
vmess.host = info[0];
|
||||
vmess.path = info[1];
|
||||
}
|
||||
}
|
||||
|
||||
if (data.TransferProtocol == "quic")
|
||||
{
|
||||
if (VMessGlobal.QUIC.Contains(vmess.host))
|
||||
@@ -98,28 +98,8 @@ namespace Netch.Servers.VMess
|
||||
}
|
||||
|
||||
data.TLSSecure = vmess.tls == "tls";
|
||||
|
||||
if (vmess.mux == null)
|
||||
{
|
||||
data.UseMux = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vmess.mux.enabled is bool enabled)
|
||||
{
|
||||
data.UseMux = enabled;
|
||||
}
|
||||
else if (vmess.mux.enabled is string muxEnabled)
|
||||
{
|
||||
data.UseMux = muxEnabled == "true"; // 针对使用字符串当作布尔值的情况
|
||||
}
|
||||
else
|
||||
{
|
||||
data.UseMux = false;
|
||||
}
|
||||
}
|
||||
|
||||
data.EncryptMethod = "auto"; // V2Ray 加密方式不包括在链接中,主动添加一个
|
||||
|
||||
return CheckServer(data) ? new[] {data} : null;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ using Microsoft.Diagnostics.Tracing.Parsers;
|
||||
using Microsoft.Diagnostics.Tracing.Session;
|
||||
using Netch.Controllers;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.Shadowsocks;
|
||||
|
||||
namespace Netch.Utils
|
||||
{
|
||||
@@ -52,7 +53,7 @@ namespace Netch.Utils
|
||||
/// <summary>
|
||||
/// 根据程序名统计流量
|
||||
/// </summary>
|
||||
public static void NetTraffic(Server server, Mode mode)
|
||||
public static void NetTraffic(in Server server, in Mode mode)
|
||||
{
|
||||
if (!Global.Flags.IsWindows10Upper)
|
||||
return;
|
||||
@@ -66,20 +67,29 @@ namespace Netch.Utils
|
||||
{
|
||||
instances.Add(((HTTPController) MainController.ModeController).pPrivoxyController.Instance);
|
||||
}
|
||||
else if (server.Type.Equals("SS") && Global.Settings.BootShadowsocksFromDLL &&
|
||||
(mode.Type == 0 || mode.Type == 1 || mode.Type == 2))
|
||||
{
|
||||
instances.Add(Process.GetCurrentProcess());
|
||||
}
|
||||
else if (MainController.ServerController != null)
|
||||
{
|
||||
if (MainController.ServerController is Guard instanceController)
|
||||
instances.Add(instanceController.Instance);
|
||||
switch (MainController.ServerController)
|
||||
{
|
||||
case SSController ssController when ssController.DllFlag:
|
||||
instances.Add(Process.GetCurrentProcess());
|
||||
break;
|
||||
case Guard instanceController:
|
||||
instances.Add(instanceController.Instance);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (MainController.ModeController != null)
|
||||
{
|
||||
if (MainController.ModeController is Guard instanceController)
|
||||
instances.Add(instanceController.Instance);
|
||||
switch (MainController.ModeController)
|
||||
{
|
||||
case NFController _:
|
||||
instances.Add(Process.GetCurrentProcess());
|
||||
break;
|
||||
case Guard instanceController:
|
||||
instances.Add(instanceController.Instance);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var processList = instances.Select(instance => instance.Id).ToList();
|
||||
|
||||
@@ -49,6 +49,8 @@ namespace Netch.Utils
|
||||
|
||||
private static RegistryKey AdapterRegistry(bool write = false)
|
||||
{
|
||||
if (Global.Outbound.Adapter == null)
|
||||
Utils.SearchOutboundAdapter();
|
||||
return Registry.LocalMachine.OpenSubKey(
|
||||
$@"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{Global.Outbound.Adapter.Id}", write);
|
||||
}
|
||||
|
||||
@@ -9,23 +9,44 @@ namespace Netch.Utils
|
||||
{
|
||||
public static class ICSHelper
|
||||
{
|
||||
public static bool Enabled
|
||||
public static bool? Enabled
|
||||
{
|
||||
get
|
||||
{
|
||||
TUNTAPController.SearchTapAdapter();
|
||||
return (
|
||||
from NetworkConnection connection in new NetworkConnectionCollection()
|
||||
where connection.DeviceName == Global.TUNTAP.Adapter.Description
|
||||
select connection.SharingEnabled
|
||||
).FirstOrDefault();
|
||||
AutoSearchTapAdapter();
|
||||
|
||||
if (Global.TUNTAP.Adapter == null)
|
||||
return null;
|
||||
|
||||
foreach (NetworkConnection connection in new NetworkConnectionCollection())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (connection.DeviceName == Global.TUNTAP.Adapter?.Description)
|
||||
{
|
||||
return connection.SharingEnabled;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Warning(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void AutoSearchTapAdapter()
|
||||
{
|
||||
if (Global.TUNTAP.Adapter == null)
|
||||
TUNTAPController.SearchTapAdapter();
|
||||
}
|
||||
|
||||
public static bool Enable()
|
||||
{
|
||||
Utils.SearchOutboundAdapter(false);
|
||||
TUNTAPController.SearchTapAdapter();
|
||||
AutoSearchTapAdapter();
|
||||
|
||||
if (Global.TUNTAP.Adapter == null || Global.Outbound.Adapter == null)
|
||||
{
|
||||
@@ -133,9 +154,19 @@ namespace Netch.Utils
|
||||
|
||||
public static void Disable()
|
||||
{
|
||||
foreach (var connection in new NetworkConnectionCollection().Cast<NetworkConnection>().Where(connection => connection.SharingEnabled))
|
||||
foreach (NetworkConnection connection in new NetworkConnectionCollection())
|
||||
{
|
||||
connection.DisableSharing();
|
||||
try
|
||||
{
|
||||
if (connection.SharingEnabled)
|
||||
{
|
||||
connection.DisableSharing();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Warning(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
CleanupWMISharingEntries();
|
||||
|
||||
@@ -2,6 +2,8 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Netch.Controllers;
|
||||
using Netch.Forms;
|
||||
using Netch.Models;
|
||||
|
||||
namespace Netch.Utils
|
||||
@@ -60,7 +62,7 @@ namespace Netch.Utils
|
||||
|
||||
for (var i = 0; i < content.Length; i++)
|
||||
{
|
||||
var text = content[i];
|
||||
var text = content[i].Trim();
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
@@ -83,8 +85,7 @@ namespace Netch.Utils
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!text.StartsWith("#") && !string.IsNullOrWhiteSpace(text))
|
||||
mode.Rule.Add(text.Trim());
|
||||
mode.Rule.Add(text);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,5 +134,40 @@ namespace Netch.Utils
|
||||
Global.Modes.Remove(mode);
|
||||
Global.MainForm.InitMode();
|
||||
}
|
||||
|
||||
public static IModeController GetModeControllerByType(int type, out ushort? port, out string portName, out PortType portType)
|
||||
{
|
||||
IModeController modeController;
|
||||
port = null;
|
||||
portName = string.Empty;
|
||||
portType = PortType.Both;
|
||||
switch (type)
|
||||
{
|
||||
case 0:
|
||||
modeController = new NFController();
|
||||
port = Global.Settings.RedirectorTCPPort;
|
||||
portName = "Redirector TCP";
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
modeController = new TUNTAPController();
|
||||
break;
|
||||
case 3:
|
||||
case 5:
|
||||
modeController = new HTTPController();
|
||||
port = Global.Settings.HTTPLocalPort;
|
||||
portName = "HTTP";
|
||||
MainForm.StatusPortInfoText.HttpPort = (ushort) port;
|
||||
break;
|
||||
case 4:
|
||||
modeController = null;
|
||||
break;
|
||||
default:
|
||||
Logging.Error("未知模式类型");
|
||||
throw new StartFailedException();
|
||||
}
|
||||
|
||||
return modeController;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,8 @@ namespace Netch.Utils
|
||||
{
|
||||
public static class PortHelper
|
||||
{
|
||||
private static readonly List<int[]> TCPExcludedRanges = new List<int[]>();
|
||||
private static readonly List<int[]> UDPExcludedRanges = new List<int[]>();
|
||||
private static readonly List<ushort[]> TCPExcludedRanges = new List<ushort[]>();
|
||||
private static readonly List<ushort[]> UDPExcludedRanges = new List<ushort[]>();
|
||||
|
||||
static PortHelper()
|
||||
{
|
||||
@@ -24,7 +24,7 @@ namespace Netch.Utils
|
||||
}
|
||||
}
|
||||
|
||||
private static void GetExcludedPortRange(PortType portType, ref List<int[]> targetList)
|
||||
private static void GetExcludedPortRange(PortType portType, ref List<ushort[]> targetList)
|
||||
{
|
||||
var lines = new List<string>();
|
||||
var process = new Process
|
||||
@@ -63,9 +63,9 @@ namespace Netch.Utils
|
||||
|
||||
var value = line.Trim().Split(' ').Where(s => s != string.Empty);
|
||||
|
||||
var port = 0;
|
||||
ushort port = 0;
|
||||
var _ = (from s1 in value
|
||||
where int.TryParse(s1, out port)
|
||||
where ushort.TryParse(s1, out port)
|
||||
select port).ToArray();
|
||||
|
||||
targetList.Add(_);
|
||||
@@ -80,7 +80,7 @@ namespace Netch.Utils
|
||||
/// <param name="type">端口类型</param>
|
||||
/// <returns>是否是保留端口</returns>
|
||||
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
||||
private static bool IsPortExcluded(int port, PortType type)
|
||||
private static bool IsPortExcluded(ushort port, PortType type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
@@ -97,7 +97,7 @@ namespace Netch.Utils
|
||||
/// <param name="port">端口</param>
|
||||
/// <param name="type">检查端口类型</param>
|
||||
/// <returns>是否被占用</returns>
|
||||
public static bool PortInUse(int port, PortType type = PortType.Both)
|
||||
public static bool PortInUse(ushort port, PortType type = PortType.Both)
|
||||
{
|
||||
var netInfo = IPGlobalProperties.GetIPGlobalProperties();
|
||||
var isTcpUsed = type != PortType.UDP &&
|
||||
@@ -111,11 +111,12 @@ namespace Netch.Utils
|
||||
return isPortExcluded && (isTcpUsed || isUdpUsed);
|
||||
}
|
||||
|
||||
public static int GetAvailablePort()
|
||||
public static ushort GetAvailablePort()
|
||||
{
|
||||
for (var i = 0; i < 55535; i++)
|
||||
var random = new Random();
|
||||
for (ushort i = 0; i < 55535; i++)
|
||||
{
|
||||
var p = new Random().Next(10000, 65535);
|
||||
var p = (ushort) random.Next(10000, 65535);
|
||||
if (!PortInUse(p))
|
||||
{
|
||||
return p;
|
||||
@@ -128,7 +129,7 @@ namespace Netch.Utils
|
||||
/// <summary>
|
||||
/// 记录Netch使用的端口
|
||||
/// </summary>
|
||||
public static readonly List<int> UsingPorts = new List<int>();
|
||||
public static readonly List<ushort> UsingPorts = new List<ushort>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -120,48 +120,36 @@ namespace Netch.Utils
|
||||
}
|
||||
|
||||
var list = new List<Server>();
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
list.AddRange(JsonConvert.DeserializeObject<List<ShadowsocksConfig>>(text).Select(server => new Shadowsocks
|
||||
{
|
||||
list.AddRange(JsonConvert.DeserializeObject<List<ShadowsocksConfig>>(text).Select(server => new Shadowsocks
|
||||
{
|
||||
Hostname = server.server,
|
||||
Port = server.server_port,
|
||||
EncryptMethod = server.method,
|
||||
Password = server.password,
|
||||
Remark = server.remarks,
|
||||
Plugin = server.plugin,
|
||||
PluginOption = server.plugin_opts
|
||||
}));
|
||||
}
|
||||
catch (JsonReaderException)
|
||||
Hostname = server.server,
|
||||
Port = server.server_port,
|
||||
EncryptMethod = server.method,
|
||||
Password = server.password,
|
||||
Remark = server.remarks,
|
||||
Plugin = server.plugin,
|
||||
PluginOption = server.plugin_opts
|
||||
}));
|
||||
}
|
||||
catch (JsonReaderException)
|
||||
{
|
||||
foreach (var line in text.GetLines())
|
||||
{
|
||||
foreach (var line in text.GetLines())
|
||||
{
|
||||
var servers = ParseUri(line);
|
||||
if (servers != null)
|
||||
{
|
||||
list.AddRange(servers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (list.Count == 0)
|
||||
{
|
||||
return null;
|
||||
list.AddRange(ParseUri(line));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Error(e.ToString());
|
||||
return null;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private static IEnumerable<Server> ParseUri(string text)
|
||||
private static IEnumerable<Server> ParseUri(in string text)
|
||||
{
|
||||
var list = new List<Server>();
|
||||
|
||||
@@ -179,19 +167,19 @@ namespace Netch.Utils
|
||||
{
|
||||
var scheme = GetUriScheme(text);
|
||||
var util = ServerHelper.GetUtilByUriScheme(scheme);
|
||||
if (util == null)
|
||||
if (util != null)
|
||||
{
|
||||
list.AddRange(util.ParseUri(text));
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Warning($"无法处理 {scheme} 协议订阅链接");
|
||||
return null;
|
||||
}
|
||||
|
||||
list.AddRange(util.ParseUri(text));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Error(e.ToString());
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach (var node in list)
|
||||
@@ -212,26 +200,35 @@ namespace Netch.Utils
|
||||
|
||||
private static Server ParseNetchUri(string text)
|
||||
{
|
||||
text = text.Substring(8);
|
||||
var NetchLink = (JObject) JsonConvert.DeserializeObject(URLSafeBase64Decode(text));
|
||||
if (NetchLink == null)
|
||||
try
|
||||
{
|
||||
text = text.Substring(8);
|
||||
|
||||
var NetchLink = (JObject) JsonConvert.DeserializeObject(URLSafeBase64Decode(text));
|
||||
if (NetchLink == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty((string) NetchLink["Hostname"]))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!ushort.TryParse((string) NetchLink["Port"], out _))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var type = (string) NetchLink["Type"];
|
||||
var s = ServerHelper.GetUtilByTypeName(type).ParseJObject(NetchLink);
|
||||
return ServerHelper.GetUtilByTypeName(s.Type).CheckServer(s) ? s : null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Warning(e.ToString());
|
||||
return null;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty((string) NetchLink["Hostname"]))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!ushort.TryParse((string) NetchLink["Port"], out _))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var type = (string) NetchLink["Type"];
|
||||
var s = ServerHelper.GetUtilByTypeName(type).ParseJObject(NetchLink);
|
||||
return ServerHelper.GetUtilByTypeName(s.Type).CheckServer(s) ? s : null;
|
||||
}
|
||||
|
||||
public static string GetNetchLink(Server s)
|
||||
|
||||
@@ -126,47 +126,38 @@ namespace Netch.Utils
|
||||
|
||||
public static string GetFileVersion(string file) => File.Exists(file) ? FileVersionInfo.GetVersionInfo(file).FileVersion : string.Empty;
|
||||
|
||||
public static bool SearchOutboundAdapter(bool log = true)
|
||||
public static bool SearchOutboundAdapter(bool logging = true)
|
||||
{
|
||||
IPAddress localEnd;
|
||||
try
|
||||
{
|
||||
localEnd = WebUtil.BestLocalEndPoint(new IPEndPoint(0x72727272, 53)).Address;
|
||||
}
|
||||
catch
|
||||
// 寻找出口适配器
|
||||
if (Win32Native.GetBestRoute(BitConverter.ToUInt32(IPAddress.Parse("114.114.114.114").GetAddressBytes(), 0),
|
||||
0, out var pRoute) != 0)
|
||||
{
|
||||
Logging.Error("GetBestRoute 搜索失败");
|
||||
return false;
|
||||
}
|
||||
|
||||
Global.Outbound.Index = pRoute.dwForwardIfIndex;
|
||||
// 根据 IP Index 寻找 出口适配器
|
||||
try
|
||||
{
|
||||
// 根据 IP 寻找 出口适配器
|
||||
Global.Outbound.Adapter = NetworkInterface.GetAllNetworkInterfaces().First(_ =>
|
||||
var adapter = NetworkInterface.GetAllNetworkInterfaces().First(_ =>
|
||||
{
|
||||
try
|
||||
{
|
||||
return _.GetIPProperties().UnicastAddresses.Any(ip =>
|
||||
{
|
||||
if (ip.Address.AddressFamily == AddressFamily.InterNetwork && ip.Address.ToString().Equals(localEnd.ToString()))
|
||||
{
|
||||
Global.Outbound.Index = _.GetIPProperties().GetIPv4Properties().Index;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
return _.GetIPProperties().GetIPv4Properties().Index == Global.Outbound.Index;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
Global.Outbound.Gateway = Global.Outbound.Adapter.GetIPProperties().GatewayAddresses[0].Address;
|
||||
if (log)
|
||||
Global.Outbound.Adapter = adapter;
|
||||
Global.Outbound.Gateway = new IPAddress(pRoute.dwForwardNextHop);
|
||||
if (logging)
|
||||
{
|
||||
Logging.Info($"出口 IPv4 地址:{Global.Outbound.Address}");
|
||||
Logging.Info($"出口 网关 地址:{Global.Outbound.Gateway}");
|
||||
Logging.Info($"出口适配器:{Global.Outbound.Adapter.Name} {Global.Outbound.Adapter.Id} {Global.Outbound.Adapter.Description}, index: {Global.Outbound.Index}");
|
||||
Logging.Info($"出口适配器:{adapter.Name} {adapter.Id} {adapter.Description}, index: {Global.Outbound.Index}");
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -206,7 +197,7 @@ namespace Netch.Utils
|
||||
}
|
||||
}
|
||||
|
||||
public static void ComponentIterator(Component component, Action<Component> func)
|
||||
public static void ComponentIterator(in Component component, in Action<Component> func)
|
||||
{
|
||||
func.Invoke(component);
|
||||
switch (component)
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace Netch.Utils
|
||||
return translateFile;
|
||||
}
|
||||
|
||||
public static void TranslateForm(Control c)
|
||||
public static void TranslateForm(in Control c)
|
||||
{
|
||||
Utils.ComponentIterator(c, component =>
|
||||
{
|
||||
|
||||
@@ -1,11 +1,347 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Netch
|
||||
{
|
||||
public static class Win32Native
|
||||
{
|
||||
public enum ForwardType
|
||||
{
|
||||
Other = 1,
|
||||
Invalid = 2,
|
||||
Direct = 3,
|
||||
Indirect = 4
|
||||
}
|
||||
|
||||
public enum ForwardProtocol
|
||||
{
|
||||
Other = 1,
|
||||
Local = 2,
|
||||
NetMGMT = 3,
|
||||
ICMP = 4,
|
||||
EGP = 5,
|
||||
GGP = 6,
|
||||
Hello = 7,
|
||||
RIP = 8,
|
||||
IS_IS = 9,
|
||||
ES_IS = 10, // 0x0000000A
|
||||
CISCO = 11, // 0x0000000B
|
||||
BBN = 12, // 0x0000000C
|
||||
OSPF = 13, // 0x0000000D
|
||||
BGP = 14, // 0x0000000E
|
||||
NT_AUTOSTATIC = 10002, // 0x00002712
|
||||
NT_STATIC = 10006, // 0x00002716
|
||||
NT_STATIC_NON_DOD = 10007 // 0x00002717
|
||||
}
|
||||
|
||||
public class RouteEntry
|
||||
{
|
||||
internal MIB_IPFORWARDROW _ipFwdNative;
|
||||
private int _metric1;
|
||||
private int _metric2;
|
||||
private int _metric3;
|
||||
private int _metric4;
|
||||
private int _metric5;
|
||||
private IPAddress _destination;
|
||||
private IPAddress _mask;
|
||||
private int _policy;
|
||||
private IPAddress _nextHop;
|
||||
private NetworkInterface _interface;
|
||||
private ForwardProtocol _protocol;
|
||||
private ForwardType _type;
|
||||
private int _nextHopAS;
|
||||
private int _age;
|
||||
private int _index;
|
||||
|
||||
public int Index
|
||||
{
|
||||
get => _index;
|
||||
set => _index = value;
|
||||
}
|
||||
|
||||
public IPAddress Destination
|
||||
{
|
||||
get => _destination;
|
||||
set => _destination = value;
|
||||
}
|
||||
|
||||
public IPAddress Mask
|
||||
{
|
||||
get => _mask;
|
||||
set => _mask = value;
|
||||
}
|
||||
|
||||
public int Policy
|
||||
{
|
||||
get => _policy;
|
||||
set => _policy = value;
|
||||
}
|
||||
|
||||
public IPAddress NextHop
|
||||
{
|
||||
get => _nextHop;
|
||||
set => _nextHop = value;
|
||||
}
|
||||
|
||||
public NetworkInterface RelatedInterface => _interface;
|
||||
|
||||
public string InterfaceName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (RelatedInterface == null)
|
||||
return string.Empty;
|
||||
return RelatedInterface.Name;
|
||||
}
|
||||
}
|
||||
|
||||
public ForwardType ForwardType
|
||||
{
|
||||
get => _type;
|
||||
set => _type = value;
|
||||
}
|
||||
|
||||
public ForwardProtocol Protocol
|
||||
{
|
||||
get => _protocol;
|
||||
set => _protocol = value;
|
||||
}
|
||||
|
||||
public int Age
|
||||
{
|
||||
get => _age;
|
||||
set => _age = value;
|
||||
}
|
||||
|
||||
public int NextHopAS
|
||||
{
|
||||
get => _nextHopAS;
|
||||
set => _nextHopAS = value;
|
||||
}
|
||||
|
||||
public int Metric1
|
||||
{
|
||||
get => _metric1;
|
||||
set => _metric1 = value;
|
||||
}
|
||||
|
||||
public int Metric2
|
||||
{
|
||||
get => _metric2;
|
||||
set => _metric2 = value;
|
||||
}
|
||||
|
||||
public int Metric3
|
||||
{
|
||||
get => _metric3;
|
||||
set => _metric3 = value;
|
||||
}
|
||||
|
||||
public int Metric4
|
||||
{
|
||||
get => _metric4;
|
||||
set => _metric4 = value;
|
||||
}
|
||||
|
||||
public int Metric5
|
||||
{
|
||||
get => _metric5;
|
||||
set => _metric5 = value;
|
||||
}
|
||||
|
||||
public RouteEntry(
|
||||
uint destination,
|
||||
uint mask,
|
||||
int policy,
|
||||
uint nextHop,
|
||||
NetworkInterface intf,
|
||||
ForwardType type,
|
||||
ForwardProtocol proto,
|
||||
int age,
|
||||
int nextHopAS,
|
||||
int metric1,
|
||||
int metric2,
|
||||
int metric3,
|
||||
int metric4,
|
||||
int metric5,
|
||||
int idx)
|
||||
{
|
||||
_age = age;
|
||||
_policy = policy;
|
||||
_protocol = proto;
|
||||
_type = type;
|
||||
_destination = new IPAddress(destination);
|
||||
_mask = new IPAddress(mask);
|
||||
_nextHop = new IPAddress(nextHop);
|
||||
_nextHopAS = nextHopAS;
|
||||
_interface = intf;
|
||||
_metric1 = metric1;
|
||||
_metric2 = metric2;
|
||||
_metric3 = metric3;
|
||||
_metric4 = metric4;
|
||||
_metric5 = metric5;
|
||||
_index = idx;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct MIB_IFROW
|
||||
{
|
||||
private const int MAX_INTERFACE_NAME_LEN = 256;
|
||||
private const int MAXLEN_IFDESCR = 256;
|
||||
private const int MAXLEN_PHYSADDR = 8;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||
public string wszName;
|
||||
public int dwIndex;
|
||||
public int dwType;
|
||||
public int dwMtu;
|
||||
public int dwSpeed;
|
||||
public int dwPhysAddrLen;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
|
||||
public byte[] bPhysAddr;
|
||||
public int dwAdminStatus;
|
||||
public int dwOperStatus;
|
||||
public int dwLastChange;
|
||||
public int dwInOctets;
|
||||
public int dwInUcastPkts;
|
||||
public int dwInNUcastPkts;
|
||||
public int dwInDiscards;
|
||||
public int dwInErrors;
|
||||
public int dwInUnknownProtos;
|
||||
public int dwOutOctets;
|
||||
public int dwOutUcastPkts;
|
||||
public int dwOutNUcastPkts;
|
||||
public int dwOutDiscards;
|
||||
public int dwOutErrors;
|
||||
public int dwOutQLen;
|
||||
public int dwDescrLen;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
|
||||
public byte[] bDescr;
|
||||
}
|
||||
|
||||
public class AdaptersTable
|
||||
{
|
||||
private Dictionary<int, NetworkInterface> _adapters = new Dictionary<int, NetworkInterface>();
|
||||
|
||||
public IDictionary<int, NetworkInterface> GetAdapters()
|
||||
{
|
||||
return _adapters;
|
||||
}
|
||||
|
||||
public NetworkInterface GetAdapter(int interfaceIndex)
|
||||
{
|
||||
NetworkInterface networkInterface = null;
|
||||
_adapters.TryGetValue(interfaceIndex, out networkInterface);
|
||||
return networkInterface;
|
||||
}
|
||||
|
||||
public int GetAdapterIndex(NetworkInterface networkInterface)
|
||||
{
|
||||
return _adapters.First(a => a.Value == networkInterface).Key;
|
||||
}
|
||||
|
||||
public AdaptersTable()
|
||||
{
|
||||
var num1 = IntPtr.Zero;
|
||||
var pdwSize = 0;
|
||||
var num2 = 0;
|
||||
num2 = GetIfTable(IntPtr.Zero, ref pdwSize, true);
|
||||
var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
|
||||
try
|
||||
{
|
||||
num1 = Marshal.AllocHGlobal(pdwSize);
|
||||
if (GetIfTable(num1, ref pdwSize, true) != 0)
|
||||
return;
|
||||
var num3 = Marshal.ReadInt32(num1);
|
||||
var ptr = new IntPtr(num1.ToInt32() + 4);
|
||||
for (var index = 0; index < num3; ++index)
|
||||
{
|
||||
var structure = (MIB_IFROW)Marshal.PtrToStructure(ptr, typeof(MIB_IFROW));
|
||||
var pIfRow = new MIB_IFROW();
|
||||
pIfRow.dwIndex = structure.dwIndex;
|
||||
if (GetIfEntry(ref pIfRow) == 0)
|
||||
{
|
||||
var str = Encoding.ASCII.GetString(structure.bDescr, 0, pIfRow.dwDescrLen - 1);
|
||||
foreach (var networkInterface in networkInterfaces)
|
||||
{
|
||||
if (networkInterface.Description == str)
|
||||
{
|
||||
_adapters.Add(structure.dwIndex, networkInterface);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ptr = new IntPtr(ptr.ToInt32() + Marshal.SizeOf(typeof(MIB_IFROW)));
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeHGlobal(num1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct MIB_IPFORWARDROW
|
||||
{
|
||||
public uint dwForwardDest;
|
||||
public uint dwForwardMask;
|
||||
public int dwForwardPolicy;
|
||||
public uint dwForwardNextHop;
|
||||
public int dwForwardIfIndex;
|
||||
public ForwardType dwForwardType;
|
||||
public ForwardProtocol dwForwardProto;
|
||||
public int dwForwardAge;
|
||||
public int dwForwardNextHopAS;
|
||||
public int dwForwardMetric1;
|
||||
public int dwForwardMetric2;
|
||||
public int dwForwardMetric3;
|
||||
public int dwForwardMetric4;
|
||||
public int dwForwardMetric5;
|
||||
|
||||
public static implicit operator MIB_IPFORWARDROW(RouteEntry value)
|
||||
{
|
||||
var mibIpforwardrow = new MIB_IPFORWARDROW();
|
||||
mibIpforwardrow.dwForwardAge = value.Age;
|
||||
mibIpforwardrow.dwForwardDest = BitConverter.ToUInt32(value.Destination.GetAddressBytes(), 0);
|
||||
mibIpforwardrow.dwForwardMask = BitConverter.ToUInt32(value.Mask.GetAddressBytes(), 0);
|
||||
mibIpforwardrow.dwForwardMetric1 = value.Metric1;
|
||||
mibIpforwardrow.dwForwardMetric2 = value.Metric2;
|
||||
mibIpforwardrow.dwForwardMetric3 = value.Metric3;
|
||||
mibIpforwardrow.dwForwardMetric4 = value.Metric4;
|
||||
mibIpforwardrow.dwForwardMetric5 = value.Metric5;
|
||||
mibIpforwardrow.dwForwardNextHop = BitConverter.ToUInt32(value.NextHop.GetAddressBytes(), 0);
|
||||
mibIpforwardrow.dwForwardNextHopAS = value.NextHopAS;
|
||||
mibIpforwardrow.dwForwardPolicy = value.Policy;
|
||||
mibIpforwardrow.dwForwardProto = value.Protocol;
|
||||
mibIpforwardrow.dwForwardType = value.ForwardType;
|
||||
var adaptersTable = new AdaptersTable();
|
||||
mibIpforwardrow.dwForwardIfIndex = adaptersTable.GetAdapterIndex(value.RelatedInterface);
|
||||
return mibIpforwardrow;
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport("iphlpapi", SetLastError = true)]
|
||||
public static extern int GetIfTable(IntPtr pIfTable, ref int pdwSize, bool bOrder);
|
||||
|
||||
[DllImport("iphlpapi", SetLastError = true)]
|
||||
public static extern int GetIfEntry(ref MIB_IFROW pIfRow);
|
||||
|
||||
[DllImport("iphlpapi", SetLastError = true)]
|
||||
public static extern int GetBestRoute(uint dwDestAddr, int dwSourceAddr, out MIB_IPFORWARDROW pRoute);
|
||||
|
||||
[DllImport("User32", CharSet = CharSet.Auto, ExactSpelling = true)]
|
||||
public static extern IntPtr GetForegroundWindow();
|
||||
|
||||
[DllImport("WinINet")]
|
||||
public static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, int dwBufferLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace NetchUpdater
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = newUpdaterPath,
|
||||
Arguments = $"{port} {updatePath} {targetPath}",
|
||||
Arguments = $"{port} \"{updatePath}\" \"{targetPath}\"",
|
||||
WorkingDirectory = tempPath,
|
||||
UseShellExecute = false
|
||||
});
|
||||
@@ -98,9 +98,9 @@ namespace NetchUpdater
|
||||
|
||||
#endregion
|
||||
|
||||
/*while (!Debugger.IsAttached)
|
||||
/*Console.WriteLine("Waiting Attach");
|
||||
while (!Debugger.IsAttached)
|
||||
{
|
||||
Console.WriteLine("Waiting Attach");
|
||||
Thread.Sleep(1000);
|
||||
}*/
|
||||
|
||||
@@ -221,7 +221,7 @@ namespace NetchUpdater
|
||||
File.WriteAllBytes("7za.exe", Resources._7za);
|
||||
|
||||
var argument = new StringBuilder();
|
||||
argument.Append($" x {archiveFileName} -o{destDirName} ");
|
||||
argument.Append($" x \"{archiveFileName}\" -o\"{destDirName}\" ");
|
||||
if (overwrite)
|
||||
argument.Append(" -y ");
|
||||
|
||||
|
||||
21
README.md
21
README.md
@@ -1,17 +1,18 @@
|
||||
# Netch
|
||||
[](https://t.me/Netch_Discuss_Group)
|
||||
[](https://t.me/Netch)
|
||||
[](https://github.com/NetchX/Netch)
|
||||
[](https://github.com/NetchX/Netch/releases)
|
||||
[](https://github.com/NetchX/Netch/releases)
|
||||
[](https://github.com/NetchX/Netch/actions)
|
||||
[](LICENSE)
|
||||
[](https://t.me/Netch) [](https://t.me/Netch_Discuss_Group)
|
||||
[](https://netch.org/)
|
||||
[](LICENSE)
|
||||
|
||||
[中文说明](/docs/README.zh-CN.md)
|
||||
|
||||
[FAQ/常见问题](https://netch.org/#/docs/zh-CN/faq)
|
||||
[常见问题](https://netch.org/#/docs/zh-CN/faq)
|
||||
|
||||
Game accelerator
|
||||
Game network accelerator
|
||||
|
||||
## TOC
|
||||
- [Netch](#netch)
|
||||
@@ -23,10 +24,17 @@ Game accelerator
|
||||
- [Requirements](#requirements)
|
||||
|
||||
## Description
|
||||
Netch is an open source game network accelerator. Unlike SSTap, which needs to add rules to function as a blacklist proxy, Netch is more similar to SocksCap64, which can scan the game directory to get their process names specifically and forward their network traffic through the proxy server
|
||||
|
||||
Netch is an open source game accelerator. Unlike SSTap, which needs to add rules to function as a blacklist proxy, Netch is more similar to SocksCap64, which can scan the game directory to get their process names specifically and forward their network traffic through the proxy server. Now supports Socks5, Shadowsocks, ShadowsocksR, VMess.
|
||||
Currently supports the following protocols
|
||||
- Socks5
|
||||
- Shadowsocks
|
||||
- ShadowsocksR
|
||||
- Trojan
|
||||
- VMess
|
||||
- VLess
|
||||
|
||||
As well, Netch avoid the restricted NAT problem caused by SSTap. You can use an NATTypeTester to test out what your NAT type is. When using SSTap to speed up some P2P gaming connections or the game is required for that kind of open NAT type, you may experience some bad situations such as unable to join the game.
|
||||
As well, Netch avoid the restricted NAT problem caused by SSTap. You can use an NATTypeTester to test out what your NAT type is. When using SSTap to speed up some P2P gaming connections or the game is required for that kind of open NAT type, you may experience some bad situations such as unable to join the game
|
||||
|
||||
## Sponsor
|
||||
<a href="https://www.jetbrains.com/?from=Netch"><img src=".github/jetbrains-variant-4.svg" alt="JetBrains" width="200"/></a>
|
||||
@@ -58,7 +66,6 @@ As well, Netch avoid the restricted NAT problem caused by SSTap. You can use an
|
||||
- [trojan](https://github.com/trojan-gfw/trojan)
|
||||
- [ACL4SSR](https://github.com/ACL4SSR/ACL4SSR)
|
||||
- [dnsmasq-china-list](https://github.com/felixonmars/dnsmasq-china-list)
|
||||
- [unbound](https://github.com/NLnetLabs/unbound)
|
||||
- [tap-windows6](https://github.com/OpenVPN/tap-windows6)
|
||||
- [Privoxy](https://www.privoxy.org/)
|
||||
- [NatTypeTester](https://github.com/HMBSbige/NatTypeTester)
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Test")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Test")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("53397641-35CA-4336-8E22-2CE12EF476AC")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -1,64 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{53397641-35CA-4336-8E22-2CE12EF476AC}</ProjectGuid>
|
||||
<ProjectTypeGuids>{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Test</RootNamespace>
|
||||
<AssemblyName>Test</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="nunit.framework, Version=3.5.0.0, Culture=neutral, PublicKeyToken=2638cd05610744eb">
|
||||
<HintPath>..\packages\NUnit.3.5.0\lib\net45\nunit.framework.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Tests.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Netch\Netch.csproj">
|
||||
<Project>{4b041b91-5790-4571-8c58-c63ffe4bc9f8}</Project>
|
||||
<Name>Netch</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net48</TargetFramework>
|
||||
<Platforms>x64</Platforms>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove=".gitignore" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Netch\Netch.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Servers.ShadowsocksR.Form;
|
||||
using Netch.Servers.ShadowsocksR;
|
||||
using Netch.Servers.VMess;
|
||||
using Netch.Servers.VMess.Form;
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="NUnit" version="3.5.0" targetFramework="net45" />
|
||||
</packages>
|
||||
2
binaries
2
binaries
Submodule binaries updated: fb15d4bffd...f081890f60
@@ -206,10 +206,6 @@ ping 的值未必准确,因为这只是你本地到代理服务器而非游戏
|
||||
|
||||
如果需要 Steam,Uplay 等启动器也被代理,参照前面的方式对 Steam,Uplay 根目录也进行扫描即可
|
||||
|
||||
如果出现了启动失败,或者无法代理成功的情况,请先尝试`选项 - 重启服务`或`选项 - 卸载服务`,或者在退出 Netch 以后,点击运行在 Netch 根目录下的 `DriverUpdater.exe` 程序进行驱动更新
|
||||
|
||||
|
||||
|
||||
## 语言支持
|
||||
|
||||
Netch 支持多种语言,在启动时会根据系统语言选择自身语言。如果需要手动切换语言,可以在启动时加入命令行参数,命令行参数为目前支持的语言代码,可以去 [NetchTranslation/i18n](https://github.com/NetchX/NetchTranslation/tree/master/i18n) 文件夹下查看外部支持的语言代码文件。Netch 目前内置 en-US,zh-CN,外置 zh-TW。欢迎大家为 [NetchTranslation](https://github.com/NetchX/NetchTranslation) 提供其他语言的翻译
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# Netch
|
||||
[](https://t.me/Netch) [](https://t.me/Netch_Discuss_Group) 
|
||||
[](https://t.me/Netch_Discuss_Group)
|
||||
[](https://t.me/Netch)
|
||||
[](https://github.com/NetchX/Netch)
|
||||
[](https://github.com/NetchX/Netch/releases)
|
||||
[](https://github.com/NetchX/Netch/releases)
|
||||
[](https://github.com/NetchX/Netch/actions)
|
||||
[](https://netch.org/)
|
||||
[](LICENSE)
|
||||
|
||||
游戏加速工具
|
||||
|
||||
@@ -15,9 +22,17 @@
|
||||
- [进阶用法](Advanced_Usage.zh-CN.md)
|
||||
- [依赖](#依赖)
|
||||
- [语言支持](#语言支持)
|
||||
|
||||
|
||||
## 简介
|
||||
Netch 是一款 Windows 平台的开源游戏加速工具,Netch 可以实现类似 SocksCap64 那样的进程代理,也可以实现 SSTap 那样的全局 TUN/TAP 代理,和 Shadowsocks-Windows 那样的本地 Socks5,HTTP 和系统代理。至于连接至远程服务器的代理协议,目前 Netch 支持以下代理协议:Shadowsocks,VMess,Socks5,ShadowsocksR
|
||||
Netch 是一款 Windows 平台的开源游戏加速工具,Netch 可以实现类似 SocksCap64 那样的进程代理,也可以实现 SSTap 那样的全局 TUN/TAP 代理,和 Shadowsocks-Windows 那样的本地 Socks5,HTTP 和系统代理
|
||||
|
||||
至于连接至远程服务器的代理协议,目前 Netch 支持以下代理协议
|
||||
- Socks5
|
||||
- Shadowsocks
|
||||
- ShadowsocksR
|
||||
- Trojan
|
||||
- VMess
|
||||
- VLess
|
||||
|
||||
与此同时 Netch 避免了 SSTap 的 NAT 问题 ,检查 NAT 类型即可知道是否有 NAT 问题。使用 SSTap 加速部分 P2P 联机,对 NAT 类型有要求的游戏时,可能会因为 NAT 类型严格遇到无法加入联机,或者其他影响游戏体验的情况
|
||||
|
||||
@@ -60,7 +75,6 @@ Netch 支持多种语言,在启动时会根据系统语言选择自身语言
|
||||
- [trojan](https://github.com/trojan-gfw/trojan)
|
||||
- [ACL4SSR](https://github.com/ACL4SSR/ACL4SSR)
|
||||
- [dnsmasq-china-list](https://github.com/felixonmars/dnsmasq-china-list)
|
||||
- [unbound](https://github.com/NLnetLabs/unbound)
|
||||
- [tap-windows6](https://github.com/OpenVPN/tap-windows6)
|
||||
- [Privoxy](https://www.privoxy.org/)
|
||||
- [NatTypeTester](https://github.com/HMBSbige/NatTypeTester)
|
||||
|
||||
2
modes
2
modes
Submodule modes updated: 034c8583ad...3ac9f3c380
Submodule translations updated: 9ee3747784...45e50093e3
Reference in New Issue
Block a user