mirror of
https://github.com/netchx/netch.git
synced 2026-05-11 23:45:06 +08:00
Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1eebb61d04 | ||
|
|
a2a66675c2 | ||
|
|
850393ab71 | ||
|
|
ea0dd3cd4a | ||
|
|
c2afc1b014 | ||
|
|
7b9d9a6d57 | ||
|
|
860482402a | ||
|
|
a58f7c7b98 | ||
|
|
6afc5e5e4d | ||
|
|
98a5e91dd2 | ||
|
|
9581a41007 | ||
|
|
d85b478868 | ||
|
|
628dd6963a | ||
|
|
5ae6f73062 | ||
|
|
50b07ebabb | ||
|
|
21f2f8da5e | ||
|
|
cfc070b1ef | ||
|
|
a4f024df69 | ||
|
|
6754268714 | ||
|
|
642cd57b71 | ||
|
|
39ea679298 | ||
|
|
1091486877 | ||
|
|
d805a4fccd | ||
|
|
902f78b563 | ||
|
|
159fbdd58d | ||
|
|
0c5464f833 | ||
|
|
b019362f5f | ||
|
|
241371c6f7 | ||
|
|
9b3f5f456f | ||
|
|
c04b8f6ffd | ||
|
|
9d6b6d15d7 | ||
|
|
39081c0a6f | ||
|
|
812fab6322 | ||
|
|
bfadb181c4 | ||
|
|
52ac05ee17 | ||
|
|
c774122fdb | ||
|
|
8e223faa71 | ||
|
|
7b0f0f35cc | ||
|
|
89ce721d4c | ||
|
|
2247a75269 | ||
|
|
c1e9856e92 | ||
|
|
41e74e0794 | ||
|
|
6f8214951a | ||
|
|
0fc5b77004 | ||
|
|
34cbcbfb0f | ||
|
|
1ad4a08a85 | ||
|
|
8e0bc8e260 | ||
|
|
bae9ecfe88 | ||
|
|
3ca3e45ce2 | ||
|
|
bcb220bc4b | ||
|
|
c50eb32828 | ||
|
|
b96f171b47 | ||
|
|
4fbbd1dbd4 | ||
|
|
2ad394dfde | ||
|
|
421b35a797 | ||
|
|
25612df086 | ||
|
|
4ac5065ce4 | ||
|
|
d4b97a99e0 | ||
|
|
3d49fe0338 |
4
.github/ISSUE_TEMPLATE/bug_report.md
vendored
4
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -2,15 +2,13 @@
|
|||||||
name: 'Bug report'
|
name: 'Bug report'
|
||||||
about: 'Create a report to help us improve'
|
about: 'Create a report to help us improve'
|
||||||
title: ''
|
title: ''
|
||||||
labels: 'Status: Review Needed'
|
labels: '需要核实'
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Make sure you have read the readme, searched and read the issues related to yours. Otherwise it will be considered as a duplicate which will be closed immediately.**
|
**Make sure you have read the readme, searched and read the issues related to yours. Otherwise it will be considered as a duplicate which will be closed immediately.**
|
||||||
|
|
||||||
**All issues about `bin/Redirector.exe` should be discussed at [issue #152](https://github.com/NetchX/Netch/issues/152).**
|
|
||||||
|
|
||||||
**Describe the bug**
|
**Describe the bug**
|
||||||
A clear and concise description of what the bug is.
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
|||||||
4
.github/ISSUE_TEMPLATE/bug_report.zh-CN.md
vendored
4
.github/ISSUE_TEMPLATE/bug_report.zh-CN.md
vendored
@@ -2,15 +2,13 @@
|
|||||||
name: '错误报告'
|
name: '错误报告'
|
||||||
about: '创建错误报告以帮助我们改进'
|
about: '创建错误报告以帮助我们改进'
|
||||||
title: ''
|
title: ''
|
||||||
labels: 'Status: Review Needed'
|
labels: '需要核实'
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**确保你已经看过 readme,也搜索并阅读过和你遇到的情况相关的问题。否则会被认为是重复的并被立刻关闭。**
|
**确保你已经看过 readme,也搜索并阅读过和你遇到的情况相关的问题。否则会被认为是重复的并被立刻关闭。**
|
||||||
|
|
||||||
**所有关于 `bin/Redirector.exe` 的问题,请在 [issue #152](https://github.com/NetchX/Netch/issues/152) 中讨论**
|
|
||||||
|
|
||||||
**错误描述**
|
**错误描述**
|
||||||
对错误的清晰简洁描述
|
对错误的清晰简洁描述
|
||||||
|
|
||||||
|
|||||||
43
.github/workflows/build.yml
vendored
43
.github/workflows/build.yml
vendored
@@ -14,26 +14,32 @@ jobs:
|
|||||||
submodules: true
|
submodules: true
|
||||||
|
|
||||||
- name: Build Solution
|
- name: Build Solution
|
||||||
|
shell: pwsh
|
||||||
|
run: .\BUILD.ps1
|
||||||
|
|
||||||
|
- name: Upload Artifact
|
||||||
|
continue-on-error: true
|
||||||
|
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: Netch
|
||||||
|
path: Netch\bin\x64\Release
|
||||||
|
|
||||||
|
- name: Package
|
||||||
|
if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') }}
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: |
|
run: |
|
||||||
.\BUILD.ps1
|
|
||||||
New-Item -ItemType Directory -Path C:\builtfiles -Force > $null
|
New-Item -ItemType Directory -Path C:\builtfiles -Force > $null
|
||||||
7z a -mx9 C:\builtfiles\Netch.7z .\Netch\bin\x64\Release\
|
7z a -mx9 C:\builtfiles\Netch.7z .\Netch\bin\x64\Release\
|
||||||
7z rn C:\builtfiles\Netch.7z Release Netch
|
7z rn C:\builtfiles\Netch.7z Release Netch
|
||||||
echo "Netch_SHA256=$(.\GetSHA256.ps1 C:\builtfiles\Netch.7z)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
echo "Netch_SHA256=$(.\GetSHA256.ps1 C:\builtfiles\Netch.7z)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||||
echo "Netch_EXE_SHA256=$(.\GetSHA256.ps1 Netch\bin\x64\Release\Netch.exe)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
echo "Netch_EXE_SHA256=$(.\GetSHA256.ps1 Netch\bin\x64\Release\Netch.exe)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||||
|
|
||||||
- name: Upload Artifact
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: Netch
|
|
||||||
path: Netch\bin\x64\Release
|
|
||||||
|
|
||||||
- name: Release
|
- name: Release
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') }}
|
||||||
with:
|
with:
|
||||||
name: ${{ env.GITHUB_TAG_NAME }}
|
name: ${{ env.GITHUB_TAG_NAME }}
|
||||||
prerelease: true
|
prerelease: true
|
||||||
@@ -49,23 +55,4 @@ jobs:
|
|||||||
## 校验和
|
## 校验和
|
||||||
| 文件名 | SHA256 |
|
| 文件名 | SHA256 |
|
||||||
| :- | :- |
|
| :- | :- |
|
||||||
| Netch.7z | ${{ env.Netch_SHA256 }} |
|
| Netch.7z | ${{ env.Netch_SHA256 }} |
|
||||||
|
|
||||||
# Deploy:
|
|
||||||
# needs: [build]
|
|
||||||
# runs-on: ubuntu-latest
|
|
||||||
# steps:
|
|
||||||
# - name: Download Artifacts
|
|
||||||
# uses: actions/download-artifact@v1
|
|
||||||
# with:
|
|
||||||
# name: Netch
|
|
||||||
|
|
||||||
# - name: Pushes to another repository
|
|
||||||
# uses: peaceiris/actions-gh-pages@v3
|
|
||||||
# with:
|
|
||||||
# personal_token: ${{ secrets.ACCESS_TOKEN }}
|
|
||||||
# publish_branch: repo
|
|
||||||
# publish_dir: ./Netch
|
|
||||||
# external_repository: ${{ github.repository_owner }}/NetchReleases
|
|
||||||
# user_name: 'github-actions[bot]'
|
|
||||||
# user_email: 'github-actions[bot]@users.noreply.github.com'
|
|
||||||
13
Netch.sln
13
Netch.sln
@@ -5,11 +5,11 @@ VisualStudioVersion = 16.0.29009.5
|
|||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "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
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetchLib", "NetchLib\NetchLib.csproj", "{A8715AF4-ACC6-43F9-9381-4294C5360623}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetchLib", "NetchLib\NetchLib.csproj", "{A8715AF4-ACC6-43F9-9381-4294C5360623}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetchUpdater", "NetchUpdater\NetchUpdater.csproj", "{828318A8-9B90-4A5F-BD6B-E632CC9D8933}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetchUpdater", "NetchUpdater\NetchUpdater.csproj", "{828318A8-9B90-4A5F-BD6B-E632CC9D8933}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{53397641-35CA-4336-8E22-2CE12EF476AC}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "Test\Test.csproj", "{53397641-35CA-4336-8E22-2CE12EF476AC}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@@ -29,10 +29,9 @@ Global
|
|||||||
{828318A8-9B90-4A5F-BD6B-E632CC9D8933}.Debug|x64.Build.0 = Debug|x64
|
{828318A8-9B90-4A5F-BD6B-E632CC9D8933}.Debug|x64.Build.0 = Debug|x64
|
||||||
{828318A8-9B90-4A5F-BD6B-E632CC9D8933}.Release|x64.ActiveCfg = Release|x64
|
{828318A8-9B90-4A5F-BD6B-E632CC9D8933}.Release|x64.ActiveCfg = Release|x64
|
||||||
{828318A8-9B90-4A5F-BD6B-E632CC9D8933}.Release|x64.Build.0 = Release|x64
|
{828318A8-9B90-4A5F-BD6B-E632CC9D8933}.Release|x64.Build.0 = Release|x64
|
||||||
{53397641-35CA-4336-8E22-2CE12EF476AC}.Debug|x64.ActiveCfg = Debug|Any CPU
|
{53397641-35CA-4336-8E22-2CE12EF476AC}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{53397641-35CA-4336-8E22-2CE12EF476AC}.Debug|x64.Build.0 = Debug|Any CPU
|
{53397641-35CA-4336-8E22-2CE12EF476AC}.Debug|x64.Build.0 = Debug|x64
|
||||||
{53397641-35CA-4336-8E22-2CE12EF476AC}.Release|x64.ActiveCfg = Release|Any CPU
|
{53397641-35CA-4336-8E22-2CE12EF476AC}.Release|x64.ActiveCfg = Release|x64
|
||||||
{53397641-35CA-4336-8E22-2CE12EF476AC}.Release|x64.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ namespace Netch.Controllers
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public bool Start()
|
public bool Start()
|
||||||
{
|
{
|
||||||
if (!aiodns_dial(Encoding.UTF8.GetBytes(Path.GetFullPath("bin\\china_site_list")),
|
if (!aiodns_dial(Encoding.UTF8.GetBytes(Path.GetFullPath(Global.Settings.AioDNS.RulePath)),
|
||||||
Encoding.UTF8.GetBytes("223.5.5.5:53"),
|
Encoding.UTF8.GetBytes($"{Global.Settings.AioDNS.ChinaDNS}:53"),
|
||||||
Encoding.UTF8.GetBytes("1.1.1.1:53"))
|
Encoding.UTF8.GetBytes($"{Global.Settings.AioDNS.OtherDNS}:53"))
|
||||||
)
|
)
|
||||||
return false;
|
return false;
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
@@ -31,7 +31,10 @@ namespace Netch.Controllers
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
pPrivoxyController.Start(MainController.ServerController.Server, mode);
|
if (pPrivoxyController.Start(MainController.ServerController.Server, mode))
|
||||||
|
{
|
||||||
|
Global.Job.AddProcess(pPrivoxyController.Instance);
|
||||||
|
}
|
||||||
|
|
||||||
if (mode.Type == 3) NativeMethods.SetGlobal($"127.0.0.1:{Global.Settings.HTTPLocalPort}", IEProxyExceptions);
|
if (mode.Type == 3) NativeMethods.SetGlobal($"127.0.0.1:{Global.Settings.HTTPLocalPort}", IEProxyExceptions);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -69,6 +69,8 @@ namespace Netch.Controllers
|
|||||||
throw new StartFailedException();
|
throw new StartFailedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StatusPortInfoText.UpdateShareLan();
|
||||||
|
|
||||||
if (!await StartMode(server, mode))
|
if (!await StartMode(server, mode))
|
||||||
{
|
{
|
||||||
throw new StartFailedException();
|
throw new StartFailedException();
|
||||||
@@ -122,8 +124,23 @@ namespace Netch.Controllers
|
|||||||
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", controller.Name));
|
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", controller.Name));
|
||||||
if (controller.Start(in server, mode))
|
if (controller.Start(in server, mode))
|
||||||
{
|
{
|
||||||
UsingPorts.Add(StatusPortInfoText.Socks5Port = controller.Socks5LocalPort());
|
if (controller is Guard guard)
|
||||||
StatusPortInfoText.ShareLan = controller.LocalAddress == "0.0.0.0";
|
{
|
||||||
|
if (guard.Instance != null)
|
||||||
|
{
|
||||||
|
Global.Job.AddProcess(guard.Instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (server is Socks5 socks5)
|
||||||
|
{
|
||||||
|
if (socks5.Auth() && !mode.SupportSocks5Auth)
|
||||||
|
UsingPorts.Add(StatusPortInfoText.Socks5Port = controller.Socks5LocalPort());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UsingPorts.Add(StatusPortInfoText.Socks5Port = controller.Socks5LocalPort());
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -134,19 +151,33 @@ namespace Netch.Controllers
|
|||||||
private static async Task<bool> StartMode(Server server, Mode mode)
|
private static async Task<bool> StartMode(Server server, Mode mode)
|
||||||
{
|
{
|
||||||
ModeController = ModeHelper.GetModeControllerByType(mode.Type, out var port, out var portName, out var portType);
|
ModeController = ModeHelper.GetModeControllerByType(mode.Type, out var port, out var portName, out var portType);
|
||||||
|
|
||||||
|
if (ModeController == null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (port != null)
|
if (port != null)
|
||||||
{
|
{
|
||||||
PortCheckAndShowMessageBox((ushort) port, portName, portType);
|
PortCheckAndShowMessageBox((ushort) port, portName, portType);
|
||||||
UsingPorts.Add((ushort) port);
|
UsingPorts.Add((ushort) port);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ModeController != null)
|
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ModeController.Name));
|
||||||
|
if (await Task.Run(() => ModeController.Start(mode)))
|
||||||
{
|
{
|
||||||
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ModeController.Name));
|
if (ModeController is Guard guard)
|
||||||
return await Task.Run(() => ModeController.Start(mode));
|
{
|
||||||
|
if (guard.Instance != null)
|
||||||
|
{
|
||||||
|
Global.Job.AddProcess(guard.Instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using System.IO;
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.ServiceProcess;
|
using System.ServiceProcess;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Netch.Forms;
|
|
||||||
using Netch.Models;
|
using Netch.Models;
|
||||||
using Netch.Servers.Socks5;
|
using Netch.Servers.Socks5;
|
||||||
using Netch.Utils;
|
using Netch.Utils;
|
||||||
@@ -47,23 +46,10 @@ namespace Netch.Controllers
|
|||||||
|
|
||||||
public bool Start(in Mode mode)
|
public bool Start(in Mode mode)
|
||||||
{
|
{
|
||||||
var binFileVersion = Utils.Utils.GetFileVersion(BinDriver);
|
if (!CheckDriver())
|
||||||
var systemFileVersion = Utils.Utils.GetFileVersion(SystemDriver);
|
return false;
|
||||||
|
|
||||||
Logging.Info("内置驱动版本: " + binFileVersion);
|
#region aio_dial
|
||||||
Logging.Info("系统驱动版本: " + systemFileVersion);
|
|
||||||
|
|
||||||
if (!systemFileVersion.Equals(binFileVersion))
|
|
||||||
{
|
|
||||||
if (File.Exists(SystemDriver))
|
|
||||||
{
|
|
||||||
Logging.Info("更新驱动");
|
|
||||||
UninstallDriver();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!InstallDriver())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
aio_dial((int) NameList.TYPE_FILTERLOOPBACK, "false");
|
aio_dial((int) NameList.TYPE_FILTERLOOPBACK, "false");
|
||||||
aio_dial((int) NameList.TYPE_FILTERTCP, "true");
|
aio_dial((int) NameList.TYPE_FILTERTCP, "true");
|
||||||
@@ -74,16 +60,80 @@ namespace Netch.Controllers
|
|||||||
|
|
||||||
SetName(mode);
|
SetName(mode);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
if (Global.Settings.ModifySystemDNS)
|
if (Global.Settings.ModifySystemDNS)
|
||||||
{
|
{
|
||||||
// 备份并替换系统 DNS
|
// 备份并替换系统 DNS
|
||||||
_sysDns = DNS.OutboundDNS;
|
_sysDns = DNS.OutboundDNS;
|
||||||
DNS.OutboundDNS = "1.1.1.1,8.8.8.8";
|
if (string.IsNullOrWhiteSpace(Global.Settings.ModifiedDNS))
|
||||||
|
Global.Settings.ModifiedDNS = "1.1.1.1,8.8.8.8";
|
||||||
|
DNS.OutboundDNS = Global.Settings.ModifiedDNS;
|
||||||
}
|
}
|
||||||
|
|
||||||
return aio_init();
|
return aio_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool CheckDriver()
|
||||||
|
{
|
||||||
|
var binFileVersion = Utils.Utils.GetFileVersion(BinDriver);
|
||||||
|
var systemFileVersion = Utils.Utils.GetFileVersion(SystemDriver);
|
||||||
|
|
||||||
|
Logging.Info("内置驱动版本: " + binFileVersion);
|
||||||
|
Logging.Info("系统驱动版本: " + systemFileVersion);
|
||||||
|
|
||||||
|
if (!File.Exists(BinDriver))
|
||||||
|
{
|
||||||
|
Logging.Warning("内置驱动不存在");
|
||||||
|
if (File.Exists(SystemDriver))
|
||||||
|
{
|
||||||
|
Logging.Warning("使用系统驱动");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logging.Error("未安装驱动");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!File.Exists(SystemDriver))
|
||||||
|
{
|
||||||
|
return InstallDriver();
|
||||||
|
}
|
||||||
|
|
||||||
|
var updateFlag = false;
|
||||||
|
|
||||||
|
if (Version.TryParse(binFileVersion, out var binResult) && Version.TryParse(systemFileVersion, out var systemResult))
|
||||||
|
{
|
||||||
|
if (binResult.CompareTo(systemResult) > 0)
|
||||||
|
{
|
||||||
|
// Bin greater than Installed
|
||||||
|
updateFlag = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Installed greater than Bin
|
||||||
|
if (systemResult.Major != binResult.Major)
|
||||||
|
{
|
||||||
|
// API breaking changes
|
||||||
|
updateFlag = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!systemFileVersion.Equals(binFileVersion))
|
||||||
|
{
|
||||||
|
updateFlag = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!updateFlag) return true;
|
||||||
|
|
||||||
|
Logging.Info("更新驱动");
|
||||||
|
UninstallDriver();
|
||||||
|
return InstallDriver();
|
||||||
|
}
|
||||||
|
|
||||||
private void SetServer(in IServerController controller, in PortType portType)
|
private void SetServer(in IServerController controller, in PortType portType)
|
||||||
{
|
{
|
||||||
if (portType == PortType.Both)
|
if (portType == PortType.Both)
|
||||||
|
|||||||
@@ -68,12 +68,14 @@ namespace Netch.Controllers
|
|||||||
|
|
||||||
SetupRouteTable();
|
SetupRouteTable();
|
||||||
|
|
||||||
|
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", Name));
|
||||||
|
|
||||||
string dns;
|
string dns;
|
||||||
if (Global.Settings.TUNTAP.UseCustomDNS)
|
if (Global.Settings.TUNTAP.UseCustomDNS)
|
||||||
{
|
{
|
||||||
if (Global.Settings.TUNTAP.DNS.Any())
|
if (Global.Settings.TUNTAP.DNS.Any())
|
||||||
{
|
{
|
||||||
dns = Global.Settings.TUNTAP.DNS.Aggregate((current, ip) => $"{current},{ip}");
|
dns = DNS.Join(Global.Settings.TUNTAP.DNS);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -226,33 +228,11 @@ namespace Netch.Controllers
|
|||||||
|
|
||||||
public bool TestFakeDNS()
|
public bool TestFakeDNS()
|
||||||
{
|
{
|
||||||
var exited = false;
|
|
||||||
var helpStr = new StringBuilder();
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
|
|
||||||
{
|
|
||||||
if (e.Data == null)
|
|
||||||
{
|
|
||||||
exited = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
helpStr.Append(e.Data);
|
|
||||||
}
|
|
||||||
|
|
||||||
InitInstance("-h");
|
InitInstance("-h");
|
||||||
// Instance.OutputDataReceived += OnOutputDataReceived;
|
|
||||||
Instance.ErrorDataReceived += OnOutputDataReceived;
|
|
||||||
Instance.Start();
|
Instance.Start();
|
||||||
Instance.BeginOutputReadLine();
|
return Instance.StandardError.ReadToEnd().Contains("-fakeDns");
|
||||||
Instance.BeginErrorReadLine();
|
|
||||||
while (!exited)
|
|
||||||
{
|
|
||||||
Thread.Sleep(200);
|
|
||||||
}
|
|
||||||
|
|
||||||
return helpStr.ToString().Contains("-fakeDns");
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace Netch.Controllers
|
|||||||
public const string Name = @"Netch";
|
public const string Name = @"Netch";
|
||||||
public const string Copyright = @"Copyright © 2019 - 2020";
|
public const string Copyright = @"Copyright © 2019 - 2020";
|
||||||
|
|
||||||
public const string AssemblyVersion = @"1.6.4";
|
public const string AssemblyVersion = @"1.6.7";
|
||||||
private const string Suffix = @"";
|
private const string Suffix = @"";
|
||||||
|
|
||||||
public static readonly string Version = $"{AssemblyVersion}{(string.IsNullOrEmpty(Suffix) ? "" : $"-{Suffix}")}";
|
public static readonly string Version = $"{AssemblyVersion}{(string.IsNullOrEmpty(Suffix) ? "" : $"-{Suffix}")}";
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
@@ -26,8 +27,9 @@ namespace Netch.Forms
|
|||||||
var texts = Clipboard.GetText();
|
var texts = Clipboard.GetText();
|
||||||
if (!string.IsNullOrWhiteSpace(texts))
|
if (!string.IsNullOrWhiteSpace(texts))
|
||||||
{
|
{
|
||||||
Global.Settings.Server.AddRange(ShareLink.ParseText(texts));
|
var servers = ShareLink.ParseText(texts);
|
||||||
NotifyTip(i18N.TranslateFormat("Import {0} server(s) form Clipboard", ShareLink.ParseText(texts).Count));
|
Global.Settings.Server.AddRange(servers);
|
||||||
|
NotifyTip(i18N.TranslateFormat("Import {0} server(s) form Clipboard", servers.Count));
|
||||||
|
|
||||||
InitServer();
|
InitServer();
|
||||||
Configuration.Save();
|
Configuration.Save();
|
||||||
@@ -98,9 +100,7 @@ namespace Netch.Forms
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private readonly object _serverLock = new object();
|
private async Task UpdateServersFromSubscribe()
|
||||||
|
|
||||||
public async Task UpdateServersFromSubscribe()
|
|
||||||
{
|
{
|
||||||
void DisableItems(bool v)
|
void DisableItems(bool v)
|
||||||
{
|
{
|
||||||
@@ -124,9 +124,11 @@ namespace Netch.Forms
|
|||||||
|
|
||||||
StatusText(i18N.Translate("Starting update subscription"));
|
StatusText(i18N.Translate("Starting update subscription"));
|
||||||
DisableItems(false);
|
DisableItems(false);
|
||||||
|
var useProxyToUpdateSubscription = Global.Settings.UseProxyToUpdateSubscription;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (Global.Settings.UseProxyToUpdateSubscription)
|
string proxyServer = null;
|
||||||
|
if (useProxyToUpdateSubscription)
|
||||||
{
|
{
|
||||||
var mode = new Models.Mode
|
var mode = new Models.Mode
|
||||||
{
|
{
|
||||||
@@ -134,40 +136,10 @@ namespace Netch.Forms
|
|||||||
Type = 5
|
Type = 5
|
||||||
};
|
};
|
||||||
await MainController.Start(ServerComboBox.SelectedItem as Server, mode);
|
await MainController.Start(ServerComboBox.SelectedItem as Server, mode);
|
||||||
|
proxyServer = $"http://127.0.0.1:{Global.Settings.HTTPLocalPort}";
|
||||||
}
|
}
|
||||||
|
|
||||||
await Task.WhenAll(Global.Settings.SubscribeLink.Select(async item => await Task.Run(async () =>
|
await Subscription.UpdateServersAsync(proxyServer);
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var request = WebUtil.CreateRequest(item.Link);
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(item.UserAgent)) request.UserAgent = item.UserAgent;
|
|
||||||
if (Global.Settings.UseProxyToUpdateSubscription)
|
|
||||||
request.Proxy = new WebProxy($"http://127.0.0.1:{Global.Settings.HTTPLocalPort}");
|
|
||||||
|
|
||||||
var servers = ShareLink.ParseText(await WebUtil.DownloadStringAsync(request));
|
|
||||||
|
|
||||||
foreach (var server in servers)
|
|
||||||
{
|
|
||||||
server.Group = item.Remark;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_serverLock)
|
|
||||||
{
|
|
||||||
Global.Settings.Server.RemoveAll(server => server.Group.Equals(item.Remark));
|
|
||||||
Global.Settings.Server.AddRange(servers);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
NotifyTip(i18N.TranslateFormat("Update {1} server(s) from {0}", item.Remark, servers.Count));
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
NotifyTip($"{i18N.TranslateFormat("Update servers error from {0}", item.Remark)}\n{e.Message}", info: false);
|
|
||||||
Logging.Error(e.ToString());
|
|
||||||
}
|
|
||||||
})).ToArray());
|
|
||||||
|
|
||||||
InitServer();
|
InitServer();
|
||||||
Configuration.Save();
|
Configuration.Save();
|
||||||
@@ -179,9 +151,16 @@ namespace Netch.Forms
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (Global.Settings.UseProxyToUpdateSubscription)
|
if (useProxyToUpdateSubscription)
|
||||||
{
|
{
|
||||||
await MainController.Stop();
|
try
|
||||||
|
{
|
||||||
|
await MainController.Stop();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DisableItems(true);
|
DisableItems(true);
|
||||||
@@ -223,7 +202,12 @@ namespace Netch.Forms
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await Task.Run(() => DNS.Cache.Clear());
|
await Task.Run(() =>
|
||||||
|
{
|
||||||
|
NativeMethods.FlushDNSResolverCache();
|
||||||
|
DNS.Cache.Clear();
|
||||||
|
});
|
||||||
|
|
||||||
StatusText(i18N.Translate("DNS cache cleanup succeeded"));
|
StatusText(i18N.Translate("DNS cache cleanup succeeded"));
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
@@ -244,19 +228,13 @@ namespace Netch.Forms
|
|||||||
|
|
||||||
private async void UpdateACL(bool useProxy)
|
private async void UpdateACL(bool useProxy)
|
||||||
{
|
{
|
||||||
void DisableItems(bool v)
|
|
||||||
{
|
|
||||||
UpdateACLToolStripMenuItem.Enabled = updateACLWithProxyToolStripMenuItem.Enabled = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (useProxy && ServerComboBox.SelectedIndex == -1)
|
if (useProxy && ServerComboBox.SelectedIndex == -1)
|
||||||
{
|
{
|
||||||
MessageBoxX.Show(i18N.Translate("Please select a server first"));
|
MessageBoxX.Show(i18N.Translate("Please select a server first"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DisableItems(false);
|
Enabled = false;
|
||||||
|
|
||||||
|
|
||||||
NotifyTip(i18N.Translate("Updating in the background"));
|
NotifyTip(i18N.Translate("Updating in the background"));
|
||||||
try
|
try
|
||||||
@@ -292,42 +270,38 @@ namespace Netch.Forms
|
|||||||
State = State.Stopped;
|
State = State.Stopped;
|
||||||
}
|
}
|
||||||
|
|
||||||
DisableItems(true);
|
Enabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void UninstallServiceToolStripMenuItem_Click(object sender, EventArgs e)
|
private async void UninstallServiceToolStripMenuItem_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
State = State.Starting;
|
Enabled = false;
|
||||||
StatusText(i18N.TranslateFormat("Uninstalling {0}", "NF Service"));
|
StatusText(i18N.TranslateFormat("Uninstalling {0}", "NF Service"));
|
||||||
var result = false;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await Task.Run(() =>
|
await Task.Run(() =>
|
||||||
{
|
{
|
||||||
if (NFController.UninstallDriver())
|
if (NFController.UninstallDriver())
|
||||||
{
|
{
|
||||||
result = true;
|
StatusText(i18N.TranslateFormat("{0} has been uninstalled", "NF Service"));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
State = State.Stopped;
|
Enabled = true;
|
||||||
if (result)
|
|
||||||
StatusText(i18N.TranslateFormat("{0} has been uninstalled", "NF Service"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void reinstallTapDriverToolStripMenuItem_Click(object sender, EventArgs e)
|
private async void reinstallTapDriverToolStripMenuItem_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
State = State.Starting;
|
|
||||||
StatusText(i18N.TranslateFormat("Uninstalling {0}", "TUN/TAP driver"));
|
StatusText(i18N.TranslateFormat("Uninstalling {0}", "TUN/TAP driver"));
|
||||||
var result = false;
|
Enabled = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await Task.Run(TUNTAP.deltapall);
|
await Task.Run(TUNTAP.deltapall);
|
||||||
result = true;
|
StatusText(i18N.TranslateFormat("{0} has been uninstalled", "TUN/TAP driver"));
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
@@ -335,9 +309,8 @@ namespace Netch.Forms
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
State = State.Stopped;
|
State = State.Waiting;
|
||||||
if (result)
|
Enabled = true;
|
||||||
StatusText(i18N.TranslateFormat("{0} has been uninstalled", "TUN/TAP driver"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using Netch.Controllers;
|
using Netch.Controllers;
|
||||||
using Netch.Utils;
|
using Netch.Utils;
|
||||||
@@ -44,15 +45,37 @@ namespace Netch.Forms
|
|||||||
if (MessageBoxX.Show(i18N.Translate("Download and install now?"), confirm: true) != DialogResult.OK)
|
if (MessageBoxX.Show(i18N.Translate("Download and install now?"), confirm: true) != DialogResult.OK)
|
||||||
return;
|
return;
|
||||||
NotifyTip(i18N.Translate("Start downloading new version"));
|
NotifyTip(i18N.Translate("Start downloading new version"));
|
||||||
|
|
||||||
|
var tagPage = await WebUtil.DownloadStringAsync(WebUtil.CreateRequest(_updater.LatestVersionUrl));
|
||||||
|
var match = Regex.Match(tagPage, @"<td .*>(?<sha256>.*)</td>", RegexOptions.Singleline);
|
||||||
|
|
||||||
|
// TODO Replace with regex get basename and sha256
|
||||||
var fileName = Path.GetFileName(new Uri(_updater.LatestVersionDownloadUrl).LocalPath);
|
var fileName = Path.GetFileName(new Uri(_updater.LatestVersionDownloadUrl).LocalPath);
|
||||||
fileName = fileName.Insert(fileName.LastIndexOf('.'), _updater.LatestVersionNumber);
|
fileName = fileName.Insert(fileName.LastIndexOf('.'), _updater.LatestVersionNumber);
|
||||||
var fileFullPath = Path.Combine(Global.NetchDir, "data", fileName);
|
var fileFullPath = Path.Combine(Global.NetchDir, "data", fileName);
|
||||||
|
|
||||||
|
var sha256 = match.Groups["sha256"].Value;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!File.Exists(fileFullPath))
|
if (File.Exists(fileFullPath))
|
||||||
{
|
{
|
||||||
await WebUtil.DownloadFileAsync(WebUtil.CreateRequest(_updater.LatestVersionDownloadUrl), fileFullPath);
|
if (Utils.Utils.SHA256CheckSum(fileFullPath) == sha256)
|
||||||
|
{
|
||||||
|
RunUpdater();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
File.Delete(fileFullPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO Replace "New Version Found" to Progress bar
|
||||||
|
await WebUtil.DownloadFileAsync(WebUtil.CreateRequest(_updater.LatestVersionDownloadUrl), fileFullPath);
|
||||||
|
|
||||||
|
if (Utils.Utils.SHA256CheckSum(fileFullPath) != sha256)
|
||||||
|
{
|
||||||
|
MessageBoxX.Show("The downloaded file has the wrong hash");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RunUpdater();
|
RunUpdater();
|
||||||
|
|||||||
@@ -79,7 +79,8 @@ namespace Netch.Forms
|
|||||||
private void LoadProfile(int index)
|
private void LoadProfile(int index)
|
||||||
{
|
{
|
||||||
var p = Global.Settings.Profiles[index];
|
var p = Global.Settings.Profiles[index];
|
||||||
ProfileNameText.Text = p.ModeRemark;
|
ProfileNameText.Text = p.ProfileName;
|
||||||
|
ModeComboBox.ResetCompletionList();
|
||||||
|
|
||||||
if (p.IsDummy)
|
if (p.IsDummy)
|
||||||
throw new Exception("Profile not found.");
|
throw new Exception("Profile not found.");
|
||||||
@@ -160,9 +161,6 @@ namespace Netch.Forms
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset Mode ComboBox Items
|
|
||||||
ModeComboBox.Text = string.Empty;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
LoadProfile(index);
|
LoadProfile(index);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Text;
|
using System.Linq;
|
||||||
using Netch.Models;
|
using Netch.Models;
|
||||||
using Netch.Utils;
|
using Netch.Utils;
|
||||||
|
|
||||||
@@ -35,10 +36,11 @@ namespace Netch.Forms
|
|||||||
|
|
||||||
// 启动需要禁用的控件
|
// 启动需要禁用的控件
|
||||||
UninstallServiceToolStripMenuItem.Enabled =
|
UninstallServiceToolStripMenuItem.Enabled =
|
||||||
updateACLWithProxyToolStripMenuItem.Enabled =
|
UpdateACLToolStripMenuItem.Enabled =
|
||||||
UpdateServersFromSubscribeLinksToolStripMenuItem.Enabled =
|
updateACLWithProxyToolStripMenuItem.Enabled =
|
||||||
UninstallTapDriverToolStripMenuItem.Enabled =
|
UpdateServersFromSubscribeLinksToolStripMenuItem.Enabled =
|
||||||
ReloadModesToolStripMenuItem.Enabled = enabled;
|
UninstallTapDriverToolStripMenuItem.Enabled =
|
||||||
|
ReloadModesToolStripMenuItem.Enabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
_state = value;
|
_state = value;
|
||||||
@@ -185,12 +187,7 @@ namespace Netch.Forms
|
|||||||
{
|
{
|
||||||
private static ushort? _socks5Port;
|
private static ushort? _socks5Port;
|
||||||
private static ushort? _httpPort;
|
private static ushort? _httpPort;
|
||||||
private static bool? _shareLan;
|
private static bool _shareLan;
|
||||||
|
|
||||||
public static bool ShareLan
|
|
||||||
{
|
|
||||||
set => _shareLan = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ushort HttpPort
|
public static ushort HttpPort
|
||||||
{
|
{
|
||||||
@@ -202,35 +199,34 @@ namespace Netch.Forms
|
|||||||
set => _socks5Port = value;
|
set => _socks5Port = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void UpdateShareLan() => _shareLan = Global.Settings.LocalAddress != "127.0.0.1";
|
||||||
|
|
||||||
public static string Value
|
public static string Value
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_socks5Port == null && _httpPort == null)
|
var strings = new List<string>();
|
||||||
return string.Empty;
|
|
||||||
|
|
||||||
var text = new StringBuilder();
|
|
||||||
if (_shareLan == true)
|
|
||||||
text.Append(i18N.Translate("Allow other Devices to connect") + " ");
|
|
||||||
|
|
||||||
if (_socks5Port != null)
|
if (_socks5Port != null)
|
||||||
text.Append($"Socks5 {i18N.Translate("Local Port", ": ")}{_socks5Port}");
|
{
|
||||||
|
strings.Add($"Socks5 {i18N.Translate("Local Port", ": ")}{_socks5Port}");
|
||||||
|
}
|
||||||
|
|
||||||
if (_httpPort != null)
|
if (_httpPort != null)
|
||||||
{
|
{
|
||||||
if (_socks5Port != null)
|
strings.Add($"HTTP {i18N.Translate("Local Port", ": ")}{_httpPort}");
|
||||||
text.Append(" | ");
|
|
||||||
text.Append($"HTTP {i18N.Translate("Local Port", ": ")}{_httpPort}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $" ({text})";
|
if (!strings.Any())
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
return $" ({(_shareLan ? i18N.Translate("Allow other Devices to connect") + " " : "")}{string.Join(" | ", strings)})";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Reset()
|
public static void Reset()
|
||||||
{
|
{
|
||||||
_httpPort = _socks5Port = null;
|
_httpPort = _socks5Port = null;
|
||||||
_shareLan = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -283,8 +283,11 @@ namespace Netch.Forms
|
|||||||
|
|
||||||
Configuration.Save();
|
Configuration.Save();
|
||||||
|
|
||||||
if (File.Exists("data\\last.json"))
|
foreach (var file in new[] {"data\\last.json", "data\\privoxy.conf"})
|
||||||
File.Delete("data\\last.json");
|
{
|
||||||
|
if (File.Exists(file))
|
||||||
|
File.Delete(file);
|
||||||
|
}
|
||||||
|
|
||||||
State = State.Terminating;
|
State = State.Terminating;
|
||||||
}
|
}
|
||||||
@@ -334,7 +337,7 @@ namespace Netch.Forms
|
|||||||
|
|
||||||
private async void SpeedPictureBox_Click(object sender, EventArgs e)
|
private async void SpeedPictureBox_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
State = State.Starting;
|
Enabled = false;
|
||||||
StatusText(i18N.Translate("Testing"));
|
StatusText(i18N.Translate("Testing"));
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -342,7 +345,7 @@ namespace Netch.Forms
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
State = State.Stopped;
|
Enabled = true;
|
||||||
StatusText(i18N.Translate("Test done"));
|
StatusText(i18N.Translate("Test done"));
|
||||||
Refresh();
|
Refresh();
|
||||||
}
|
}
|
||||||
@@ -469,7 +472,7 @@ namespace Netch.Forms
|
|||||||
Activate();
|
Activate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void NotifyTip(string text, int timeout = 0, bool info = true)
|
public void NotifyTip(string text, int timeout = 0, bool info = true)
|
||||||
{
|
{
|
||||||
// 会阻塞线程 timeout 秒
|
// 会阻塞线程 timeout 秒
|
||||||
NotifyIcon.ShowBalloonTip(timeout,
|
NotifyIcon.ShowBalloonTip(timeout,
|
||||||
|
|||||||
@@ -168,28 +168,37 @@ namespace Netch.Forms
|
|||||||
|
|
||||||
private void ControlButton_Click(object sender, EventArgs e)
|
private void ControlButton_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (_checkActions.All(pair => pair.Value.Invoke(pair.Key.Text)))
|
Utils.Utils.ComponentIterator(this, component => Utils.Utils.ChangeControlForeColor(component, Color.Black));
|
||||||
|
|
||||||
|
var flag = true;
|
||||||
|
foreach (var pair in _checkActions.Where(pair => !pair.Value.Invoke(pair.Key.Text)))
|
||||||
{
|
{
|
||||||
foreach (var pair in _saveActions)
|
Utils.Utils.ChangeControlForeColor(pair.Key, Color.Red);
|
||||||
{
|
flag = false;
|
||||||
switch (pair.Key)
|
|
||||||
{
|
|
||||||
case CheckBox c:
|
|
||||||
pair.Value.Invoke(c.Checked);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
pair.Value.Invoke(pair.Key.Text);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Global.Settings.Server.IndexOf(Server) == -1)
|
|
||||||
Global.Settings.Server.Add(Server);
|
|
||||||
|
|
||||||
MessageBoxX.Show(i18N.Translate("Saved"));
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (!flag)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var pair in _saveActions)
|
||||||
|
{
|
||||||
|
switch (pair.Key)
|
||||||
|
{
|
||||||
|
case CheckBox c:
|
||||||
|
pair.Value.Invoke(c.Checked);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pair.Value.Invoke(pair.Key.Text);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Global.Settings.Server.IndexOf(Server) == -1)
|
||||||
|
Global.Settings.Server.Add(Server);
|
||||||
|
|
||||||
|
MessageBoxX.Show(i18N.Translate("Saved"));
|
||||||
|
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|||||||
1079
Netch/Forms/SettingForm.Designer.cs
generated
1079
Netch/Forms/SettingForm.Designer.cs
generated
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,13 @@
|
|||||||
using Netch.Utils;
|
using Netch.Utils;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using TaskScheduler;
|
|
||||||
|
|
||||||
namespace Netch.Forms
|
namespace Netch.Forms
|
||||||
{
|
{
|
||||||
@@ -20,8 +21,9 @@ namespace Netch.Forms
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void SettingForm2_Load(object sender, EventArgs e)
|
private void SettingForm_Load(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
|
TUNTAPUseCustomDNSCheckBox_CheckedChanged(null, null);
|
||||||
Task.Run(() => BeginInvoke(new Action(() => UseFakeDNSCheckBox.Visible = Global.Flags.SupportFakeDns)));
|
Task.Run(() => BeginInvoke(new Action(() => UseFakeDNSCheckBox.Visible = Global.Flags.SupportFakeDns)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,17 +32,17 @@ namespace Netch.Forms
|
|||||||
#region General
|
#region General
|
||||||
|
|
||||||
BindTextBox<ushort>(Socks5PortTextBox,
|
BindTextBox<ushort>(Socks5PortTextBox,
|
||||||
p => CheckPort("Socks5", p, Global.Settings.Socks5LocalPort),
|
p => p.ToString() != HTTPPortTextBox.Text && p.ToString() != RedirectorTextBox.Text,
|
||||||
p => Global.Settings.Socks5LocalPort = p,
|
p => Global.Settings.Socks5LocalPort = p,
|
||||||
Global.Settings.Socks5LocalPort);
|
Global.Settings.Socks5LocalPort);
|
||||||
BindTextBox<ushort>(HTTPPortTextBox,
|
BindTextBox<ushort>(HTTPPortTextBox,
|
||||||
p => CheckPort("HTTP", p, Global.Settings.HTTPLocalPort),
|
p => p.ToString() != Socks5PortTextBox.Text && p.ToString() != RedirectorTextBox.Text,
|
||||||
p => Global.Settings.HTTPLocalPort = p,
|
p => Global.Settings.HTTPLocalPort = p,
|
||||||
Global.Settings.HTTPLocalPort);
|
Global.Settings.HTTPLocalPort);
|
||||||
BindTextBox<ushort>(RedirectorTextBox,
|
BindTextBox<ushort>(RedirectorTextBox,
|
||||||
s => CheckPort("RedirectorTCP", s, Global.Settings.RedirectorTCPPort),
|
p => p.ToString() != Socks5PortTextBox.Text && p.ToString() != HTTPPortTextBox.Text,
|
||||||
s => Global.Settings.RedirectorTCPPort = s,
|
p => Global.Settings.RedirectorTCPPort = p,
|
||||||
Global.Settings.HTTPLocalPort);
|
Global.Settings.RedirectorTCPPort);
|
||||||
BindCheckBox(AllowDevicesCheckBox,
|
BindCheckBox(AllowDevicesCheckBox,
|
||||||
c => Global.Settings.LocalAddress = AllowDevicesCheckBox.Checked ? "0.0.0.0" : "127.0.0.1",
|
c => Global.Settings.LocalAddress = AllowDevicesCheckBox.Checked ? "0.0.0.0" : "127.0.0.1",
|
||||||
Global.Settings.LocalAddress switch
|
Global.Settings.LocalAddress switch
|
||||||
@@ -50,7 +52,6 @@ namespace Netch.Forms
|
|||||||
_ => false
|
_ => false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
BindCheckBox(BootShadowsocksFromDLLCheckBox,
|
BindCheckBox(BootShadowsocksFromDLLCheckBox,
|
||||||
c => Global.Settings.BootShadowsocksFromDLL = c,
|
c => Global.Settings.BootShadowsocksFromDLL = c,
|
||||||
Global.Settings.BootShadowsocksFromDLL);
|
Global.Settings.BootShadowsocksFromDLL);
|
||||||
@@ -83,13 +84,19 @@ namespace Netch.Forms
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region Process Mode
|
#region Process Mode
|
||||||
|
|
||||||
BindCheckBox(ModifySystemDNSCheckBox,
|
BindCheckBox(ModifySystemDNSCheckBox,
|
||||||
b => Global.Settings.ModifySystemDNS = b,
|
b => Global.Settings.ModifySystemDNS = b,
|
||||||
Global.Settings.ModifySystemDNS);
|
Global.Settings.ModifySystemDNS);
|
||||||
|
|
||||||
|
ModifySystemDNSCheckBox_CheckedChanged(null, null);
|
||||||
|
|
||||||
|
BindTextBox(ModifiedDNSTextBox,
|
||||||
|
s => DNS.TrySplit(s, out _, 2),
|
||||||
|
s => Global.Settings.ModifiedDNS = s,
|
||||||
|
Global.Settings.ModifiedDNS);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region TUN/TAP
|
#region TUN/TAP
|
||||||
@@ -111,6 +118,11 @@ namespace Netch.Forms
|
|||||||
Global.Settings.TUNTAP.UseCustomDNS);
|
Global.Settings.TUNTAP.UseCustomDNS);
|
||||||
TUNTAPUseCustomDNSCheckBox_CheckedChanged(null, null);
|
TUNTAPUseCustomDNSCheckBox_CheckedChanged(null, null);
|
||||||
|
|
||||||
|
BindTextBox(TUNTAPDNSTextBox,
|
||||||
|
s => !UseCustomDNSCheckBox.Checked || DNS.TrySplit(s, out _, 2),
|
||||||
|
s => Global.Settings.TUNTAP.DNS = DNS.Split(s).ToList(),
|
||||||
|
DNS.Join(Global.Settings.TUNTAP.DNS));
|
||||||
|
|
||||||
BindCheckBox(ProxyDNSCheckBox,
|
BindCheckBox(ProxyDNSCheckBox,
|
||||||
b => Global.Settings.TUNTAP.ProxyDNS = b,
|
b => Global.Settings.TUNTAP.ProxyDNS = b,
|
||||||
Global.Settings.TUNTAP.ProxyDNS);
|
Global.Settings.TUNTAP.ProxyDNS);
|
||||||
@@ -139,6 +151,9 @@ namespace Netch.Forms
|
|||||||
BindCheckBox(TLSAllowInsecureCheckBox,
|
BindCheckBox(TLSAllowInsecureCheckBox,
|
||||||
b => Global.Settings.V2RayConfig.AllowInsecure = b,
|
b => Global.Settings.V2RayConfig.AllowInsecure = b,
|
||||||
Global.Settings.V2RayConfig.AllowInsecure);
|
Global.Settings.V2RayConfig.AllowInsecure);
|
||||||
|
BindCheckBox(UseMuxCheckBox,
|
||||||
|
b => Global.Settings.V2RayConfig.UseMux = b,
|
||||||
|
Global.Settings.V2RayConfig.UseMux);
|
||||||
|
|
||||||
BindTextBox<int>(mtuTextBox,
|
BindTextBox<int>(mtuTextBox,
|
||||||
i => true,
|
i => true,
|
||||||
@@ -205,6 +220,25 @@ namespace Netch.Forms
|
|||||||
Global.Settings.UpdateSubscribeatWhenOpened);
|
Global.Settings.UpdateSubscribeatWhenOpened);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region AioDNS
|
||||||
|
|
||||||
|
BindTextBox(AioDNSRulePathTextBox,
|
||||||
|
s => true,
|
||||||
|
s => Global.Settings.AioDNS.RulePath = s,
|
||||||
|
Global.Settings.AioDNS.RulePath);
|
||||||
|
|
||||||
|
BindTextBox(ChinaDNSTextBox,
|
||||||
|
s => IPAddress.TryParse(s, out _),
|
||||||
|
s => Global.Settings.AioDNS.ChinaDNS = s,
|
||||||
|
Global.Settings.AioDNS.ChinaDNS);
|
||||||
|
|
||||||
|
BindTextBox(OtherDNSTextBox,
|
||||||
|
s => IPAddress.TryParse(s, out _),
|
||||||
|
s => Global.Settings.AioDNS.OtherDNS = s,
|
||||||
|
Global.Settings.AioDNS.OtherDNS);
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TUNTAPUseCustomDNSCheckBox_CheckedChanged(object sender, EventArgs e)
|
private void TUNTAPUseCustomDNSCheckBox_CheckedChanged(object sender, EventArgs e)
|
||||||
@@ -214,12 +248,12 @@ namespace Netch.Forms
|
|||||||
if (UseCustomDNSCheckBox.Checked)
|
if (UseCustomDNSCheckBox.Checked)
|
||||||
{
|
{
|
||||||
TUNTAPDNSTextBox.Text = Global.Settings.TUNTAP.DNS.Any()
|
TUNTAPDNSTextBox.Text = Global.Settings.TUNTAP.DNS.Any()
|
||||||
? Global.Settings.TUNTAP.DNS.Aggregate((current, ip) => $"{current},{ip}")
|
? DNS.Join(Global.Settings.TUNTAP.DNS)
|
||||||
: "1.1.1.1";
|
: "1.1.1.1";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TUNTAPDNSTextBox.Text = "Local DNS";
|
TUNTAPDNSTextBox.Text = "AioDNS";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,70 +282,48 @@ namespace Netch.Forms
|
|||||||
|
|
||||||
private void ControlButton_Click(object sender, EventArgs e)
|
private void ControlButton_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (!_checkActions.All(pair => pair.Value.Invoke(pair.Key.Text)))
|
Utils.Utils.ComponentIterator(this, component => Utils.Utils.ChangeControlForeColor(component, Color.Black));
|
||||||
return;
|
|
||||||
|
|
||||||
#region Check
|
#region Check
|
||||||
|
|
||||||
#region TUNTAP
|
var flag = true;
|
||||||
|
foreach (var pair in _checkActions.Where(pair => !pair.Value.Invoke(pair.Key.Text)))
|
||||||
var dns = new string[0];
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
if (UseCustomDNSCheckBox.Checked)
|
Utils.Utils.ChangeControlForeColor(pair.Key, Color.Red);
|
||||||
{
|
flag = false;
|
||||||
dns = TUNTAPDNSTextBox.Text.Split(',').Where(s => !string.IsNullOrEmpty(s)).Select(s => s.Trim())
|
|
||||||
.ToArray();
|
|
||||||
if (dns.Any())
|
|
||||||
{
|
|
||||||
foreach (var ip in dns)
|
|
||||||
IPAddress.Parse(ip);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MessageBoxX.Show("DNS can not be empty");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
|
||||||
|
if (!flag)
|
||||||
{
|
{
|
||||||
if (exception is FormatException)
|
|
||||||
MessageBoxX.Show(i18N.Translate("IP address format illegal. Try again."));
|
|
||||||
|
|
||||||
if (UseCustomDNSCheckBox.Checked)
|
|
||||||
{
|
|
||||||
TUNTAPDNSTextBox.Text = Global.Settings.TUNTAP.DNS.Aggregate((current, ip) => $"{current},{ip}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Behavior
|
#region CheckSTUN
|
||||||
|
|
||||||
// STUN
|
var stunFlag = true;
|
||||||
string stunServer;
|
var stunServer = string.Empty;
|
||||||
int stunServerPort;
|
ushort stunServerPort = 3478;
|
||||||
try
|
|
||||||
|
var stun = STUN_ServerComboBox.Text.Split(':');
|
||||||
|
|
||||||
|
if (stun.Any())
|
||||||
{
|
{
|
||||||
var stun = STUN_ServerComboBox.Text.Split(':');
|
|
||||||
stunServer = stun[0];
|
stunServer = stun[0];
|
||||||
|
|
||||||
stunServerPort = 3478;
|
|
||||||
if (stun.Length > 1)
|
if (stun.Length > 1)
|
||||||
stunServerPort = int.Parse(stun[1]);
|
if (!ushort.TryParse(stun[1], out stunServerPort))
|
||||||
|
{
|
||||||
if (stunServerPort <= 0)
|
stunFlag = false;
|
||||||
{
|
}
|
||||||
throw new FormatException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (FormatException)
|
else
|
||||||
{
|
{
|
||||||
MessageBoxX.Show(i18N.Translate("STUN_ServerPort value illegal. Try again."));
|
stunFlag = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stunFlag)
|
||||||
|
{
|
||||||
|
Utils.Utils.ChangeControlForeColor(STUN_ServerComboBox, Color.Red);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,73 +338,19 @@ namespace Netch.Forms
|
|||||||
pair.Value.Invoke(pair.Key);
|
pair.Value.Invoke(pair.Key);
|
||||||
}
|
}
|
||||||
|
|
||||||
Global.Settings.TUNTAP.DNS = dns.ToList();
|
|
||||||
Global.Settings.STUN_Server = stunServer;
|
Global.Settings.STUN_Server = stunServer;
|
||||||
Global.Settings.STUN_Server_Port = stunServerPort;
|
Global.Settings.STUN_Server_Port = stunServerPort;
|
||||||
|
Global.Settings.Language = LanguageComboBox.Text;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Register Startup Item
|
Utils.Utils.RegisterNetchStartupItem();
|
||||||
|
|
||||||
var scheduler = new TaskSchedulerClass();
|
|
||||||
scheduler.Connect();
|
|
||||||
var folder = scheduler.GetFolder("\\");
|
|
||||||
|
|
||||||
var taskIsExists = false;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
folder.GetTask("Netch Startup");
|
|
||||||
taskIsExists = true;
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Global.Settings.RunAtStartup)
|
|
||||||
{
|
|
||||||
if (taskIsExists)
|
|
||||||
folder.DeleteTask("Netch Startup", 0);
|
|
||||||
|
|
||||||
var task = scheduler.NewTask(0);
|
|
||||||
task.RegistrationInfo.Author = "Netch";
|
|
||||||
task.RegistrationInfo.Description = "Netch run at startup.";
|
|
||||||
task.Principal.RunLevel = _TASK_RUNLEVEL.TASK_RUNLEVEL_HIGHEST;
|
|
||||||
|
|
||||||
task.Triggers.Create(_TASK_TRIGGER_TYPE2.TASK_TRIGGER_LOGON);
|
|
||||||
var action = (IExecAction) task.Actions.Create(_TASK_ACTION_TYPE.TASK_ACTION_EXEC);
|
|
||||||
action.Path = Application.ExecutablePath;
|
|
||||||
|
|
||||||
|
|
||||||
task.Settings.ExecutionTimeLimit = "PT0S";
|
|
||||||
task.Settings.DisallowStartIfOnBatteries = false;
|
|
||||||
task.Settings.RunOnlyIfIdle = false;
|
|
||||||
|
|
||||||
folder.RegisterTaskDefinition("Netch Startup", task, (int) _TASK_CREATION.TASK_CREATE, null, null,
|
|
||||||
_TASK_LOGON_TYPE.TASK_LOGON_INTERACTIVE_TOKEN, "");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (taskIsExists)
|
|
||||||
folder.DeleteTask("Netch Startup", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
Configuration.Save();
|
Configuration.Save();
|
||||||
MessageBoxX.Show(i18N.Translate("Saved"));
|
MessageBoxX.Show(i18N.Translate("Saved"));
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool CheckPort(string portName, ushort port, ushort originPort, PortType portType = PortType.Both)
|
|
||||||
{
|
|
||||||
if (port == originPort) return true;
|
|
||||||
if (!PortHelper.PortInUse(port, portType)) return true;
|
|
||||||
|
|
||||||
MessageBoxX.Show(i18N.TranslateFormat("The {0} port is in use.", portName));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void ICSCheckBox_CheckedChanged(object sender, EventArgs e)
|
private async void ICSCheckBox_CheckedChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -454,5 +412,10 @@ namespace Netch.Forms
|
|||||||
private readonly Dictionary<Control, Func<string, bool>> _checkActions = new Dictionary<Control, Func<string, bool>>();
|
private readonly Dictionary<Control, Func<string, bool>> _checkActions = new Dictionary<Control, Func<string, bool>>();
|
||||||
|
|
||||||
private readonly Dictionary<Control, Action<Control>> _saveActions = new Dictionary<Control, Action<Control>>();
|
private readonly Dictionary<Control, Action<Control>> _saveActions = new Dictionary<Control, Action<Control>>();
|
||||||
|
|
||||||
|
private void ModifySystemDNSCheckBox_CheckedChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
ModifiedDNSTextBox.Enabled = ModifySystemDNSCheckBox.Checked;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,64 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<root>
|
||||||
<root>
|
|
||||||
<!--
|
|
||||||
Microsoft ResX Schema
|
|
||||||
|
|
||||||
Version 2.0
|
|
||||||
|
|
||||||
The primary goals of this format is to allow a simple XML format
|
|
||||||
that is mostly human readable. The generation and parsing of the
|
|
||||||
various data types are done through the TypeConverter classes
|
|
||||||
associated with the data types.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
... ado.net/XML headers & schema ...
|
|
||||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
|
||||||
<resheader name="version">2.0</resheader>
|
|
||||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
|
||||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
|
||||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
|
||||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
|
||||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
|
||||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
|
||||||
</data>
|
|
||||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
|
||||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
|
||||||
<comment>This is a comment</comment>
|
|
||||||
</data>
|
|
||||||
|
|
||||||
There are any number of "resheader" rows that contain simple
|
|
||||||
name/value pairs.
|
|
||||||
|
|
||||||
Each data row contains a name, and value. The row also contains a
|
|
||||||
type or mimetype. Type corresponds to a .NET class that support
|
|
||||||
text/value conversion through the TypeConverter architecture.
|
|
||||||
Classes that don't support this are serialized and stored with the
|
|
||||||
mimetype set.
|
|
||||||
|
|
||||||
The mimetype is used for serialized objects, and tells the
|
|
||||||
ResXResourceReader how to depersist the object. This is currently not
|
|
||||||
extensible. For a given mimetype the value must be set accordingly:
|
|
||||||
|
|
||||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
|
||||||
that the ResXResourceWriter will generate, however the reader can
|
|
||||||
read any of the formats listed below.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.binary.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.soap.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
|
||||||
value : The object must be serialized into a byte array
|
|
||||||
: using a System.ComponentModel.TypeConverter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
-->
|
|
||||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
<xsd:element name="root" msdata:IsDataSet="true">
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
@@ -117,8 +57,8 @@
|
|||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
<assembly alias="System.Drawing.Common" name="System.Drawing.Common, Version=5.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" />
|
||||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing.Common" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
AAABAAMAAAAAAAEAIAAoIAQANgAAAEBAAAABACAAKEIAAF4gBAAgIAAAAQAgAKgQAACGYgQAKAAAAAAB
|
AAABAAMAAAAAAAEAIAAoIAQANgAAAEBAAAABACAAKEIAAF4gBAAgIAAAAQAgAKgQAACGYgQAKAAAAAAB
|
||||||
AAAAAgAAAQAgAAAAAAAAIAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAAAAgAAAQAgAAAAAAAAIAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
|||||||
@@ -109,14 +109,14 @@ namespace Netch.Forms
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Global.Settings.SubscribeLink.Any(link => link.Remark.Equals(RemarkTextBox.Text)))
|
|
||||||
{
|
|
||||||
MessageBoxX.Show("Remark Name Duplicate!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_editingIndex == -1)
|
if (_editingIndex == -1)
|
||||||
{
|
{
|
||||||
|
if (Global.Settings.SubscribeLink.Any(link => link.Remark.Equals(RemarkTextBox.Text)))
|
||||||
|
{
|
||||||
|
MessageBoxX.Show("Remark Name Duplicate!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Global.Settings.SubscribeLink.Add(new SubscribeLink
|
Global.Settings.SubscribeLink.Add(new SubscribeLink
|
||||||
{
|
{
|
||||||
Remark = RemarkTextBox.Text,
|
Remark = RemarkTextBox.Text,
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
using System;
|
using Netch.Controllers;
|
||||||
|
using Netch.Forms;
|
||||||
|
using Netch.Models;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using Netch.Controllers;
|
using WindowsJobAPI;
|
||||||
using Netch.Forms;
|
|
||||||
using Netch.Models;
|
|
||||||
|
|
||||||
namespace Netch
|
namespace Netch
|
||||||
{
|
{
|
||||||
@@ -87,5 +87,10 @@ namespace Netch
|
|||||||
/// 用于存储模式
|
/// 用于存储模式
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly List<Mode> Modes = new List<Mode>();
|
public static readonly List<Mode> Modes = new List<Mode>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Windows Job API
|
||||||
|
/// </summary>
|
||||||
|
public static readonly JobObject Job = new JobObject();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,30 +131,30 @@ namespace Netch.Models
|
|||||||
/// <returns>模式文件字符串</returns>
|
/// <returns>模式文件字符串</returns>
|
||||||
public string ToFileString()
|
public string ToFileString()
|
||||||
{
|
{
|
||||||
string fileString;
|
StringBuilder fileString = new StringBuilder();
|
||||||
|
|
||||||
switch (Type)
|
switch (Type)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
// 进程模式
|
// 进程模式
|
||||||
fileString = $"# {Remark}";
|
fileString.Append($"# {Remark}");
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
// TUN/TAP 规则内 IP CIDR,无 Bypass China 设置
|
// TUN/TAP 规则内 IP CIDR,无 Bypass China 设置
|
||||||
fileString = $"# {Remark}, {Type}, 0";
|
fileString.Append($"# {Remark}, {Type}, 0");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fileString = $"# {Remark}, {Type}, {(BypassChina ? 1 : 0)}";
|
fileString.Append($"# {Remark}, {Type}, {(BypassChina ? 1 : 0)}");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
fileString += Global.EOF;
|
if (Rule.Any())
|
||||||
|
{
|
||||||
|
fileString.Append(Global.EOF);
|
||||||
|
fileString.Append(string.Join(Global.EOF, Rule));
|
||||||
|
}
|
||||||
|
|
||||||
fileString = Rule.Aggregate(fileString, (current, item) => $"{current}{item}{Global.EOF}");
|
return fileString.ToString();
|
||||||
// 去除最后的行尾符
|
|
||||||
fileString = fileString.Substring(0, fileString.Length - 2);
|
|
||||||
|
|
||||||
return fileString;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string TypeToString()
|
public string TypeToString()
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using Netch.Utils;
|
|||||||
|
|
||||||
namespace Netch.Models
|
namespace Netch.Models
|
||||||
{
|
{
|
||||||
public class Server
|
public class Server:ICloneable
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 备注
|
/// 备注
|
||||||
@@ -57,6 +57,11 @@ namespace Netch.Models
|
|||||||
return $"[{ServerHelper.GetUtilByTypeName(Type)?.ShortName ?? "WTF"}][{Group}] {Remark}";
|
return $"[{ServerHelper.GetUtilByTypeName(Type)?.ShortName ?? "WTF"}][{Group}] {Remark}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public object Clone()
|
||||||
|
{
|
||||||
|
return MemberwiseClone();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 测试延迟
|
/// 测试延迟
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Netch.Models
|
namespace Netch.Models
|
||||||
{
|
{
|
||||||
@@ -65,6 +67,17 @@ namespace Netch.Models
|
|||||||
public bool AllowInsecure = true;
|
public bool AllowInsecure = true;
|
||||||
|
|
||||||
public KcpConfig KcpConfig = new KcpConfig();
|
public KcpConfig KcpConfig = new KcpConfig();
|
||||||
|
|
||||||
|
public bool UseMux = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AioDNSConfig
|
||||||
|
{
|
||||||
|
public string RulePath = "bin\\china_site_list";
|
||||||
|
|
||||||
|
public string ChinaDNS = "223.5.5.5";
|
||||||
|
|
||||||
|
public string OtherDNS = "1.1.1.1";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -127,6 +140,11 @@ namespace Netch.Models
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool ModifySystemDNS = false;
|
public bool ModifySystemDNS = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 要修改为的系统 DNS
|
||||||
|
/// </summary>
|
||||||
|
public string ModifiedDNS = "1.1.1.1,8.8.8.8";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 解析服务器主机名
|
/// 解析服务器主机名
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -233,5 +251,7 @@ namespace Netch.Models
|
|||||||
public string Language = "System";
|
public string Language = "System";
|
||||||
|
|
||||||
public V2rayConfig V2RayConfig = new V2rayConfig();
|
public V2rayConfig V2RayConfig = new V2rayConfig();
|
||||||
|
|
||||||
|
public AioDNSConfig AioDNS = new AioDNSConfig();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,11 +67,12 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ILMerge" Version="3.0.41" />
|
<PackageReference Include="ILMerge" Version="3.0.41" />
|
||||||
<PackageReference Include="MaxMind.GeoIP2" Version="3.3.0" />
|
<PackageReference Include="MaxMind.GeoIP2" Version="3.3.0" />
|
||||||
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="2.0.61" />
|
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="2.0.62" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
<PackageReference Include="System.Collections.Immutable" Version="5.0.0-rc.2.20475.5" />
|
<PackageReference Include="System.Collections.Immutable" Version="5.0.0" />
|
||||||
<PackageReference Include="System.Reflection.Metadata" Version="5.0.0-rc.2.20475.5" />
|
<PackageReference Include="System.Reflection.Metadata" Version="5.0.0" />
|
||||||
<PackageReference Include="WindowsAPICodePack-Shell" Version="1.1.1" />
|
<PackageReference Include="WindowsAPICodePack-Shell" Version="1.1.1" />
|
||||||
|
<PackageReference Include="WindowsJobAPI" Version="5.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -16,13 +16,15 @@ namespace Netch.Servers.Shadowsocks
|
|||||||
public string LocalAddress { get; set; }
|
public string LocalAddress { get; set; }
|
||||||
|
|
||||||
private Mode _savedMode;
|
private Mode _savedMode;
|
||||||
public bool DllFlag => Global.Settings.BootShadowsocksFromDLL && (_savedMode.Type == 0 || _savedMode.Type == 1 || _savedMode.Type == 2);
|
public bool DllFlag;
|
||||||
|
|
||||||
public bool Start(in Server s, in Mode mode)
|
public bool Start(in Server s, in Mode mode)
|
||||||
{
|
{
|
||||||
_savedMode = mode;
|
_savedMode = mode;
|
||||||
Server = s;
|
Server = s;
|
||||||
var server = (Shadowsocks) s;
|
var server = (Shadowsocks) s;
|
||||||
|
DllFlag = Global.Settings.BootShadowsocksFromDLL && (_savedMode.Type == 0 || _savedMode.Type == 1 || _savedMode.Type == 2);
|
||||||
|
|
||||||
//从DLL启动Shaowsocks
|
//从DLL启动Shaowsocks
|
||||||
if (DllFlag)
|
if (DllFlag)
|
||||||
{
|
{
|
||||||
@@ -76,14 +78,13 @@ namespace Netch.Servers.Shadowsocks
|
|||||||
|
|
||||||
public override void Stop()
|
public override void Stop()
|
||||||
{
|
{
|
||||||
if (Instance == null)
|
if (DllFlag)
|
||||||
ShadowsocksDLL.Stop();
|
ShadowsocksDLL.Stop();
|
||||||
else
|
else
|
||||||
StopInstance();
|
StopInstance();
|
||||||
_savedMode = null;
|
_savedMode = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class ShadowsocksDLL
|
private class ShadowsocksDLL
|
||||||
{
|
{
|
||||||
[DllImport("shadowsocks-windows-dynamic", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("shadowsocks-windows-dynamic", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ namespace Netch.Servers.Trojan
|
|||||||
{
|
{
|
||||||
local_addr = this.LocalAddress(),
|
local_addr = this.LocalAddress(),
|
||||||
local_port = this.Socks5LocalPort(),
|
local_port = this.Socks5LocalPort(),
|
||||||
remote_addr = server.AutoResolveHostname(),
|
remote_addr = server.Hostname,
|
||||||
remote_port = server.Port,
|
remote_port = server.Port,
|
||||||
password = new List<string>
|
password = new List<string>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ namespace Netch.Servers.VLESS
|
|||||||
|
|
||||||
public class VLESSGlobal
|
public class VLESSGlobal
|
||||||
{
|
{
|
||||||
|
|
||||||
public static List<string> TransferProtocols => VMessGlobal.TransferProtocols;
|
public static List<string> TransferProtocols => VMessGlobal.TransferProtocols;
|
||||||
|
|
||||||
public static readonly List<string> FakeTypes = new List<string>
|
public static readonly List<string> FakeTypes = new List<string>
|
||||||
@@ -42,5 +41,12 @@ namespace Netch.Servers.VLESS
|
|||||||
"none",
|
"none",
|
||||||
"http"
|
"http"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static readonly List<string> TLSSecure = new List<string>
|
||||||
|
{
|
||||||
|
"",
|
||||||
|
"tls",
|
||||||
|
"xtls"
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -39,22 +39,20 @@ namespace Netch.Servers.VLESS.VLESSForm
|
|||||||
s => true,
|
s => true,
|
||||||
s => server.Path = s,
|
s => server.Path = s,
|
||||||
server.Path);
|
server.Path);
|
||||||
CreateComboBox("TLSSecure", "TLS Secure",
|
CreateComboBox("UseMux", "Use Mux",
|
||||||
new List<string> {"", "true", "false"},
|
new List<string> {"", "true", "false"},
|
||||||
s =>
|
s => server.UseMux = s switch
|
||||||
{
|
{
|
||||||
server.TLSSecure = s switch
|
"" => null,
|
||||||
{
|
"true" => true,
|
||||||
"" => null,
|
"false" => false,
|
||||||
"true" => true,
|
_ => null
|
||||||
"false" => false,
|
|
||||||
_ => null
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
server.TLSSecure?.ToString() ?? string.Empty);
|
server.UseMux?.ToString().ToLower() ?? "");
|
||||||
CreateCheckBox("UseMux", "Use Mux",
|
CreateComboBox("TLSSecure", "TLS Secure",
|
||||||
b => server.UseMux = b,
|
VLESSGlobal.TLSSecure,
|
||||||
server.UseMux);
|
s => server.TLSSecureType = s,
|
||||||
|
server.TLSSecureType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15,7 +15,24 @@ namespace Netch.Servers.VLESS
|
|||||||
|
|
||||||
public Server ParseJObject(in JObject j)
|
public Server ParseJObject(in JObject j)
|
||||||
{
|
{
|
||||||
return j.ToObject<VLESS>();
|
var server = j.ToObject<VLESS>();
|
||||||
|
if (server == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (server.TLSSecure != null)
|
||||||
|
{
|
||||||
|
if ((bool) server.TLSSecure)
|
||||||
|
{
|
||||||
|
server.TLSSecureType = "tls";
|
||||||
|
server.TLSSecure = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
server.TLSSecure = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return server;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Edit(Server s)
|
public void Edit(Server s)
|
||||||
|
|||||||
@@ -48,22 +48,20 @@ namespace Netch.Servers.VMess.Form
|
|||||||
s => true,
|
s => true,
|
||||||
s => server.QUICSecret = s,
|
s => server.QUICSecret = s,
|
||||||
server.QUICSecret);
|
server.QUICSecret);
|
||||||
CreateComboBox("TLSSecure", "TLS Secure",
|
CreateComboBox("UseMux", "Use Mux",
|
||||||
new List<string> {"", "true", "false"},
|
new List<string> {"", "true", "false"},
|
||||||
s =>
|
s => server.UseMux = s switch
|
||||||
{
|
{
|
||||||
server.TLSSecure = s switch
|
"" => null,
|
||||||
{
|
"true" => true,
|
||||||
"" => null,
|
"false" => false,
|
||||||
"true" => true,
|
_ => null
|
||||||
"false" => false,
|
|
||||||
_ => null
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
server.TLSSecure?.ToString() ?? string.Empty);
|
server.UseMux?.ToString().ToLower() ?? "");
|
||||||
CreateCheckBox("UseMux", "Use Mux",
|
CreateComboBox("TLSSecure", "TLS Secure",
|
||||||
s => server.UseMux = s,
|
VMessGlobal.TLSSecure,
|
||||||
server.UseMux);
|
s => server.TLSSecureType = s,
|
||||||
|
server.TLSSecureType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Netch.Models;
|
using Netch.Models;
|
||||||
using Netch.Servers.VMess.Models;
|
using Netch.Servers.VMess.Models;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
@@ -18,9 +19,9 @@ namespace Netch.Servers.VMess.Utils
|
|||||||
|
|
||||||
routing(server, mode, ref v2rayConfig);
|
routing(server, mode, ref v2rayConfig);
|
||||||
|
|
||||||
outbound(server, ref v2rayConfig);
|
outbound(server, mode, ref v2rayConfig);
|
||||||
|
|
||||||
return JsonConvert.SerializeObject(v2rayConfig);
|
return JsonConvert.SerializeObject(v2rayConfig, Formatting.Indented, new JsonSerializerSettings {NullValueHandling = NullValueHandling.Ignore});
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@@ -58,44 +59,68 @@ namespace Netch.Servers.VMess.Utils
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
RulesItem rulesItem;
|
var directRuleObject = new RulesItem
|
||||||
|
{
|
||||||
|
type = "field",
|
||||||
|
ip = new List<string>(),
|
||||||
|
domain = new List<string>(),
|
||||||
|
outboundTag = "direct"
|
||||||
|
};
|
||||||
|
|
||||||
|
var blockRuleObject = new RulesItem
|
||||||
|
{
|
||||||
|
type = "field",
|
||||||
|
ip = new List<string>(),
|
||||||
|
domain = new List<string>(),
|
||||||
|
outboundTag = "block"
|
||||||
|
};
|
||||||
|
|
||||||
if (mode.BypassChina)
|
if (mode.BypassChina)
|
||||||
{
|
{
|
||||||
rulesItem = new RulesItem
|
if (mode.Type > 2)
|
||||||
{
|
{
|
||||||
type = "field",
|
directRuleObject.domain.Add("geosite:cn");
|
||||||
ip = new List<string>
|
}
|
||||||
{
|
|
||||||
"geoip:cn",
|
if (mode.Type == 1 || mode.Type == 2)
|
||||||
"geoip:private"
|
{
|
||||||
},
|
if (Global.Flags.SupportFakeDns && Global.Settings.TUNTAP.UseFakeDNS)
|
||||||
domain = new List<string>
|
directRuleObject.domain.Add("geosite:cn");
|
||||||
{
|
else
|
||||||
"geosite:cn"
|
directRuleObject.ip.Add("geoip:cn");
|
||||||
},
|
}
|
||||||
outboundTag = "direct"
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (mode.Type <= 2)
|
||||||
{
|
{
|
||||||
rulesItem = new RulesItem
|
blockRuleObject.ip.Add("geoip:private");
|
||||||
{
|
|
||||||
type = "field",
|
|
||||||
ip = new List<string>
|
|
||||||
{
|
|
||||||
"geoip:private"
|
|
||||||
},
|
|
||||||
outboundTag = "direct"
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
v2rayConfig.routing = new Routing
|
v2rayConfig.routing = new Routing
|
||||||
{
|
{
|
||||||
rules = new List<RulesItem>
|
rules = new List<RulesItem>()
|
||||||
{
|
|
||||||
rulesItem
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool CheckRuleItem(ref RulesItem rulesItem)
|
||||||
|
{
|
||||||
|
bool ipResult, domainResult;
|
||||||
|
if (!(ipResult = rulesItem.ip.Any()))
|
||||||
|
{
|
||||||
|
rulesItem.ip = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(domainResult = rulesItem.domain.Any()))
|
||||||
|
{
|
||||||
|
rulesItem.domain = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ipResult || domainResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CheckRuleItem(ref directRuleObject))
|
||||||
|
v2rayConfig.routing.rules.Add(directRuleObject);
|
||||||
|
if (CheckRuleItem(ref blockRuleObject))
|
||||||
|
v2rayConfig.routing.rules.Add(blockRuleObject);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@@ -103,7 +128,7 @@ namespace Netch.Servers.VMess.Utils
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void outbound(Server server, ref V2rayConfig v2rayConfig)
|
private static void outbound(Server server, Mode mode, ref V2rayConfig v2rayConfig)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -121,31 +146,25 @@ namespace Netch.Servers.VMess.Utils
|
|||||||
{
|
{
|
||||||
case Socks5.Socks5 socks5:
|
case Socks5.Socks5 socks5:
|
||||||
{
|
{
|
||||||
var serversItem = new ServersItem
|
|
||||||
{
|
|
||||||
users = new List<SocksUsersItem>()
|
|
||||||
};
|
|
||||||
outbound.settings.servers = new List<ServersItem>
|
outbound.settings.servers = new List<ServersItem>
|
||||||
{
|
{
|
||||||
serversItem
|
new ServersItem
|
||||||
};
|
|
||||||
|
|
||||||
serversItem.address = server.AutoResolveHostname();
|
|
||||||
serversItem.port = server.Port;
|
|
||||||
serversItem.method = null;
|
|
||||||
serversItem.password = null;
|
|
||||||
|
|
||||||
if (socks5.Auth())
|
|
||||||
{
|
|
||||||
var socksUsersItem = new SocksUsersItem
|
|
||||||
{
|
{
|
||||||
user = socks5.Username,
|
users = socks5.Auth()
|
||||||
pass = socks5.Password,
|
? new List<SocksUsersItem>
|
||||||
level = 1
|
{
|
||||||
};
|
new SocksUsersItem
|
||||||
|
{
|
||||||
serversItem.users.Add(socksUsersItem);
|
user = socks5.Username,
|
||||||
}
|
pass = socks5.Password,
|
||||||
|
level = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
address = server.AutoResolveHostname(),
|
||||||
|
port = server.Port
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
outbound.mux.enabled = false;
|
outbound.mux.enabled = false;
|
||||||
outbound.mux.concurrency = -1;
|
outbound.mux.concurrency = -1;
|
||||||
@@ -156,37 +175,36 @@ namespace Netch.Servers.VMess.Utils
|
|||||||
{
|
{
|
||||||
var vnextItem = new VnextItem
|
var vnextItem = new VnextItem
|
||||||
{
|
{
|
||||||
users = new List<UsersItem>()
|
users = new List<UsersItem>(),
|
||||||
|
address = server.AutoResolveHostname(),
|
||||||
|
port = server.Port
|
||||||
};
|
};
|
||||||
outbound.settings.vnext = new List<VnextItem>
|
outbound.settings.vnext = new List<VnextItem> {vnextItem};
|
||||||
|
|
||||||
|
var usersItem = new UsersItem
|
||||||
{
|
{
|
||||||
vnextItem
|
id = vless.UserID,
|
||||||
|
alterId = 0,
|
||||||
|
flow = string.Empty,
|
||||||
|
encryption = vless.EncryptMethod
|
||||||
};
|
};
|
||||||
|
|
||||||
vnextItem.address = server.AutoResolveHostname();
|
|
||||||
vnextItem.port = server.Port;
|
|
||||||
|
|
||||||
var usersItem = new UsersItem();
|
|
||||||
vnextItem.users.Add(usersItem);
|
vnextItem.users.Add(usersItem);
|
||||||
|
|
||||||
usersItem.id = vless.UserID;
|
|
||||||
usersItem.alterId = 0;
|
|
||||||
usersItem.flow = string.Empty;
|
|
||||||
usersItem.encryption = vless.EncryptMethod;
|
|
||||||
|
|
||||||
outbound.mux.enabled = vless.UseMux;
|
|
||||||
outbound.mux.concurrency = vless.UseMux ? 8 : -1;
|
|
||||||
|
|
||||||
var streamSettings = outbound.streamSettings;
|
var streamSettings = outbound.streamSettings;
|
||||||
boundStreamSettings(vless, ref streamSettings);
|
boundStreamSettings(vless, ref streamSettings);
|
||||||
|
|
||||||
if (vless.TransferProtocol == "xtls")
|
if (vless.TLSSecureType == "xtls")
|
||||||
{
|
{
|
||||||
usersItem.flow = string.IsNullOrEmpty(vless.Flow) ? "xtls-rprx-origin" : vless.Flow;
|
usersItem.flow = string.IsNullOrEmpty(vless.Flow) ? "xtls-rprx-origin" : vless.Flow;
|
||||||
|
|
||||||
outbound.mux.enabled = false;
|
outbound.mux.enabled = false;
|
||||||
outbound.mux.concurrency = -1;
|
outbound.mux.concurrency = -1;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outbound.mux.enabled = vless.UseMux ?? Global.Settings.V2RayConfig.UseMux;
|
||||||
|
outbound.mux.concurrency = vless.UseMux ?? Global.Settings.V2RayConfig.UseMux ? 8 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
outbound.protocol = "vless";
|
outbound.protocol = "vless";
|
||||||
outbound.settings.servers = null;
|
outbound.settings.servers = null;
|
||||||
@@ -196,35 +214,42 @@ namespace Netch.Servers.VMess.Utils
|
|||||||
{
|
{
|
||||||
var vnextItem = new VnextItem
|
var vnextItem = new VnextItem
|
||||||
{
|
{
|
||||||
users = new List<UsersItem>()
|
users = new List<UsersItem>(),
|
||||||
|
address = server.AutoResolveHostname(),
|
||||||
|
port = server.Port
|
||||||
};
|
};
|
||||||
outbound.settings.vnext = new List<VnextItem>
|
outbound.settings.vnext = new List<VnextItem> {vnextItem};
|
||||||
|
|
||||||
|
var usersItem = new UsersItem
|
||||||
{
|
{
|
||||||
vnextItem
|
id = vmess.UserID,
|
||||||
|
alterId = vmess.AlterID,
|
||||||
|
security = vmess.EncryptMethod
|
||||||
};
|
};
|
||||||
|
|
||||||
vnextItem.address = server.AutoResolveHostname();
|
|
||||||
vnextItem.port = server.Port;
|
|
||||||
|
|
||||||
var usersItem = new UsersItem();
|
|
||||||
vnextItem.users.Add(usersItem);
|
vnextItem.users.Add(usersItem);
|
||||||
|
|
||||||
usersItem.id = vmess.UserID;
|
|
||||||
usersItem.alterId = vmess.AlterID;
|
|
||||||
usersItem.security = vmess.EncryptMethod;
|
|
||||||
|
|
||||||
outbound.mux.enabled = vmess.UseMux;
|
|
||||||
outbound.mux.concurrency = vmess.UseMux ? 8 : -1;
|
|
||||||
|
|
||||||
var streamSettings = outbound.streamSettings;
|
var streamSettings = outbound.streamSettings;
|
||||||
boundStreamSettings(vmess, ref streamSettings);
|
boundStreamSettings(vmess, ref streamSettings);
|
||||||
|
|
||||||
|
outbound.mux.enabled = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux;
|
||||||
|
outbound.mux.concurrency = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux ? 8 : -1;
|
||||||
outbound.protocol = "vmess";
|
outbound.protocol = "vmess";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v2rayConfig.outbounds = new List<Outbounds> {outbound};
|
v2rayConfig.outbounds = new List<Outbounds>
|
||||||
|
{
|
||||||
|
outbound,
|
||||||
|
new Outbounds
|
||||||
|
{
|
||||||
|
tag = "direct", protocol = "freedom"
|
||||||
|
},
|
||||||
|
new Outbounds
|
||||||
|
{
|
||||||
|
tag = "block", protocol = "blackhole"
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@@ -237,25 +262,24 @@ namespace Netch.Servers.VMess.Utils
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
streamSettings.network = server.TransferProtocol;
|
streamSettings.network = server.TransferProtocol;
|
||||||
var host = server.Host;
|
|
||||||
if (server.TLSSecure ?? Global.Settings.V2RayConfig.AllowInsecure)
|
|
||||||
{
|
|
||||||
streamSettings.security = "tls";
|
|
||||||
|
|
||||||
|
if ((streamSettings.security = server.TLSSecureType) != "")
|
||||||
|
{
|
||||||
var tlsSettings = new TlsSettings
|
var tlsSettings = new TlsSettings
|
||||||
{
|
{
|
||||||
allowInsecure = true
|
allowInsecure = Global.Settings.V2RayConfig.AllowInsecure,
|
||||||
|
serverName = !string.IsNullOrWhiteSpace(server.Host) ? server.Host : null
|
||||||
};
|
};
|
||||||
if (!string.IsNullOrWhiteSpace(host))
|
|
||||||
{
|
|
||||||
tlsSettings.serverName = host;
|
|
||||||
}
|
|
||||||
|
|
||||||
streamSettings.tlsSettings = tlsSettings;
|
switch (server.TLSSecureType)
|
||||||
}
|
{
|
||||||
else
|
case "tls":
|
||||||
{
|
streamSettings.tlsSettings = tlsSettings;
|
||||||
streamSettings.security = "";
|
break;
|
||||||
|
case "xtls":
|
||||||
|
streamSettings.xtlsSettings = tlsSettings;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (server.TransferProtocol)
|
switch (server.TransferProtocol)
|
||||||
@@ -277,21 +301,16 @@ namespace Netch.Servers.VMess.Utils
|
|||||||
seed = !string.IsNullOrWhiteSpace(server.Path) ? server.Path : null
|
seed = !string.IsNullOrWhiteSpace(server.Path) ? server.Path : null
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
streamSettings.kcpSettings = kcpSettings;
|
streamSettings.kcpSettings = kcpSettings;
|
||||||
break;
|
break;
|
||||||
case "ws":
|
case "ws":
|
||||||
var path = server.Path;
|
|
||||||
var wsSettings = new WsSettings
|
var wsSettings = new WsSettings
|
||||||
{
|
{
|
||||||
connectionReuse = true,
|
connectionReuse = true,
|
||||||
headers = !string.IsNullOrWhiteSpace(host)
|
headers = !string.IsNullOrWhiteSpace(server.Host)
|
||||||
? new Headers
|
? new Headers {Host = server.Host}
|
||||||
{
|
|
||||||
Host = host
|
|
||||||
}
|
|
||||||
: null,
|
: null,
|
||||||
path = !string.IsNullOrWhiteSpace(path) ? path : null
|
path = !string.IsNullOrWhiteSpace(server.Path) ? server.Path : null
|
||||||
};
|
};
|
||||||
|
|
||||||
streamSettings.wsSettings = wsSettings;
|
streamSettings.wsSettings = wsSettings;
|
||||||
@@ -311,34 +330,22 @@ namespace Netch.Servers.VMess.Utils
|
|||||||
case "quic":
|
case "quic":
|
||||||
var quicSettings = new QuicSettings
|
var quicSettings = new QuicSettings
|
||||||
{
|
{
|
||||||
security = host,
|
security = server.Host,
|
||||||
key = server.Path,
|
key = server.Path,
|
||||||
header = new Header
|
header = new Header
|
||||||
{
|
{
|
||||||
type = server.FakeType
|
type = server.FakeType
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (server.TLSSecure ?? Global.Settings.V2RayConfig.AllowInsecure)
|
|
||||||
|
if (server.TLSSecureType != "")
|
||||||
{
|
{
|
||||||
|
// tls or xtls
|
||||||
streamSettings.tlsSettings.serverName = server.Hostname;
|
streamSettings.tlsSettings.serverName = server.Hostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
streamSettings.quicSettings = quicSettings;
|
streamSettings.quicSettings = quicSettings;
|
||||||
break;
|
break;
|
||||||
case "xtls":
|
|
||||||
streamSettings.security = server.TransferProtocol;
|
|
||||||
|
|
||||||
var xtlsSettings = new TlsSettings
|
|
||||||
{
|
|
||||||
allowInsecure = true
|
|
||||||
};
|
|
||||||
if (!string.IsNullOrWhiteSpace(host))
|
|
||||||
{
|
|
||||||
xtlsSettings.serverName = host;
|
|
||||||
}
|
|
||||||
|
|
||||||
streamSettings.xtlsSettings = xtlsSettings;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
if (server.FakeType == "http")
|
if (server.FakeType == "http")
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Netch.Models;
|
using Netch.Models;
|
||||||
|
|
||||||
@@ -64,12 +65,18 @@ namespace Netch.Servers.VMess
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// TLS 底层传输安全
|
/// TLS 底层传输安全
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Obsolete]
|
||||||
public bool? TLSSecure { get; set; }
|
public bool? TLSSecure { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TLS 底层传输安全
|
||||||
|
/// </summary>
|
||||||
|
public string TLSSecureType { get; set; } = VMessGlobal.TLSSecure[0];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Mux 多路复用
|
/// Mux 多路复用
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool UseMux { get; set; } = true;
|
public bool? UseMux { get; set; } = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class VMessGlobal
|
public class VMessGlobal
|
||||||
@@ -114,5 +121,14 @@ namespace Netch.Servers.VMess
|
|||||||
"dtls",
|
"dtls",
|
||||||
"wireguard"
|
"wireguard"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TLS 安全类型
|
||||||
|
/// </summary>
|
||||||
|
public static readonly List<string> TLSSecure = new List<string>
|
||||||
|
{
|
||||||
|
"",
|
||||||
|
"tls"
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -13,7 +13,7 @@ namespace Netch.Servers.VMess
|
|||||||
StoppedKeywords.AddRange(new[] {"config file not readable", "failed to"});
|
StoppedKeywords.AddRange(new[] {"config file not readable", "failed to"});
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Name { get; protected set; } = "V2Ray";
|
public override string Name { get; protected set; } = "VMess";
|
||||||
public override string MainFile { get; protected set; } = "v2ray.exe";
|
public override string MainFile { get; protected set; } = "v2ray.exe";
|
||||||
public Server Server { get; set; }
|
public Server Server { get; set; }
|
||||||
public ushort? Socks5LocalPort { get; set; }
|
public ushort? Socks5LocalPort { get; set; }
|
||||||
|
|||||||
@@ -20,7 +20,24 @@ namespace Netch.Servers.VMess
|
|||||||
|
|
||||||
public Server ParseJObject(in JObject j)
|
public Server ParseJObject(in JObject j)
|
||||||
{
|
{
|
||||||
return j.ToObject<VMess>();
|
var server = j.ToObject<VMess>();
|
||||||
|
if (server == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (server.TLSSecure != null)
|
||||||
|
{
|
||||||
|
if ((bool) server.TLSSecure)
|
||||||
|
{
|
||||||
|
server.TLSSecureType = "tls";
|
||||||
|
server.TLSSecure = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
server.TLSSecure = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return server;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Edit(Server s)
|
public void Edit(Server s)
|
||||||
@@ -49,7 +66,7 @@ namespace Netch.Servers.VMess
|
|||||||
type = server.FakeType,
|
type = server.FakeType,
|
||||||
host = server.Host,
|
host = server.Host,
|
||||||
path = server.Path,
|
path = server.Path,
|
||||||
tls = server.TLSSecure ?? Global.Settings.V2RayConfig.AllowInsecure ? "tls" : ""
|
tls = server.TLSSecureType
|
||||||
});
|
});
|
||||||
return "vmess://" + ShareLink.URLSafeBase64Encode(vmessJson);
|
return "vmess://" + ShareLink.URLSafeBase64Encode(vmessJson);
|
||||||
}
|
}
|
||||||
@@ -97,7 +114,7 @@ namespace Netch.Servers.VMess
|
|||||||
data.Path = vmess.path;
|
data.Path = vmess.path;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.TLSSecure = vmess.tls == "tls";
|
data.TLSSecureType = vmess.tls;
|
||||||
data.EncryptMethod = "auto"; // V2Ray 加密方式不包括在链接中,主动添加一个
|
data.EncryptMethod = "auto"; // V2Ray 加密方式不包括在链接中,主动添加一个
|
||||||
|
|
||||||
return CheckServer(data) ? new[] {data} : null;
|
return CheckServer(data) ? new[] {data} : null;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using Microsoft.Diagnostics.Tracing.Session;
|
|||||||
using Netch.Controllers;
|
using Netch.Controllers;
|
||||||
using Netch.Models;
|
using Netch.Models;
|
||||||
using Netch.Servers.Shadowsocks;
|
using Netch.Servers.Shadowsocks;
|
||||||
|
using Netch.Servers.Socks5;
|
||||||
|
|
||||||
namespace Netch.Utils
|
namespace Netch.Utils
|
||||||
{
|
{
|
||||||
@@ -63,26 +64,28 @@ namespace Netch.Utils
|
|||||||
|
|
||||||
//var processList = Process.GetProcessesByName(ProcessName).Select(p => p.Id).ToHashSet();
|
//var processList = Process.GetProcessesByName(ProcessName).Select(p => p.Id).ToHashSet();
|
||||||
var instances = new List<Process>();
|
var instances = new List<Process>();
|
||||||
if (server.Type.Equals("Socks5") && MainController.ModeController.Name == "HTTP")
|
switch (MainController.ServerController)
|
||||||
{
|
{
|
||||||
instances.Add(((HTTPController) MainController.ModeController).pPrivoxyController.Instance);
|
case null:
|
||||||
}
|
break;
|
||||||
else if (MainController.ServerController != null)
|
case SSController ssController when ssController.DllFlag:
|
||||||
{
|
instances.Add(Process.GetCurrentProcess());
|
||||||
switch (MainController.ServerController)
|
break;
|
||||||
{
|
case Guard instanceController:
|
||||||
case SSController ssController when ssController.DllFlag:
|
if (instanceController.Instance != null)
|
||||||
instances.Add(Process.GetCurrentProcess());
|
|
||||||
break;
|
|
||||||
case Guard instanceController:
|
|
||||||
instances.Add(instanceController.Instance);
|
instances.Add(instanceController.Instance);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (MainController.ModeController != null)
|
|
||||||
|
if (!instances.Any())
|
||||||
{
|
{
|
||||||
switch (MainController.ModeController)
|
switch (MainController.ModeController)
|
||||||
{
|
{
|
||||||
|
case null:
|
||||||
|
break;
|
||||||
|
case HTTPController httpController:
|
||||||
|
instances.Add(httpController.pPrivoxyController.Instance);
|
||||||
|
break;
|
||||||
case NFController _:
|
case NFController _:
|
||||||
instances.Add(Process.GetCurrentProcess());
|
instances.Add(Process.GetCurrentProcess());
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -30,14 +30,14 @@ namespace Netch.Utils
|
|||||||
Global.Settings = settingJObject?.ToObject<Setting>() ?? new Setting();
|
Global.Settings = settingJObject?.ToObject<Setting>() ?? new Setting();
|
||||||
Global.Settings.Server.Clear();
|
Global.Settings.Server.Clear();
|
||||||
|
|
||||||
foreach (JObject server in settingJObject["Server"])
|
if (settingJObject?["Server"] != null)
|
||||||
{
|
foreach (JObject server in settingJObject["Server"])
|
||||||
var serverResult = ServerHelper.ParseJObject(server);
|
{
|
||||||
if (serverResult != null)
|
var serverResult = ServerHelper.ParseJObject(server);
|
||||||
Global.Settings.Server.Add(serverResult);
|
if (serverResult != null)
|
||||||
}
|
Global.Settings.Server.Add(serverResult);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (JsonException)
|
catch (JsonException)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -62,7 +62,15 @@ namespace Netch.Utils
|
|||||||
Directory.CreateDirectory(DATA_DIR);
|
Directory.CreateDirectory(DATA_DIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
File.WriteAllText(SETTINGS_JSON, JsonConvert.SerializeObject(Global.Settings, Formatting.Indented));
|
File.WriteAllText(SETTINGS_JSON,
|
||||||
|
JsonConvert.SerializeObject(
|
||||||
|
Global.Settings,
|
||||||
|
Formatting.Indented,
|
||||||
|
new JsonSerializerSettings
|
||||||
|
{
|
||||||
|
NullValueHandling = NullValueHandling.Ignore
|
||||||
|
}
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
|
|
||||||
@@ -75,5 +77,24 @@ namespace Netch.Utils
|
|||||||
}
|
}
|
||||||
set => AdapterRegistry(true).SetValue("NameServer", value, RegistryValueKind.String);
|
set => AdapterRegistry(true).SetValue("NameServer", value, RegistryValueKind.String);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<string> Split(string dns)
|
||||||
|
{
|
||||||
|
return dns.Split(',').Where(ip => !string.IsNullOrWhiteSpace(ip)).Select(ip => ip.Trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TrySplit(string value, out IEnumerable<string> result, ushort maxCount = 0)
|
||||||
|
{
|
||||||
|
result = Split(value).ToArray();
|
||||||
|
|
||||||
|
return maxCount == 0 || result.Count() <= maxCount
|
||||||
|
&&
|
||||||
|
result.All(ip => IPAddress.TryParse(ip, out _));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Join(IEnumerable<string> dns)
|
||||||
|
{
|
||||||
|
return string.Join(",", dns);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,7 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using Netch.Servers.Shadowsocks;
|
using Netch.Servers.Shadowsocks;
|
||||||
using Netch.Servers.Shadowsocks.Models;
|
using Netch.Servers.Shadowsocks.Models;
|
||||||
|
using Netch.Servers.VMess;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using Server = Netch.Models.Server;
|
using Server = Netch.Models.Server;
|
||||||
@@ -233,7 +234,14 @@ namespace Netch.Utils
|
|||||||
|
|
||||||
public static string GetNetchLink(Server s)
|
public static string GetNetchLink(Server s)
|
||||||
{
|
{
|
||||||
return "Netch://" + URLSafeBase64Encode(JsonConvert.SerializeObject(s));
|
var server = (Server) s.Clone();
|
||||||
|
if (server is VMess vmess)
|
||||||
|
{
|
||||||
|
vmess.TLSSecure = !string.IsNullOrEmpty(vmess.TLSSecureType);
|
||||||
|
vmess.TLSSecureType = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Netch://" + URLSafeBase64Encode(JsonConvert.SerializeObject(server, new JsonSerializerSettings {NullValueHandling = NullValueHandling.Ignore}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
57
Netch/Utils/Subscription.cs
Normal file
57
Netch/Utils/Subscription.cs
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Netch.Models;
|
||||||
|
|
||||||
|
namespace Netch.Utils
|
||||||
|
{
|
||||||
|
public static class Subscription
|
||||||
|
{
|
||||||
|
private static readonly object ServerLock = new object();
|
||||||
|
|
||||||
|
public static async Task UpdateServersAsync(string proxyServer = default)
|
||||||
|
{
|
||||||
|
await Task.WhenAll(
|
||||||
|
Global.Settings.SubscribeLink.Select(item =>
|
||||||
|
Task.Run(() => UpdateServer(item, proxyServer))
|
||||||
|
).ToArray()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void UpdateServer(SubscribeLink item, string proxyServer)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var request = WebUtil.CreateRequest(item.Link);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(item.UserAgent)) request.UserAgent = item.UserAgent;
|
||||||
|
if (!string.IsNullOrEmpty(proxyServer)) request.Proxy = new WebProxy(proxyServer);
|
||||||
|
|
||||||
|
List<Server> servers;
|
||||||
|
|
||||||
|
var result = WebUtil.DownloadString(request, out var rep);
|
||||||
|
if (rep.StatusCode == HttpStatusCode.OK)
|
||||||
|
servers = ShareLink.ParseText(result);
|
||||||
|
else
|
||||||
|
throw new Exception($"{item.Remark} Response Status Code: {rep.StatusCode}");
|
||||||
|
|
||||||
|
foreach (var server in servers) server.Group = item.Remark;
|
||||||
|
|
||||||
|
lock (ServerLock)
|
||||||
|
{
|
||||||
|
Global.Settings.Server.RemoveAll(server => server.Group.Equals(item.Remark));
|
||||||
|
Global.Settings.Server.AddRange(servers);
|
||||||
|
}
|
||||||
|
|
||||||
|
Global.MainForm.NotifyTip(i18N.TranslateFormat("Update {1} server(s) from {0}", item.Remark, servers.Count));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Global.MainForm.NotifyTip($"{i18N.TranslateFormat("Update servers error from {0}", item.Remark)}\n{e.Message}", info: false);
|
||||||
|
Logging.Error(e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
@@ -7,10 +7,12 @@ using System.Linq;
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
using System.Security.Cryptography;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using MaxMind.GeoIP2;
|
using MaxMind.GeoIP2;
|
||||||
|
using TaskScheduler;
|
||||||
|
|
||||||
namespace Netch.Utils
|
namespace Netch.Utils
|
||||||
{
|
{
|
||||||
@@ -37,12 +39,12 @@ namespace Netch.Utils
|
|||||||
public static async Task<int> TCPingAsync(IPAddress ip, int port, int timeout = 1000, CancellationToken ct = default)
|
public static async Task<int> TCPingAsync(IPAddress ip, int port, int timeout = 1000, CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
using var client = new TcpClient(ip.AddressFamily);
|
using var client = new TcpClient(ip.AddressFamily);
|
||||||
|
|
||||||
|
var stopwatch = Stopwatch.StartNew();
|
||||||
|
|
||||||
var task = client.ConnectAsync(ip, port);
|
var task = client.ConnectAsync(ip, port);
|
||||||
|
|
||||||
var stopwatch = new Stopwatch();
|
var resTask = await Task.WhenAny(task, Task.Delay(timeout, ct));
|
||||||
stopwatch.Start();
|
|
||||||
|
|
||||||
var resTask = await Task.WhenAny(Task.Delay(timeout, ct), task);
|
|
||||||
|
|
||||||
stopwatch.Stop();
|
stopwatch.Stop();
|
||||||
if (resTask == task && client.Connected)
|
if (resTask == task && client.Connected)
|
||||||
@@ -96,7 +98,7 @@ namespace Netch.Utils
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var sha256 = System.Security.Cryptography.SHA256.Create();
|
var sha256 = SHA256.Create();
|
||||||
var fileStream = File.OpenRead(filePath);
|
var fileStream = File.OpenRead(filePath);
|
||||||
return sha256.ComputeHash(fileStream).Aggregate(string.Empty, (current, b) => current + b.ToString("x2"));
|
return sha256.ComputeHash(fileStream).Aggregate(string.Empty, (current, b) => current + b.ToString("x2"));
|
||||||
}
|
}
|
||||||
@@ -237,5 +239,62 @@ namespace Netch.Utils
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void RegisterNetchStartupItem()
|
||||||
|
{
|
||||||
|
var scheduler = new TaskSchedulerClass();
|
||||||
|
scheduler.Connect();
|
||||||
|
var folder = scheduler.GetFolder("\\");
|
||||||
|
|
||||||
|
var taskIsExists = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
folder.GetTask("Netch Startup");
|
||||||
|
taskIsExists = true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Global.Settings.RunAtStartup)
|
||||||
|
{
|
||||||
|
if (taskIsExists)
|
||||||
|
folder.DeleteTask("Netch Startup", 0);
|
||||||
|
|
||||||
|
var task = scheduler.NewTask(0);
|
||||||
|
task.RegistrationInfo.Author = "Netch";
|
||||||
|
task.RegistrationInfo.Description = "Netch run at startup.";
|
||||||
|
task.Principal.RunLevel = _TASK_RUNLEVEL.TASK_RUNLEVEL_HIGHEST;
|
||||||
|
|
||||||
|
task.Triggers.Create(_TASK_TRIGGER_TYPE2.TASK_TRIGGER_LOGON);
|
||||||
|
var action = (IExecAction) task.Actions.Create(_TASK_ACTION_TYPE.TASK_ACTION_EXEC);
|
||||||
|
action.Path = Application.ExecutablePath;
|
||||||
|
|
||||||
|
|
||||||
|
task.Settings.ExecutionTimeLimit = "PT0S";
|
||||||
|
task.Settings.DisallowStartIfOnBatteries = false;
|
||||||
|
task.Settings.RunOnlyIfIdle = false;
|
||||||
|
|
||||||
|
folder.RegisterTaskDefinition("Netch Startup", task, (int) _TASK_CREATION.TASK_CREATE, null, null,
|
||||||
|
_TASK_LOGON_TYPE.TASK_LOGON_INTERACTIVE_TOKEN, "");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (taskIsExists)
|
||||||
|
folder.DeleteTask("Netch Startup", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ChangeControlForeColor(Component component, Color color)
|
||||||
|
{
|
||||||
|
switch (component)
|
||||||
|
{
|
||||||
|
case TextBox _:
|
||||||
|
case ComboBox _:
|
||||||
|
if (((Control) component).ForeColor != color) ((Control) component).ForeColor = color;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -47,6 +47,22 @@ namespace Netch.Utils
|
|||||||
return memoryStream.ToArray();
|
return memoryStream.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步下载并编码为字符串
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="req"></param>
|
||||||
|
/// <param name="rep"></param>
|
||||||
|
/// <param name="encoding">编码,默认UTF-8</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string DownloadString(HttpWebRequest req, out HttpWebResponse rep, string encoding = "UTF-8")
|
||||||
|
{
|
||||||
|
rep = (HttpWebResponse) req.GetResponse();
|
||||||
|
using var responseStream = rep.GetResponseStream();
|
||||||
|
using var streamReader = new StreamReader(responseStream, Encoding.GetEncoding(encoding));
|
||||||
|
|
||||||
|
return streamReader.ReadToEnd();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 异步下载并编码为字符串
|
/// 异步下载并编码为字符串
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,67 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
||||||
<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>
|
||||||
<PropertyGroup>
|
<TargetFramework>net48</TargetFramework>
|
||||||
<Platforms>x86;x64</Platforms>
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
<ProjectGuid>{A8715AF4-ACC6-43F9-9381-4294C5360623}</ProjectGuid>
|
<Platforms>x64</Platforms>
|
||||||
<OutputType>Library</OutputType>
|
<UseWindowsForms>true</UseWindowsForms>
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
<LangVersion>latest</LangVersion>
|
||||||
<RootNamespace>NetchLib</RootNamespace>
|
</PropertyGroup>
|
||||||
<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>
|
</Project>
|
||||||
@@ -75,7 +75,7 @@ namespace System.Windows.Forms
|
|||||||
|
|
||||||
private bool IsOriginalItems => Items.Count == AutoFillTag.Length;
|
private bool IsOriginalItems => Items.Count == AutoFillTag.Length;
|
||||||
|
|
||||||
private void ResetCompletionList()
|
public void ResetCompletionList()
|
||||||
{
|
{
|
||||||
Keyword = null;
|
Keyword = null;
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -70,3 +70,5 @@ As well, Netch avoid the restricted NAT problem caused by SSTap. You can use an
|
|||||||
- [Privoxy](https://www.privoxy.org/)
|
- [Privoxy](https://www.privoxy.org/)
|
||||||
- [NatTypeTester](https://github.com/HMBSbige/NatTypeTester)
|
- [NatTypeTester](https://github.com/HMBSbige/NatTypeTester)
|
||||||
- [NetFilter SDK](https://netfiltersdk.com/)
|
- [NetFilter SDK](https://netfiltersdk.com/)
|
||||||
|
|
||||||
|
[](https://starchart.cc/NetchX/Netch)
|
||||||
|
|||||||
2
binaries
2
binaries
Submodule binaries updated: f081890f60...357fa5b8f9
Reference in New Issue
Block a user