mirror of
https://github.com/netchx/netch.git
synced 2026-05-11 23:45:06 +08:00
Compare commits
66 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bdaab4f1ac | ||
|
|
9ad5e16f47 | ||
|
|
c861ed4116 | ||
|
|
c39b758fe6 | ||
|
|
e1901587a5 | ||
|
|
8aea21a2c6 | ||
|
|
d97d461354 | ||
|
|
d8f3bdaa78 | ||
|
|
7516ecf946 | ||
|
|
69d6397383 | ||
|
|
7854a91fef | ||
|
|
853da97ffc | ||
|
|
a0fbcb588d | ||
|
|
1e2c284a18 | ||
|
|
499898fdf5 | ||
|
|
5874bf7599 | ||
|
|
137456f6e6 | ||
|
|
5fe0e33722 | ||
|
|
6c1d2c9e4e | ||
|
|
0196dbb487 | ||
|
|
0343a1ab0c | ||
|
|
5ddc75ae16 | ||
|
|
bcb587e4b5 | ||
|
|
ba50a23914 | ||
|
|
1912d2055f | ||
|
|
ab2348afc7 | ||
|
|
a42890fdbd | ||
|
|
5d96127b5a | ||
|
|
f2912a334a | ||
|
|
09bddd9ad4 | ||
|
|
8fc4e3151f | ||
|
|
d616380deb | ||
|
|
c6817e39b2 | ||
|
|
b08cd53cee | ||
|
|
bf8dd98013 | ||
|
|
89c3ffaaf6 | ||
|
|
1dcb96819b | ||
|
|
e33cd6d2d2 | ||
|
|
7998be0c74 | ||
|
|
238892ea2c | ||
|
|
08332667ad | ||
|
|
bc6bc52b9a | ||
|
|
2977afe00e | ||
|
|
f36ff457b4 | ||
|
|
d1d58cc39c | ||
|
|
bd0b3a6f2e | ||
|
|
35eae6094e | ||
|
|
725fdc2e9a | ||
|
|
bd05f875f2 | ||
|
|
ea3fb188e4 | ||
|
|
ee3ac561b5 | ||
|
|
4fb090d7a4 | ||
|
|
9302900b5d | ||
|
|
6dd50f1510 | ||
|
|
91f73b936d | ||
|
|
9ddcc3ae3c | ||
|
|
9d637a3c67 | ||
|
|
8ff8582dd7 | ||
|
|
b76a22da33 | ||
|
|
ee61c5dbd3 | ||
|
|
658ed3245f | ||
|
|
d443c6d311 | ||
|
|
caa6b8fa94 | ||
|
|
26af839d01 | ||
|
|
08db39f72b | ||
|
|
5e1f25a27e |
71
.github/workflows/build.yml
vendored
Normal file
71
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
name: GitHub Actions & Netch CI
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Get tag name
|
||||
uses: olegtarasov/get-tag@v1
|
||||
|
||||
- name: submodules-init
|
||||
uses: snickerbockers/submodules-init@v4
|
||||
|
||||
- uses: nuget/setup-nuget@v1
|
||||
- run: nuget restore Netch.sln
|
||||
|
||||
- name: Setup MSBuild.exe
|
||||
uses: microsoft/setup-msbuild@v1.0.0
|
||||
|
||||
- name: Build .NET 4.8 Netch
|
||||
shell: pwsh
|
||||
run: |
|
||||
.\build.ps1
|
||||
New-Item -ItemType Directory -Path C:\builtfiles -Force > $null
|
||||
Compress-Archive -Path Netch\bin\x64\Release\win-x64\* -DestinationPath C:\builtfiles\Netch.x64-${{ env.GITHUB_TAG_NAME }}.zip
|
||||
echo "::set-env name=Netch64_SHA256::$(.\getSHA256.ps1 C:\builtfiles\Netch.x64-${{ env.GITHUB_TAG_NAME }}.zip)"
|
||||
Compress-Archive -Path Netch\bin\x86\Release\win-x86\* -DestinationPath C:\builtfiles\Netch.x86-${{ env.GITHUB_TAG_NAME }}.zip
|
||||
echo "::set-env name=Netch86_SHA256::$(.\getSHA256.ps1 C:\builtfiles\Netch.x86-${{ env.GITHUB_TAG_NAME }}.zip)"
|
||||
|
||||
- name: Upload Netch.x64
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: Netch.x64
|
||||
path: Netch\bin\x64\Release\win-x64
|
||||
|
||||
- name: Upload Netch.x86
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: Netch.x86
|
||||
path: Netch\bin\x86\Release\win-x86
|
||||
|
||||
# Create a new release: create a tag, then 'git push origin <tagname>', wait for it to build
|
||||
- name: Create a new GitHub release if a new tag is pushed
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
name: ${{ env.GITHUB_TAG_NAME }}
|
||||
prerelease: true
|
||||
draft: false
|
||||
files: |
|
||||
C:\builtfiles\Netch.x64-${{ env.GITHUB_TAG_NAME }}.zip
|
||||
C:\builtfiles\Netch.x86-${{ env.GITHUB_TAG_NAME }}.zip
|
||||
body: |
|
||||
|
||||
[](https://t.me/Netch) [](https://t.me/Netch_Discuss_Group)
|
||||
|
||||
## 更新日志:
|
||||
* 这是 GitHub Action 自动化部署,更新日志应该很快会手动更新:D
|
||||
|
||||
## 文件校验
|
||||
| 文件名 | SHA256 |
|
||||
| :- | :- |
|
||||
| <sub>Netch.x64-${{ env.GITHUB_TAG_NAME }}.zip</sub> | <sub>${{ env.Netch64_SHA256 }}</sub> |
|
||||
| <sub>Netch.x86-${{ env.GITHUB_TAG_NAME }}.zip</sub> | <sub>${{ env.Netch86_SHA256 }}</sub> |
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
env:
|
||||
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||
5
GetSHA256.ps1
Normal file
5
GetSHA256.ps1
Normal file
@@ -0,0 +1,5 @@
|
||||
param([string]$file)
|
||||
$hash = [Security.Cryptography.HashAlgorithm]::Create( "SHA256" )
|
||||
$stream = ([IO.StreamReader]$file).BaseStream
|
||||
-join ($hash.ComputeHash($stream) | ForEach { "{0:X2}" -f $_ })
|
||||
$stream.Close()
|
||||
18
Netch.sln
18
Netch.sln
@@ -3,24 +3,40 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29009.5
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Netch", "Netch\Netch.csproj", "{4B041B91-5790-4571-8C58-C63FFE4BC9F8}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Netch", "Netch\Netch.csproj", "{4B041B91-5790-4571-8C58-C63FFE4BC9F8}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetchLib", "NetchLib\NetchLib.csproj", "{A8715AF4-ACC6-43F9-9381-4294C5360623}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Debug|x64.Build.0 = Debug|x64
|
||||
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Debug|x86.Build.0 = Debug|x86
|
||||
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Release|Any CPU.ActiveCfg = Release|x86
|
||||
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Release|x64.ActiveCfg = Release|x64
|
||||
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Release|x64.Build.0 = Release|x64
|
||||
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Release|x86.ActiveCfg = Release|x86
|
||||
{4B041B91-5790-4571-8C58-C63FFE4BC9F8}.Release|x86.Build.0 = Release|x86
|
||||
{A8715AF4-ACC6-43F9-9381-4294C5360623}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{A8715AF4-ACC6-43F9-9381-4294C5360623}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{A8715AF4-ACC6-43F9-9381-4294C5360623}.Debug|x64.Build.0 = Debug|x64
|
||||
{A8715AF4-ACC6-43F9-9381-4294C5360623}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{A8715AF4-ACC6-43F9-9381-4294C5360623}.Debug|x86.Build.0 = Debug|x86
|
||||
{A8715AF4-ACC6-43F9-9381-4294C5360623}.Release|Any CPU.ActiveCfg = Release|x86
|
||||
{A8715AF4-ACC6-43F9-9381-4294C5360623}.Release|x64.ActiveCfg = Release|x64
|
||||
{A8715AF4-ACC6-43F9-9381-4294C5360623}.Release|x64.Build.0 = Release|x64
|
||||
{A8715AF4-ACC6-43F9-9381-4294C5360623}.Release|x86.ActiveCfg = Release|x86
|
||||
{A8715AF4-ACC6-43F9-9381-4294C5360623}.Release|x86.Build.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
112
Netch/Controllers/DNSController.cs
Normal file
112
Netch/Controllers/DNSController.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
using Netch.Forms;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
public class DNSController
|
||||
{
|
||||
/// <summary>
|
||||
/// 进程实例
|
||||
/// </summary>
|
||||
public Process Instance;
|
||||
|
||||
/// <summary>
|
||||
/// 启动NatTypeTester
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool Start()
|
||||
{
|
||||
MainForm.Instance.StatusText($"{Utils.i18N.Translate("Starting dns2tcp Service")}");
|
||||
try
|
||||
{
|
||||
if (!File.Exists("bin\\dns2tcp.exe"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Instance = MainController.GetProcess();
|
||||
Instance.StartInfo.FileName = "bin\\dns2tcp.exe";
|
||||
|
||||
Instance.StartInfo.Arguments = " -L 127.0.0.1:53 -R 1.1.1.1:53";
|
||||
|
||||
Instance.OutputDataReceived += OnOutputDataReceived;
|
||||
Instance.ErrorDataReceived += OnOutputDataReceived;
|
||||
|
||||
Instance.Start();
|
||||
Instance.BeginOutputReadLine();
|
||||
Instance.BeginErrorReadLine();
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Utils.Logging.Info("dns2tcp 进程出错");
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Instance != null && !Instance.HasExited)
|
||||
{
|
||||
Instance.Kill();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Utils.Logging.Info(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(e.Data))
|
||||
{
|
||||
if (File.Exists("logging\\dns2tcp.log"))
|
||||
{
|
||||
File.Delete("logging\\dns2tcp.log");
|
||||
}
|
||||
File.AppendAllText("logging\\dns2tcp.log", $"{e.Data}\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* public static DNS.Server.DnsServer Server = new DNS.Server.DnsServer(new Resolver());
|
||||
|
||||
public bool Start()
|
||||
{
|
||||
MainForm.Instance.StatusText($"{Utils.i18N.Translate("Status")}{Utils.i18N.Translate(": ")}{Utils.i18N.Translate("Starting LocalDns service")}");
|
||||
try
|
||||
{
|
||||
_ = Server.Listen(new IPEndPoint(IPAddress.IPv6Any, 53));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Utils.Logging.Info(e.ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
Server.Dispose();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Utils.Logging.Info(e.ToString());
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,16 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
public class MainController
|
||||
{
|
||||
[DllImport("dnsapi", EntryPoint = "DnsFlushResolverCache")]
|
||||
public static extern UInt32 FlushDNSResolverCache();
|
||||
public static Process GetProcess()
|
||||
{
|
||||
var process = new Process();
|
||||
@@ -51,6 +56,11 @@ namespace Netch.Controllers
|
||||
/// </summary>
|
||||
public TUNTAPController pTUNTAPController;
|
||||
|
||||
/// <summary>
|
||||
/// NTT 控制器
|
||||
/// </summary>
|
||||
public NTTController pNTTController;
|
||||
|
||||
/// <summary>
|
||||
/// 启动
|
||||
/// </summary>
|
||||
@@ -59,6 +69,8 @@ namespace Netch.Controllers
|
||||
/// <returns>是否启动成功</returns>
|
||||
public bool Start(Models.Server server, Models.Mode mode)
|
||||
{
|
||||
FlushDNSResolverCache();
|
||||
|
||||
var result = false;
|
||||
switch (server.Type)
|
||||
{
|
||||
@@ -106,8 +118,18 @@ namespace Netch.Controllers
|
||||
{
|
||||
pNFController = new NFController();
|
||||
}
|
||||
if (pNTTController == null)
|
||||
{
|
||||
pNTTController = new NTTController();
|
||||
}
|
||||
// 进程代理模式,启动 NF 控制器
|
||||
result = pNFController.Start(server, mode);
|
||||
if (result)
|
||||
Task.Run(() =>
|
||||
{
|
||||
pNTTController.Start();
|
||||
});
|
||||
|
||||
}
|
||||
else if (mode.Type == 1)
|
||||
{
|
||||
@@ -115,8 +137,17 @@ namespace Netch.Controllers
|
||||
{
|
||||
pTUNTAPController = new TUNTAPController();
|
||||
}
|
||||
if (pNTTController == null)
|
||||
{
|
||||
pNTTController = new NTTController();
|
||||
}
|
||||
// TUN/TAP 黑名单代理模式,启动 TUN/TAP 控制器
|
||||
result = pTUNTAPController.Start(server, mode);
|
||||
if (result)
|
||||
Task.Run(() =>
|
||||
{
|
||||
pNTTController.Start();
|
||||
});
|
||||
}
|
||||
else if (mode.Type == 2)
|
||||
{
|
||||
@@ -124,8 +155,17 @@ namespace Netch.Controllers
|
||||
{
|
||||
pTUNTAPController = new TUNTAPController();
|
||||
}
|
||||
if (pNTTController == null)
|
||||
{
|
||||
pNTTController = new NTTController();
|
||||
}
|
||||
// TUN/TAP 白名单代理模式,启动 TUN/TAP 控制器
|
||||
result = pTUNTAPController.Start(server, mode);
|
||||
if (result)
|
||||
Task.Run(() =>
|
||||
{
|
||||
pNTTController.Start();
|
||||
});
|
||||
}
|
||||
else if (mode.Type == 3 || mode.Type == 5)
|
||||
{
|
||||
@@ -171,7 +211,7 @@ namespace Netch.Controllers
|
||||
{
|
||||
pVMessController.Stop();
|
||||
}
|
||||
|
||||
|
||||
if (pNFController != null)
|
||||
{
|
||||
pNFController.Stop();
|
||||
@@ -184,10 +224,15 @@ namespace Netch.Controllers
|
||||
{
|
||||
pHTTPController.Stop();
|
||||
}
|
||||
|
||||
|
||||
if (pNTTController != null)
|
||||
{
|
||||
pNTTController.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
public void KillProcess(string name) {
|
||||
public void KillProcess(string name)
|
||||
{
|
||||
var processes = Process.GetProcessesByName(name);
|
||||
foreach (var p in processes)
|
||||
{
|
||||
@@ -198,7 +243,7 @@ namespace Netch.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsChildProcess(Process process,string name)
|
||||
private static bool IsChildProcess(Process process, string name)
|
||||
{
|
||||
bool result;
|
||||
try
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Netch.Forms;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.ServiceProcess;
|
||||
@@ -31,6 +32,9 @@ namespace Netch.Controllers
|
||||
/// </summary>
|
||||
public Models.State State = Models.State.Waiting;
|
||||
|
||||
// 生成驱动文件路径
|
||||
public string driverPath = string.Format("{0}\\drivers\\netfilter2.sys", Environment.SystemDirectory);
|
||||
|
||||
/// <summary>
|
||||
/// 启动
|
||||
/// </summary>
|
||||
@@ -39,65 +43,59 @@ namespace Netch.Controllers
|
||||
/// <returns>是否成功</returns>
|
||||
public bool Start(Models.Server server, Models.Mode mode)
|
||||
{
|
||||
if (!File.Exists("bin\\Redirector.exe"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 生成驱动文件路径
|
||||
var driver = string.Format("{0}\\drivers\\netfilter2.sys", Environment.SystemDirectory);
|
||||
MainForm.Instance.StatusText($"{Utils.i18N.Translate("Status")}{Utils.i18N.Translate(": ")}{Utils.i18N.Translate("Starting Redirector")}");
|
||||
|
||||
// 检查驱动是否存在
|
||||
if (!File.Exists(driver))
|
||||
if (File.Exists(driverPath))
|
||||
{
|
||||
// 生成系统版本
|
||||
var version = $"{Environment.OSVersion.Version.Major.ToString()}.{Environment.OSVersion.Version.Minor.ToString()}";
|
||||
|
||||
// 检查系统版本并复制对应驱动
|
||||
try
|
||||
//检查驱动版本号
|
||||
FileVersionInfo fileVerInfo = System.Diagnostics.FileVersionInfo.GetVersionInfo(driverPath);
|
||||
if (new Version(fileVerInfo.FileVersion) < new Version(UpdateChecker.NFDriverVersion))
|
||||
{
|
||||
switch (version)
|
||||
//需要更新驱动
|
||||
try
|
||||
{
|
||||
case "10.0":
|
||||
File.Copy("bin\\Win-10.sys", driver);
|
||||
Utils.Logging.Info("已复制 Win10 驱动");
|
||||
break;
|
||||
case "6.3":
|
||||
case "6.2":
|
||||
File.Copy("bin\\Win-8.sys", driver);
|
||||
Utils.Logging.Info("已复制 Win8 驱动");
|
||||
break;
|
||||
case "6.1":
|
||||
case "6.0":
|
||||
File.Copy("bin\\Win-7.sys", driver);
|
||||
Utils.Logging.Info("已复制 Win7 驱动");
|
||||
break;
|
||||
default:
|
||||
Utils.Logging.Info($"不支持的系统版本:{version}");
|
||||
var service = new ServiceController("netfilter2");
|
||||
if (service.Status == ServiceControllerStatus.Running)
|
||||
{
|
||||
service.Stop();
|
||||
service.WaitForStatus(ServiceControllerStatus.Stopped);
|
||||
}
|
||||
nfapinet.NFAPI.nf_unRegisterDriver("netfilter2");
|
||||
|
||||
//删除老驱动
|
||||
File.Delete(driverPath);
|
||||
if (!InstallDriver())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Utils.Logging.Info("复制驱动文件失败");
|
||||
Utils.Logging.Info(e.ToString());
|
||||
return false;
|
||||
catch (Exception)
|
||||
{
|
||||
Utils.Logging.Info($"更新驱动出错");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 注册驱动文件
|
||||
var result = nfapinet.NFAPI.nf_registerDriver("netfilter2");
|
||||
if (result != nfapinet.NF_STATUS.NF_STATUS_SUCCESS)
|
||||
{
|
||||
Utils.Logging.Info($"注册驱动失败,返回值:{result}");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!InstallDriver())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
//启动驱动服务
|
||||
var service = new ServiceController("netfilter2");
|
||||
if (service.Status == ServiceControllerStatus.Stopped)
|
||||
if (service.Status == ServiceControllerStatus.Running)
|
||||
{
|
||||
//防止其他程序占用 重置NF百万ID限制 待定
|
||||
/*service.Stop();
|
||||
MainForm.Instance.StatusText($"{Utils.i18N.Translate("Status")}{Utils.i18N.Translate(": ")}{Utils.i18N.Translate("Starting netfilter2 Service")}");
|
||||
service.Start();*/
|
||||
}
|
||||
else if (service.Status == ServiceControllerStatus.Stopped)
|
||||
{
|
||||
MainForm.Instance.StatusText($"{Utils.i18N.Translate("Status")}{Utils.i18N.Translate(": ")}{Utils.i18N.Translate("Starting netfilter2 Service")}");
|
||||
service.Start();
|
||||
}
|
||||
}
|
||||
@@ -114,6 +112,13 @@ namespace Netch.Controllers
|
||||
}
|
||||
|
||||
var processes = "";
|
||||
|
||||
//开启进程白名单模式
|
||||
if (!Global.Settings.ProcessBypassMode)
|
||||
{
|
||||
processes += "NTT.exe,";
|
||||
}
|
||||
|
||||
foreach (var proc in mode.Rule)
|
||||
{
|
||||
processes += proc;
|
||||
@@ -122,32 +127,92 @@ namespace Netch.Controllers
|
||||
processes = processes.Substring(0, processes.Length - 1);
|
||||
|
||||
Instance = MainController.GetProcess();
|
||||
Instance.StartInfo.FileName = "bin\\Redirector.exe";
|
||||
|
||||
var fallback = "";
|
||||
|
||||
if (server.Type != "Socks5")
|
||||
if (Global.Settings.UseRedirector2)
|
||||
{
|
||||
fallback = $"-r 127.0.0.1:{Global.Settings.Socks5LocalPort} -p \"{processes}\"";
|
||||
if (!File.Exists("bin\\Redirector2.exe"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Instance.StartInfo.FileName = "bin\\Redirector2.exe";
|
||||
|
||||
|
||||
if (server.Type != "Socks5")
|
||||
{
|
||||
fallback += $" 127.0.0.1:{Global.Settings.Socks5LocalPort}";
|
||||
fallback += $" \"{processes}\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = Utils.DNS.Lookup(server.Hostname);
|
||||
if (result == null)
|
||||
{
|
||||
Utils.Logging.Info("无法解析服务器 IP 地址");
|
||||
return false;
|
||||
}
|
||||
|
||||
fallback += $" {result}:{server.Port}";
|
||||
fallback += $" \"{processes}\"";
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(server.Username) && !string.IsNullOrWhiteSpace(server.Password))
|
||||
{
|
||||
fallback += $" \"{server.Username}\"";
|
||||
fallback += $" \"{server.Password}\"";
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = Utils.DNS.Lookup(server.Hostname);
|
||||
if (result == null)
|
||||
if (!File.Exists("bin\\Redirector.exe"))
|
||||
{
|
||||
Utils.Logging.Info("无法解析服务器 IP 地址");
|
||||
return false;
|
||||
}
|
||||
Instance.StartInfo.FileName = "bin\\Redirector.exe";
|
||||
|
||||
fallback = $"-r {result}:{server.Port} -p \"{processes}\"";
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(server.Username) && !string.IsNullOrWhiteSpace(server.Password))
|
||||
//开启进程白名单模式
|
||||
if (Global.Settings.ProcessBypassMode)
|
||||
{
|
||||
fallback += $" -username \"{server.Username}\" -password \"{server.Password}\"";
|
||||
processes += ",Shadowsocks.exe";
|
||||
processes += ",ShadowsocksR.exe";
|
||||
processes += ",Privoxy.exe";
|
||||
processes += ",simple-obfs.exe";
|
||||
processes += ",v2ray.exe,v2ctl.exe,v2ray-plugin.exe";
|
||||
fallback += " -bypass true ";
|
||||
}
|
||||
else
|
||||
{
|
||||
fallback += " -bypass false ";
|
||||
}
|
||||
|
||||
if (server.Type != "Socks5")
|
||||
{
|
||||
fallback += $"-r 127.0.0.1:{Global.Settings.Socks5LocalPort} -p \"{processes}\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = Utils.DNS.Lookup(server.Hostname);
|
||||
if (result == null)
|
||||
{
|
||||
Utils.Logging.Info("无法解析服务器 IP 地址");
|
||||
return false;
|
||||
}
|
||||
|
||||
fallback += $"-r {result}:{server.Port} -p \"{processes}\"";
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(server.Username) && !string.IsNullOrWhiteSpace(server.Password))
|
||||
{
|
||||
fallback += $" -username \"{server.Username}\" -password \"{server.Password}\"";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Instance.StartInfo.Arguments = fallback + $" -t {Global.Settings.RedirectorTCPPort}";
|
||||
Utils.Logging.Info($"{fallback}");
|
||||
|
||||
if (File.Exists("logging\\redirector.log"))
|
||||
File.Delete("logging\\redirector.log");
|
||||
|
||||
Instance.StartInfo.Arguments = fallback;
|
||||
Instance.OutputDataReceived += OnOutputDataReceived;
|
||||
Instance.ErrorDataReceived += OnOutputDataReceived;
|
||||
State = Models.State.Starting;
|
||||
@@ -155,7 +220,6 @@ namespace Netch.Controllers
|
||||
Instance.BeginOutputReadLine();
|
||||
Instance.BeginErrorReadLine();
|
||||
|
||||
var IsFallback = false;
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
@@ -164,33 +228,6 @@ namespace Netch.Controllers
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (State == Models.State.Stopped)
|
||||
{
|
||||
if (!IsFallback)
|
||||
{
|
||||
IsFallback = true;
|
||||
Stop();
|
||||
Utils.Logging.Info($"尝试去除 \"-t {Global.Settings.RedirectorTCPPort}\" 参数后启动 \"bin\\Redirector.exe\"");
|
||||
Instance.StartInfo.Arguments = fallback;
|
||||
Utils.Logging.Info($"当前 \"bin\\Redirector.exe\" 启动参数为 \"{Instance.StartInfo.Arguments}\"");
|
||||
Global.Settings.RedirectorTCPPort = 2800;
|
||||
Instance.CancelOutputRead();
|
||||
Instance.CancelErrorRead();
|
||||
Instance.OutputDataReceived += OnOutputDataReceived;
|
||||
Instance.ErrorDataReceived += OnOutputDataReceived;
|
||||
State = Models.State.Starting;
|
||||
Instance.Start();
|
||||
Instance.BeginOutputReadLine();
|
||||
Instance.BeginErrorReadLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
Utils.Logging.Info("NF 进程启动失败");
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Utils.Logging.Info("NF 进程启动超时");
|
||||
@@ -216,6 +253,52 @@ namespace Netch.Controllers
|
||||
Utils.Logging.Info(e.ToString());
|
||||
}
|
||||
}
|
||||
public bool InstallDriver()
|
||||
{
|
||||
|
||||
// 生成系统版本
|
||||
var version = $"{Environment.OSVersion.Version.Major.ToString()}.{Environment.OSVersion.Version.Minor.ToString()}";
|
||||
|
||||
// 检查系统版本并复制对应驱动
|
||||
try
|
||||
{
|
||||
switch (version)
|
||||
{
|
||||
case "10.0":
|
||||
File.Copy("bin\\Win-10.sys", driverPath);
|
||||
Utils.Logging.Info("已复制 Win10 驱动");
|
||||
break;
|
||||
case "6.3":
|
||||
case "6.2":
|
||||
File.Copy("bin\\Win-8.sys", driverPath);
|
||||
Utils.Logging.Info("已复制 Win8 驱动");
|
||||
break;
|
||||
case "6.1":
|
||||
case "6.0":
|
||||
File.Copy("bin\\Win-7.sys", driverPath);
|
||||
Utils.Logging.Info("已复制 Win7 驱动");
|
||||
break;
|
||||
default:
|
||||
Utils.Logging.Info($"不支持的系统版本:{version}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Utils.Logging.Info("复制驱动文件失败");
|
||||
Utils.Logging.Info(e.ToString());
|
||||
return false;
|
||||
}
|
||||
MainForm.Instance.StatusText($"{Utils.i18N.Translate("Status")}{Utils.i18N.Translate(": ")}{Utils.i18N.Translate("Register driver")}");
|
||||
// 注册驱动文件
|
||||
var result = nfapinet.NFAPI.nf_registerDriver("netfilter2");
|
||||
if (result != nfapinet.NF_STATUS.NF_STATUS_SUCCESS)
|
||||
{
|
||||
Utils.Logging.Info($"注册驱动失败,返回值:{result}");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
@@ -229,7 +312,7 @@ namespace Netch.Controllers
|
||||
{
|
||||
State = Models.State.Stopped;
|
||||
}
|
||||
else if (e.Data.Contains("Started"))
|
||||
else if (e.Data.Contains("Start") || e.Data.Contains("Redirect to"))
|
||||
{
|
||||
State = Models.State.Started;
|
||||
}
|
||||
|
||||
96
Netch/Controllers/NTTController.cs
Normal file
96
Netch/Controllers/NTTController.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
using Netch.Forms;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
public class NTTController
|
||||
{
|
||||
/// <summary>
|
||||
/// 进程实例
|
||||
/// </summary>
|
||||
public Process Instance;
|
||||
|
||||
/// <summary>
|
||||
/// 当前状态
|
||||
/// </summary>
|
||||
public Models.State State = Models.State.Waiting;
|
||||
|
||||
/// <summary>
|
||||
/// 启动NatTypeTester
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public (bool, string, string, string) Start()
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
MainForm.Instance.NatTypeStatusText($"{Utils.i18N.Translate("Starting NatTester")}");
|
||||
try
|
||||
{
|
||||
if (!File.Exists("bin\\NTT.exe"))
|
||||
{
|
||||
return (false, null, null, null);
|
||||
}
|
||||
|
||||
Instance = MainController.GetProcess();
|
||||
Instance.StartInfo.FileName = "bin\\NTT.exe";
|
||||
|
||||
Instance.StartInfo.Arguments = $" {Global.Settings.STUN_Server} {Global.Settings.STUN_Server_Port}";
|
||||
|
||||
Instance.OutputDataReceived += OnOutputDataReceived;
|
||||
Instance.ErrorDataReceived += OnOutputDataReceived;
|
||||
|
||||
State = Models.State.Starting;
|
||||
Instance.Start();
|
||||
Instance.BeginOutputReadLine();
|
||||
Instance.BeginErrorReadLine();
|
||||
Instance.WaitForExit();
|
||||
|
||||
string[] result = File.ReadAllText("logging\\NTT.log").ToString().Split('#');
|
||||
var natType = result[0];
|
||||
var localEnd = result[1];
|
||||
var publicEnd = result[2];
|
||||
MainForm.Instance.NatTypeStatusText(natType);
|
||||
|
||||
return (true, natType, localEnd, publicEnd);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Utils.Logging.Info("NTT 进程出错");
|
||||
Stop();
|
||||
return (false, null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Instance != null && !Instance.HasExited)
|
||||
{
|
||||
Instance.Kill();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Utils.Logging.Info(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(e.Data))
|
||||
{
|
||||
if (File.Exists("logging\\NTT.log"))
|
||||
{
|
||||
File.Delete("logging\\NTT.log");
|
||||
}
|
||||
File.AppendAllText("logging\\NTT.log", $"{e.Data}\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Netch.Forms;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
@@ -25,6 +26,7 @@ namespace Netch.Controllers
|
||||
/// <returns>是否启动成功</returns>
|
||||
public bool Start(Models.Server server, Models.Mode mode)
|
||||
{
|
||||
MainForm.Instance.StatusText($"{Utils.i18N.Translate("Status")}{Utils.i18N.Translate(": ")}{Utils.i18N.Translate("Starting Shadowsocks")}");
|
||||
if (!File.Exists("bin\\Shadowsocks.exe"))
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Netch.Forms;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
@@ -25,6 +26,7 @@ namespace Netch.Controllers
|
||||
/// <returns>是否启动成功</returns>
|
||||
public bool Start(Models.Server server, Models.Mode mode)
|
||||
{
|
||||
MainForm.Instance.StatusText($"{Utils.i18N.Translate("Status")}{Utils.i18N.Translate(": ")}{Utils.i18N.Translate("Starting ShadowsocksR")}");
|
||||
if (!File.Exists("bin\\ShadowsocksR.exe"))
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
using Netch.Forms;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Controllers
|
||||
@@ -32,6 +33,14 @@ namespace Netch.Controllers
|
||||
public Models.Server SavedServer = new Models.Server();
|
||||
public Models.Mode SavedMode = new Models.Mode();
|
||||
|
||||
/// <summary>
|
||||
/// 本地 DNS 服务控制器
|
||||
/// </summary>
|
||||
public DNSController pDNSController = new DNSController();
|
||||
|
||||
// ByPassLan IP
|
||||
List<string> BypassLanIPs = new List<string>() { "10.0.0.0/8", "172.16.0.0/16", "192.168.0.0/24" };
|
||||
|
||||
/// <summary>
|
||||
/// 配置 TUNTAP 适配器
|
||||
/// </summary>
|
||||
@@ -58,6 +67,7 @@ namespace Netch.Controllers
|
||||
/// </summary>
|
||||
public bool SetupBypass()
|
||||
{
|
||||
MainForm.Instance.StatusText($"{Utils.i18N.Translate("Status")}{Utils.i18N.Translate(": ")}{Utils.i18N.Translate("SetupBypass")}");
|
||||
// 让服务器 IP 走直连
|
||||
foreach (var address in ServerAddresses)
|
||||
{
|
||||
@@ -95,6 +105,17 @@ namespace Netch.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var ip in BypassLanIPs)
|
||||
{
|
||||
var info = ip.Split('/');
|
||||
var address = IPAddress.Parse(info[0]);
|
||||
|
||||
if (!IPAddress.IsLoopback(address))
|
||||
{
|
||||
NativeMethods.CreateRoute(address.ToString(), int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
|
||||
}
|
||||
}
|
||||
|
||||
if (SavedMode.Type == 2) // 处理仅规则内走直连
|
||||
{
|
||||
// 将 TUN/TAP 网卡权重放到最高
|
||||
@@ -151,6 +172,54 @@ namespace Netch.Controllers
|
||||
}
|
||||
}
|
||||
}
|
||||
//处理NAT类型检测,由于协议的原因,无法仅通过域名确定需要代理的IP,自己记录解析了返回的IP,仅支持默认检测服务器
|
||||
if (Global.Settings.STUN_Server == "stun.stunprotocol.org")
|
||||
{
|
||||
try
|
||||
{
|
||||
var nttAddress = Dns.GetHostAddresses(Global.Settings.STUN_Server)[0];
|
||||
if (int.TryParse("32", out var prefix))
|
||||
{
|
||||
NativeMethods.CreateRoute(nttAddress.ToString(), prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
|
||||
}
|
||||
var nttrAddress = Dns.GetHostAddresses("stunresponse.coldthunder11.com")[0];
|
||||
if (int.TryParse("32", out var prefixr))
|
||||
{
|
||||
NativeMethods.CreateRoute(nttrAddress.ToString(), prefixr, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
Logging.Info("NAT类型测试域名解析失败,将不会被添加到代理列表。");
|
||||
}
|
||||
}
|
||||
//处理DNS代理
|
||||
if (Global.Settings.TUNTAP.ProxyDNS)
|
||||
{
|
||||
if (Global.Settings.TUNTAP.UseCustomDNS)
|
||||
{
|
||||
string dns = "";
|
||||
foreach (var value in Global.Settings.TUNTAP.DNS)
|
||||
{
|
||||
dns += value;
|
||||
dns += ',';
|
||||
}
|
||||
|
||||
dns = dns.Trim();
|
||||
dns = dns.Substring(0, dns.Length - 1);
|
||||
if (int.TryParse("32", out var prefix))
|
||||
{
|
||||
NativeMethods.CreateRoute(dns, prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (int.TryParse("32", out var prefix))
|
||||
{
|
||||
NativeMethods.CreateRoute("1.1.1.1", prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -192,6 +261,49 @@ namespace Netch.Controllers
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Global.Settings.STUN_Server == "stun.stunprotocol.org")
|
||||
{
|
||||
try
|
||||
{
|
||||
var nttAddress = Dns.GetHostAddresses(Global.Settings.STUN_Server)[0];
|
||||
if (int.TryParse("32", out var prefix))
|
||||
{
|
||||
NativeMethods.DeleteRoute(nttAddress.ToString(), prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
|
||||
}
|
||||
var nttrAddress = Dns.GetHostAddresses("stunresponse.coldthunder11.com")[0];
|
||||
if (int.TryParse("32", out var prefixr))
|
||||
{
|
||||
NativeMethods.DeleteRoute(nttrAddress.ToString(), prefixr, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
if (Global.Settings.TUNTAP.ProxyDNS)
|
||||
{
|
||||
if (Global.Settings.TUNTAP.UseCustomDNS)
|
||||
{
|
||||
string dns = "";
|
||||
foreach (var value in Global.Settings.TUNTAP.DNS)
|
||||
{
|
||||
dns += value;
|
||||
dns += ',';
|
||||
}
|
||||
|
||||
dns = dns.Trim();
|
||||
dns = dns.Substring(0, dns.Length - 1);
|
||||
if (int.TryParse("32", out var prefix))
|
||||
{
|
||||
NativeMethods.DeleteRoute(dns, prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (int.TryParse("32", out var prefix))
|
||||
{
|
||||
NativeMethods.DeleteRoute("1.1.1.1", prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var ip in Global.Settings.BypassIPs)
|
||||
@@ -204,6 +316,16 @@ namespace Netch.Controllers
|
||||
NativeMethods.DeleteRoute(address.ToString(), int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
|
||||
}
|
||||
}
|
||||
foreach (var ip in BypassLanIPs)
|
||||
{
|
||||
var info = ip.Split('/');
|
||||
var address = IPAddress.Parse(info[0]);
|
||||
|
||||
if (!IPAddress.IsLoopback(address))
|
||||
{
|
||||
NativeMethods.DeleteRoute(address.ToString(), int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
|
||||
}
|
||||
}
|
||||
|
||||
if (SavedMode.BypassChina)
|
||||
{
|
||||
@@ -237,6 +359,7 @@ namespace Netch.Controllers
|
||||
/// <returns>是否成功</returns>
|
||||
public bool Start(Models.Server server, Models.Mode mode)
|
||||
{
|
||||
MainForm.Instance.StatusText($"{Utils.i18N.Translate("Status")}{Utils.i18N.Translate(": ")}{Utils.i18N.Translate("Starting Tap")}");
|
||||
foreach (var proc in Process.GetProcessesByName("tun2socks"))
|
||||
{
|
||||
try
|
||||
@@ -292,7 +415,9 @@ namespace Netch.Controllers
|
||||
}
|
||||
else
|
||||
{
|
||||
dns = "1.1.1.1,1.0.0.1";
|
||||
pDNSController.Start();
|
||||
dns = "127.0.0.1";
|
||||
//dns = "1.1.1.1,1.0.0.1";
|
||||
}
|
||||
|
||||
if (server.Type == "Socks5")
|
||||
@@ -302,7 +427,7 @@ namespace Netch.Controllers
|
||||
else
|
||||
{
|
||||
Instance.StartInfo.Arguments = string.Format("-proxyServer 127.0.0.1:{0} -tunAddr {1} -tunMask {2} -tunGw {3} -tunDns {4} -tunName \"{5}\"", Global.Settings.Socks5LocalPort, Global.Settings.TUNTAP.Address, Global.Settings.TUNTAP.Netmask, Global.Settings.TUNTAP.Gateway, dns, adapterName);
|
||||
}
|
||||
}
|
||||
|
||||
Instance.StartInfo.CreateNoWindow = true;
|
||||
Instance.StartInfo.RedirectStandardError = true;
|
||||
@@ -353,6 +478,7 @@ namespace Netch.Controllers
|
||||
//pDNSController.Stop();
|
||||
//修复点击停止按钮后再启动,DNS服务没监听的BUG
|
||||
ClearBypass();
|
||||
pDNSController.Stop();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
@@ -26,7 +26,8 @@ namespace Netch.Controllers
|
||||
|
||||
public const string Name = @"Netch";
|
||||
public const string Copyright = @"Copyright © 2019 - 2020";
|
||||
public const string Version = @"1.3.8";
|
||||
public const string Version = @"1.4.0";
|
||||
public const string NFDriverVersion = @"1.5.9.0";
|
||||
|
||||
public async void Check(bool notifyNoFound, bool isPreRelease)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Netch.Forms;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
@@ -26,6 +27,7 @@ namespace Netch.Controllers
|
||||
/// <returns>是否启动成功</returns>
|
||||
public bool Start(Models.Server server, Models.Mode mode)
|
||||
{
|
||||
MainForm.Instance.StatusText($"{Utils.i18N.Translate("Status")}{Utils.i18N.Translate(": ")}{Utils.i18N.Translate("Starting V2ray")}");
|
||||
if (!File.Exists("bin\\v2ray.exe") || !File.Exists("bin\\v2ctl.exe"))
|
||||
{
|
||||
return false;
|
||||
@@ -125,14 +127,18 @@ namespace Netch.Controllers
|
||||
enabled = server.UseMux
|
||||
}
|
||||
},
|
||||
new Models.Information.VMess.Outbounds
|
||||
//此处修复一个诡异的BUG 感谢@ColinWood Tap模式 Mux不能为Null 否则Netch内存占用极大
|
||||
/*new Models.Information.VMess.Outbounds
|
||||
{
|
||||
tag = "direct",
|
||||
protocol = "freedom",
|
||||
settings = null,
|
||||
streamSettings = null,
|
||||
*//*mux = new Models.Information.VMess.OutboundMux(){
|
||||
enabled = true
|
||||
}*//*
|
||||
mux = null
|
||||
}
|
||||
}*/
|
||||
},
|
||||
routing = new Models.Information.VMess.Routing
|
||||
{
|
||||
@@ -145,7 +151,7 @@ namespace Netch.Controllers
|
||||
{
|
||||
"geoip:cn",
|
||||
"geoip:private"
|
||||
|
||||
|
||||
},
|
||||
domain = new List<string>
|
||||
{
|
||||
|
||||
353
Netch/Forms/MainForm.Designer.cs
generated
353
Netch/Forms/MainForm.Designer.cs
generated
@@ -53,23 +53,27 @@ namespace Netch.Forms
|
||||
this.AboutToolStripButton = new System.Windows.Forms.ToolStripButton();
|
||||
this.VersionLabel = new System.Windows.Forms.ToolStripLabel();
|
||||
this.ConfigurationGroupBox = new System.Windows.Forms.GroupBox();
|
||||
this.CopyLinkPictureBox = new System.Windows.Forms.PictureBox();
|
||||
this.DeleteModePictureBox = new System.Windows.Forms.PictureBox();
|
||||
this.EditModePictureBox = new System.Windows.Forms.PictureBox();
|
||||
this.ProfileNameText = new System.Windows.Forms.TextBox();
|
||||
this.configLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.ProfileLabel = new System.Windows.Forms.Label();
|
||||
this.SpeedPictureBox = new System.Windows.Forms.PictureBox();
|
||||
this.DeletePictureBox = new System.Windows.Forms.PictureBox();
|
||||
this.EditPictureBox = new System.Windows.Forms.PictureBox();
|
||||
this.ModeLabel = new System.Windows.Forms.Label();
|
||||
this.ServerLabel = new System.Windows.Forms.Label();
|
||||
this.ProfileNameText = new System.Windows.Forms.TextBox();
|
||||
this.ModeComboBox = new System.Windows.Forms.SearchComboBox();
|
||||
this.ServerComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.ServerLabel = new System.Windows.Forms.Label();
|
||||
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.EditPictureBox = new System.Windows.Forms.PictureBox();
|
||||
this.CopyLinkPictureBox = new System.Windows.Forms.PictureBox();
|
||||
this.DeletePictureBox = new System.Windows.Forms.PictureBox();
|
||||
this.SpeedPictureBox = new System.Windows.Forms.PictureBox();
|
||||
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.EditModePictureBox = new System.Windows.Forms.PictureBox();
|
||||
this.DeleteModePictureBox = new System.Windows.Forms.PictureBox();
|
||||
this.StatusStrip = new System.Windows.Forms.StatusStrip();
|
||||
this.StatusLabel = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.UsedBandwidthLabel = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.DownloadSpeedLabel = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.UploadSpeedLabel = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.NatTypeStatusLabel = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.ControlButton = new System.Windows.Forms.Button();
|
||||
this.NotifyIcon = new System.Windows.Forms.NotifyIcon(this.components);
|
||||
this.NotifyMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||
@@ -80,12 +84,15 @@ namespace Netch.Forms
|
||||
this.ProfileTable = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.MenuStrip.SuspendLayout();
|
||||
this.ConfigurationGroupBox.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.CopyLinkPictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.DeleteModePictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.EditModePictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.SpeedPictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.DeletePictureBox)).BeginInit();
|
||||
this.configLayoutPanel.SuspendLayout();
|
||||
this.tableLayoutPanel2.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.EditPictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.CopyLinkPictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.DeletePictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.SpeedPictureBox)).BeginInit();
|
||||
this.tableLayoutPanel3.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.EditModePictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.DeleteModePictureBox)).BeginInit();
|
||||
this.StatusStrip.SuspendLayout();
|
||||
this.NotifyMenu.SuspendLayout();
|
||||
this.ProfileGroupBox.SuspendLayout();
|
||||
@@ -268,46 +275,180 @@ namespace Netch.Forms
|
||||
//
|
||||
// ConfigurationGroupBox
|
||||
//
|
||||
this.ConfigurationGroupBox.Controls.Add(this.CopyLinkPictureBox);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.DeleteModePictureBox);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.EditModePictureBox);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.ProfileNameText);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.ProfileLabel);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.SpeedPictureBox);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.DeletePictureBox);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.EditPictureBox);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.ModeLabel);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.ModeComboBox);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.ServerComboBox);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.ServerLabel);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.configLayoutPanel);
|
||||
this.ConfigurationGroupBox.Location = new System.Drawing.Point(12, 28);
|
||||
this.ConfigurationGroupBox.Name = "ConfigurationGroupBox";
|
||||
this.ConfigurationGroupBox.Size = new System.Drawing.Size(605, 113);
|
||||
this.ConfigurationGroupBox.Size = new System.Drawing.Size(605, 115);
|
||||
this.ConfigurationGroupBox.TabIndex = 1;
|
||||
this.ConfigurationGroupBox.TabStop = false;
|
||||
this.ConfigurationGroupBox.Text = "Configuration";
|
||||
//
|
||||
// configLayoutPanel
|
||||
//
|
||||
this.configLayoutPanel.ColumnCount = 3;
|
||||
this.configLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.configLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.configLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.configLayoutPanel.Controls.Add(this.ProfileLabel, 0, 2);
|
||||
this.configLayoutPanel.Controls.Add(this.ModeLabel, 0, 1);
|
||||
this.configLayoutPanel.Controls.Add(this.ServerLabel, 0, 0);
|
||||
this.configLayoutPanel.Controls.Add(this.ProfileNameText, 1, 2);
|
||||
this.configLayoutPanel.Controls.Add(this.ModeComboBox, 1, 1);
|
||||
this.configLayoutPanel.Controls.Add(this.ServerComboBox, 1, 0);
|
||||
this.configLayoutPanel.Controls.Add(this.tableLayoutPanel2, 2, 0);
|
||||
this.configLayoutPanel.Controls.Add(this.tableLayoutPanel3, 2, 1);
|
||||
this.configLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
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.Size = new System.Drawing.Size(599, 93);
|
||||
this.configLayoutPanel.TabIndex = 15;
|
||||
//
|
||||
// ProfileLabel
|
||||
//
|
||||
this.ProfileLabel.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.ProfileLabel.AutoSize = true;
|
||||
this.ProfileLabel.Location = new System.Drawing.Point(3, 69);
|
||||
this.ProfileLabel.Name = "ProfileLabel";
|
||||
this.ProfileLabel.Size = new System.Drawing.Size(45, 17);
|
||||
this.ProfileLabel.TabIndex = 10;
|
||||
this.ProfileLabel.Text = "Profile";
|
||||
//
|
||||
// ModeLabel
|
||||
//
|
||||
this.ModeLabel.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.ModeLabel.AutoSize = true;
|
||||
this.ModeLabel.Location = new System.Drawing.Point(3, 38);
|
||||
this.ModeLabel.Name = "ModeLabel";
|
||||
this.ModeLabel.Size = new System.Drawing.Size(43, 17);
|
||||
this.ModeLabel.TabIndex = 3;
|
||||
this.ModeLabel.Text = "Mode";
|
||||
//
|
||||
// ServerLabel
|
||||
//
|
||||
this.ServerLabel.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.ServerLabel.AutoSize = true;
|
||||
this.ServerLabel.Location = new System.Drawing.Point(3, 7);
|
||||
this.ServerLabel.Name = "ServerLabel";
|
||||
this.ServerLabel.Size = new System.Drawing.Size(45, 17);
|
||||
this.ServerLabel.TabIndex = 0;
|
||||
this.ServerLabel.Text = "Server";
|
||||
//
|
||||
// ProfileNameText
|
||||
//
|
||||
this.ProfileNameText.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.ProfileNameText.Location = new System.Drawing.Point(54, 65);
|
||||
this.ProfileNameText.Name = "ProfileNameText";
|
||||
this.ProfileNameText.Size = new System.Drawing.Size(442, 23);
|
||||
this.ProfileNameText.TabIndex = 11;
|
||||
//
|
||||
// ModeComboBox
|
||||
//
|
||||
this.ModeComboBox.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.Suggest;
|
||||
this.ModeComboBox.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
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.Name = "ModeComboBox";
|
||||
this.ModeComboBox.Size = new System.Drawing.Size(442, 24);
|
||||
this.ModeComboBox.TabIndex = 2;
|
||||
this.ModeComboBox.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.ComboBox_DrawItem);
|
||||
//
|
||||
// ServerComboBox
|
||||
//
|
||||
this.ServerComboBox.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.ServerComboBox.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
|
||||
this.ServerComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.ServerComboBox.FormattingEnabled = true;
|
||||
this.ServerComboBox.IntegralHeight = false;
|
||||
this.ServerComboBox.Location = new System.Drawing.Point(54, 3);
|
||||
this.ServerComboBox.MaxDropDownItems = 16;
|
||||
this.ServerComboBox.Name = "ServerComboBox";
|
||||
this.ServerComboBox.Size = new System.Drawing.Size(442, 24);
|
||||
this.ServerComboBox.TabIndex = 1;
|
||||
this.ServerComboBox.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.ComboBox_DrawItem);
|
||||
//
|
||||
// tableLayoutPanel2
|
||||
//
|
||||
this.tableLayoutPanel2.ColumnCount = 4;
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F));
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F));
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F));
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F));
|
||||
this.tableLayoutPanel2.Controls.Add(this.EditPictureBox, 0, 0);
|
||||
this.tableLayoutPanel2.Controls.Add(this.CopyLinkPictureBox, 3, 0);
|
||||
this.tableLayoutPanel2.Controls.Add(this.DeletePictureBox, 1, 0);
|
||||
this.tableLayoutPanel2.Controls.Add(this.SpeedPictureBox, 2, 0);
|
||||
this.tableLayoutPanel2.Location = new System.Drawing.Point(502, 3);
|
||||
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
|
||||
this.tableLayoutPanel2.RowCount = 1;
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel2.Size = new System.Drawing.Size(94, 24);
|
||||
this.tableLayoutPanel2.TabIndex = 12;
|
||||
//
|
||||
// EditPictureBox
|
||||
//
|
||||
this.EditPictureBox.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.EditPictureBox.Image = ((System.Drawing.Image)(resources.GetObject("EditPictureBox.Image")));
|
||||
this.EditPictureBox.Location = new System.Drawing.Point(3, 3);
|
||||
this.EditPictureBox.Name = "EditPictureBox";
|
||||
this.EditPictureBox.Size = new System.Drawing.Size(16, 16);
|
||||
this.EditPictureBox.TabIndex = 7;
|
||||
this.EditPictureBox.TabStop = false;
|
||||
this.EditPictureBox.Click += new System.EventHandler(this.EditPictureBox_Click);
|
||||
//
|
||||
// CopyLinkPictureBox
|
||||
//
|
||||
this.CopyLinkPictureBox.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.CopyLinkPictureBox.Image = global::Netch.Properties.Resources.CopyLink;
|
||||
this.CopyLinkPictureBox.Location = new System.Drawing.Point(582, 25);
|
||||
this.CopyLinkPictureBox.Location = new System.Drawing.Point(72, 3);
|
||||
this.CopyLinkPictureBox.Name = "CopyLinkPictureBox";
|
||||
this.CopyLinkPictureBox.Size = new System.Drawing.Size(18, 18);
|
||||
this.CopyLinkPictureBox.TabIndex = 14;
|
||||
this.CopyLinkPictureBox.TabStop = false;
|
||||
this.CopyLinkPictureBox.Click += new System.EventHandler(this.CopyLinkPictureBox_Click);
|
||||
//
|
||||
// DeleteModePictureBox
|
||||
// DeletePictureBox
|
||||
//
|
||||
this.DeleteModePictureBox.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.DeleteModePictureBox.Image = global::Netch.Properties.Resources.delete;
|
||||
this.DeleteModePictureBox.Location = new System.Drawing.Point(540, 57);
|
||||
this.DeleteModePictureBox.Name = "DeleteModePictureBox";
|
||||
this.DeleteModePictureBox.Size = new System.Drawing.Size(16, 16);
|
||||
this.DeleteModePictureBox.TabIndex = 13;
|
||||
this.DeleteModePictureBox.TabStop = false;
|
||||
this.DeleteModePictureBox.Click += new System.EventHandler(this.DeleteModePictureBox_Click);
|
||||
this.DeletePictureBox.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.DeletePictureBox.Image = ((System.Drawing.Image)(resources.GetObject("DeletePictureBox.Image")));
|
||||
this.DeletePictureBox.Location = new System.Drawing.Point(26, 3);
|
||||
this.DeletePictureBox.Name = "DeletePictureBox";
|
||||
this.DeletePictureBox.Size = new System.Drawing.Size(16, 16);
|
||||
this.DeletePictureBox.TabIndex = 8;
|
||||
this.DeletePictureBox.TabStop = false;
|
||||
this.DeletePictureBox.Click += new System.EventHandler(this.DeletePictureBox_Click);
|
||||
//
|
||||
// SpeedPictureBox
|
||||
//
|
||||
this.SpeedPictureBox.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.SpeedPictureBox.Image = ((System.Drawing.Image)(resources.GetObject("SpeedPictureBox.Image")));
|
||||
this.SpeedPictureBox.Location = new System.Drawing.Point(49, 3);
|
||||
this.SpeedPictureBox.Name = "SpeedPictureBox";
|
||||
this.SpeedPictureBox.Size = new System.Drawing.Size(16, 16);
|
||||
this.SpeedPictureBox.TabIndex = 9;
|
||||
this.SpeedPictureBox.TabStop = false;
|
||||
this.SpeedPictureBox.Click += new System.EventHandler(this.SpeedPictureBox_Click);
|
||||
//
|
||||
// tableLayoutPanel3
|
||||
//
|
||||
this.tableLayoutPanel3.ColumnCount = 4;
|
||||
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F));
|
||||
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F));
|
||||
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F));
|
||||
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(502, 34);
|
||||
this.tableLayoutPanel3.Name = "tableLayoutPanel3";
|
||||
this.tableLayoutPanel3.RowCount = 1;
|
||||
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel3.Size = new System.Drawing.Size(94, 24);
|
||||
this.tableLayoutPanel3.TabIndex = 13;
|
||||
//
|
||||
// EditModePictureBox
|
||||
//
|
||||
@@ -315,104 +456,23 @@ namespace Netch.Forms
|
||||
this.EditModePictureBox.ErrorImage = global::Netch.Properties.Resources.edit;
|
||||
this.EditModePictureBox.Image = global::Netch.Properties.Resources.edit;
|
||||
this.EditModePictureBox.InitialImage = global::Netch.Properties.Resources.edit;
|
||||
this.EditModePictureBox.Location = new System.Drawing.Point(518, 56);
|
||||
this.EditModePictureBox.Location = new System.Drawing.Point(3, 3);
|
||||
this.EditModePictureBox.Name = "EditModePictureBox";
|
||||
this.EditModePictureBox.Size = new System.Drawing.Size(16, 16);
|
||||
this.EditModePictureBox.TabIndex = 12;
|
||||
this.EditModePictureBox.TabStop = false;
|
||||
this.EditModePictureBox.Click += new System.EventHandler(this.EditModePictureBox_Click);
|
||||
//
|
||||
// ProfileNameText
|
||||
// DeleteModePictureBox
|
||||
//
|
||||
this.ProfileNameText.Location = new System.Drawing.Point(57, 83);
|
||||
this.ProfileNameText.Name = "ProfileNameText";
|
||||
this.ProfileNameText.Size = new System.Drawing.Size(455, 23);
|
||||
this.ProfileNameText.TabIndex = 11;
|
||||
//
|
||||
// ProfileLabel
|
||||
//
|
||||
this.ProfileLabel.AutoSize = true;
|
||||
this.ProfileLabel.Location = new System.Drawing.Point(6, 86);
|
||||
this.ProfileLabel.Name = "ProfileLabel";
|
||||
this.ProfileLabel.Size = new System.Drawing.Size(45, 17);
|
||||
this.ProfileLabel.TabIndex = 10;
|
||||
this.ProfileLabel.Text = "Profile";
|
||||
//
|
||||
// SpeedPictureBox
|
||||
//
|
||||
this.SpeedPictureBox.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.SpeedPictureBox.Image = ((System.Drawing.Image)(resources.GetObject("SpeedPictureBox.Image")));
|
||||
this.SpeedPictureBox.Location = new System.Drawing.Point(562, 26);
|
||||
this.SpeedPictureBox.Name = "SpeedPictureBox";
|
||||
this.SpeedPictureBox.Size = new System.Drawing.Size(16, 16);
|
||||
this.SpeedPictureBox.TabIndex = 9;
|
||||
this.SpeedPictureBox.TabStop = false;
|
||||
this.SpeedPictureBox.Click += new System.EventHandler(this.SpeedPictureBox_Click);
|
||||
//
|
||||
// DeletePictureBox
|
||||
//
|
||||
this.DeletePictureBox.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.DeletePictureBox.Image = ((System.Drawing.Image)(resources.GetObject("DeletePictureBox.Image")));
|
||||
this.DeletePictureBox.Location = new System.Drawing.Point(540, 26);
|
||||
this.DeletePictureBox.Name = "DeletePictureBox";
|
||||
this.DeletePictureBox.Size = new System.Drawing.Size(16, 16);
|
||||
this.DeletePictureBox.TabIndex = 8;
|
||||
this.DeletePictureBox.TabStop = false;
|
||||
this.DeletePictureBox.Click += new System.EventHandler(this.DeletePictureBox_Click);
|
||||
//
|
||||
// EditPictureBox
|
||||
//
|
||||
this.EditPictureBox.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.EditPictureBox.Image = ((System.Drawing.Image)(resources.GetObject("EditPictureBox.Image")));
|
||||
this.EditPictureBox.Location = new System.Drawing.Point(518, 26);
|
||||
this.EditPictureBox.Name = "EditPictureBox";
|
||||
this.EditPictureBox.Size = new System.Drawing.Size(16, 16);
|
||||
this.EditPictureBox.TabIndex = 7;
|
||||
this.EditPictureBox.TabStop = false;
|
||||
this.EditPictureBox.Click += new System.EventHandler(this.EditPictureBox_Click);
|
||||
//
|
||||
// ModeLabel
|
||||
//
|
||||
this.ModeLabel.AutoSize = true;
|
||||
this.ModeLabel.Location = new System.Drawing.Point(6, 56);
|
||||
this.ModeLabel.Name = "ModeLabel";
|
||||
this.ModeLabel.Size = new System.Drawing.Size(43, 17);
|
||||
this.ModeLabel.TabIndex = 3;
|
||||
this.ModeLabel.Text = "Mode";
|
||||
//
|
||||
// ModeComboBox
|
||||
//
|
||||
this.ModeComboBox.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.Suggest;
|
||||
this.ModeComboBox.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
|
||||
this.ModeComboBox.FormattingEnabled = true;
|
||||
this.ModeComboBox.IntegralHeight = false;
|
||||
this.ModeComboBox.Location = new System.Drawing.Point(57, 53);
|
||||
this.ModeComboBox.Name = "ModeComboBox";
|
||||
this.ModeComboBox.Size = new System.Drawing.Size(455, 24);
|
||||
this.ModeComboBox.TabIndex = 2;
|
||||
this.ModeComboBox.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.ComboBox_DrawItem);
|
||||
//
|
||||
// ServerComboBox
|
||||
//
|
||||
this.ServerComboBox.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
|
||||
this.ServerComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.ServerComboBox.FormattingEnabled = true;
|
||||
this.ServerComboBox.IntegralHeight = false;
|
||||
this.ServerComboBox.Location = new System.Drawing.Point(57, 22);
|
||||
this.ServerComboBox.MaxDropDownItems = 16;
|
||||
this.ServerComboBox.Name = "ServerComboBox";
|
||||
this.ServerComboBox.Size = new System.Drawing.Size(455, 24);
|
||||
this.ServerComboBox.TabIndex = 1;
|
||||
this.ServerComboBox.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.ComboBox_DrawItem);
|
||||
//
|
||||
// ServerLabel
|
||||
//
|
||||
this.ServerLabel.AutoSize = true;
|
||||
this.ServerLabel.Location = new System.Drawing.Point(6, 26);
|
||||
this.ServerLabel.Name = "ServerLabel";
|
||||
this.ServerLabel.Size = new System.Drawing.Size(45, 17);
|
||||
this.ServerLabel.TabIndex = 0;
|
||||
this.ServerLabel.Text = "Server";
|
||||
this.DeleteModePictureBox.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.DeleteModePictureBox.Image = global::Netch.Properties.Resources.delete;
|
||||
this.DeleteModePictureBox.Location = new System.Drawing.Point(26, 3);
|
||||
this.DeleteModePictureBox.Name = "DeleteModePictureBox";
|
||||
this.DeleteModePictureBox.Size = new System.Drawing.Size(16, 16);
|
||||
this.DeleteModePictureBox.TabIndex = 13;
|
||||
this.DeleteModePictureBox.TabStop = false;
|
||||
this.DeleteModePictureBox.Click += new System.EventHandler(this.DeleteModePictureBox_Click);
|
||||
//
|
||||
// StatusStrip
|
||||
//
|
||||
@@ -421,8 +481,9 @@ namespace Netch.Forms
|
||||
this.StatusLabel,
|
||||
this.UsedBandwidthLabel,
|
||||
this.DownloadSpeedLabel,
|
||||
this.UploadSpeedLabel});
|
||||
this.StatusStrip.Location = new System.Drawing.Point(0, 254);
|
||||
this.UploadSpeedLabel,
|
||||
this.NatTypeStatusLabel});
|
||||
this.StatusStrip.Location = new System.Drawing.Point(0, 250);
|
||||
this.StatusStrip.Name = "StatusStrip";
|
||||
this.StatusStrip.Size = new System.Drawing.Size(629, 22);
|
||||
this.StatusStrip.SizingGrip = false;
|
||||
@@ -456,9 +517,15 @@ namespace Netch.Forms
|
||||
this.UploadSpeedLabel.Text = "↑: 0 KB/s";
|
||||
this.UploadSpeedLabel.Visible = false;
|
||||
//
|
||||
// NatTypeStatusLabel
|
||||
//
|
||||
this.NatTypeStatusLabel.Name = "NatTypeStatusLabel";
|
||||
this.NatTypeStatusLabel.Size = new System.Drawing.Size(0, 17);
|
||||
//
|
||||
// ControlButton
|
||||
//
|
||||
this.ControlButton.Location = new System.Drawing.Point(542, 219);
|
||||
this.ControlButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.ControlButton.Location = new System.Drawing.Point(542, 215);
|
||||
this.ControlButton.Name = "ControlButton";
|
||||
this.ControlButton.Size = new System.Drawing.Size(75, 27);
|
||||
this.ControlButton.TabIndex = 3;
|
||||
@@ -500,7 +567,8 @@ namespace Netch.Forms
|
||||
//
|
||||
// SettingsButton
|
||||
//
|
||||
this.SettingsButton.Location = new System.Drawing.Point(12, 219);
|
||||
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.Name = "SettingsButton";
|
||||
this.SettingsButton.Size = new System.Drawing.Size(72, 27);
|
||||
this.SettingsButton.TabIndex = 4;
|
||||
@@ -511,7 +579,7 @@ namespace Netch.Forms
|
||||
// ProfileGroupBox
|
||||
//
|
||||
this.ProfileGroupBox.Controls.Add(this.ProfileTable);
|
||||
this.ProfileGroupBox.Location = new System.Drawing.Point(12, 147);
|
||||
this.ProfileGroupBox.Location = new System.Drawing.Point(12, 146);
|
||||
this.ProfileGroupBox.Name = "ProfileGroupBox";
|
||||
this.ProfileGroupBox.Size = new System.Drawing.Size(605, 65);
|
||||
this.ProfileGroupBox.TabIndex = 13;
|
||||
@@ -538,7 +606,7 @@ namespace Netch.Forms
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
|
||||
this.ClientSize = new System.Drawing.Size(629, 276);
|
||||
this.ClientSize = new System.Drawing.Size(629, 272);
|
||||
this.Controls.Add(this.ProfileGroupBox);
|
||||
this.Controls.Add(this.SettingsButton);
|
||||
this.Controls.Add(this.ControlButton);
|
||||
@@ -558,13 +626,16 @@ namespace Netch.Forms
|
||||
this.MenuStrip.ResumeLayout(false);
|
||||
this.MenuStrip.PerformLayout();
|
||||
this.ConfigurationGroupBox.ResumeLayout(false);
|
||||
this.ConfigurationGroupBox.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.CopyLinkPictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.DeleteModePictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.EditModePictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.SpeedPictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.DeletePictureBox)).EndInit();
|
||||
this.configLayoutPanel.ResumeLayout(false);
|
||||
this.configLayoutPanel.PerformLayout();
|
||||
this.tableLayoutPanel2.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.EditPictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.CopyLinkPictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.DeletePictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.SpeedPictureBox)).EndInit();
|
||||
this.tableLayoutPanel3.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.EditModePictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.DeleteModePictureBox)).EndInit();
|
||||
this.StatusStrip.ResumeLayout(false);
|
||||
this.StatusStrip.PerformLayout();
|
||||
this.NotifyMenu.ResumeLayout(false);
|
||||
@@ -623,5 +694,9 @@ namespace Netch.Forms
|
||||
private System.Windows.Forms.PictureBox EditModePictureBox;
|
||||
private System.Windows.Forms.PictureBox DeleteModePictureBox;
|
||||
private System.Windows.Forms.PictureBox CopyLinkPictureBox;
|
||||
private System.Windows.Forms.ToolStripStatusLabel NatTypeStatusLabel;
|
||||
private System.Windows.Forms.TableLayoutPanel configLayoutPanel;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,11 @@ namespace Netch.Forms
|
||||
|
||||
public List<Button> ProfileButtons = new List<Button>();
|
||||
|
||||
/// <summary>
|
||||
/// 主窗体的静态实例
|
||||
/// </summary>
|
||||
public static MainForm Instance = null;
|
||||
|
||||
public MainForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
@@ -48,6 +53,7 @@ namespace Netch.Forms
|
||||
|
||||
CheckForIllegalCrossThreadCalls = false;
|
||||
// MenuStrip.Renderer = new Override.ToolStripProfessionalRender();
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
private void CheckUpdate()
|
||||
@@ -232,60 +238,66 @@ namespace Netch.Forms
|
||||
|
||||
private void ComboBox_DrawItem(object sender, DrawItemEventArgs e)
|
||||
{
|
||||
var cbx = sender as ComboBox;
|
||||
|
||||
// 绘制背景颜色
|
||||
e.Graphics.FillRectangle(new SolidBrush(Color.White), e.Bounds);
|
||||
|
||||
if (e.Index >= 0)
|
||||
try
|
||||
{
|
||||
// 绘制 备注/名称 字符串
|
||||
e.Graphics.DrawString(cbx.Items[e.Index].ToString(), cbx.Font, new SolidBrush(Color.Black), e.Bounds);
|
||||
|
||||
if (cbx.Items[e.Index] is Models.Server)
|
||||
var cbx = sender as ComboBox;
|
||||
|
||||
// 绘制背景颜色
|
||||
e.Graphics.FillRectangle(new SolidBrush(Color.White), e.Bounds);
|
||||
|
||||
if (e.Index >= 0)
|
||||
{
|
||||
var item = cbx.Items[e.Index] as Models.Server;
|
||||
// 绘制 备注/名称 字符串
|
||||
e.Graphics.DrawString(cbx.Items[e.Index].ToString(), cbx.Font, new SolidBrush(Color.Black), e.Bounds);
|
||||
|
||||
// 计算延迟底色
|
||||
SolidBrush brush;
|
||||
if (item.Delay > 200)
|
||||
if (cbx.Items[e.Index] is Models.Server)
|
||||
{
|
||||
// 红色
|
||||
brush = new SolidBrush(Color.Red);
|
||||
var item = cbx.Items[e.Index] as Models.Server;
|
||||
|
||||
// 计算延迟底色
|
||||
SolidBrush brush;
|
||||
if (item.Delay > 200)
|
||||
{
|
||||
// 红色
|
||||
brush = new SolidBrush(Color.Red);
|
||||
}
|
||||
else if (item.Delay > 80)
|
||||
{
|
||||
// 黄色
|
||||
brush = new SolidBrush(Color.Yellow);
|
||||
}
|
||||
else if (item.Delay >= 0)
|
||||
{
|
||||
// 绿色
|
||||
brush = new SolidBrush(Color.FromArgb(50, 255, 56));
|
||||
}
|
||||
else
|
||||
{
|
||||
// 灰色
|
||||
brush = new SolidBrush(Color.Gray);
|
||||
}
|
||||
|
||||
// 绘制延迟底色
|
||||
e.Graphics.FillRectangle(brush, ServerComboBox.Size.Width - 60, e.Bounds.Y, 60, e.Bounds.Height);
|
||||
|
||||
// 绘制延迟字符串
|
||||
e.Graphics.DrawString(item.Delay.ToString(), cbx.Font, new SolidBrush(Color.Black), ServerComboBox.Size.Width - 58, e.Bounds.Y);
|
||||
}
|
||||
else if (item.Delay > 80)
|
||||
else if (cbx.Items[e.Index] is Models.Mode)
|
||||
{
|
||||
// 黄色
|
||||
brush = new SolidBrush(Color.Yellow);
|
||||
var item = cbx.Items[e.Index] as Models.Mode;
|
||||
|
||||
// 绘制延迟底色
|
||||
e.Graphics.FillRectangle(new SolidBrush(Color.Gray), ServerComboBox.Size.Width - 60, e.Bounds.Y, 60, e.Bounds.Height);
|
||||
|
||||
// 绘制延迟字符串
|
||||
e.Graphics.DrawString(item.Rule.Count.ToString(), cbx.Font, new SolidBrush(Color.Black), ServerComboBox.Size.Width - 58, e.Bounds.Y);
|
||||
}
|
||||
else if (item.Delay >= 0)
|
||||
{
|
||||
// 绿色
|
||||
brush = new SolidBrush(Color.FromArgb(50, 255, 56));
|
||||
}
|
||||
else
|
||||
{
|
||||
// 灰色
|
||||
brush = new SolidBrush(Color.Gray);
|
||||
}
|
||||
|
||||
// 绘制延迟底色
|
||||
e.Graphics.FillRectangle(brush, ServerComboBox.Size.Width - 60, e.Bounds.Y, 60, e.Bounds.Height);
|
||||
|
||||
// 绘制延迟字符串
|
||||
e.Graphics.DrawString(item.Delay.ToString(), cbx.Font, new SolidBrush(Color.Black), ServerComboBox.Size.Width - 58, e.Bounds.Y);
|
||||
}
|
||||
else if (cbx.Items[e.Index] is Models.Mode)
|
||||
{
|
||||
var item = cbx.Items[e.Index] as Models.Mode;
|
||||
|
||||
// 绘制延迟底色
|
||||
e.Graphics.FillRectangle(new SolidBrush(Color.Gray), ServerComboBox.Size.Width - 60, e.Bounds.Y, 60, e.Bounds.Height);
|
||||
|
||||
// 绘制延迟字符串
|
||||
e.Graphics.DrawString(item.Rule.Count.ToString(), cbx.Font, new SolidBrush(Color.Black), ServerComboBox.Size.Width - 58, e.Bounds.Y);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{ }
|
||||
}
|
||||
|
||||
private void MainForm_Load(object sender, EventArgs e)
|
||||
@@ -476,6 +488,7 @@ namespace Netch.Forms
|
||||
|
||||
if (Global.Settings.SubscribeLink.Count > 0)
|
||||
{
|
||||
StatusLabel.Text = $"{Utils.i18N.Translate("Status")}{Utils.i18N.Translate(": ")}{Utils.i18N.Translate("Starting update subscription")}";
|
||||
DeletePictureBox.Enabled = false;
|
||||
|
||||
UpdateServersFromSubscribeLinksToolStripMenuItem.Enabled = false;
|
||||
@@ -556,8 +569,10 @@ namespace Netch.Forms
|
||||
MenuStrip.Enabled = ConfigurationGroupBox.Enabled = ControlButton.Enabled = SettingsButton.Enabled = true;
|
||||
ControlButton.Text = Utils.i18N.Translate("Start");
|
||||
MainController.Stop();
|
||||
NatTypeStatusLabel.Text = "";
|
||||
}
|
||||
Utils.Configuration.Save();
|
||||
StatusLabel.Text = $"{Utils.i18N.Translate("Status")}{Utils.i18N.Translate(": ")}{Utils.i18N.Translate("Subscription updated")}";
|
||||
}).ContinueWith(task =>
|
||||
{
|
||||
BeginInvoke(new Action(() =>
|
||||
@@ -759,6 +774,7 @@ namespace Netch.Forms
|
||||
|
||||
private void ControlButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
SaveConfigs();
|
||||
if (State == Models.State.Waiting || State == Models.State.Stopped)
|
||||
{
|
||||
// 当前 ServerComboBox 中至少有一项
|
||||
@@ -786,7 +802,10 @@ namespace Netch.Forms
|
||||
var mode = ModeComboBox.SelectedItem as Models.Mode;
|
||||
|
||||
MainController = new MainController();
|
||||
if (MainController.Start(server, mode))
|
||||
|
||||
var startResult = MainController.Start(server, mode);
|
||||
|
||||
if (startResult)
|
||||
{
|
||||
// UsedBandwidthLabel.Visible = UploadSpeedLabel.Visible = DownloadSpeedLabel.Visible = true;
|
||||
// MainController.pNFController.OnBandwidthUpdated += OnBandwidthUpdated;
|
||||
@@ -856,6 +875,28 @@ namespace Netch.Forms
|
||||
}
|
||||
|
||||
State = Models.State.Started;
|
||||
if (Global.Settings.StartedTcping)
|
||||
{
|
||||
// 自动检测延迟
|
||||
Task.Run(() =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (State == Models.State.Started)
|
||||
{
|
||||
server.Test();
|
||||
// 重载服务器列表
|
||||
InitServer();
|
||||
|
||||
Thread.Sleep(Global.Settings.StartedTcping_Interval * 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -883,6 +924,7 @@ namespace Netch.Forms
|
||||
var mode = ModeComboBox.SelectedItem as Models.Mode;
|
||||
|
||||
MainController.Stop();
|
||||
NatTypeStatusLabel.Text = "";
|
||||
|
||||
// LastUploadBandwidth = 0;
|
||||
// LastDownloadBandwidth = 0;
|
||||
@@ -998,6 +1040,10 @@ namespace Netch.Forms
|
||||
{
|
||||
MessageBox.Show(Utils.i18N.Translate("Please select an mode first"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
}
|
||||
else if (ProfileNameText.Text == "")
|
||||
{
|
||||
MessageBox.Show(Utils.i18N.Translate("Please enter a profile name first"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
}
|
||||
else
|
||||
{
|
||||
SaveProfile(index);
|
||||
@@ -1006,6 +1052,11 @@ namespace Netch.Forms
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ProfileButtons[index].Text == Utils.i18N.Translate("Error") || ProfileButtons[index].Text == Utils.i18N.Translate("None"))
|
||||
{
|
||||
MessageBox.Show(Utils.i18N.Translate("No saved profile here. Save a profile first by Ctrl+Click on the button"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ProfileNameText.Text = LoadProfile(index);
|
||||
@@ -1051,6 +1102,15 @@ namespace Netch.Forms
|
||||
public void InitProfile()
|
||||
{
|
||||
var num_profile = Global.Settings.ProfileCount;
|
||||
if (num_profile == 0)
|
||||
{
|
||||
ProfileGroupBox.Size = new Size(0, 0);
|
||||
ConfigurationGroupBox.Size -= new Size(0, 25);
|
||||
this.Size -= new Size(0, 70 + 25);
|
||||
configLayoutPanel.RowStyles[2].Height = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
ProfileTable.ColumnCount = num_profile;
|
||||
|
||||
while (Global.Settings.profiles.Count < num_profile)
|
||||
@@ -1194,12 +1254,35 @@ namespace Netch.Forms
|
||||
if (ServerComboBox.SelectedIndex != -1)
|
||||
{
|
||||
var selectedMode = (Models.Server)ServerComboBox.SelectedItem;
|
||||
Clipboard.SetText(Utils.ShareLink.GetShareLink(selectedMode));
|
||||
try
|
||||
{
|
||||
//听说巨硬BUG经常会炸,所以Catch一下 :D
|
||||
Clipboard.SetText(Utils.ShareLink.GetShareLink(selectedMode));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show(Utils.i18N.Translate("Please select a server first"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
}
|
||||
}
|
||||
public void StatusText(string text)
|
||||
{
|
||||
StatusLabel.Text = text;
|
||||
}
|
||||
public void NatTypeStatusText(string text)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
NatTypeStatusLabel.Text = "NAT" + Utils.i18N.Translate(": ") + text;
|
||||
}
|
||||
else
|
||||
{
|
||||
NatTypeStatusLabel.Text = "NAT" + Utils.i18N.Translate(": ") + Utils.i18N.Translate("Test failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,20 +121,18 @@
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="SpeedPictureBox.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<data name="EditPictureBox.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAk9JREFUOE9N
|
||||
k19ojWEcx8+xsRgzbSlaJouGRCNuXIyMXJ1LpVyYFAttqylEsdKQC1yZpF24oJQrN0q5UJKUlP3DWTPz
|
||||
pzmm2Tk753nf9+fzfd/3nJ2nPr3v8z7P7/d7nu/v+ybMbBUsA703wwk/sKcPJz07POzszOg8HXAKBr55
|
||||
bLMmWKOgxZCEBfH7zg9/fev55Gw8G9jUXGC/IFMI7HXGt7ZBZ9fGHNtsJVQogYIrQMFVOc8GLn5x4eby
|
||||
UWB6k8AXU75N5gJ9aoBkMYGqL4JLbHB9bFRA+Xj207Pr0fcbTNtgC1QWE1TC6t/5INvF0UdmwgqlkZ4N
|
||||
rJvvP3JBmul6OArSrloJ6mAz3H383bMHE6FApZFlqitpbcbZhTnfWrzA9rNUDfVKsAFSY1Q5+9mFopWP
|
||||
IU6TGnJ2nrXetCslY6hwnRLo/q1XWVTr/iHwdCECQS2PFpl81IUnBLZ+LNit8bALRyA8gTTY0f816vVl
|
||||
Klwh2UneH5GweJ53076d5pv04SrSQiLWKkEVbFUl9VtItPYRZ6/iVr7549sx5sORuP2wBw5BgxIsgY2w
|
||||
DVZAlwLVc21/GwdTWRfvhXp4Cbv1rgRrQRbeDge466xaplO8x5FxMEvWCctBRTpgH4RGWgdyoRZuSyiJ
|
||||
qcrSIQ5+DgtBCXQCuXAphFaWjfVsnMD752iX2tQ5b6g7sAv0w20CiV50b3gCuTDB1ub7mGjvYCF0XRzc
|
||||
B/rrGkGqK7BYVI5MaFILSdzVdI9WHuRvG42Cj4Mc2g4toEJKUAMZSJlZzX8eY2N9ZDKIEQAAAABJRU5E
|
||||
rkJggg==
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAg9JREFUOE+F
|
||||
U81uElEYnTdw58qFunBlYnwAE7e+QhMT38CNcefWxKWufADjiqqtmsZIW2gRulBTY4fGGGmLMFOGn5aB
|
||||
GYa5c+f4nTsINKF6kkPIxz3nO/f7Llas1IXXGyW8Wi9h+T/kmVx+C7WGA8F14S2LxR8HdfjDAMMwFI7O
|
||||
YQg/CI14pVDGKIoGYnDZomMgB4gk0VAqgUoWkxjHMd5t7eCkTz2uWIxGd601nHYPR66H+nH7LKXW9LrG
|
||||
JBrHeL+9g1N/gDRNl4wBoxHhKDJxmWierPG3lGeiaGrQ9DpPjMFADJjA7fSko4ff0nWerDntWQJegQbl
|
||||
XRsLEiweZMAEEoFn1opl9GXopa97sFaLlWmCY0nAjo2WdCYn3ednIGvHodPCSIw+2z9hrRQqZoWzBLOu
|
||||
jBvJ1MlYyARK+LGl8LCWYq+vsyvMttA17oduiwOaru4vEhGvdzSuVRUu2THu7KvJDCYJxrHKugr5XdZk
|
||||
6kSsgWJXo+pr7J5q3K7GeFoXA75EDuRfYOyCdLZFTDhhipyboDsIv2QGg6H5YREorvSyzgTFH7wEnh8g
|
||||
0frxdAbn4Vs/xYtmNguK10TcCXjF+JmUrlpvNj/lDxqu2cDZFxialb1sKly0FZYl8oZc4yRK+CYeiPie
|
||||
8IYlH3dz+W3zuub5Vv5x33/V8VwG9aimsCniMEl92dZN0SxRB+D+Hw2grtB8iuYFAAAAAElFTkSuQmCC
|
||||
</value>
|
||||
</data>
|
||||
<data name="DeletePictureBox.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
@@ -151,18 +149,20 @@
|
||||
R+QMmWB7l2jP55IkExaBIP+X+VaqtcbLMAynmftgqMOzv61mlBRRiHFjAAAAAElFTkSuQmCC
|
||||
</value>
|
||||
</data>
|
||||
<data name="EditPictureBox.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<data name="SpeedPictureBox.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAg9JREFUOE+F
|
||||
U81uElEYnTdw58qFunBlYnwAE7e+QhMT38CNcefWxKWufADjiqqtmsZIW2gRulBTY4fGGGmLMFOGn5aB
|
||||
GYa5c+f4nTsINKF6kkPIxz3nO/f7Llas1IXXGyW8Wi9h+T/kmVx+C7WGA8F14S2LxR8HdfjDAMMwFI7O
|
||||
YQg/CI14pVDGKIoGYnDZomMgB4gk0VAqgUoWkxjHMd5t7eCkTz2uWIxGd601nHYPR66H+nH7LKXW9LrG
|
||||
JBrHeL+9g1N/gDRNl4wBoxHhKDJxmWierPG3lGeiaGrQ9DpPjMFADJjA7fSko4ff0nWerDntWQJegQbl
|
||||
XRsLEiweZMAEEoFn1opl9GXopa97sFaLlWmCY0nAjo2WdCYn3ednIGvHodPCSIw+2z9hrRQqZoWzBLOu
|
||||
jBvJ1MlYyARK+LGl8LCWYq+vsyvMttA17oduiwOaru4vEhGvdzSuVRUu2THu7KvJDCYJxrHKugr5XdZk
|
||||
6kSsgWJXo+pr7J5q3K7GeFoXA75EDuRfYOyCdLZFTDhhipyboDsIv2QGg6H5YREorvSyzgTFH7wEnh8g
|
||||
0frxdAbn4Vs/xYtmNguK10TcCXjF+JmUrlpvNj/lDxqu2cDZFxialb1sKly0FZYl8oZc4yRK+CYeiPie
|
||||
8IYlH3dz+W3zuub5Vv5x33/V8VwG9aimsCniMEl92dZN0SxRB+D+Hw2grtB8iuYFAAAAAElFTkSuQmCC
|
||||
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAk9JREFUOE9N
|
||||
k19ojWEcx8+xsRgzbSlaJouGRCNuXIyMXJ1LpVyYFAttqylEsdKQC1yZpF24oJQrN0q5UJKUlP3DWTPz
|
||||
pzmm2Tk753nf9+fzfd/3nJ2nPr3v8z7P7/d7nu/v+ybMbBUsA703wwk/sKcPJz07POzszOg8HXAKBr55
|
||||
bLMmWKOgxZCEBfH7zg9/fev55Gw8G9jUXGC/IFMI7HXGt7ZBZ9fGHNtsJVQogYIrQMFVOc8GLn5x4eby
|
||||
UWB6k8AXU75N5gJ9aoBkMYGqL4JLbHB9bFRA+Xj207Pr0fcbTNtgC1QWE1TC6t/5INvF0UdmwgqlkZ4N
|
||||
rJvvP3JBmul6OArSrloJ6mAz3H383bMHE6FApZFlqitpbcbZhTnfWrzA9rNUDfVKsAFSY1Q5+9mFopWP
|
||||
IU6TGnJ2nrXetCslY6hwnRLo/q1XWVTr/iHwdCECQS2PFpl81IUnBLZ+LNit8bALRyA8gTTY0f816vVl
|
||||
Klwh2UneH5GweJ53076d5pv04SrSQiLWKkEVbFUl9VtItPYRZ6/iVr7549sx5sORuP2wBw5BgxIsgY2w
|
||||
DVZAlwLVc21/GwdTWRfvhXp4Cbv1rgRrQRbeDge466xaplO8x5FxMEvWCctBRTpgH4RGWgdyoRZuSyiJ
|
||||
qcrSIQ5+DgtBCXQCuXAphFaWjfVsnMD752iX2tQ5b6g7sAv0w20CiV50b3gCuTDB1ub7mGjvYCF0XRzc
|
||||
B/rrGkGqK7BYVI5MaFILSdzVdI9WHuRvG42Cj4Mc2g4toEJKUAMZSJlZzX8eY2N9ZDKIEQAAAABJRU5E
|
||||
rkJggg==
|
||||
</value>
|
||||
</data>
|
||||
<metadata name="StatusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
|
||||
199
Netch/Forms/SettingForm.Designer.cs
generated
199
Netch/Forms/SettingForm.Designer.cs
generated
@@ -30,14 +30,13 @@
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SettingForm));
|
||||
this.PortGroupBox = new System.Windows.Forms.GroupBox();
|
||||
this.RedirectorLabel = new System.Windows.Forms.Label();
|
||||
this.RedirectorTextBox = new System.Windows.Forms.TextBox();
|
||||
this.AllowDevicesCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.HTTPPortLabel = new System.Windows.Forms.Label();
|
||||
this.HTTPPortTextBox = new System.Windows.Forms.TextBox();
|
||||
this.Socks5PortLabel = new System.Windows.Forms.Label();
|
||||
this.Socks5PortTextBox = new System.Windows.Forms.TextBox();
|
||||
this.TUNTAPGroupBox = new System.Windows.Forms.GroupBox();
|
||||
this.TUNTAPProxyDNSCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.TUNTAPUseCustomDNSCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.TUNTAPDNSLabel = new System.Windows.Forms.Label();
|
||||
this.TUNTAPDNSTextBox = new System.Windows.Forms.TextBox();
|
||||
@@ -50,7 +49,18 @@
|
||||
this.ControlButton = new System.Windows.Forms.Button();
|
||||
this.GlobalBypassIPsButton = new System.Windows.Forms.Button();
|
||||
this.BehaviorGroupBox = new System.Windows.Forms.GroupBox();
|
||||
this.DetectionInterval_Label = new System.Windows.Forms.Label();
|
||||
this.DetectionInterval_TextBox = new System.Windows.Forms.TextBox();
|
||||
this.EnableStartedTcping_CheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.DelayTestAfterStartup_Label = new System.Windows.Forms.Label();
|
||||
this.BypassModeCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.Redirector2checkBox = new System.Windows.Forms.CheckBox();
|
||||
this.ExperimentalFunction_Label = new System.Windows.Forms.Label();
|
||||
this.STUN_ServerPortTextBox = new System.Windows.Forms.TextBox();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.RunAtStartup = new System.Windows.Forms.CheckBox();
|
||||
this.STUN_ServerTextBox = new System.Windows.Forms.TextBox();
|
||||
this.MinimizeWhenStartedCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.ProfileCount_Label = new System.Windows.Forms.Label();
|
||||
this.ProfileCount_TextBox = new System.Windows.Forms.TextBox();
|
||||
@@ -65,8 +75,6 @@
|
||||
//
|
||||
// PortGroupBox
|
||||
//
|
||||
this.PortGroupBox.Controls.Add(this.RedirectorLabel);
|
||||
this.PortGroupBox.Controls.Add(this.RedirectorTextBox);
|
||||
this.PortGroupBox.Controls.Add(this.AllowDevicesCheckBox);
|
||||
this.PortGroupBox.Controls.Add(this.HTTPPortLabel);
|
||||
this.PortGroupBox.Controls.Add(this.HTTPPortTextBox);
|
||||
@@ -79,23 +87,6 @@
|
||||
this.PortGroupBox.TabStop = false;
|
||||
this.PortGroupBox.Text = "Local Port";
|
||||
//
|
||||
// RedirectorLabel
|
||||
//
|
||||
this.RedirectorLabel.AutoSize = true;
|
||||
this.RedirectorLabel.Location = new System.Drawing.Point(9, 110);
|
||||
this.RedirectorLabel.Name = "RedirectorLabel";
|
||||
this.RedirectorLabel.Size = new System.Drawing.Size(95, 17);
|
||||
this.RedirectorLabel.TabIndex = 6;
|
||||
this.RedirectorLabel.Text = "Redirector TCP";
|
||||
//
|
||||
// RedirectorTextBox
|
||||
//
|
||||
this.RedirectorTextBox.Location = new System.Drawing.Point(120, 107);
|
||||
this.RedirectorTextBox.Name = "RedirectorTextBox";
|
||||
this.RedirectorTextBox.Size = new System.Drawing.Size(294, 23);
|
||||
this.RedirectorTextBox.TabIndex = 7;
|
||||
this.RedirectorTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
//
|
||||
// AllowDevicesCheckBox
|
||||
//
|
||||
this.AllowDevicesCheckBox.AutoSize = true;
|
||||
@@ -143,6 +134,7 @@
|
||||
//
|
||||
// TUNTAPGroupBox
|
||||
//
|
||||
this.TUNTAPGroupBox.Controls.Add(this.TUNTAPProxyDNSCheckBox);
|
||||
this.TUNTAPGroupBox.Controls.Add(this.TUNTAPUseCustomDNSCheckBox);
|
||||
this.TUNTAPGroupBox.Controls.Add(this.TUNTAPDNSLabel);
|
||||
this.TUNTAPGroupBox.Controls.Add(this.TUNTAPDNSTextBox);
|
||||
@@ -154,11 +146,21 @@
|
||||
this.TUNTAPGroupBox.Controls.Add(this.TUNTAPAddressTextBox);
|
||||
this.TUNTAPGroupBox.Location = new System.Drawing.Point(12, 158);
|
||||
this.TUNTAPGroupBox.Name = "TUNTAPGroupBox";
|
||||
this.TUNTAPGroupBox.Size = new System.Drawing.Size(420, 164);
|
||||
this.TUNTAPGroupBox.Size = new System.Drawing.Size(420, 187);
|
||||
this.TUNTAPGroupBox.TabIndex = 3;
|
||||
this.TUNTAPGroupBox.TabStop = false;
|
||||
this.TUNTAPGroupBox.Text = "TUN/TAP";
|
||||
//
|
||||
// TUNTAPProxyDNSCheckBox
|
||||
//
|
||||
this.TUNTAPProxyDNSCheckBox.AutoSize = true;
|
||||
this.TUNTAPProxyDNSCheckBox.Location = new System.Drawing.Point(120, 162);
|
||||
this.TUNTAPProxyDNSCheckBox.Name = "TUNTAPProxyDNSCheckBox";
|
||||
this.TUNTAPProxyDNSCheckBox.Size = new System.Drawing.Size(153, 21);
|
||||
this.TUNTAPProxyDNSCheckBox.TabIndex = 10;
|
||||
this.TUNTAPProxyDNSCheckBox.Text = "Proxy DNS in Mode 2";
|
||||
this.TUNTAPProxyDNSCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// TUNTAPUseCustomDNSCheckBox
|
||||
//
|
||||
this.TUNTAPUseCustomDNSCheckBox.AutoSize = true;
|
||||
@@ -241,7 +243,7 @@
|
||||
// ControlButton
|
||||
//
|
||||
this.ControlButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.ControlButton.Location = new System.Drawing.Point(357, 549);
|
||||
this.ControlButton.Location = new System.Drawing.Point(781, 356);
|
||||
this.ControlButton.Name = "ControlButton";
|
||||
this.ControlButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.ControlButton.TabIndex = 11;
|
||||
@@ -252,7 +254,7 @@
|
||||
// GlobalBypassIPsButton
|
||||
//
|
||||
this.GlobalBypassIPsButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.GlobalBypassIPsButton.Location = new System.Drawing.Point(12, 549);
|
||||
this.GlobalBypassIPsButton.Location = new System.Drawing.Point(12, 356);
|
||||
this.GlobalBypassIPsButton.Name = "GlobalBypassIPsButton";
|
||||
this.GlobalBypassIPsButton.Size = new System.Drawing.Size(128, 23);
|
||||
this.GlobalBypassIPsButton.TabIndex = 10;
|
||||
@@ -262,7 +264,18 @@
|
||||
//
|
||||
// BehaviorGroupBox
|
||||
//
|
||||
this.BehaviorGroupBox.Controls.Add(this.DetectionInterval_Label);
|
||||
this.BehaviorGroupBox.Controls.Add(this.DetectionInterval_TextBox);
|
||||
this.BehaviorGroupBox.Controls.Add(this.EnableStartedTcping_CheckBox);
|
||||
this.BehaviorGroupBox.Controls.Add(this.DelayTestAfterStartup_Label);
|
||||
this.BehaviorGroupBox.Controls.Add(this.BypassModeCheckBox);
|
||||
this.BehaviorGroupBox.Controls.Add(this.Redirector2checkBox);
|
||||
this.BehaviorGroupBox.Controls.Add(this.ExperimentalFunction_Label);
|
||||
this.BehaviorGroupBox.Controls.Add(this.STUN_ServerPortTextBox);
|
||||
this.BehaviorGroupBox.Controls.Add(this.label2);
|
||||
this.BehaviorGroupBox.Controls.Add(this.label1);
|
||||
this.BehaviorGroupBox.Controls.Add(this.RunAtStartup);
|
||||
this.BehaviorGroupBox.Controls.Add(this.STUN_ServerTextBox);
|
||||
this.BehaviorGroupBox.Controls.Add(this.MinimizeWhenStartedCheckBox);
|
||||
this.BehaviorGroupBox.Controls.Add(this.ProfileCount_Label);
|
||||
this.BehaviorGroupBox.Controls.Add(this.ProfileCount_TextBox);
|
||||
@@ -270,27 +283,127 @@
|
||||
this.BehaviorGroupBox.Controls.Add(this.StartWhenOpenedCheckBox);
|
||||
this.BehaviorGroupBox.Controls.Add(this.StopWhenExitedCheckBox);
|
||||
this.BehaviorGroupBox.Controls.Add(this.ExitWhenClosedCheckBox);
|
||||
this.BehaviorGroupBox.Location = new System.Drawing.Point(12, 330);
|
||||
this.BehaviorGroupBox.Location = new System.Drawing.Point(438, 12);
|
||||
this.BehaviorGroupBox.Name = "BehaviorGroupBox";
|
||||
this.BehaviorGroupBox.Size = new System.Drawing.Size(420, 213);
|
||||
this.BehaviorGroupBox.Size = new System.Drawing.Size(420, 333);
|
||||
this.BehaviorGroupBox.TabIndex = 8;
|
||||
this.BehaviorGroupBox.TabStop = false;
|
||||
this.BehaviorGroupBox.Text = "Behavior";
|
||||
//
|
||||
// DetectionInterval_Label
|
||||
//
|
||||
this.DetectionInterval_Label.AutoSize = true;
|
||||
this.DetectionInterval_Label.Location = new System.Drawing.Point(230, 151);
|
||||
this.DetectionInterval_Label.Name = "DetectionInterval_Label";
|
||||
this.DetectionInterval_Label.Size = new System.Drawing.Size(128, 17);
|
||||
this.DetectionInterval_Label.TabIndex = 18;
|
||||
this.DetectionInterval_Label.Text = "Detection interval(/s)";
|
||||
//
|
||||
// DetectionInterval_TextBox
|
||||
//
|
||||
this.DetectionInterval_TextBox.Location = new System.Drawing.Point(364, 148);
|
||||
this.DetectionInterval_TextBox.Name = "DetectionInterval_TextBox";
|
||||
this.DetectionInterval_TextBox.Size = new System.Drawing.Size(47, 23);
|
||||
this.DetectionInterval_TextBox.TabIndex = 17;
|
||||
this.DetectionInterval_TextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
//
|
||||
// EnableStartedTcping_CheckBox
|
||||
//
|
||||
this.EnableStartedTcping_CheckBox.AutoSize = true;
|
||||
this.EnableStartedTcping_CheckBox.Location = new System.Drawing.Point(152, 150);
|
||||
this.EnableStartedTcping_CheckBox.Name = "EnableStartedTcping_CheckBox";
|
||||
this.EnableStartedTcping_CheckBox.Size = new System.Drawing.Size(66, 21);
|
||||
this.EnableStartedTcping_CheckBox.TabIndex = 15;
|
||||
this.EnableStartedTcping_CheckBox.Text = "Enable";
|
||||
this.EnableStartedTcping_CheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// DelayTestAfterStartup_Label
|
||||
//
|
||||
this.DelayTestAfterStartup_Label.AutoSize = true;
|
||||
this.DelayTestAfterStartup_Label.Location = new System.Drawing.Point(6, 151);
|
||||
this.DelayTestAfterStartup_Label.Name = "DelayTestAfterStartup_Label";
|
||||
this.DelayTestAfterStartup_Label.Size = new System.Drawing.Size(141, 17);
|
||||
this.DelayTestAfterStartup_Label.TabIndex = 16;
|
||||
this.DelayTestAfterStartup_Label.Text = "Delay test after startup";
|
||||
//
|
||||
// BypassModeCheckBox
|
||||
//
|
||||
this.BypassModeCheckBox.AutoSize = true;
|
||||
this.BypassModeCheckBox.Location = new System.Drawing.Point(276, 236);
|
||||
this.BypassModeCheckBox.Name = "BypassModeCheckBox";
|
||||
this.BypassModeCheckBox.Size = new System.Drawing.Size(135, 21);
|
||||
this.BypassModeCheckBox.TabIndex = 14;
|
||||
this.BypassModeCheckBox.Text = "进程代理白名单模式";
|
||||
this.BypassModeCheckBox.UseVisualStyleBackColor = true;
|
||||
this.BypassModeCheckBox.CheckedChanged += new System.EventHandler(this.BypassModeCheckBox_CheckedChanged);
|
||||
//
|
||||
// Redirector2checkBox
|
||||
//
|
||||
this.Redirector2checkBox.AutoSize = true;
|
||||
this.Redirector2checkBox.Location = new System.Drawing.Point(152, 235);
|
||||
this.Redirector2checkBox.Name = "Redirector2checkBox";
|
||||
this.Redirector2checkBox.Size = new System.Drawing.Size(118, 21);
|
||||
this.Redirector2checkBox.TabIndex = 11;
|
||||
this.Redirector2checkBox.Text = "是否启用2号核心";
|
||||
this.Redirector2checkBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// ExperimentalFunction_Label
|
||||
//
|
||||
this.ExperimentalFunction_Label.AutoSize = true;
|
||||
this.ExperimentalFunction_Label.Location = new System.Drawing.Point(6, 236);
|
||||
this.ExperimentalFunction_Label.Name = "ExperimentalFunction_Label";
|
||||
this.ExperimentalFunction_Label.Size = new System.Drawing.Size(133, 17);
|
||||
this.ExperimentalFunction_Label.TabIndex = 13;
|
||||
this.ExperimentalFunction_Label.Text = "Experimental function";
|
||||
//
|
||||
// STUN_ServerPortTextBox
|
||||
//
|
||||
this.STUN_ServerPortTextBox.Location = new System.Drawing.Point(117, 206);
|
||||
this.STUN_ServerPortTextBox.Name = "STUN_ServerPortTextBox";
|
||||
this.STUN_ServerPortTextBox.Size = new System.Drawing.Size(294, 23);
|
||||
this.STUN_ServerPortTextBox.TabIndex = 8;
|
||||
this.STUN_ServerPortTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.Location = new System.Drawing.Point(6, 209);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(110, 17);
|
||||
this.label2.TabIndex = 12;
|
||||
this.label2.Text = "STUN Server Port";
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(6, 180);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(82, 17);
|
||||
this.label1.TabIndex = 10;
|
||||
this.label1.Text = "STUN Server";
|
||||
//
|
||||
// RunAtStartup
|
||||
//
|
||||
this.RunAtStartup.AutoSize = true;
|
||||
this.RunAtStartup.Location = new System.Drawing.Point(120, 130);
|
||||
this.RunAtStartup.Location = new System.Drawing.Point(12, 75);
|
||||
this.RunAtStartup.Name = "RunAtStartup";
|
||||
this.RunAtStartup.Size = new System.Drawing.Size(109, 21);
|
||||
this.RunAtStartup.TabIndex = 11;
|
||||
this.RunAtStartup.Text = "Run at startup";
|
||||
this.RunAtStartup.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// STUN_ServerTextBox
|
||||
//
|
||||
this.STUN_ServerTextBox.Location = new System.Drawing.Point(117, 177);
|
||||
this.STUN_ServerTextBox.Name = "STUN_ServerTextBox";
|
||||
this.STUN_ServerTextBox.Size = new System.Drawing.Size(294, 23);
|
||||
this.STUN_ServerTextBox.TabIndex = 11;
|
||||
this.STUN_ServerTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
//
|
||||
// MinimizeWhenStartedCheckBox
|
||||
//
|
||||
this.MinimizeWhenStartedCheckBox.AutoSize = true;
|
||||
this.MinimizeWhenStartedCheckBox.Location = new System.Drawing.Point(120, 103);
|
||||
this.MinimizeWhenStartedCheckBox.Location = new System.Drawing.Point(206, 48);
|
||||
this.MinimizeWhenStartedCheckBox.Name = "MinimizeWhenStartedCheckBox";
|
||||
this.MinimizeWhenStartedCheckBox.Size = new System.Drawing.Size(158, 21);
|
||||
this.MinimizeWhenStartedCheckBox.TabIndex = 10;
|
||||
@@ -300,7 +413,7 @@
|
||||
// ProfileCount_Label
|
||||
//
|
||||
this.ProfileCount_Label.AutoSize = true;
|
||||
this.ProfileCount_Label.Location = new System.Drawing.Point(9, 185);
|
||||
this.ProfileCount_Label.Location = new System.Drawing.Point(6, 123);
|
||||
this.ProfileCount_Label.Name = "ProfileCount_Label";
|
||||
this.ProfileCount_Label.Size = new System.Drawing.Size(79, 17);
|
||||
this.ProfileCount_Label.TabIndex = 8;
|
||||
@@ -308,16 +421,16 @@
|
||||
//
|
||||
// ProfileCount_TextBox
|
||||
//
|
||||
this.ProfileCount_TextBox.Location = new System.Drawing.Point(222, 182);
|
||||
this.ProfileCount_TextBox.Location = new System.Drawing.Point(203, 120);
|
||||
this.ProfileCount_TextBox.Name = "ProfileCount_TextBox";
|
||||
this.ProfileCount_TextBox.Size = new System.Drawing.Size(192, 23);
|
||||
this.ProfileCount_TextBox.Size = new System.Drawing.Size(208, 23);
|
||||
this.ProfileCount_TextBox.TabIndex = 9;
|
||||
this.ProfileCount_TextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
//
|
||||
// CheckUpdateWhenOpenedCheckBox
|
||||
//
|
||||
this.CheckUpdateWhenOpenedCheckBox.AutoSize = true;
|
||||
this.CheckUpdateWhenOpenedCheckBox.Location = new System.Drawing.Point(120, 157);
|
||||
this.CheckUpdateWhenOpenedCheckBox.Location = new System.Drawing.Point(206, 75);
|
||||
this.CheckUpdateWhenOpenedCheckBox.Name = "CheckUpdateWhenOpenedCheckBox";
|
||||
this.CheckUpdateWhenOpenedCheckBox.Size = new System.Drawing.Size(190, 21);
|
||||
this.CheckUpdateWhenOpenedCheckBox.TabIndex = 8;
|
||||
@@ -328,7 +441,7 @@
|
||||
// StartWhenOpenedCheckBox
|
||||
//
|
||||
this.StartWhenOpenedCheckBox.AutoSize = true;
|
||||
this.StartWhenOpenedCheckBox.Location = new System.Drawing.Point(120, 76);
|
||||
this.StartWhenOpenedCheckBox.Location = new System.Drawing.Point(12, 48);
|
||||
this.StartWhenOpenedCheckBox.Name = "StartWhenOpenedCheckBox";
|
||||
this.StartWhenOpenedCheckBox.Size = new System.Drawing.Size(137, 21);
|
||||
this.StartWhenOpenedCheckBox.TabIndex = 7;
|
||||
@@ -339,7 +452,7 @@
|
||||
// StopWhenExitedCheckBox
|
||||
//
|
||||
this.StopWhenExitedCheckBox.AutoSize = true;
|
||||
this.StopWhenExitedCheckBox.Location = new System.Drawing.Point(120, 49);
|
||||
this.StopWhenExitedCheckBox.Location = new System.Drawing.Point(206, 22);
|
||||
this.StopWhenExitedCheckBox.Name = "StopWhenExitedCheckBox";
|
||||
this.StopWhenExitedCheckBox.Size = new System.Drawing.Size(127, 21);
|
||||
this.StopWhenExitedCheckBox.TabIndex = 6;
|
||||
@@ -350,7 +463,7 @@
|
||||
// ExitWhenClosedCheckBox
|
||||
//
|
||||
this.ExitWhenClosedCheckBox.AutoSize = true;
|
||||
this.ExitWhenClosedCheckBox.Location = new System.Drawing.Point(120, 22);
|
||||
this.ExitWhenClosedCheckBox.Location = new System.Drawing.Point(12, 21);
|
||||
this.ExitWhenClosedCheckBox.Name = "ExitWhenClosedCheckBox";
|
||||
this.ExitWhenClosedCheckBox.Size = new System.Drawing.Size(123, 21);
|
||||
this.ExitWhenClosedCheckBox.TabIndex = 5;
|
||||
@@ -362,7 +475,7 @@
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
|
||||
this.ClientSize = new System.Drawing.Size(444, 583);
|
||||
this.ClientSize = new System.Drawing.Size(868, 390);
|
||||
this.Controls.Add(this.BehaviorGroupBox);
|
||||
this.Controls.Add(this.PortGroupBox);
|
||||
this.Controls.Add(this.GlobalBypassIPsButton);
|
||||
@@ -408,8 +521,6 @@
|
||||
private System.Windows.Forms.Button GlobalBypassIPsButton;
|
||||
private System.Windows.Forms.CheckBox TUNTAPUseCustomDNSCheckBox;
|
||||
private System.Windows.Forms.CheckBox AllowDevicesCheckBox;
|
||||
private System.Windows.Forms.TextBox RedirectorTextBox;
|
||||
private System.Windows.Forms.Label RedirectorLabel;
|
||||
private System.Windows.Forms.GroupBox BehaviorGroupBox;
|
||||
private System.Windows.Forms.CheckBox ExitWhenClosedCheckBox;
|
||||
private System.Windows.Forms.CheckBox StopWhenExitedCheckBox;
|
||||
@@ -419,5 +530,17 @@
|
||||
private System.Windows.Forms.TextBox ProfileCount_TextBox;
|
||||
private System.Windows.Forms.CheckBox MinimizeWhenStartedCheckBox;
|
||||
private System.Windows.Forms.CheckBox RunAtStartup;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.TextBox STUN_ServerTextBox;
|
||||
private System.Windows.Forms.TextBox STUN_ServerPortTextBox;
|
||||
private System.Windows.Forms.CheckBox TUNTAPProxyDNSCheckBox;
|
||||
private System.Windows.Forms.CheckBox Redirector2checkBox;
|
||||
private System.Windows.Forms.Label ExperimentalFunction_Label;
|
||||
private System.Windows.Forms.CheckBox BypassModeCheckBox;
|
||||
private System.Windows.Forms.TextBox DetectionInterval_TextBox;
|
||||
private System.Windows.Forms.CheckBox EnableStartedTcping_CheckBox;
|
||||
private System.Windows.Forms.Label DelayTestAfterStartup_Label;
|
||||
private System.Windows.Forms.Label DetectionInterval_Label;
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,7 @@ namespace Netch.Forms
|
||||
TUNTAPNetmaskLabel.Text = Utils.i18N.Translate(TUNTAPNetmaskLabel.Text);
|
||||
TUNTAPGatewayLabel.Text = Utils.i18N.Translate(TUNTAPGatewayLabel.Text);
|
||||
TUNTAPUseCustomDNSCheckBox.Text = Utils.i18N.Translate(TUNTAPUseCustomDNSCheckBox.Text);
|
||||
TUNTAPProxyDNSCheckBox.Text = Utils.i18N.Translate(TUNTAPProxyDNSCheckBox.Text);
|
||||
GlobalBypassIPsButton.Text = Utils.i18N.Translate(GlobalBypassIPsButton.Text);
|
||||
ControlButton.Text = Utils.i18N.Translate(ControlButton.Text);
|
||||
|
||||
@@ -61,16 +62,20 @@ namespace Netch.Forms
|
||||
CheckUpdateWhenOpenedCheckBox.Checked = Global.Settings.CheckUpdateWhenOpened;
|
||||
MinimizeWhenStartedCheckBox.Checked = Global.Settings.MinimizeWhenStarted;
|
||||
RunAtStartup.Checked = Global.Settings.RunAtStartup;
|
||||
Redirector2checkBox.Checked = Global.Settings.UseRedirector2;
|
||||
BypassModeCheckBox.Checked = Global.Settings.ProcessBypassMode;
|
||||
EnableStartedTcping_CheckBox.Checked = Global.Settings.StartedTcping;
|
||||
DetectionInterval_TextBox.Text = Global.Settings.StartedTcping_Interval.ToString();
|
||||
|
||||
Socks5PortTextBox.Text = Global.Settings.Socks5LocalPort.ToString();
|
||||
HTTPPortTextBox.Text = Global.Settings.HTTPLocalPort.ToString();
|
||||
RedirectorTextBox.Text = Global.Settings.RedirectorTCPPort.ToString();
|
||||
|
||||
TUNTAPAddressTextBox.Text = Global.Settings.TUNTAP.Address;
|
||||
TUNTAPNetmaskTextBox.Text = Global.Settings.TUNTAP.Netmask;
|
||||
TUNTAPGatewayTextBox.Text = Global.Settings.TUNTAP.Gateway;
|
||||
|
||||
TUNTAPUseCustomDNSCheckBox.Checked = Global.Settings.TUNTAP.UseCustomDNS;
|
||||
TUNTAPProxyDNSCheckBox.Checked = Global.Settings.TUNTAP.ProxyDNS;
|
||||
|
||||
BehaviorGroupBox.Text = Utils.i18N.Translate(BehaviorGroupBox.Text);
|
||||
ExitWhenClosedCheckBox.Text = Utils.i18N.Translate(ExitWhenClosedCheckBox.Text);
|
||||
@@ -80,8 +85,15 @@ namespace Netch.Forms
|
||||
RunAtStartup.Text = Utils.i18N.Translate(RunAtStartup.Text);
|
||||
CheckUpdateWhenOpenedCheckBox.Text = Utils.i18N.Translate(CheckUpdateWhenOpenedCheckBox.Text);
|
||||
ProfileCount_Label.Text = Utils.i18N.Translate(ProfileCount_Label.Text);
|
||||
ExperimentalFunction_Label.Text = Utils.i18N.Translate(ExperimentalFunction_Label.Text);
|
||||
DelayTestAfterStartup_Label.Text = Utils.i18N.Translate(DelayTestAfterStartup_Label.Text);
|
||||
EnableStartedTcping_CheckBox.Text = Utils.i18N.Translate(EnableStartedTcping_CheckBox.Text);
|
||||
DetectionInterval_Label.Text = Utils.i18N.Translate(DetectionInterval_Label.Text);
|
||||
DelayTestAfterStartup_Label.Text = Utils.i18N.Translate(DelayTestAfterStartup_Label.Text);
|
||||
|
||||
ProfileCount_TextBox.Text = Global.Settings.ProfileCount.ToString();
|
||||
STUN_ServerTextBox.Text = Global.Settings.STUN_Server.ToString();
|
||||
STUN_ServerPortTextBox.Text = Global.Settings.STUN_Server_Port.ToString();
|
||||
|
||||
if (Global.Settings.TUNTAP.DNS.Count > 0)
|
||||
{
|
||||
@@ -141,6 +153,9 @@ namespace Netch.Forms
|
||||
Global.Settings.CheckUpdateWhenOpened = CheckUpdateWhenOpenedCheckBox.Checked;
|
||||
Global.Settings.MinimizeWhenStarted = MinimizeWhenStartedCheckBox.Checked;
|
||||
Global.Settings.RunAtStartup = RunAtStartup.Checked;
|
||||
Global.Settings.UseRedirector2 = Redirector2checkBox.Checked;
|
||||
Global.Settings.ProcessBypassMode = BypassModeCheckBox.Checked;
|
||||
Global.Settings.StartedTcping = EnableStartedTcping_CheckBox.Checked;
|
||||
|
||||
// 开机自启判断
|
||||
TaskSchedulerClass scheduler = new TaskSchedulerClass();
|
||||
@@ -223,27 +238,6 @@ namespace Netch.Forms
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var RedirectorPort = int.Parse(RedirectorTextBox.Text);
|
||||
|
||||
if (RedirectorPort > 0 && RedirectorPort < 65536)
|
||||
{
|
||||
Global.Settings.RedirectorTCPPort = RedirectorPort;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new FormatException();
|
||||
}
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
RedirectorTextBox.Text = Global.Settings.RedirectorTCPPort.ToString();
|
||||
MessageBox.Show(Utils.i18N.Translate("Port value illegal. Try again."), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (AllowDevicesCheckBox.Checked)
|
||||
{
|
||||
Global.Settings.LocalAddress = "0.0.0.0";
|
||||
@@ -289,7 +283,7 @@ namespace Netch.Forms
|
||||
{
|
||||
var ProfileCount = int.Parse(ProfileCount_TextBox.Text);
|
||||
|
||||
if (ProfileCount>0)
|
||||
if (ProfileCount > -1)
|
||||
{
|
||||
Global.Settings.ProfileCount = ProfileCount;
|
||||
}
|
||||
@@ -305,6 +299,51 @@ namespace Netch.Forms
|
||||
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
var STUN_Server = STUN_ServerTextBox.Text;
|
||||
Global.Settings.STUN_Server = STUN_Server;
|
||||
|
||||
var STUN_ServerPort = int.Parse(STUN_ServerPortTextBox.Text);
|
||||
|
||||
if (STUN_ServerPort > 0)
|
||||
{
|
||||
Global.Settings.STUN_Server_Port = STUN_ServerPort;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new FormatException();
|
||||
}
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
ProfileCount_TextBox.Text = Global.Settings.ProfileCount.ToString();
|
||||
MessageBox.Show(Utils.i18N.Translate("STUN_ServerPort value illegal. Try again."), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
Global.Settings.StartedTcping = EnableStartedTcping_CheckBox.Checked;
|
||||
|
||||
var DetectionInterval = int.Parse(DetectionInterval_TextBox.Text);
|
||||
|
||||
if (DetectionInterval > 0)
|
||||
{
|
||||
Global.Settings.StartedTcping_Interval = DetectionInterval;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new FormatException();
|
||||
}
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
ProfileCount_TextBox.Text = Global.Settings.ProfileCount.ToString();
|
||||
MessageBox.Show(Utils.i18N.Translate("STUN_ServerPort value illegal. Try again."), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Global.Settings.TUNTAP.Address = TUNTAPAddressTextBox.Text;
|
||||
Global.Settings.TUNTAP.Netmask = TUNTAPNetmaskTextBox.Text;
|
||||
@@ -317,10 +356,25 @@ namespace Netch.Forms
|
||||
}
|
||||
|
||||
Global.Settings.TUNTAP.UseCustomDNS = TUNTAPUseCustomDNSCheckBox.Checked;
|
||||
Global.Settings.TUNTAP.ProxyDNS = TUNTAPProxyDNSCheckBox.Checked;
|
||||
|
||||
Utils.Configuration.Save();
|
||||
MessageBox.Show(Utils.i18N.Translate("Saved"), Utils.i18N.Translate("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
Close();
|
||||
}
|
||||
|
||||
private void BypassModeCheckBox_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (BypassModeCheckBox.Checked)
|
||||
{
|
||||
Redirector2checkBox.Checked = false;
|
||||
Redirector2checkBox.Enabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Redirector2checkBox.Enabled = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ namespace Netch
|
||||
"table",
|
||||
"rc4",
|
||||
"rc4-md5",
|
||||
"rc4-md5-6",
|
||||
"aes-128-cfb",
|
||||
"aes-192-cfb",
|
||||
"aes-256-cfb",
|
||||
|
||||
@@ -31,6 +31,11 @@ namespace Netch.Models
|
||||
/// 使用自定义 DNS 设置
|
||||
/// </summary>
|
||||
public bool UseCustomDNS = false;
|
||||
|
||||
/// <summary>
|
||||
/// 模式2下是否代理DNS
|
||||
/// </summary>
|
||||
public bool ProxyDNS = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -97,7 +102,7 @@ namespace Netch.Models
|
||||
/// <summary>
|
||||
/// Redirector TCP 占用端口
|
||||
/// </summary>
|
||||
public int RedirectorTCPPort = 2800;
|
||||
//public int RedirectorTCPPort = 2800;
|
||||
|
||||
/// <summary>
|
||||
/// HTTP 和 Socks5 本地代理地址
|
||||
@@ -138,5 +143,35 @@ namespace Netch.Models
|
||||
/// 快捷配置数量
|
||||
/// </summary>
|
||||
public int ProfileCount = 4;
|
||||
|
||||
/// <summary>
|
||||
/// STUN测试服务器
|
||||
/// </summary>
|
||||
public string STUN_Server = "stun.l.google.com";
|
||||
|
||||
/// <summary>
|
||||
/// STUN测试服务器
|
||||
/// </summary>
|
||||
public int STUN_Server_Port = 19302;
|
||||
|
||||
/// <summary>
|
||||
/// 是否切换为2号核心
|
||||
/// </summary>
|
||||
public bool UseRedirector2 = false;
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用进程代理白名单模式
|
||||
/// </summary>
|
||||
public bool ProcessBypassMode = false;
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用启动后延迟测试
|
||||
/// </summary>
|
||||
public bool StartedTcping = false;
|
||||
|
||||
/// <summary>
|
||||
/// 启动后延迟测试间隔/秒
|
||||
/// </summary>
|
||||
public int StartedTcping_Interval = 3;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,99 +1,115 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
||||
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net48</TargetFramework>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<UseWPF>true</UseWPF>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<StartupObject>Netch.Netch</StartupObject>
|
||||
<ApplicationManifest>App.manifest</ApplicationManifest>
|
||||
<ApplicationIcon>Netch.ico</ApplicationIcon>
|
||||
<Platforms>x86;x64</Platforms>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net48</TargetFramework>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<UseWPF>true</UseWPF>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<StartupObject>Netch.Netch</StartupObject>
|
||||
<ApplicationManifest>App.manifest</ApplicationManifest>
|
||||
<ApplicationIcon>Netch.ico</ApplicationIcon>
|
||||
<Platforms>x86;x64</Platforms>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<WarningsAsErrors />
|
||||
<NoWarn />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<WarningsAsErrors />
|
||||
<NoWarn />
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'">
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<NoWarn />
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<WarningsAsErrors />
|
||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'">
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<NoWarn />
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<WarningsAsErrors />
|
||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<NoWarn />
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<WarningsAsErrors />
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<NoWarn />
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<WarningsAsErrors />
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<NoWarn />
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<WarningsAsErrors />
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<NoWarn />
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<WarningsAsErrors />
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove=".gitignore" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Remove=".gitignore" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<COMReference Include="TaskScheduler.dll">
|
||||
<Guid>e34cb9f1-c7f7-424c-be29-027dcc09363a</Guid>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<VersionMinor>0</VersionMinor>
|
||||
<WrapperTool>tlbimp</WrapperTool>
|
||||
<Lcid>0</Lcid>
|
||||
<Isolated>false</Isolated>
|
||||
<EmbedInteropTypes>false</EmbedInteropTypes>
|
||||
</COMReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<COMReference Include="TaskScheduler.dll">
|
||||
<Guid>e34cb9f1-c7f7-424c-be29-027dcc09363a</Guid>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<VersionMinor>0</VersionMinor>
|
||||
<WrapperTool>tlbimp</WrapperTool>
|
||||
<Lcid>0</Lcid>
|
||||
<Isolated>false</Isolated>
|
||||
<EmbedInteropTypes>false</EmbedInteropTypes>
|
||||
</COMReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ini-parser" Version="2.5.2" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="System.Buffers" Version="4.5.0" />
|
||||
<PackageReference Include="WindowsAPICodePack-Shell" Version="1.1.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DNS" Version="5.0.0" />
|
||||
<PackageReference Include="DnsClient" Version="1.2.0" />
|
||||
<PackageReference Include="ini-parser" Version="2.5.2" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="System.Buffers" Version="4.5.0" />
|
||||
<PackageReference Include="WindowsAPICodePack-Shell" Version="1.1.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.ServiceProcess" />
|
||||
<Reference Include="System.Web" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\NetchLib\NetchLib.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Resources.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.ServiceProcess" />
|
||||
<Reference Include="System.Web" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Resources.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Properties\Settings.Designer.cs">
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
||||
<Exec Command="@ECHO OFF
RD /S /Q $(TargetDir)bin > NUL 2>&1
RD /S /Q $(TargetDir)i18n > NUL 2>&1
RD /S /Q $(TargetDir)mode > NUL 2>&1

MKDIR $(TargetDir)bin > NUL 2>&1
MKDIR $(TargetDir)i18n > NUL 2>&1
MKDIR $(TargetDir)mode > NUL 2>&1

COPY /Y $(SolutionDir)binaries\$(PlatformName)\* $(TargetDir)bin > NUL 2>&1
COPY /Y $(SolutionDir)binaries\* $(TargetDir)bin > NUL 2>&1
MOVE /Y $(TargetDir)bin\nfapinet.dll $(TargetDir)nfapinet.dll > NUL 2>&1
COPY /Y $(SolutionDir)translations\i18n\* $(TargetDir)i18n > NUL 2>&1
COPY /Y $(SolutionDir)modes\mode\*.txt $(TargetDir)mode > NUL 2>&1
MKDIR $(TargetDir)bin\tap-driver > NUL 2>&1
COPY /Y $(SolutionDir)binaries\$(PlatformName)\tap-driver\* $(TargetDir)bin\tap-driver > NUL 2>&1" />
|
||||
</Target>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
<ItemGroup>
|
||||
<None Update="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<Target Condition="'$(VisualStudioDir)' != ''" Name="PostBuild" AfterTargets="PostBuildEvent">
|
||||
<Exec Command="@ECHO OFF
RD /S /Q $(TargetDir)bin > NUL 2>&1
RD /S /Q $(TargetDir)i18n > NUL 2>&1
RD /S /Q $(TargetDir)mode > NUL 2>&1

MKDIR $(TargetDir)bin > NUL 2>&1
MKDIR $(TargetDir)i18n > NUL 2>&1
MKDIR $(TargetDir)mode > NUL 2>&1

COPY /Y $(SolutionDir)binaries\$(PlatformName)\* $(TargetDir)bin > NUL 2>&1
COPY /Y $(SolutionDir)binaries\* $(TargetDir)bin > NUL 2>&1
MOVE /Y $(TargetDir)bin\nfapinet.dll $(TargetDir)nfapinet.dll > NUL 2>&1
COPY /Y $(SolutionDir)translations\i18n\* $(TargetDir)i18n > NUL 2>&1
COPY /Y $(SolutionDir)modes\mode\*.txt $(TargetDir)mode > NUL 2>&1
MKDIR $(TargetDir)bin\tap-driver > NUL 2>&1
COPY /Y $(SolutionDir)binaries\$(PlatformName)\tap-driver\* $(TargetDir)bin\tap-driver > NUL 2>&1" />
|
||||
</Target>
|
||||
</Project>
|
||||
|
||||
@@ -8,8 +8,8 @@ namespace Netch.Override
|
||||
protected override WebRequest GetWebRequest(Uri address)
|
||||
{
|
||||
var request = base.GetWebRequest(address);
|
||||
request.Timeout = 4000;
|
||||
((HttpWebRequest)request).ReadWriteTimeout = 4000;
|
||||
request.Timeout = 10000;
|
||||
((HttpWebRequest)request).ReadWriteTimeout = 10000;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
42
Netch/Properties/Settings.Designer.cs
generated
42
Netch/Properties/Settings.Designer.cs
generated
@@ -1,30 +1,26 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
// 此代码由工具生成。
|
||||
// 运行时版本:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果
|
||||
// 重新生成代码,这些更改将会丢失。
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Netch.Properties
|
||||
{
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
|
||||
{
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default
|
||||
{
|
||||
get
|
||||
{
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Netch.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.4.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
59
Netch/Resolver.cs
Normal file
59
Netch/Resolver.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
using DNS.Protocol;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Netch
|
||||
{
|
||||
public class Resolver : DNS.Client.RequestResolver.IRequestResolver
|
||||
{
|
||||
public Task<IResponse> Resolve(IRequest request)
|
||||
{
|
||||
IResponse response = Response.FromRequest(request);
|
||||
|
||||
foreach (var question in response.Questions)
|
||||
{
|
||||
if (question.Type == RecordType.A)
|
||||
{
|
||||
var client = new DnsClient.LookupClient(DnsClient.NameServer.GooglePublicDns);
|
||||
client.UseTcpOnly = true;
|
||||
client.UseCache = true;
|
||||
|
||||
try
|
||||
{
|
||||
var result = client.Query(question.Name.ToString(), DnsClient.QueryType.A);
|
||||
foreach (var item in result.Answers.ARecords())
|
||||
{
|
||||
response.AnswerRecords.Add(new DNS.Protocol.ResourceRecords.IPAddressResourceRecord(question.Name, item.Address));
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// 跳过
|
||||
}
|
||||
}
|
||||
else if (question.Type == RecordType.AAAA)
|
||||
{
|
||||
var client = new DnsClient.LookupClient(DnsClient.NameServer.GooglePublicDns);
|
||||
client.UseTcpOnly = true;
|
||||
client.UseCache = true;
|
||||
|
||||
try
|
||||
{
|
||||
var result = client.Query(question.Name.ToString(), DnsClient.QueryType.AAAA);
|
||||
foreach (var item in result.Answers.AaaaRecords())
|
||||
{
|
||||
response.AnswerRecords.Add(new DNS.Protocol.ResourceRecords.IPAddressResourceRecord(question.Name, item.Address));
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// 跳过
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Task.FromResult(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,10 +12,24 @@
|
||||
"Stop": "停止",
|
||||
"Waiting for command": "等待命令中",
|
||||
"Starting": "正在启动中",
|
||||
"Start failed": "启动失败",
|
||||
"Start failed": "启动失败,请打开软件目录logging文件夹查看日志",
|
||||
"Started": "已启动",
|
||||
"Stopping": "正在停止中",
|
||||
"Stopped": "已停止",
|
||||
"Starting Shadowsocks": "正在启动Shadowsocks",
|
||||
"Starting ShadowsocksR": "正在启动ShadowsocksR",
|
||||
"Starting V2ray": "正在启动V2ray",
|
||||
"Starting Tap": "正在启动Tap",
|
||||
"Starting NatTester": "正在启动Nat测试",
|
||||
"Starting LocalDns service": "正在启动本地DNS服务",
|
||||
"Starting Redirector": "正在启动Redirector",
|
||||
"Starting netfilter2 Service": "正在启动netfilter2服务",
|
||||
"Starting dns2tcp Service": "正在启动dns2tcp服务",
|
||||
"SetupBypass": "设置绕行规则",
|
||||
"Test failed": "测试失败",
|
||||
"Starting update subscription": "正在更新订阅",
|
||||
"Subscription updated": "订阅更新完毕",
|
||||
"Register driver": "正在注册驱动",
|
||||
|
||||
"Server": "服务器",
|
||||
"Import Servers From Clipboard": "从剪贴板导入服务器",
|
||||
@@ -83,6 +97,8 @@
|
||||
"Please press Stop button first": "请先点击停止按钮",
|
||||
"Please select a server first": "请先选择一个服务器",
|
||||
"Please select an mode first": "请先选择一个模式",
|
||||
"Please enter a profile name first": "请先为该配置设置一个名称",
|
||||
"No saved profile here. Save a profile first by Ctrl+Click on the button": "当前按钮下没有保存配置,请先使用ctrl+左键点击该按钮保存一个配置",
|
||||
|
||||
"Used": "已使用",
|
||||
"Status": "状态",
|
||||
@@ -126,6 +142,7 @@
|
||||
"Netmask": "子网掩码",
|
||||
"Gateway": "网关",
|
||||
"Use Custom DNS": "使用自定义 DNS",
|
||||
"Proxy DNS in Mode 2": "在模式2下代理DNS",
|
||||
"Behavior": "行为",
|
||||
"Exit when closed": "关闭时退出",
|
||||
"Stop when exited": "退出时停止",
|
||||
@@ -134,7 +151,12 @@
|
||||
"Check update when opened": "打开软件时检查更新",
|
||||
"ProfileCount": "快捷配置数量(重启软件生效)",
|
||||
"ProfileCount value illegal. Try again.": "快捷配置数值非法。请重试。",
|
||||
"STUN_ServerPort value illegal. Try again.": "STUN端口数值非法。请重试。",
|
||||
"TUN/TAP driver is not detected. Is it installed now?": "未检测到TUN/TAP驱动,是否现在安装?",
|
||||
"Experimental function": "实验性功能",
|
||||
"Delay test after startup": "启动后延迟测试",
|
||||
"Enable": "启用",
|
||||
"Detection interval(/s)": "检测间隔(/秒)",
|
||||
|
||||
"Profile": "配置名",
|
||||
"Profiles": "配置",
|
||||
|
||||
@@ -109,39 +109,45 @@ namespace Netch.Utils
|
||||
var AddressGot = false;
|
||||
foreach (var adapter in NetworkInterface.GetAllNetworkInterfaces())
|
||||
{
|
||||
var adapterProperties = adapter.GetIPProperties();
|
||||
var p = adapterProperties.GetIPv4Properties();
|
||||
Logging.Info($"检测适配器:{adapter.Name} {adapter.Id} {adapter.Description}, index: {p.Index}");
|
||||
|
||||
// 通过索引查找对应适配器的 IPv4 地址
|
||||
if (p.Index == Global.Adapter.Index)
|
||||
try
|
||||
{
|
||||
var AdapterIPs = "";
|
||||
var adapterProperties = adapter.GetIPProperties();
|
||||
var p = adapterProperties.GetIPv4Properties();
|
||||
Logging.Info($"检测适配器:{adapter.Name} {adapter.Id} {adapter.Description}, index: {p.Index}");
|
||||
|
||||
foreach (var ip in adapterProperties.UnicastAddresses)
|
||||
// 通过索引查找对应适配器的 IPv4 地址
|
||||
if (p.Index == Global.Adapter.Index)
|
||||
{
|
||||
if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
|
||||
var AdapterIPs = "";
|
||||
|
||||
foreach (var ip in adapterProperties.UnicastAddresses)
|
||||
{
|
||||
AddressGot = true;
|
||||
Global.Adapter.Address = ip.Address;
|
||||
Logging.Info($"当前出口 IPv4 地址:{Global.Adapter.Address}");
|
||||
break;
|
||||
if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
|
||||
{
|
||||
AddressGot = true;
|
||||
Global.Adapter.Address = ip.Address;
|
||||
Logging.Info($"当前出口 IPv4 地址:{Global.Adapter.Address}");
|
||||
break;
|
||||
}
|
||||
AdapterIPs = $"{ip.Address} | ";
|
||||
}
|
||||
AdapterIPs = $"{ip.Address} | ";
|
||||
|
||||
if (!AddressGot)
|
||||
{
|
||||
if (AdapterIPs.Length > 3)
|
||||
{
|
||||
AdapterIPs = AdapterIPs.Substring(0, AdapterIPs.Length - 3);
|
||||
Logging.Info($"所有出口地址:{AdapterIPs}");
|
||||
}
|
||||
Logging.Info("出口无 IPv4 地址,当前只支持 IPv4 地址");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!AddressGot)
|
||||
{
|
||||
if (AdapterIPs.Length > 3)
|
||||
{
|
||||
AdapterIPs = AdapterIPs.Substring(0, AdapterIPs.Length - 3);
|
||||
Logging.Info($"所有出口地址:{AdapterIPs}");
|
||||
}
|
||||
Logging.Info("出口无 IPv4 地址,当前只支持 IPv4 地址");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
catch (Exception)
|
||||
{ }
|
||||
}
|
||||
|
||||
if (!AddressGot)
|
||||
|
||||
@@ -290,80 +290,88 @@ namespace Netch.Utils
|
||||
}
|
||||
else if (text.StartsWith("ssr://"))
|
||||
{
|
||||
var data = new Server();
|
||||
data.Type = "SSR";
|
||||
|
||||
text = text.Substring(6);
|
||||
list.Add(SsrServerFromLink(text));
|
||||
|
||||
var parser = new Regex(@"^(?<server>.+):(?<port>(-?\d+?)):(?<protocol>.+?):(?<method>.+?):(?<obfs>.+?):(?<password>.+?)/\?(?<info>.*)$");
|
||||
var match = parser.Match(URLSafeBase64Decode(text));
|
||||
/* var data = new Server();
|
||||
data.Type = "SSR";
|
||||
|
||||
if (match.Success)
|
||||
{
|
||||
data.Hostname = match.Groups["server"].Value;
|
||||
data.Port = int.Parse(match.Groups["port"].Value);
|
||||
if (data.Port < 0)
|
||||
{
|
||||
data.Port += 65536;
|
||||
}
|
||||
data.Password = URLSafeBase64Decode(match.Groups["password"].Value);
|
||||
text = text.Substring(6);
|
||||
|
||||
data.EncryptMethod = match.Groups["method"].Value;
|
||||
if (!Global.EncryptMethods.SSR.Contains(data.EncryptMethod))
|
||||
{
|
||||
Logging.Info(string.Format("不支持的 SSR 加密方式:{0}", data.EncryptMethod));
|
||||
return null;
|
||||
}
|
||||
var parser = new Regex(@"^(?<server>.+):(?<port>(-?\d+?)):(?<protocol>.+?):(?<method>.+?):(?<obfs>.+?):(?<password>.+?)/\?(?<info>.*)$");
|
||||
var parser2 = new Regex(@"^(?<server>.+):(?<port>(-?\d+?)):(?<protocol>.+?):(?<method>.+?):(?<obfs>.+?):(?<password>.+?)/$");
|
||||
var match = parser2.Match(URLSafeBase64Decode(text));
|
||||
if (!match.Success)
|
||||
{
|
||||
match = parser2.Match(UnBase64String(text));
|
||||
}
|
||||
|
||||
data.Protocol = match.Groups["protocol"].Value;
|
||||
if (!Global.Protocols.Contains(data.Protocol))
|
||||
{
|
||||
Logging.Info(string.Format("不支持的 SSR 协议:{0}", data.Protocol));
|
||||
return null;
|
||||
}
|
||||
if (match.Success)
|
||||
{
|
||||
data.Hostname = match.Groups["server"].Value;
|
||||
data.Port = int.Parse(match.Groups["port"].Value);
|
||||
if (data.Port < 0)
|
||||
{
|
||||
data.Port += 65536;
|
||||
}
|
||||
data.Password = URLSafeBase64Decode(match.Groups["password"].Value);
|
||||
|
||||
data.OBFS = match.Groups["obfs"].Value;
|
||||
if (data.OBFS == @"tls1.2_ticket_fastauth")
|
||||
{
|
||||
data.OBFS = @"tls1.2_ticket_auth";
|
||||
}
|
||||
if (!Global.OBFSs.Contains(data.OBFS))
|
||||
{
|
||||
Logging.Info(string.Format("不支持的 SSR 混淆:{0}", data.OBFS));
|
||||
return null;
|
||||
}
|
||||
data.EncryptMethod = match.Groups["method"].Value;
|
||||
if (!Global.EncryptMethods.SSR.Contains(data.EncryptMethod))
|
||||
{
|
||||
Logging.Info(string.Format("不支持的 SSR 加密方式:{0}", data.EncryptMethod));
|
||||
return null;
|
||||
}
|
||||
|
||||
var info = match.Groups["info"].Value;
|
||||
var dict = new Dictionary<string, string>();
|
||||
foreach (var str in info.Split('&'))
|
||||
{
|
||||
var splited = str.Split('=');
|
||||
dict.Add(splited[0], splited[1]);
|
||||
}
|
||||
data.Protocol = match.Groups["protocol"].Value;
|
||||
if (!Global.Protocols.Contains(data.Protocol))
|
||||
{
|
||||
Logging.Info(string.Format("不支持的 SSR 协议:{0}", data.Protocol));
|
||||
return null;
|
||||
}
|
||||
|
||||
if (dict.ContainsKey("remarks"))
|
||||
{
|
||||
data.Remark = URLSafeBase64Decode(dict["remarks"]);
|
||||
}
|
||||
data.OBFS = match.Groups["obfs"].Value;
|
||||
if (data.OBFS == @"tls1.2_ticket_fastauth")
|
||||
{
|
||||
data.OBFS = @"tls1.2_ticket_auth";
|
||||
}
|
||||
if (!Global.OBFSs.Contains(data.OBFS))
|
||||
{
|
||||
Logging.Info(string.Format("不支持的 SSR 混淆:{0}", data.OBFS));
|
||||
return null;
|
||||
}
|
||||
|
||||
if (dict.ContainsKey("protoparam"))
|
||||
{
|
||||
data.ProtocolParam = URLSafeBase64Decode(dict["protoparam"]);
|
||||
}
|
||||
var info = match.Groups["info"].Value;
|
||||
var dict = new Dictionary<string, string>();
|
||||
foreach (var str in info.Split('&'))
|
||||
{
|
||||
var splited = str.Split('=');
|
||||
dict.Add(splited[0], splited[1]);
|
||||
}
|
||||
|
||||
if (dict.ContainsKey("obfsparam"))
|
||||
{
|
||||
data.OBFSParam = URLSafeBase64Decode(dict["obfsparam"]);
|
||||
}
|
||||
if (dict.ContainsKey("remarks"))
|
||||
{
|
||||
data.Remark = URLSafeBase64Decode(dict["remarks"]);
|
||||
}
|
||||
|
||||
if (Global.EncryptMethods.SS.Contains(data.EncryptMethod) && data.Protocol == "origin" && data.OBFS == "plain")
|
||||
{
|
||||
data.OBFS = "";
|
||||
data.Type = "SS";
|
||||
}
|
||||
}
|
||||
if (dict.ContainsKey("protoparam"))
|
||||
{
|
||||
data.ProtocolParam = URLSafeBase64Decode(dict["protoparam"]);
|
||||
}
|
||||
|
||||
if (dict.ContainsKey("obfsparam"))
|
||||
{
|
||||
data.OBFSParam = URLSafeBase64Decode(dict["obfsparam"]);
|
||||
}
|
||||
|
||||
if (Global.EncryptMethods.SS.Contains(data.EncryptMethod) && data.Protocol == "origin" && data.OBFS == "plain")
|
||||
{
|
||||
data.OBFS = "";
|
||||
data.Type = "SS";
|
||||
}
|
||||
list.Add(data);
|
||||
}*/
|
||||
|
||||
list.Add(data);
|
||||
}
|
||||
else if (text.StartsWith("vmess://"))
|
||||
{
|
||||
@@ -517,5 +525,123 @@ namespace Netch.Utils
|
||||
|
||||
return list;
|
||||
}
|
||||
public static string UnBase64String(string value)
|
||||
{
|
||||
if (value == null || value == "")
|
||||
{
|
||||
return "";
|
||||
}
|
||||
byte[] bytes = Convert.FromBase64String(value);
|
||||
return Encoding.UTF8.GetString(bytes);
|
||||
}
|
||||
public static string ToBase64String(string value)
|
||||
{
|
||||
if (value == null || value == "")
|
||||
{
|
||||
return "";
|
||||
}
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(value);
|
||||
return Convert.ToBase64String(bytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SSR链接解析器
|
||||
/// Copy From https://github.com/HMBSbige/ShadowsocksR-Windows/blob/d9dc8d032a6e04c14b9dc6c8f673c9cc5aa9f607/shadowsocks-csharp/Model/Server.cs#L428
|
||||
/// Thx :D
|
||||
/// </summary>
|
||||
/// <param name="ssrUrl"></param>
|
||||
/// <returns></returns>
|
||||
public static Server SsrServerFromLink(string ssrUrl)
|
||||
{
|
||||
// ssr://host:port:protocol:method:obfs:base64pass/?obfsparam=base64&remarks=base64&group=base64&udpport=0&uot=1
|
||||
var ssr = Regex.Match(ssrUrl, "ssr://([A-Za-z0-9_-]+)", RegexOptions.IgnoreCase);
|
||||
if (!ssr.Success)
|
||||
throw new FormatException();
|
||||
|
||||
var data = URLSafeBase64Decode(ssr.Groups[1].Value);
|
||||
var params_dict = new Dictionary<string, string>();
|
||||
|
||||
var param_start_pos = data.IndexOf("?", StringComparison.Ordinal);
|
||||
if (param_start_pos > 0)
|
||||
{
|
||||
params_dict = ParseParam(data.Substring(param_start_pos + 1));
|
||||
data = data.Substring(0, param_start_pos);
|
||||
}
|
||||
if (data.IndexOf("/", StringComparison.Ordinal) >= 0)
|
||||
{
|
||||
data = data.Substring(0, data.LastIndexOf("/", StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
var UrlFinder = new Regex("^(.+):([^:]+):([^:]*):([^:]+):([^:]*):([^:]+)");
|
||||
var match = UrlFinder.Match(data);
|
||||
|
||||
if (match == null || !match.Success)
|
||||
throw new FormatException();
|
||||
|
||||
var serverAddr = match.Groups[1].Value;
|
||||
var Server_Port = ushort.Parse(match.Groups[2].Value);
|
||||
var Protocol = match.Groups[3].Value.Length == 0 ? "origin" : match.Groups[3].Value;
|
||||
Protocol = Protocol.Replace("_compatible", "");
|
||||
var Method = match.Groups[4].Value;
|
||||
var obfs = match.Groups[5].Value.Length == 0 ? "plain" : match.Groups[5].Value;
|
||||
obfs = obfs.Replace("_compatible", "");
|
||||
var Password = URLSafeBase64Decode(match.Groups[6].Value);
|
||||
var ProtocolParam = "";
|
||||
var ObfsParam = "";
|
||||
var Remarks = "";
|
||||
var Group = "";
|
||||
|
||||
if (params_dict.ContainsKey("protoparam"))
|
||||
{
|
||||
ProtocolParam = URLSafeBase64Decode(params_dict["protoparam"]);
|
||||
}
|
||||
if (params_dict.ContainsKey("obfsparam"))
|
||||
{
|
||||
ObfsParam = URLSafeBase64Decode(params_dict["obfsparam"]);
|
||||
}
|
||||
if (params_dict.ContainsKey("remarks"))
|
||||
{
|
||||
Remarks = URLSafeBase64Decode(params_dict["remarks"]);
|
||||
}
|
||||
Group = params_dict.ContainsKey("group") ? URLSafeBase64Decode(params_dict["group"]) : string.Empty;
|
||||
|
||||
/*if (params_dict.ContainsKey("uot"))
|
||||
{
|
||||
UdpOverTcp = int.Parse(params_dict["uot"]) != 0;
|
||||
}
|
||||
if (params_dict.ContainsKey("udpport"))
|
||||
{
|
||||
Server_Udp_Port = ushort.Parse(params_dict["udpport"]);
|
||||
}*/
|
||||
Server server = new Server();
|
||||
server.Type = "SSR";
|
||||
server.Hostname = serverAddr;
|
||||
server.Port = Server_Port;
|
||||
server.Protocol = Protocol;
|
||||
server.EncryptMethod = Method;
|
||||
server.OBFS = obfs;
|
||||
server.Password = Password;
|
||||
server.ProtocolParam = ProtocolParam;
|
||||
server.OBFSParam = ObfsParam;
|
||||
server.Remark = Remarks;
|
||||
server.Group = Group;
|
||||
return server;
|
||||
}
|
||||
private static Dictionary<string, string> ParseParam(string paramStr)
|
||||
{
|
||||
var paramsDict = new Dictionary<string, string>();
|
||||
var obfsParams = paramStr.Split('&');
|
||||
foreach (var p in obfsParams)
|
||||
{
|
||||
if (p.IndexOf('=') > 0)
|
||||
{
|
||||
var index = p.IndexOf('=');
|
||||
var key = p.Substring(0, index);
|
||||
var val = p.Substring(index + 1);
|
||||
paramsDict[key] = val;
|
||||
}
|
||||
}
|
||||
return paramsDict;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
3
NetchLib/.gitignore
vendored
Normal file
3
NetchLib/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
/bin
|
||||
/obj
|
||||
/NetchLib.csproj.user
|
||||
67
NetchLib/NetchLib.csproj
Normal file
67
NetchLib/NetchLib.csproj
Normal file
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Platforms>x86;x64</Platforms>
|
||||
<ProjectGuid>{A8715AF4-ACC6-43F9-9381-4294C5360623}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>NetchLib</RootNamespace>
|
||||
<AssemblyName>NetchLib</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<WarningsAsErrors />
|
||||
<NoWarn />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'">
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<NoWarn />
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<WarningsAsErrors />
|
||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<NoWarn />
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<WarningsAsErrors />
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<NoWarn />
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<WarningsAsErrors />
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SearchComboBox.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
36
NetchLib/Properties/AssemblyInfo.cs
Normal file
36
NetchLib/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
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("NetchLib")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("NetchLib")]
|
||||
[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("a8715af4-acc6-43f9-9381-4294c5360623")]
|
||||
|
||||
// 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,6 +1,6 @@
|
||||
# Netch
|
||||
[](https://t.me/Netch)
|
||||
|
||||
[](https://t.me/Netch) [](https://t.me/Netch_Discuss_Group) 
|
||||
|
||||
Game accelerator
|
||||
|
||||
[简体中文](docs/README.zh-CN.md) (此版本内容更丰富)
|
||||
@@ -24,8 +24,8 @@ As well, Netch avoid the restricted NAT problem caused by SSTap. You can use an
|
||||
|
||||
[](https://nyancat.info)
|
||||
|
||||
NyanCAT Network,全中转高质量节点,多条低倍率节点保证流量无忧,节点极低延迟涵盖五大洲。Netflix 视频党,游戏党,海外回国党必备,无需年付,月付 19 元起
|
||||
[Telegram 群组](https://t.me/NyanCaaaat)
|
||||
NyanCAT Network,全中转高质量节点,多条低倍率节点保证流量无忧,节点极低延迟涵盖五大洲。Netflix 视频党,游戏党,海外回国党必备,无需年付,月付 19 元起。[测速图](https://t.me/BGP2020/935)
|
||||
[加入 Telegram 群组](https://t.me/NyanCaaaat)
|
||||
|
||||
[](https://www.mansora.net/cart.php)
|
||||
|
||||
|
||||
2
binaries
2
binaries
Submodule binaries updated: ab7f65c101...a26274a834
69
build.ps1
Normal file
69
build.ps1
Normal file
@@ -0,0 +1,69 @@
|
||||
# REM The reason we don't use dotnet build is that dotnet build doesn't support COM references yet https://github.com/microsoft/msbuild/issues/3986
|
||||
param([string]$buildtfm = 'all')
|
||||
|
||||
Write-Host 'dotnet SDK version'
|
||||
dotnet --version
|
||||
|
||||
$exe = 'Netch.exe'
|
||||
$mainDir = (Get-Item -Path ".\").FullName
|
||||
$net_baseoutput = "$mainDir\Netch\bin\$configuration"
|
||||
|
||||
Write-Host $mainDir
|
||||
Write-Host $net_baseoutput
|
||||
|
||||
function Build-NetFrameworkx64
|
||||
{
|
||||
Write-Host 'Building .NET Framework x64'
|
||||
|
||||
$outdir = "$net_baseoutput\x64"
|
||||
|
||||
msbuild -v:m -m -t:Build /p:Configuration="Release" /p:Platform="x64" /p:TargetFramework=net48 /p:Runtimeidentifier=win-x64 /restore
|
||||
if ($LASTEXITCODE) { cd $mainDir ; exit $LASTEXITCODE }
|
||||
|
||||
Write-Host 'Build x64 Complete ,Started Copy bin,mode,i18n file'
|
||||
|
||||
Copy-Item "$mainDir\binaries\x64\*" "$net_baseoutput\x64\Release\win-x64\bin"
|
||||
Copy-Item "$mainDir\binaries\x64\tap-driver" "$net_baseoutput\x64\Release\win-x64\bin\tap-driver" -recurse
|
||||
Copy-Item "$mainDir\binaries\*.acl" "$net_baseoutput\x64\Release\win-x64\bin"
|
||||
Copy-Item "$mainDir\binaries\*.conf" "$net_baseoutput\x64\Release\win-x64\bin"
|
||||
Copy-Item "$mainDir\binaries\*.dat" "$net_baseoutput\x64\Release\win-x64\bin"
|
||||
Copy-Item "$mainDir\binaries\*.exe" "$net_baseoutput\x64\Release\win-x64\bin"
|
||||
Move-Item "$net_baseoutput\x64\Release\win-x64\bin\nfapinet.dll" "$net_baseoutput\x64\Release\win-x64\nfapinet.dll"
|
||||
Copy-Item "$mainDir\translations\i18n" "$net_baseoutput\x64\Release\win-x64\i18n" -recurse
|
||||
mkdir "$net_baseoutput\x64\Release\win-x64\mode"
|
||||
Copy-Item "$mainDir\modes\mode\*.txt" "$net_baseoutput\x64\Release\win-x64\mode"
|
||||
|
||||
Write-Host 'x64 ALL DONE'
|
||||
|
||||
}
|
||||
function Build-NetFrameworkx86
|
||||
{
|
||||
Write-Host 'Building .NET Framework x86'
|
||||
|
||||
$outdir = "$net_baseoutput\x86"
|
||||
|
||||
msbuild -v:m -m -t:Build /p:Configuration="Release" /p:Platform="x86" /p:TargetFramework=net48 /p:Runtimeidentifier=win-x86 /restore
|
||||
if ($LASTEXITCODE) { cd $mainDir ; exit $LASTEXITCODE }
|
||||
|
||||
Write-Host 'Build x86 Complete ,Started Copy bin,mode,i18n file'
|
||||
|
||||
Copy-Item "$mainDir\binaries\x86\*" "$net_baseoutput\x86\Release\win-x86\bin"
|
||||
Copy-Item "$mainDir\binaries\x86\tap-driver" "$net_baseoutput\x86\Release\win-x86\bin\tap-driver" -recurse
|
||||
Copy-Item "$mainDir\binaries\*.acl" "$net_baseoutput\x86\Release\win-x86\bin"
|
||||
Copy-Item "$mainDir\binaries\*.conf" "$net_baseoutput\x86\Release\win-x86\bin"
|
||||
Copy-Item "$mainDir\binaries\*.dat" "$net_baseoutput\x86\Release\win-x86\bin"
|
||||
Copy-Item "$mainDir\binaries\*.exe" "$net_baseoutput\x86\Release\win-x86\bin"
|
||||
Move-Item "$net_baseoutput\x86\Release\win-x86\bin\nfapinet.dll" "$net_baseoutput\x86\Release\win-x86\nfapinet.dll"
|
||||
Copy-Item "$mainDir\translations\i18n" "$net_baseoutput\x86\Release\win-x86\i18n" -recurse
|
||||
mkdir "$net_baseoutput\x86\Release\win-x86\mode"
|
||||
Copy-Item "$mainDir\modes\mode\*.txt" "$net_baseoutput\x86\Release\win-x86\mode"
|
||||
|
||||
Write-Host 'x86 ALL DONE'
|
||||
}
|
||||
|
||||
cd $mainDir\Netch
|
||||
|
||||
Build-NetFrameworkx64
|
||||
Build-NetFrameworkx86
|
||||
|
||||
cd $mainDir
|
||||
@@ -25,8 +25,8 @@ Netch 是一款 Windows 平台的开源游戏加速工具,Netch 可以实现
|
||||
|
||||
[](https://nyancat.info)
|
||||
|
||||
NyanCAT Network,全中转高质量节点,多条低倍率节点保证流量无忧,节点极低延迟涵盖五大洲。Netflix 视频党,游戏党,海外回国党必备,无需年付,月付 19 元起
|
||||
[Telegram 群组](https://t.me/NyanCaaaat)
|
||||
NyanCAT Network,全中转高质量节点,多条低倍率节点保证流量无忧,节点极低延迟涵盖五大洲。Netflix 视频党,游戏党,海外回国党必备,无需年付,月付 19 元起。[测速图](https://t.me/BGP2020/935)
|
||||
[加入 Telegram 群组](https://t.me/NyanCaaaat)
|
||||
|
||||
[](https://www.mansora.net/cart.php)
|
||||
|
||||
|
||||
2
modes
2
modes
Submodule modes updated: 9b3ce74bd6...de2c3c7cf1
Reference in New Issue
Block a user