Compare commits

..

76 Commits

Author SHA1 Message Date
ChsBuffer
63f51a481c Bump version to 1.8.5 2021-05-28 23:39:55 +08:00
Connection Refused
e89c742f3f Add aiodns 2021-05-28 23:31:54 +08:00
ChsBuffer
458c6047af Update cloak.ps1 2021-05-28 23:29:13 +08:00
ChsBuffer
561def7fe1 Fix a typo caused China DNS not be bypassed
close #649
2021-05-28 23:28:34 +08:00
ChsBuffer
9e68fb12fb Update DNSUtils.Lookup() timeout 2021-05-28 23:24:47 +08:00
Connection Refused
d7360b3688 Update dependabot.yml 2021-05-28 23:14:11 +08:00
Connection Refused
7844c183e7 Update download.ps1 2021-05-28 23:10:56 +08:00
Connection Refused
8325bd1fe3 Update README.md 2021-05-28 23:06:35 +08:00
ChsBuffer
0a59d6aa3f Update Text
Update zh-CN
2021-05-28 22:20:19 +08:00
ChsBuffer
7fa05e7dad Update i18N
Update SettingForm AioDNSListenPortTextBox
2021-05-28 21:20:24 +08:00
ChsBuffer
b948040f9d Refactor: Replace -console argument with Show/Hide Console MenuItem 2021-05-28 21:09:23 +08:00
ChsBuffer
0c76198bd4 Update AioDNS default listen port 2021-05-28 20:59:34 +08:00
ChsBuffer
d917e5a8fa Remove AioDNS.RulePath setting
Add AioDNS.ListenPort setting
Update General setting layout
2021-05-28 20:59:15 +08:00
ChsBuffer
015e4ada94 Fix: Disable Task StopIfGoingOnBatteries
close #651
2021-05-28 15:57:15 +08:00
ChsBuffer
86b1741dd0 Revert NatTest Monitor lock 2021-05-28 14:53:27 +08:00
ChsBuffer
4af18025a7 Refactor Interops Debug log 2021-05-27 22:34:30 +08:00
ChsBuffer
3678c98fec Fix AioDNS rule config 2021-05-27 22:34:29 +08:00
ChsBuffer
9f809b4d27 Refactor: Move Updater namespace to Netch.Services 2021-05-27 22:34:29 +08:00
ChsBuffer
e3a3396d18 Refactor Started Ping 2021-05-27 22:34:28 +08:00
Connection Refused
43c19c6698 Update README.md 2021-05-25 12:35:51 +08:00
Connection Refused
9ee2a2a31a Merge pull request #650 from NetchX/dependabot/nuget/Microsoft.Diagnostics.Tracing.TraceEvent-2.0.69
Bump Microsoft.Diagnostics.Tracing.TraceEvent from 2.0.68 to 2.0.69
2021-05-25 12:28:04 +08:00
dependabot[bot]
489c3fc39d Bump Microsoft.Diagnostics.Tracing.TraceEvent from 2.0.68 to 2.0.69
Bumps [Microsoft.Diagnostics.Tracing.TraceEvent](https://github.com/Microsoft/perfview) from 2.0.68 to 2.0.69.
- [Release notes](https://github.com/Microsoft/perfview/releases)
- [Commits](https://github.com/Microsoft/perfview/compare/P2.0.68...P2.0.69)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-24 23:06:14 +00:00
ChsBuffer
657266df47 Update README.md 2021-05-24 16:21:12 +08:00
ChsBuffer
82ed5189c8 Refactor: Asynchronous and Lock 2021-05-17 16:25:58 +08:00
Bruce Wayne
ebe2978724 Update sha256.ps1 2021-05-14 10:16:11 +08:00
ChsBuffer
764d42efe2 Bump version to 1.8.4 2021-05-11 22:03:11 +08:00
ChsBuffer
8b81df03c4 Update TUNController.cs 2021-05-11 22:02:45 +08:00
ChsBuffer
4cc5998440 Fix suffixed version newer than release version 2021-05-11 17:17:51 +08:00
ChsBuffer
2051dd1bfe Update Nuget Packages 2021-05-10 10:08:45 +08:00
ChsBuffer
b167674d37 Update NetRoute.FillTemplate 2021-05-10 10:07:34 +08:00
ChsBuffer
74caeeaf42 Refactor TUNController 2021-05-09 15:31:43 +08:00
ChsBuffer
60dd3c8965 Refactor: Rearrange MainForm 2021-05-07 15:34:37 +08:00
ChsBuffer
ee2d35cb5d Refactor: ModeHelper, Mode.Type, Netch.Enums.ModeType 2021-05-06 23:43:13 +08:00
ChsBuffer
6f6ff85549 Refactor Guard Thread safety 2021-05-04 10:23:53 +08:00
ChsBuffer
9a8c4d6093 Fix: CloseLogFile() Thread safety 2021-05-04 10:17:33 +08:00
ChsBuffer
00268d67fa TUNController: check Interop Init() return value.
when false, throws MessageException
2021-05-04 00:24:09 +08:00
Connection Refused
b1f89c177d Update README.md 2021-05-01 11:53:07 +08:00
ChsBuffer
4a543dcf1a Refactor: Extract GetNetworkInterface By InterfaceIndex
close #630
2021-04-30 18:45:51 +08:00
ChsBuffer
5b5262e03e Update code style 2021-04-30 17:20:29 +08:00
ChsBuffer
60f0637b03 Refactor: MainForm AddServerMenuStrip get IServerUtil from Tag 2021-04-30 17:02:34 +08:00
ChsBuffer
460d295a66 Refactor TryReleaseTcpPort Process.MainModule.FileName null handling 2021-04-30 17:01:11 +08:00
ChsBuffer
ccd46144ab Refactor: save configuration 2021-04-30 15:48:43 +08:00
ChsBuffer
84e481f704 fix typo 2021-04-30 15:45:12 +08:00
ChsBuffer
fb64951003 Refactor: name, namespace 2021-04-30 15:24:37 +08:00
Connection Refused
258880ef95 Update README.md 2021-04-27 08:56:05 +08:00
Connection Refused
2bda0bdf8e Update issue templates 2021-04-27 08:47:18 +08:00
Connection Refused
bc0e5d0dcf Rename scripts 2021-04-27 08:43:35 +08:00
Connection Refused
4e4af89fbe Remove README.zh-CN.md 2021-04-27 08:43:31 +08:00
Connection Refused
1e9ff83aa2 Update README.md 2021-04-27 08:40:22 +08:00
Connection Refused
a4d8619944 Update README.md 2021-04-27 08:38:39 +08:00
Connection Refused
0bb54abe6c Update README.md 2021-04-27 08:03:51 +08:00
Connection Refused
0ad18ee566 Update README.md 2021-04-27 08:03:26 +08:00
Connection Refused
80460c0a21 Update README.md 2021-04-27 08:02:14 +08:00
Connection Refused
098680482e Merge pull request #628 from NetchX/dependabot/nuget/Microsoft.Diagnostics.Tracing.TraceEvent-2.0.68
Bump Microsoft.Diagnostics.Tracing.TraceEvent from 2.0.67 to 2.0.68
2021-04-27 07:24:17 +08:00
dependabot[bot]
16d7f53ee3 Bump Microsoft.Diagnostics.Tracing.TraceEvent from 2.0.67 to 2.0.68
Bumps [Microsoft.Diagnostics.Tracing.TraceEvent](https://github.com/Microsoft/perfview) from 2.0.67 to 2.0.68.
- [Release notes](https://github.com/Microsoft/perfview/releases)
- [Commits](https://github.com/Microsoft/perfview/compare/P2.0.67...P2.0.68)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-26 23:06:25 +00:00
Connection Refused
ed946c44a2 Merge pull request #627 from NetchX/dependabot/nuget/Microsoft.Diagnostics.Tracing.TraceEvent-2.0.67
Bump Microsoft.Diagnostics.Tracing.TraceEvent from 2.0.66 to 2.0.67
2021-04-24 01:38:08 +08:00
dependabot[bot]
62c28ccab2 Bump Microsoft.Diagnostics.Tracing.TraceEvent from 2.0.66 to 2.0.67
Bumps [Microsoft.Diagnostics.Tracing.TraceEvent](https://github.com/Microsoft/perfview) from 2.0.66 to 2.0.67.
- [Release notes](https://github.com/Microsoft/perfview/releases)
- [Commits](https://github.com/Microsoft/perfview/compare/P2.0.66...P2.0.67)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-22 23:12:13 +00:00
ChsBuffer
a2326389db Fix: Use WMI to set dummy Dns on the tun interface to ensure DNS is hijacked 2021-04-21 18:25:37 +08:00
Connection Refused
b0086cc854 Add ethereum donate address 2021-04-21 17:33:25 +08:00
Connection Refused
d2548d2893 Add ethereum donate address 2021-04-21 17:32:50 +08:00
Connection Refused
101d8c5a25 Update telegram links 2021-04-21 17:27:33 +08:00
Bruce Wayne
1b36b707f6 Update issue forms 2021-04-21 11:20:03 +08:00
Bruce Wayne
a94bf0d53d Update issue forms 2021-04-21 11:17:24 +08:00
Bruce Wayne
32a9261041 Update issue forms 2021-04-21 09:43:29 +08:00
Bruce Wayne
2b0530d9b0 Update issue forms 2021-04-21 09:23:52 +08:00
Bruce Wayne
2d85e78b77 Drop old issue template 2021-04-21 09:22:12 +08:00
Connection Refused
b8b4dbfb0a Update release.yml 2021-04-18 15:53:29 +08:00
Connection Refused
025eda8286 Update README.md 2021-04-18 15:53:05 +08:00
Connection Refused
44da2e8011 Bump version to 1.8.3 2021-04-09 09:22:27 +08:00
Connection Refused
54daff70b3 Update build.ps1 2021-04-09 09:21:17 +08:00
Connection Refused
b218e785d8 Update build.ps1 2021-04-09 09:21:05 +08:00
Connection Refused
5b857cc518 Merge pull request #610 from NetchX/dependabot/nuget/Vanara.PInvoke.User32-3.3.8
Bump Vanara.PInvoke.User32 from 3.3.7 to 3.3.8
2021-04-08 22:59:04 +08:00
Connection Refused
4693025576 Merge pull request #609 from NetchX/dependabot/nuget/Vanara.PInvoke.IpHlpApi-3.3.8
Bump Vanara.PInvoke.IpHlpApi from 3.3.7 to 3.3.8
2021-04-08 22:58:55 +08:00
dependabot[bot]
46eefd3db9 Bump Vanara.PInvoke.User32 from 3.3.7 to 3.3.8
Bumps [Vanara.PInvoke.User32](https://github.com/dahall/vanara) from 3.3.7 to 3.3.8.
- [Release notes](https://github.com/dahall/vanara/releases)
- [Commits](https://github.com/dahall/vanara/compare/v3.3.7...v3.3.8)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-07 23:04:23 +00:00
dependabot[bot]
eb1ee9e820 Bump Vanara.PInvoke.IpHlpApi from 3.3.7 to 3.3.8
Bumps [Vanara.PInvoke.IpHlpApi](https://github.com/dahall/vanara) from 3.3.7 to 3.3.8.
- [Release notes](https://github.com/dahall/vanara/releases)
- [Commits](https://github.com/dahall/vanara/compare/v3.3.7...v3.3.8)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-07 23:04:15 +00:00
Connection Refused
b501ed38c4 Enable SelfContained 2021-04-05 02:16:48 +08:00
75 changed files with 950 additions and 1094 deletions

View File

@@ -12,6 +12,7 @@ tab_width = 4
# Microsoft .NET properties
csharp_new_line_before_members_in_object_initializers = false
csharp_preferred_modifier_order = public, private, protected, internal, new, abstract, virtual, sealed, override, static, readonly, extern, unsafe, volatile, async:suggestion
csharp_space_after_cast = false
csharp_style_var_elsewhere = true:suggestion
csharp_style_var_for_built_in_types = true:suggestion
csharp_style_var_when_type_is_apparent = true:suggestion
@@ -27,7 +28,7 @@ dotnet_style_qualification_for_property = false:suggestion
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
# ReSharper properties
resharper_align_multiline_switch_expression = true
resharper_align_multiline_switch_expression = false
resharper_align_multline_type_parameter_constrains = true
resharper_blank_lines_after_block_statements = 0
resharper_blank_lines_after_multiline_statements = 1
@@ -73,7 +74,7 @@ resharper_place_simple_initializer_on_single_line = true
resharper_place_simple_switch_expression_on_single_line = true
resharper_show_autodetect_configure_formatting_tip = false
resharper_space_around_arrow_op = true
resharper_space_within_single_line_array_initializer_braces = false
resharper_space_within_single_line_array_initializer_braces = true
resharper_use_indent_from_vs = false
resharper_wrap_array_initializer_style = wrap_if_long
resharper_wrap_before_arrow_with_expressions = true

View File

@@ -1,32 +0,0 @@
---
name: 'Bug report'
about: 'Create a report to help us improve'
title: ''
labels: '需要核实'
assignees: ''
---
**Make sure you have read the readme, searched and read the issues related to yours. Otherwise it will be considered as a duplicate which will be closed immediately.**
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Open Netch
2. ...
**Log**
Attaching any log files in the folder `Netch\logging` is strongly recommended.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Environment (please complete the following information):**
- OS: [e.g. Windows 10 Pro 64-bit 1903]
- Netch Version: [e.g. 1.0.0-STABLE.x64]
**Additional context**
Add any other context about the problem here.

View File

@@ -1,12 +1,7 @@
name: Bug report
description: "Create a report to help us improve"
title: ""
labels: 需要核实
issue_body: true
description: Create a report to help us improve
labels: bug
body:
- type: markdown
attributes:
value: "**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.**"
- type: textarea
id: error
attributes:
@@ -19,7 +14,6 @@ body:
attributes:
label: To Reproduce
placeholder: |
Steps to reproduce the behavior:
1. Open Netch
2. ...
validations:
@@ -30,26 +24,28 @@ body:
label: CAPTCHA
description: Please confirm the options below.
options:
- label: I am human
- label: 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.
required: true
- type: textarea
id: log
attributes:
render: shell
label: Log
description: Attaching any log files in the folder `Netch\logging` is strongly recommended.
description: Attaching any log files in the folder `logging` is strongly recommended.
validations:
required: true
- type: textarea
id: environment
attributes:
label: Environment
render: txt
placeholder: |
- OS: [e.g. Windows 10 Pro 64-bit 1903]
- Netch Version: [e.g. 1.0.0-STABLE.x64]
- OS: [e.g. Windows 10 x64 Professional Workstation 20H2 19042.928]
- Netch Version: [e.g. 1.0.0]
validations:
required: true
- type: markdown
- type: textarea
id: info
attributes:
value: |
In the text box below, you can attach any relevant screenshots and files.
label: Additional information
description: >
If you have any additional information for us, use the field below.

View File

@@ -1,29 +0,0 @@
---
name: '错误报告'
about: '创建错误报告以帮助我们改进'
title: ''
labels: '需要核实'
assignees: ''
---
**确保你已经看过 readme也搜索并阅读过和你遇到的情况相关的问题。否则会被认为是重复的并被立刻关闭。**
**错误描述**
对错误的清晰简洁描述
**复现步骤**
1. 打开 Netch 软件
2. ...
**日志**
强烈建议附上任何在 `Netch\logging` 文件夹下面的日志。
**错误截图**
如果适用,请添加屏幕截图以帮助解释您的问题
**信息**
- 操作系统:[例如 Windows 10 专业版 64 位 1903]
- 软件版本:[例如 1.0.0-STABLE 64 位]
**额外信息**

View File

@@ -1,54 +1,43 @@
name: 错误报告
description: "创建错误报告以帮助我们改进"
title: ""
labels: 需要核实
issue_body: true
description: 创建错误报告以帮助我们改进
labels: bug
body:
- type: markdown
attributes:
value: "**确保你已经看过 readme也搜索并阅读过和你遇到的情况相关的问题。否则会被认为是重复的并被立刻关闭。**"
- type: textarea
id: error
attributes:
label: "错误描述"
label: 错误描述
description: 对错误的清晰简洁描述
validations:
required: true
- type: textarea
id: reproduce
attributes:
label: "复现步骤"
label: 复现步骤
placeholder: |
1. 打开 Netch 软件
2. ...
validations:
required: true
- type: checkboxes
id: captcha
attributes:
label: 验证
description: 请确认下面选项
options:
- label: 我是人类
required: true
- type: textarea
id: log
attributes:
render: shell
label: 日志
description: 强烈建议附上任何在 `Netch\logging` 文件夹下面的日志
description: 强烈建议附上任何在 `logging` 文件夹下面的日志
validations:
required: true
- type: textarea
id: environment
attributes:
label: 操作环境
render: txt
placeholder: |
操作系统:[Windows 10 专业版 64 位 1903]
软件版本:[1.0.0-STABLE 64 位]
操作系统:[Windows 10 x64 Professional Workstation 20H2 19042.928]
软件版本:[1.0.0]
validations:
required: true
- type: markdown
- type: textarea
id: info
attributes:
value: |
label: 额外信息
description: >
下面的文本框中你可以附上跟 issue 相关的截图、文件

View File

@@ -1,8 +1,9 @@
blank_issues_enabled: false
contact_links:
- name: Telegram Channel
url: https://t.me/Netch
url: https://t.me/netch_channel
about: Telegram Channel
- name: Telegram Group
url: https://t.me/Netch_Discuss_Group
about: Telegram Group
url: https://t.me/netch_group
about: Telegram Group

View File

@@ -1,16 +0,0 @@
---
name: 'Feature request'
about: 'Suggest an idea for this project'
title: ''
labels: 'Status: Review Needed'
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.**
**Describe the feature you want**
A clear and concise description of what you want to happen.
**Additional context** (Optional)
Add any other context or screenshots about the feature request here.

View File

@@ -1,16 +1,11 @@
name: request
description: "Suggest an idea for this project"
title: ""
labels: 需要核实
issue_body: true
name: Feature request
description: Suggest an idea for this project
labels: enhancement
body:
- type: markdown
attributes:
value: "**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.**"
- type: textarea
id: description
attributes:
label: "Describe the feature you want"
label: Describe the feature you want
description: A clear and concise description of what you want to happen.
validations:
required: true

View File

@@ -1,15 +0,0 @@
---
name: '功能请求'
about: '建议这个项目的想法'
title: ''
labels: 'Status: Review Needed'
assignees: ''
---
**确保你已经看过 readme也搜索并阅读过和你遇到的情况相关的问题。否则会被认为是重复的并被立刻关闭。**
**功能描述**
简明扼要地描述需要的功能
**额外信息**

View File

@@ -1,16 +1,11 @@
name: 功能请求
description: "建议这个项目的想法"
title: ""
labels: 需要核实
issue_body: true
description: 建议这个项目的想法
labels: enhancement
body:
- type: markdown
attributes:
value: "**确保你已经看过 readme也搜索并阅读过和你遇到的情况相关的问题。否则会被认为是重复的并被立刻关闭。**"
- type: textarea
id: description
attributes:
label: "功能描述"
label: 功能描述
description: 简明扼要地描述需要的功能
validations:
required: true

View File

@@ -1,34 +1,21 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
time: "07:00"
time: "00:00"
timezone: "Asia/Shanghai"
labels:
- "Automatic"
open-pull-requests-limit: 99
- "automatic"
open-pull-requests-limit: 114514
- package-ecosystem: "nuget"
directory: "/"
schedule:
interval: "daily"
time: "07:15"
time: "00:10"
timezone: "Asia/Shanghai"
labels:
- "Automatic"
open-pull-requests-limit: 99
- package-ecosystem: "gitsubmodule"
directory: "/"
schedule:
interval: "daily"
time: "07:15"
timezone: "Asia/Shanghai"
labels:
- "Automatic"
open-pull-requests-limit: 99
- "automatic"
open-pull-requests-limit: 114514

View File

@@ -40,7 +40,7 @@ jobs:
files: |
Netch.7z
body: |
[![](https://img.shields.io/badge/Telegram-Channel-blue)](https://t.me/Netch) [![](https://img.shields.io/badge/Telegram-Group-green)](https://t.me/Netch_Discuss_Group)
[![](https://img.shields.io/badge/Telegram-Channel-blue)](https://t.me/netch_channel) [![](https://img.shields.io/badge/Telegram-Group-green)](https://t.me/netch_group)
## 更新日志
* 这是 GitHub Actions 自动化部署,更新日志应该很快会手动更新

View File

@@ -8,7 +8,6 @@
{
public const string Show = "-show";
public const string ForceUpdate = "-forceUpdate";
public const string Console = "-console";
}
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.IO;
using static Netch.Interops.AioDNSInterops;
using Netch.Interfaces;
using static Netch.Interops.AioDNS;
namespace Netch.Controllers
{
@@ -8,6 +9,8 @@ namespace Netch.Controllers
{
public string Name { get; } = "DNS Service";
private const string RulePath = "bin\\aiodns.conf";
public void Stop()
{
Free();
@@ -21,7 +24,7 @@ namespace Netch.Controllers
{
Dial(NameList.TYPE_REST, "");
Dial(NameList.TYPE_ADDR, $"{Global.Settings.LocalAddress}:{Global.Settings.AioDNS.ListenPort}");
Dial(NameList.TYPE_LIST, Path.GetFullPath(Global.Settings.AioDNS.RulePath));
Dial(NameList.TYPE_LIST, Path.GetFullPath(RulePath));
Dial(NameList.TYPE_CDNS, $"{Global.Settings.AioDNS.ChinaDNS}");
Dial(NameList.TYPE_ODNS, $"{Global.Settings.AioDNS.OtherDNS}");

View File

@@ -199,15 +199,22 @@ namespace Netch.Controllers
_logStreamWriter!.WriteLine(line);
}
private readonly object LogStreamLock = new();
private void CloseLogFile()
{
if (!RedirectToFile)
return;
_flushFileStreamTimer.Enabled = false;
_logStreamWriter?.Close();
_logFileStream?.Close();
_logStreamWriter = _logStreamWriter = null;
lock (LogStreamLock)
{
if (_logFileStream == null)
return;
_flushFileStreamTimer.Enabled = false;
_logStreamWriter?.Close();
_logFileStream?.Close();
_logStreamWriter = _logStreamWriter = null;
}
}
#endregion

View File

@@ -1,9 +1,10 @@
using Netch.Models;
using Netch.Servers.Socks5;
using Netch.Utils;
using System;
using System.IO;
using System.Threading.Tasks;
using Netch.Interfaces;
using Netch.Models;
using Netch.Servers.Socks5;
using Netch.Utils;
namespace Netch.Controllers
{
@@ -54,7 +55,7 @@ namespace Netch.Controllers
public static void Start(Server server, Mode mode)
{
Global.Logger.Info($"启动主控制器: {server.Type} [{mode.Type}]{mode.Remark}");
Global.Logger.Info($"启动主控制器: {server.Type} [{(int)mode.Type}]{mode.Remark}");
Server = server;
Mode = mode;
@@ -186,16 +187,9 @@ namespace Netch.Controllers
{
foreach (var p in PortHelper.GetProcessByUsedTcpPort(port))
{
string fileName;
try
{
fileName = p.MainModule?.FileName ?? throw new Exception(); // TODO what's this exception?
}
catch (Exception e)
{
Global.Logger.Warning(e.ToString());
var fileName = p.MainModule?.FileName;
if (fileName == null)
continue;
}
if (fileName.StartsWith(Global.NetchDir))
{

View File

@@ -1,14 +1,15 @@
using Netch.Interops;
using Netch.Models;
using Netch.Servers.Shadowsocks;
using Netch.Servers.Socks5;
using Netch.Utils;
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using static Netch.Interops.RedirectorInterop;
using Netch.Interfaces;
using Netch.Interops;
using Netch.Models;
using Netch.Servers.Shadowsocks;
using Netch.Servers.Socks5;
using Netch.Utils;
using static Netch.Interops.Redirector;
namespace Netch.Controllers
{
@@ -148,7 +149,7 @@ namespace Netch.Controllers
{
Dial(NameList.TYPE_CLRNAME, "");
var invalidList = new List<string>();
foreach (var s in mode.FullRule)
foreach (var s in mode.GetRules())
{
if (s.StartsWith("!"))
{

View File

@@ -1,8 +1,9 @@
using Netch.Utils;
using System;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Netch.Interfaces;
using Netch.Utils;
namespace Netch.Controllers
{
@@ -21,7 +22,7 @@ namespace Netch.Controllers
/// 启动 NatTypeTester
/// </summary>
/// <returns></returns>
public async Task<(string?, string?, string?)> Start()
public async Task<(string? result, string? localEnd, string? publicEnd)> Start()
{
string? localEnd = null, publicEnd = null, result = null, bindingTest = null;
@@ -35,7 +36,7 @@ namespace Netch.Controllers
try
{
File.WriteAllText(Path.Combine(Global.NetchDir, $"logging\\{Name}.log"), $"{output}\r\n{error}");
await File.WriteAllTextAsync(Path.Combine(Global.NetchDir, $"logging\\{Name}.log"), $"{output}\r\n{error}");
}
catch (Exception e)
{

View File

@@ -1,13 +1,15 @@
using Netch.Forms;
using Netch.Models;
using Netch.Servers.Socks5;
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Netch.Forms;
using Netch.Interfaces;
using Netch.Models;
using Netch.Servers.Socks5;
using Netch.Utils;
namespace Netch.Controllers
{
@@ -19,8 +21,6 @@ namespace Netch.Controllers
protected override IEnumerable<string> StartedKeywords { get; set; } = new[] { "└" };
private readonly OutboundAdapter _outbound = new();
protected override Encoding? InstanceOutputEncoding { get; } = Encoding.UTF8;
private LogForm? _form;
@@ -32,13 +32,15 @@ namespace Netch.Controllers
_form = new LogForm(Global.MainForm);
_form.CreateControl();
var argument = new StringBuilder($@"-i \Device\NPF_{_outbound.NetworkInterface.Id}");
var outboundNetworkInterface = NetworkInterfaceUtils.GetBest();
var argument = new StringBuilder($@"-i \Device\NPF_{outboundNetworkInterface.Id}");
if (server is Socks5 socks5 && !socks5.Auth())
argument.Append($" --destination {server.AutoResolveHostname()}:{server.Port}");
else
argument.Append($" --destination 127.0.0.1:{Global.Settings.Socks5LocalPort}");
argument.Append($" {mode.FullRule.FirstOrDefault() ?? "-P n"}");
argument.Append($" {mode.GetRules().FirstOrDefault() ?? "-P n"}");
StartInstanceAuto(argument.ToString());
}

View File

@@ -1,40 +1,46 @@
using Netch.Models;
using Netch.Servers.Socks5;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using static Netch.Interops.TUNInterop;
using Netch.Enums;
using Netch.Interfaces;
using Netch.Models;
using Netch.Servers.Socks5;
using Netch.Utils;
using Netch.Interops;
using static Netch.Interops.tun2socks;
namespace Netch.Controllers
{
public class TUNController : IModeController
{
private readonly List<string> _directIPs = new();
public string Name => "tun2socks";
private readonly List<string> _proxyIPs = new();
private const string DummyDns = "6.6.6.6";
public readonly DNSController DNSController = new();
private readonly DNSController _aioDnsController = new();
public string Name { get; } = "tun2socks";
private NetRoute _outbound;
private NetRoute _tun;
private readonly OutboundAdapter _outboundAdapter = new();
private IAdapter _tunAdapter = null!;
private IPAddress _serverAddresses = null!;
private Mode _mode = null!;
public void Start(in Mode mode)
{
_mode = mode;
var server = MainController.Server!;
_serverAddresses = DnsUtils.Lookup(server.Hostname)!; // server address have been cached when MainController.Start
IPAddress address;
(_outbound, address) = NetRoute.GetBestRouteTemplate();
CheckDriver();
Dial(NameList.TYPE_ADAPMTU, "1500");
Dial(NameList.TYPE_BYPBIND, _outboundAdapter.Address.ToString());
Dial(NameList.TYPE_BYPBIND, address.ToString());
Dial(NameList.TYPE_BYPLIST, "disabled");
#region Server
@@ -78,32 +84,111 @@ namespace Netch.Controllers
else
{
MainController.PortCheck(Global.Settings.AioDNS.ListenPort, "DNS");
DNSController.Start();
_aioDnsController.Start();
Dial(NameList.TYPE_DNSADDR, $"127.0.0.1:{Global.Settings.AioDNS.ListenPort}");
}
#endregion
Global.Logger.Debug("tun2socks init");
Init();
if (!Init())
throw new MessageException("tun2socks start failed, reboot your system and start again.");
_tunAdapter = new TunAdapter();
var tunIndex = (int)RouteHelper.ConvertLuidToIndex(tun_luid());
_tun = NetRoute.TemplateBuilder(Global.Settings.TUNTAP.Gateway, tunIndex);
NativeMethods.CreateUnicastIP(AddressFamily.InterNetwork,
RouteHelper.CreateUnicastIP(AddressFamily.InterNetwork,
Global.Settings.TUNTAP.Address,
(byte)Utils.Utils.SubnetToCidr(Global.Settings.TUNTAP.Netmask),
_tunAdapter.InterfaceIndex);
(ulong)tunIndex);
SetupRouteTable(mode);
}
private readonly string BinDriver = Path.Combine(Global.NetchDir, @"bin\wintun.dll");
private readonly string SysDriver = $@"{Environment.SystemDirectory}\wintun.dll";
#region Route
private void SetupRouteTable(Mode mode)
{
Global.MainForm.StatusText(i18N.Translate("Setup Route Table Rule"));
Global.Logger.Info("设置路由规则");
// Server Address
if (!IPAddress.IsLoopback(_serverAddresses))
RouteUtils.CreateRoute(_outbound.FillTemplate(_serverAddresses.ToString(), 32));
// Global Bypass IPs
RouteUtils.CreateRouteFill(_outbound, Global.Settings.TUNTAP.BypassIPs);
var tunNetworkInterface = NetworkInterfaceUtils.Get(_tun.InterfaceIndex);
switch (mode.Type)
{
case ModeType.ProxyRuleIPs:
// rules
RouteUtils.CreateRouteFill(_tun, mode.GetRules());
if (Global.Settings.TUNTAP.ProxyDNS)
{
tunNetworkInterface.SetDns(DummyDns);
// proxy dummy dns
RouteUtils.CreateRoute(_tun.FillTemplate(DummyDns, 32));
if (!Global.Settings.TUNTAP.UseCustomDNS)
// proxy AioDNS other dns
RouteUtils.CreateRoute(_tun.FillTemplate(Utils.Utils.GetHostFromUri(Global.Settings.AioDNS.OtherDNS), 32));
}
break;
case ModeType.BypassRuleIPs:
RouteUtils.CreateRouteFill(_outbound, mode.GetRules());
tunNetworkInterface.SetDns(DummyDns);
if (!Global.Settings.TUNTAP.UseCustomDNS)
// bypass AioDNS other dns
RouteUtils.CreateRoute(_outbound.FillTemplate(Utils.Utils.GetHostFromUri(Global.Settings.AioDNS.ChinaDNS), 32));
NetworkInterfaceUtils.SetInterfaceMetric(_tun.InterfaceIndex, 0);
RouteUtils.CreateRoute(_tun.FillTemplate("0.0.0.0", 0));
break;
}
}
private void ClearRouteTable()
{
if (!IPAddress.IsLoopback(_serverAddresses))
RouteUtils.DeleteRoute(_outbound.FillTemplate(_serverAddresses.ToString(), 32));
RouteUtils.DeleteRouteFill(_outbound, Global.Settings.TUNTAP.BypassIPs);
switch (_mode.Type)
{
case ModeType.BypassRuleIPs:
RouteUtils.DeleteRouteFill(_outbound, _mode.GetRules());
NetworkInterfaceUtils.SetInterfaceMetric(_outbound.InterfaceIndex);
break;
}
}
#endregion
public void Stop()
{
var tasks = new[]
{
Task.Run(Free),
Task.Run(ClearRouteTable),
Task.Run(_aioDnsController.Stop)
};
Task.WaitAll(tasks);
}
private void CheckDriver()
{
var binHash = Utils.Utils.SHA256CheckSum(BinDriver);
var sysHash = Utils.Utils.SHA256CheckSum(SysDriver);
string binDriver = Path.Combine(Global.NetchDir, @"bin\wintun.dll");
string sysDriver = $@"{Environment.SystemDirectory}\wintun.dll";
var binHash = Utils.Utils.SHA256CheckSum(binDriver);
var sysHash = Utils.Utils.SHA256CheckSum(sysDriver);
Global.Logger.Info("自带 wintun.dll Hash: " + binHash);
Global.Logger.Info("系统 wintun.dll Hash: " + sysHash);
if (binHash == sysHash)
@@ -111,7 +196,8 @@ namespace Netch.Controllers
try
{
File.Copy(BinDriver, SysDriver, true);
Global.Logger.Info("Copy wintun.dll to System Directory");
File.Copy(binDriver, sysDriver, true);
}
catch (Exception e)
{
@@ -119,190 +205,5 @@ namespace Netch.Controllers
throw new MessageException($"Failed to copy wintun.dll to system directory: {e.Message}");
}
}
/// <summary>
/// TUN/TAP停止
/// </summary>
public void Stop()
{
var tasks = new[]
{
Task.Run(Free),
Task.Run(ClearRouteTable),
Task.Run(DNSController.Stop)
};
Task.WaitAll(tasks);
}
/// <summary>
/// 设置绕行规则
/// </summary>
/// <returns>是否设置成功</returns>
private void SetupRouteTable(Mode mode)
{
Global.MainForm.StatusText(i18N.Translate("SetupBypass"));
Global.Logger.Info("设置路由规则");
Global.Logger.Info("绕行 → 服务器 IP");
if (!IPAddress.IsLoopback(_serverAddresses))
RouteAction(Action.Create, $"{_serverAddresses}/32", RouteType.Outbound);
Global.Logger.Info("绕行 → 全局绕过 IP");
RouteAction(Action.Create, Global.Settings.TUNTAP.BypassIPs, RouteType.Outbound);
#region Rule IPs
switch (mode.Type)
{
case 1:
// 代理规则 IP
Global.Logger.Info("代理 → 规则 IP");
RouteAction(Action.Create, mode.FullRule, RouteType.TUNTAP);
if (Global.Settings.TUNTAP.ProxyDNS)
{
Global.Logger.Info("代理 → 自定义 DNS");
if (Global.Settings.TUNTAP.UseCustomDNS)
RouteAction(Action.Create, Global.Settings.TUNTAP.HijackDNS.Select(ip => $"{ip}/32"), RouteType.TUNTAP);
else
RouteAction(Action.Create, $"{Global.Settings.AioDNS.OtherDNS}/32", RouteType.TUNTAP);
}
break;
case 2:
// 绕过规则 IP
Global.Logger.Info("绕行 → 规则 IP");
RouteAction(Action.Create, mode.FullRule, RouteType.Outbound);
break;
}
#endregion
if (mode.Type == 2)
{
Global.Logger.Info("代理 → 全局");
SetInterface(RouteType.TUNTAP, 0);
RouteAction(Action.Create, "0.0.0.0/0", RouteType.TUNTAP, record: false);
}
}
private void SetInterface(RouteType routeType, int? metric = null)
{
var adapter = routeType == RouteType.Outbound ? _outboundAdapter : _tunAdapter;
var arguments = $"interface ip set interface {adapter.InterfaceIndex} ";
if (metric != null)
arguments += $"metric={metric} ";
Utils.Utils.ProcessRunHiddenAsync("netsh", arguments).Wait();
}
/// <summary>
/// 清除绕行规则
/// </summary>
private bool ClearRouteTable()
{
var mode = MainController.Mode!;
RouteAction(Action.Delete, _directIPs, RouteType.Outbound);
RouteAction(Action.Delete, _proxyIPs, RouteType.TUNTAP);
_directIPs.Clear();
_proxyIPs.Clear();
if (mode.Type == 2)
{
SetInterface(RouteType.Outbound);
}
return true;
}
#region Package
private void RouteAction(Action action, in IEnumerable<string> ipNetworks, RouteType routeType, int metric = 0, bool record = true)
{
foreach (var address in ipNetworks)
RouteAction(action, address, routeType, metric);
}
private bool RouteAction(Action action, in string ipNetwork, RouteType routeType, int metric = 0, bool record = true)
{
#region
if (!TryParseIPNetwork(ipNetwork, out var ip, out var cidr))
return false;
IAdapter adapter = routeType switch
{
RouteType.Outbound => _outboundAdapter,
RouteType.TUNTAP => _tunAdapter,
_ => throw new ArgumentOutOfRangeException(nameof(routeType), routeType, null)
};
List<string> ipList = routeType switch
{
RouteType.Outbound => _directIPs,
RouteType.TUNTAP => _proxyIPs,
_ => throw new ArgumentOutOfRangeException(nameof(routeType), routeType, null)
};
string gateway = adapter.Gateway.ToString();
var index = adapter.InterfaceIndex;
#endregion
bool result;
switch (action)
{
case Action.Create:
result = NativeMethods.CreateRoute(AddressFamily.InterNetwork, ip, (byte)cidr, gateway, index, metric);
if (result && record)
ipList.Add(ipNetwork);
break;
case Action.Delete:
result = NativeMethods.DeleteRoute(AddressFamily.InterNetwork, ip, (byte)cidr, gateway, index, metric);
break;
default:
throw new ArgumentOutOfRangeException(nameof(action), action, null);
}
Global.Logger.Debug($"{action}Route(\"{ip}\", {cidr}, \"{gateway}\", {index}, {metric})");
if (!result)
Global.Logger.Warning($"Failed to invoke {action}Route(\"{ip}\", {cidr}, \"{gateway}\", {index}, {metric})");
return result;
}
bool TryParseIPNetwork(string ipNetwork, out string ip, out int cidr)
{
ip = null!;
cidr = 0;
var s = ipNetwork.Split('/');
if (s.Length != 2)
{
Global.Logger.Warning($"Failed to parse rule {ipNetwork}");
return false;
}
ip = s[0];
cidr = int.Parse(s[1]);
return true;
}
private enum RouteType
{
Outbound,
TUNTAP
}
private enum Action
{
Create,
Delete
}
#endregion
}
}

View File

@@ -19,8 +19,8 @@ namespace Netch.Controllers
public const string Name = @"Netch";
public const string Copyright = @"Copyright © 2019 - 2021";
public const string AssemblyVersion = @"1.8.3";
private const string Suffix = @"Beta1145141919";
public const string AssemblyVersion = @"1.8.5";
private const string Suffix = @"";
public static readonly string Version = $"{AssemblyVersion}{(string.IsNullOrEmpty(Suffix) ? "" : $"-{Suffix}")}";

10
Netch/Enums/Modes.cs Normal file
View File

@@ -0,0 +1,10 @@
namespace Netch.Enums
{
public enum ModeType
{
Process = 0,
ProxyRuleIPs = 1,
BypassRuleIPs = 2,
Pcap2Socks = 6
}
}

View File

@@ -43,6 +43,7 @@
this.CleanDNSCacheToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.UninstallServiceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.removeNetchFirewallRulesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ShowHideConsoleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.HelpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.CheckForUpdatesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.fAQToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
@@ -190,6 +191,7 @@
//
this.OptionsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.OpenDirectoryToolStripMenuItem,
this.ShowHideConsoleToolStripMenuItem,
this.CleanDNSCacheToolStripMenuItem,
this.UninstallServiceToolStripMenuItem,
this.removeNetchFirewallRulesToolStripMenuItem});
@@ -226,6 +228,13 @@
this.removeNetchFirewallRulesToolStripMenuItem.Text = "Remove Netch Firewall Rules";
this.removeNetchFirewallRulesToolStripMenuItem.Click += new System.EventHandler(this.RemoveNetchFirewallRulesToolStripMenuItem_Click);
//
// ShowHideConsoleToolStripMenuItem
//
this.ShowHideConsoleToolStripMenuItem.Name = "ShowHideConsoleToolStripMenuItem";
this.ShowHideConsoleToolStripMenuItem.Size = new System.Drawing.Size(243, 22);
this.ShowHideConsoleToolStripMenuItem.Text = "Show/Hide Console";
this.ShowHideConsoleToolStripMenuItem.Click += new System.EventHandler(this.ShowHideConsoleToolStripMenuItem_Click);
//
// HelpToolStripMenuItem
//
this.HelpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
@@ -782,5 +791,6 @@
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
private System.Windows.Forms.ContainerControl ButtomControlContainerControl;
private System.Windows.Forms.ToolStripMenuItem ShowHideConsoleToolStripMenuItem;
}
}

View File

@@ -14,18 +14,15 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Netch.Enums;
using Netch.Interfaces;
using Netch.Services;
using Vanara.PInvoke;
namespace Netch.Forms
{
public partial class MainForm : Form
{
private void createRouteTableModeToolStripMenuItem_Click(object sender, EventArgs e)
{
Hide();
new Route().ShowDialog();
Show();
}
#region Start
private readonly Dictionary<string, object> _mainFormText = new();
@@ -47,8 +44,6 @@ namespace Netch.Forms
// 监听电源事件
SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
CheckForIllegalCrossThreadCalls = false;
}
private void AddAddServerToolStripMenuItems()
@@ -60,7 +55,8 @@ namespace Netch.Forms
{
Name = $"Add{fullName}ServerToolStripMenuItem",
Size = new Size(259, 22),
Text = i18N.TranslateFormat("Add [{0}] Server", fullName)
Text = i18N.TranslateFormat("Add [{0}] Server", fullName),
Tag = serversUtil
};
_mainFormText.Add(control.Name, new[] { "Add [{0}] Server", fullName });
@@ -89,23 +85,23 @@ namespace Netch.Forms
// 加载快速配置
LoadProfiles();
Task.Run(() =>
BeginInvoke(new Action(async () =>
{
// 检查更新
if (Global.Settings.CheckUpdateWhenOpened)
CheckUpdate();
});
await CheckUpdate();
}));
Task.Run(() =>
BeginInvoke(new Action(async () =>
{
// 检查订阅更新
if (Global.Settings.UpdateServersWhenOpened)
UpdateServersFromSubscribe().Wait();
await UpdateServersFromSubscribe();
// 打开软件时启动加速,产生开始按钮点击事件
if (Global.Settings.StartWhenOpened)
ControlButton_Click(null, null);
});
}));
}
private void RecordSize()
@@ -227,15 +223,10 @@ namespace Netch.Forms
if (sender == null)
throw new ArgumentNullException(nameof(sender));
// TODO get Util from Tag
var s = ((ToolStripMenuItem)sender).Text;
var start = s.IndexOf("[", StringComparison.Ordinal) + 1;
var end = s.IndexOf("]", start, StringComparison.Ordinal);
var result = s.Substring(start, end - start);
var util = (IServerUtil)((ToolStripMenuItem)sender).Tag;
Hide();
ServerHelper.GetUtilByFullName(result).Create();
util.Create();
LoadServers();
Configuration.Save();
@@ -253,6 +244,13 @@ namespace Netch.Forms
Show();
}
private void createRouteTableModeToolStripMenuItem_Click(object sender, EventArgs e)
{
Hide();
new Route().ShowDialog();
Show();
}
#endregion
#region Subscription
@@ -309,32 +307,29 @@ namespace Netch.Forms
#region Options
private void CheckForUpdatesToolStripMenuItem_Click(object sender, EventArgs e)
private async void CheckForUpdatesToolStripMenuItem_Click(object sender, EventArgs e)
{
Task.Run(() =>
void OnNewVersionNotFound(object? o, EventArgs? args)
{
void OnNewVersionNotFound(object? o, EventArgs? args)
{
NotifyTip(i18N.Translate("Already latest version"));
}
NotifyTip(i18N.Translate("Already latest version"));
}
void OnNewVersionFoundFailed(object? o, EventArgs? args)
{
NotifyTip(i18N.Translate("New version found failed"), info: false);
}
void OnNewVersionFoundFailed(object? o, EventArgs? args)
{
NotifyTip(i18N.Translate("New version found failed"), info: false);
}
try
{
UpdateChecker.NewVersionNotFound += OnNewVersionNotFound;
UpdateChecker.NewVersionFoundFailed += OnNewVersionFoundFailed;
CheckUpdate();
}
finally
{
UpdateChecker.NewVersionNotFound -= OnNewVersionNotFound;
UpdateChecker.NewVersionFoundFailed -= OnNewVersionFoundFailed;
}
});
try
{
UpdateChecker.NewVersionNotFound += OnNewVersionNotFound;
UpdateChecker.NewVersionFoundFailed += OnNewVersionFoundFailed;
await CheckUpdate();
}
finally
{
UpdateChecker.NewVersionNotFound -= OnNewVersionNotFound;
UpdateChecker.NewVersionFoundFailed -= OnNewVersionFoundFailed;
}
}
private void OpenDirectoryToolStripMenuItem_Click(object sender, EventArgs e)
@@ -370,11 +365,10 @@ namespace Netch.Forms
StatusText(i18N.TranslateFormat("Uninstalling {0}", "NF Service"));
try
{
await Task.Run(() =>
{
if (NFController.UninstallDriver())
NotifyTip(i18N.TranslateFormat("{0} has been uninstalled", "NF Service"));
});
var task = Task.Run(NFController.UninstallDriver);
if (await task)
NotifyTip(i18N.TranslateFormat("{0} has been uninstalled", "NF Service"));
}
finally
{
@@ -388,6 +382,13 @@ namespace Netch.Forms
Firewall.RemoveNetchFwRules();
}
private void ShowHideConsoleToolStripMenuItem_Click(object sender, EventArgs e)
{
var windowStyles = (User32.WindowStyles)User32.GetWindowLong(Netch.ConsoleHwnd, User32.WindowLongFlags.GWL_STYLE);
var visible = windowStyles.HasFlag(User32.WindowStyles.WS_VISIBLE);
User32.ShowWindow(Netch.ConsoleHwnd, visible ? ShowWindowCommand.SW_HIDE : ShowWindowCommand.SW_SHOW);
}
#endregion
/// <summary>
@@ -421,12 +422,9 @@ namespace Netch.Forms
try
{
await Task.Run(() =>
{
Updater.Updater.DownloadAndUpdate(Path.Combine(Global.NetchDir, "data"),
Global.NetchDir,
(_, args) => BeginInvoke(new Action(() => NewVersionLabel.Text = $"{args.ProgressPercentage}%")));
});
await Updater.DownloadAndUpdate(Path.Combine(Global.NetchDir, "data"),
Global.NetchDir,
(_, args) => BeginInvoke(new Action(() => NewVersionLabel.Text = $"{args.ProgressPercentage}%")));
}
catch (Exception exception)
{
@@ -465,21 +463,20 @@ namespace Netch.Forms
{
if (!IsWaiting())
{
// 停止
await StopAsyncCore();
await StopCore();
return;
}
Configuration.Save();
// 服务器、模式 需选择
if (!(ServerComboBox.SelectedItem is Server server))
if (ServerComboBox.SelectedItem is not Server server)
{
MessageBoxX.Show(i18N.Translate("Please select a server first"));
return;
}
if (!(ModeComboBox.SelectedItem is Models.Mode mode))
if (ModeComboBox.SelectedItem is not Models.Mode mode)
{
MessageBoxX.Show(i18N.Translate("Please select a mode first"));
return;
@@ -512,21 +509,17 @@ namespace Netch.Forms
{
while (State == State.Started)
{
bool StartedPingEnabled()
{
return Global.Settings.StartedPingInterval >= 0;
}
if (StartedPingEnabled())
if (Global.Settings.StartedPingInterval >= 0)
{
server.Test();
ServerComboBox.Refresh();
}
if (StartedPingEnabled())
Thread.Sleep(Global.Settings.StartedPingInterval * 1000);
}
else
{
Thread.Sleep(5000);
}
}
});
}
@@ -566,11 +559,11 @@ namespace Netch.Forms
private void LoadServers()
{
ServerComboBox.Items.Clear();
ServerComboBox.Items.AddRange(Global.Settings.Server.ToArray());
ServerComboBox.Items.AddRange(Global.Settings.Server.Cast<object>().ToArray());
SelectLastServer();
}
public void SelectLastServer()
private void SelectLastServer()
{
// 如果值合法,选中该位置
if (Global.Settings.ServerComboBoxSelectedIndex > 0 && Global.Settings.ServerComboBoxSelectedIndex < ServerComboBox.Items.Count)
@@ -608,15 +601,20 @@ namespace Netch.Forms
private void SpeedPictureBox_Click(object sender, EventArgs e)
{
void Enable()
{
ServerComboBox.Refresh();
Enabled = true;
StatusText();
}
Enabled = false;
StatusText(i18N.Translate("Testing"));
if (!IsWaiting() || ModifierKeys == Keys.Control)
{
(ServerComboBox.SelectedItem as Server)?.Test();
ServerComboBox.Refresh();
Enabled = true;
StatusText();
Enable();
}
else
{
@@ -625,11 +623,8 @@ namespace Netch.Forms
void OnTestDelayFinished(object? o1, EventArgs? e1)
{
Refresh();
ServerHelper.DelayTestHelper.TestDelayFinished -= OnTestDelayFinished;
Enabled = true;
StatusText();
Enable();
}
}
}
@@ -688,7 +683,7 @@ namespace Netch.Forms
SelectLastMode();
}
public void SelectLastMode()
private void SelectLastMode()
{
// 如果值合法,选中该位置
if (Global.Settings.ModeComboBoxSelectedIndex > 0 && Global.Settings.ModeComboBoxSelectedIndex < ModeComboBox.Items.Count)
@@ -730,13 +725,13 @@ namespace Netch.Forms
switch (mode.Type)
{
case 0:
case ModeType.Process:
Hide();
new Process(mode).ShowDialog();
Show();
break;
case 1:
case 2:
case ModeType.ProxyRuleIPs:
case ModeType.BypassRuleIPs:
Hide();
new Route(mode).ShowDialog();
Show();
@@ -1005,25 +1000,19 @@ namespace Netch.Forms
}
}
private async Task StopAsyncCore()
{
State = State.Stopping;
await MainController.StopAsync();
State = State.Stopped;
}
public void Stop()
public async Task Stop()
{
if (IsWaiting())
return;
if (InvokeRequired)
{
Invoke(new Action(Stop));
return;
}
await StopCore();
}
StopAsyncCore().Wait();
private async Task StopCore()
{
State = State.Stopping;
await MainController.StopAsync();
State = State.Stopped;
}
private bool IsWaiting()
@@ -1123,28 +1112,33 @@ namespace Netch.Forms
}
}
private void NatTypeStatusLabel_Click(object sender, EventArgs e)
private async void NatTypeStatusLabel_Click(object sender, EventArgs e)
{
if (_state == State.Started && NttTested)
NatTest();
if (_state == State.Started && !Monitor.IsEntered(_natTestLock))
await NatTest();
}
private static bool NttTested;
private bool _natTestLock = true;
/// <summary>
/// 测试 NAT
/// </summary>
public void NatTest()
private async Task NatTest()
{
if (!MainController.Mode!.TestNatRequired())
return;
NttTested = false;
Task.Run(() =>
{
NatTypeStatusText(i18N.Translate("Starting NatTester"));
if (!_natTestLock)
return;
var (result, localEnd, publicEnd) = MainController.NTTController.Start().Result;
_natTestLock = false;
try
{
NatTypeStatusText(i18N.Translate("Testing NAT"));
// Monitor.TryEnter() Monitor.Exit() (a.k.a. lock) not work with async/await
var (result, _, publicEnd) = await MainController.NTTController.Start();
if (!string.IsNullOrEmpty(publicEnd))
{
@@ -1155,9 +1149,11 @@ namespace Netch.Forms
{
NatTypeStatusText(result ?? "Error");
}
NttTested = true;
});
}
finally
{
_natTestLock = true;
}
}
#endregion
@@ -1235,8 +1231,7 @@ namespace Netch.Forms
if (File.Exists(file))
File.Delete(file);
if (IsWaiting())
await StopAsyncCore();
await Stop();
Dispose();
Environment.Exit(Environment.ExitCode);
@@ -1266,12 +1261,12 @@ namespace Netch.Forms
#region Updater
private void CheckUpdate()
private async Task CheckUpdate()
{
try
{
UpdateChecker.NewVersionFound += OnUpdateCheckerOnNewVersionFound;
UpdateChecker.Check(Global.Settings.CheckBetaUpdate).Wait();
await UpdateChecker.Check(Global.Settings.CheckBetaUpdate);
if (Flags.AlwaysShowNewVersionFound)
OnUpdateCheckerOnNewVersionFound(null!, null!);
}
@@ -1386,7 +1381,7 @@ namespace Netch.Forms
private void ComboBox_DrawItem(object sender, DrawItemEventArgs e)
{
if (!(sender is ComboBox cbx))
if (sender is not ComboBox cbx)
return;
// 绘制背景颜色
@@ -1401,38 +1396,38 @@ namespace Netch.Forms
switch (cbx.Items[e.Index])
{
case Server item:
{
// 计算延迟底色
var numBoxBackBrush = item.Delay switch { > 200 => Brushes.Red, > 80 => Brushes.Yellow, >= 0 => _greenBrush, _ => Brushes.Gray };
{
// 计算延迟底色
var numBoxBackBrush = item.Delay switch { > 200 => Brushes.Red, > 80 => Brushes.Yellow, >= 0 => _greenBrush, _ => Brushes.Gray };
// 绘制延迟底色
e.Graphics.FillRectangle(numBoxBackBrush, _numberBoxX, e.Bounds.Y, _numberBoxWidth, e.Bounds.Height);
// 绘制延迟底色
e.Graphics.FillRectangle(numBoxBackBrush, _numberBoxX, e.Bounds.Y, _numberBoxWidth, e.Bounds.Height);
// 绘制延迟字符串
TextRenderer.DrawText(e.Graphics,
item.Delay.ToString(),
cbx.Font,
new Point(_numberBoxX + _numberBoxWrap, e.Bounds.Y),
Color.Black,
TextFormatFlags.Left);
// 绘制延迟字符串
TextRenderer.DrawText(e.Graphics,
item.Delay.ToString(),
cbx.Font,
new Point(_numberBoxX + _numberBoxWrap, e.Bounds.Y),
Color.Black,
TextFormatFlags.Left);
break;
}
break;
}
case Models.Mode item:
{
// 绘制 模式Box 底色
e.Graphics.FillRectangle(Brushes.Gray, _numberBoxX, e.Bounds.Y, _numberBoxWidth, e.Bounds.Height);
{
// 绘制 模式Box 底色
e.Graphics.FillRectangle(Brushes.Gray, _numberBoxX, e.Bounds.Y, _numberBoxWidth, e.Bounds.Height);
// 绘制 模式行数 字符串
TextRenderer.DrawText(e.Graphics,
item.Rule.Count.ToString(),
cbx.Font,
new Point(_numberBoxX + _numberBoxWrap, e.Bounds.Y),
Color.Black,
TextFormatFlags.Left);
// 绘制 模式行数 字符串
TextRenderer.DrawText(e.Graphics,
item.Content.Count.ToString(),
cbx.Font,
new Point(_numberBoxX + _numberBoxWrap, e.Bounds.Y),
Color.Black,
TextFormatFlags.Left);
break;
}
break;
}
}
}

View File

@@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using Netch.Enums;
namespace Netch.Forms.Mode
{
@@ -24,7 +25,7 @@ namespace Netch.Forms.Mode
/// <param name="mode">模式</param>
public Process(Models.Mode? mode = null)
{
if (mode != null && mode.Type is not 0)
if (mode != null && mode.Type is not ModeType.Process)
throw new ArgumentOutOfRangeException();
InitializeComponent();
@@ -62,7 +63,7 @@ namespace Netch.Forms.Mode
RemarkTextBox.TextChanged -= RemarkTextBox_TextChanged;
RemarkTextBox.Text = _mode.Remark;
FilenameTextBox.Text = _mode.RelativePath;
RuleAddRange(_mode.Rule);
RuleAddRange(_mode.Content);
}
i18N.TranslateForm(this);
@@ -116,8 +117,8 @@ namespace Netch.Forms.Mode
if (_mode != null)
{
_mode.Remark = RemarkTextBox.Text;
_mode.Rule.Clear();
_mode.Rule.AddRange(RuleRichTextBox.Lines);
_mode.Content.Clear();
_mode.Content.AddRange(RuleRichTextBox.Lines);
_mode.WriteFile();
MessageBoxX.Show(i18N.Translate("Mode updated successfully"));
@@ -134,11 +135,11 @@ namespace Netch.Forms.Mode
var mode = new Models.Mode(fullName)
{
Type = 0,
Type = ModeType.Process,
Remark = RemarkTextBox.Text
};
mode.Rule.AddRange(RuleRichTextBox.Lines);
mode.Content.AddRange(RuleRichTextBox.Lines);
mode.WriteFile();
MessageBoxX.Show(i18N.Translate("Mode added successfully"));

View File

@@ -4,18 +4,20 @@ using Netch.Utils;
using System;
using System.IO;
using System.Windows.Forms;
using Netch.Enums;
namespace Netch.Forms.Mode
{
public partial class Route : Form
{
private readonly TagItem<int>[] _items = { new(1, "Proxy Rule IPs"), new(2, "Bypass Rule IPs") };
private readonly TagItem<ModeType>[] _items =
{ new(ModeType.ProxyRuleIPs, "Proxy Rule IPs"), new(ModeType.BypassRuleIPs, "Bypass Rule IPs") };
private readonly Models.Mode? _mode;
public Route(Models.Mode? mode = null)
{
if (mode != null && mode.Type is not (1 or 2))
if (mode != null && mode.Type is not (ModeType.ProxyRuleIPs or ModeType.BypassRuleIPs))
throw new ArgumentOutOfRangeException();
_mode = mode;
@@ -37,7 +39,7 @@ namespace Netch.Forms.Mode
RemarkTextBox.Text = _mode.Remark;
comboBox1.SelectedValue = _mode.Type; // ComboBox SelectedValue worked after ctor
FilenameTextBox.Text = _mode.RelativePath;
richTextBox1.Lines = _mode.Rule.ToArray();
richTextBox1.Lines = _mode.Content.ToArray();
}
i18N.TranslateForm(this);
@@ -60,9 +62,9 @@ namespace Netch.Forms.Mode
if (_mode != null)
{
_mode.Remark = RemarkTextBox.Text;
_mode.Rule.Clear();
_mode.Rule.AddRange(richTextBox1.Lines);
_mode.Type = (int)comboBox1.SelectedValue;
_mode.Content.Clear();
_mode.Content.AddRange(richTextBox1.Lines);
_mode.Type = (ModeType)comboBox1.SelectedValue;
_mode.WriteFile();
MessageBoxX.Show(i18N.Translate("Mode updated successfully"));
@@ -79,11 +81,11 @@ namespace Netch.Forms.Mode
var mode = new Models.Mode(fullName)
{
Type = (int)comboBox1.SelectedValue,
Type = (ModeType)comboBox1.SelectedValue,
Remark = RemarkTextBox.Text
};
mode.Rule.AddRange(richTextBox1.Lines);
mode.Content.AddRange(richTextBox1.Lines);
mode.WriteFile();
MessageBoxX.Show(i18N.Translate("Mode added successfully"));

View File

@@ -104,8 +104,8 @@ namespace Netch.Forms
this.CheckBetaUpdateCheckBox = new System.Windows.Forms.CheckBox();
this.UpdateServersWhenOpenedCheckBox = new System.Windows.Forms.CheckBox();
this.AioDNSTabPage = new System.Windows.Forms.TabPage();
this.AioDNSRuleRuleLabel = new System.Windows.Forms.Label();
this.AioDNSRulePathTextBox = new System.Windows.Forms.TextBox();
this.AioDNSListenPortLabel = new System.Windows.Forms.Label();
this.AioDNSListenPortTextBox = new System.Windows.Forms.TextBox();
this.ChinaDNSLabel = new System.Windows.Forms.Label();
this.ChinaDNSTextBox = new System.Windows.Forms.TextBox();
this.OtherDNSLabel = new System.Windows.Forms.Label();
@@ -175,7 +175,7 @@ namespace Netch.Forms
this.PortGroupBox.Controls.Add(this.AllowDevicesCheckBox);
this.PortGroupBox.Location = new System.Drawing.Point(8, 6);
this.PortGroupBox.Name = "PortGroupBox";
this.PortGroupBox.Size = new System.Drawing.Size(241, 140);
this.PortGroupBox.Size = new System.Drawing.Size(241, 115);
this.PortGroupBox.TabIndex = 0;
this.PortGroupBox.TabStop = false;
this.PortGroupBox.Text = "Local Port";
@@ -217,7 +217,7 @@ namespace Netch.Forms
// AllowDevicesCheckBox
//
this.AllowDevicesCheckBox.AutoSize = true;
this.AllowDevicesCheckBox.Location = new System.Drawing.Point(6, 107);
this.AllowDevicesCheckBox.Location = new System.Drawing.Point(6, 84);
this.AllowDevicesCheckBox.Name = "AllowDevicesCheckBox";
this.AllowDevicesCheckBox.Size = new System.Drawing.Size(206, 21);
this.AllowDevicesCheckBox.TabIndex = 6;
@@ -240,9 +240,9 @@ namespace Netch.Forms
this.ServerPingTypeLabel.AutoSize = true;
this.ServerPingTypeLabel.Location = new System.Drawing.Point(267, 44);
this.ServerPingTypeLabel.Name = "ServerPingTypeLabel";
this.ServerPingTypeLabel.Size = new System.Drawing.Size(98, 17);
this.ServerPingTypeLabel.Size = new System.Drawing.Size(86, 17);
this.ServerPingTypeLabel.TabIndex = 2;
this.ServerPingTypeLabel.Text = "ServerPingType";
this.ServerPingTypeLabel.Text = "Ping Protocol";
//
// ICMPingRadioBtn
//
@@ -269,24 +269,24 @@ namespace Netch.Forms
// ProfileCountLabel
//
this.ProfileCountLabel.AutoSize = true;
this.ProfileCountLabel.Location = new System.Drawing.Point(12, 160);
this.ProfileCountLabel.Location = new System.Drawing.Point(15, 140);
this.ProfileCountLabel.Name = "ProfileCountLabel";
this.ProfileCountLabel.Size = new System.Drawing.Size(79, 17);
this.ProfileCountLabel.Size = new System.Drawing.Size(83, 17);
this.ProfileCountLabel.TabIndex = 5;
this.ProfileCountLabel.Text = "ProfileCount";
this.ProfileCountLabel.Text = "Profile Count";
//
// ProfileCountTextBox
//
this.ProfileCountTextBox.Location = new System.Drawing.Point(120, 157);
this.ProfileCountTextBox.Location = new System.Drawing.Point(182, 137);
this.ProfileCountTextBox.Name = "ProfileCountTextBox";
this.ProfileCountTextBox.Size = new System.Drawing.Size(90, 23);
this.ProfileCountTextBox.Size = new System.Drawing.Size(70, 23);
this.ProfileCountTextBox.TabIndex = 6;
this.ProfileCountTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// DetectionTickLabel
//
this.DetectionTickLabel.AutoSize = true;
this.DetectionTickLabel.Location = new System.Drawing.Point(225, 160);
this.DetectionTickLabel.Location = new System.Drawing.Point(15, 170);
this.DetectionTickLabel.Name = "DetectionTickLabel";
this.DetectionTickLabel.Size = new System.Drawing.Size(117, 17);
this.DetectionTickLabel.TabIndex = 7;
@@ -294,33 +294,33 @@ namespace Netch.Forms
//
// DetectionTickTextBox
//
this.DetectionTickTextBox.Location = new System.Drawing.Point(366, 157);
this.DetectionTickTextBox.Location = new System.Drawing.Point(182, 167);
this.DetectionTickTextBox.Name = "DetectionTickTextBox";
this.DetectionTickTextBox.Size = new System.Drawing.Size(68, 23);
this.DetectionTickTextBox.Size = new System.Drawing.Size(70, 23);
this.DetectionTickTextBox.TabIndex = 8;
this.DetectionTickTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// StartedPingLabel
//
this.StartedPingLabel.AutoSize = true;
this.StartedPingLabel.Location = new System.Drawing.Point(12, 187);
this.StartedPingLabel.Location = new System.Drawing.Point(15, 200);
this.StartedPingLabel.Name = "StartedPingLabel";
this.StartedPingLabel.Size = new System.Drawing.Size(126, 17);
this.StartedPingLabel.Size = new System.Drawing.Size(153, 17);
this.StartedPingLabel.TabIndex = 9;
this.StartedPingLabel.Text = "Delay test after start";
this.StartedPingLabel.Text = "Delay test after start(sec)";
//
// StartedPingIntervalTextBox
//
this.StartedPingIntervalTextBox.Location = new System.Drawing.Point(177, 184);
this.StartedPingIntervalTextBox.Location = new System.Drawing.Point(182, 197);
this.StartedPingIntervalTextBox.Name = "StartedPingIntervalTextBox";
this.StartedPingIntervalTextBox.Size = new System.Drawing.Size(68, 23);
this.StartedPingIntervalTextBox.Size = new System.Drawing.Size(70, 23);
this.StartedPingIntervalTextBox.TabIndex = 10;
this.StartedPingIntervalTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// STUNServerLabel
//
this.STUNServerLabel.AutoSize = true;
this.STUNServerLabel.Location = new System.Drawing.Point(12, 216);
this.STUNServerLabel.Location = new System.Drawing.Point(15, 230);
this.STUNServerLabel.Name = "STUNServerLabel";
this.STUNServerLabel.Size = new System.Drawing.Size(82, 17);
this.STUNServerLabel.TabIndex = 11;
@@ -329,15 +329,15 @@ namespace Netch.Forms
// STUN_ServerComboBox
//
this.STUN_ServerComboBox.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.Suggest;
this.STUN_ServerComboBox.Location = new System.Drawing.Point(120, 213);
this.STUN_ServerComboBox.Location = new System.Drawing.Point(182, 227);
this.STUN_ServerComboBox.Name = "STUN_ServerComboBox";
this.STUN_ServerComboBox.Size = new System.Drawing.Size(314, 25);
this.STUN_ServerComboBox.Size = new System.Drawing.Size(264, 25);
this.STUN_ServerComboBox.TabIndex = 12;
//
// LanguageLabel
//
this.LanguageLabel.AutoSize = true;
this.LanguageLabel.Location = new System.Drawing.Point(12, 254);
this.LanguageLabel.Location = new System.Drawing.Point(15, 260);
this.LanguageLabel.Name = "LanguageLabel";
this.LanguageLabel.Size = new System.Drawing.Size(65, 17);
this.LanguageLabel.TabIndex = 15;
@@ -347,9 +347,9 @@ namespace Netch.Forms
//
this.LanguageComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.LanguageComboBox.FormattingEnabled = true;
this.LanguageComboBox.Location = new System.Drawing.Point(120, 251);
this.LanguageComboBox.Location = new System.Drawing.Point(182, 257);
this.LanguageComboBox.Name = "LanguageComboBox";
this.LanguageComboBox.Size = new System.Drawing.Size(121, 25);
this.LanguageComboBox.Size = new System.Drawing.Size(110, 25);
this.LanguageComboBox.TabIndex = 16;
//
// NFTabPage
@@ -872,8 +872,8 @@ namespace Netch.Forms
//
// AioDNSTabPage
//
this.AioDNSTabPage.Controls.Add(this.AioDNSRuleRuleLabel);
this.AioDNSTabPage.Controls.Add(this.AioDNSRulePathTextBox);
this.AioDNSTabPage.Controls.Add(this.AioDNSListenPortLabel);
this.AioDNSTabPage.Controls.Add(this.AioDNSListenPortTextBox);
this.AioDNSTabPage.Controls.Add(this.ChinaDNSLabel);
this.AioDNSTabPage.Controls.Add(this.ChinaDNSTextBox);
this.AioDNSTabPage.Controls.Add(this.OtherDNSLabel);
@@ -886,27 +886,27 @@ namespace Netch.Forms
this.AioDNSTabPage.Text = "AioDNS";
this.AioDNSTabPage.UseVisualStyleBackColor = true;
//
// AioDNSRuleRuleLabel
// AioDNSListenPortLabel
//
this.AioDNSRuleRuleLabel.AutoSize = true;
this.AioDNSRuleRuleLabel.Location = new System.Drawing.Point(16, 30);
this.AioDNSRuleRuleLabel.Name = "AioDNSRuleRuleLabel";
this.AioDNSRuleRuleLabel.Size = new System.Drawing.Size(56, 17);
this.AioDNSRuleRuleLabel.TabIndex = 0;
this.AioDNSRuleRuleLabel.Text = "Rule File";
this.AioDNSListenPortLabel.AutoSize = true;
this.AioDNSListenPortLabel.Location = new System.Drawing.Point(15, 103);
this.AioDNSListenPortLabel.Name = "AioDNSListenPortLabel";
this.AioDNSListenPortLabel.Size = new System.Drawing.Size(69, 17);
this.AioDNSListenPortLabel.TabIndex = 0;
this.AioDNSListenPortLabel.Text = "Listen Port";
//
// AioDNSRulePathTextBox
// AioDNSListenPortTextBox
//
this.AioDNSRulePathTextBox.Enabled = false;
this.AioDNSRulePathTextBox.Location = new System.Drawing.Point(150, 30);
this.AioDNSRulePathTextBox.Name = "AioDNSRulePathTextBox";
this.AioDNSRulePathTextBox.Size = new System.Drawing.Size(201, 23);
this.AioDNSRulePathTextBox.TabIndex = 1;
this.AioDNSListenPortTextBox.Location = new System.Drawing.Point(150, 100);
this.AioDNSListenPortTextBox.Name = "AioDNSListenPortTextBox";
this.AioDNSListenPortTextBox.Size = new System.Drawing.Size(80, 23);
this.AioDNSListenPortTextBox.TabIndex = 1;
this.AioDNSListenPortTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// ChinaDNSLabel
//
this.ChinaDNSLabel.AutoSize = true;
this.ChinaDNSLabel.Location = new System.Drawing.Point(16, 70);
this.ChinaDNSLabel.Location = new System.Drawing.Point(15, 23);
this.ChinaDNSLabel.Name = "ChinaDNSLabel";
this.ChinaDNSLabel.Size = new System.Drawing.Size(70, 17);
this.ChinaDNSLabel.TabIndex = 2;
@@ -914,7 +914,7 @@ namespace Netch.Forms
//
// ChinaDNSTextBox
//
this.ChinaDNSTextBox.Location = new System.Drawing.Point(150, 70);
this.ChinaDNSTextBox.Location = new System.Drawing.Point(150, 20);
this.ChinaDNSTextBox.Name = "ChinaDNSTextBox";
this.ChinaDNSTextBox.Size = new System.Drawing.Size(201, 23);
this.ChinaDNSTextBox.TabIndex = 3;
@@ -923,7 +923,7 @@ namespace Netch.Forms
// OtherDNSLabel
//
this.OtherDNSLabel.AutoSize = true;
this.OtherDNSLabel.Location = new System.Drawing.Point(16, 110);
this.OtherDNSLabel.Location = new System.Drawing.Point(15, 63);
this.OtherDNSLabel.Name = "OtherDNSLabel";
this.OtherDNSLabel.Size = new System.Drawing.Size(71, 17);
this.OtherDNSLabel.TabIndex = 4;
@@ -931,7 +931,7 @@ namespace Netch.Forms
//
// OtherDNSTextBox
//
this.OtherDNSTextBox.Location = new System.Drawing.Point(150, 110);
this.OtherDNSTextBox.Location = new System.Drawing.Point(150, 60);
this.OtherDNSTextBox.Name = "OtherDNSTextBox";
this.OtherDNSTextBox.Size = new System.Drawing.Size(201, 23);
this.OtherDNSTextBox.TabIndex = 5;
@@ -1067,8 +1067,8 @@ namespace Netch.Forms
private System.Windows.Forms.TextBox ttiTextBox;
private System.Windows.Forms.CheckBox UseMuxCheckBox;
private System.Windows.Forms.TabPage AioDNSTabPage;
private System.Windows.Forms.Label AioDNSRuleRuleLabel;
private System.Windows.Forms.TextBox AioDNSRulePathTextBox;
private System.Windows.Forms.Label AioDNSListenPortLabel;
private System.Windows.Forms.TextBox AioDNSListenPortTextBox;
private System.Windows.Forms.Label OtherDNSLabel;
private System.Windows.Forms.Label ChinaDNSLabel;
private System.Windows.Forms.TextBox OtherDNSTextBox;

View File

@@ -211,12 +211,15 @@ namespace Netch.Forms
#region AioDNS
BindTextBox(AioDNSRulePathTextBox, _ => true, s => Global.Settings.AioDNS.RulePath = s, Global.Settings.AioDNS.RulePath);
BindTextBox(ChinaDNSTextBox, _ => true, s => Global.Settings.AioDNS.ChinaDNS = s, Global.Settings.AioDNS.ChinaDNS);
BindTextBox(OtherDNSTextBox, _ => true, s => Global.Settings.AioDNS.OtherDNS = s, Global.Settings.AioDNS.OtherDNS);
BindTextBox(AioDNSListenPortTextBox,
s => ushort.TryParse(s, out _),
s => Global.Settings.AioDNS.ListenPort = ushort.Parse(s),
Global.Settings.AioDNS.ListenPort);
#endregion
}

View File

@@ -1,4 +1,4 @@
namespace Netch.Controllers
namespace Netch.Interfaces
{
public interface IController
{

View File

@@ -1,6 +1,6 @@
using Netch.Models;
namespace Netch.Controllers
namespace Netch.Interfaces
{
public interface IModeController : IController
{

View File

@@ -1,6 +1,6 @@
using Netch.Models;
namespace Netch.Controllers
namespace Netch.Interfaces
{
public interface IServerController : IController
{

View File

@@ -1,8 +1,8 @@
using Netch.Controllers;
using System;
using System;
using System.Collections.Generic;
using Netch.Models;
namespace Netch.Models
namespace Netch.Interfaces
{
public interface IServerUtil
{
@@ -28,7 +28,7 @@ namespace Netch.Models
/// </summary>
string[] UriScheme { get; }
public abstract Type ServerType { get; }
public Type ServerType { get; }
public void Edit(Server s);
@@ -36,9 +36,9 @@ namespace Netch.Models
string GetShareLink(Server s);
public abstract IServerController GetController();
public IServerController GetController();
public abstract IEnumerable<Server> ParseUri(string text);
public IEnumerable<Server> ParseUri(string text);
bool CheckServer(Server s);
}

View File

@@ -3,12 +3,13 @@ using System.Text;
namespace Netch.Interops
{
public static class AioDNSInterops
public static class AioDNS
{
private const string aiodns_bin = "aiodns.bin";
public static bool Dial(NameList name, string value)
{
Global.Logger.Debug($"[aiodns] Dial {name}: {value}");
return aiodns_dial(name, Encoding.UTF8.GetBytes(value));
}

View File

@@ -2,7 +2,7 @@ using System.Runtime.InteropServices;
namespace Netch.Interops
{
public static class RedirectorInterop
public static class Redirector
{
public enum NameList
{
@@ -42,7 +42,7 @@ namespace Netch.Interops
public static bool Dial(NameList name, string value)
{
Global.Logger.Debug($"Dial {name} {value}");
Global.Logger.Debug($"[Redirector] Dial {name}: {value}");
return aio_dial(name, value);
}

View File

@@ -0,0 +1,26 @@
using System.Net.Sockets;
using System.Runtime.InteropServices;
namespace Netch.Interops
{
public static class RouteHelper
{
[DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)]
public static extern ulong ConvertLuidToIndex(ulong id);
[DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)]
public static extern bool CreateIPv4(string address, string netmask, ulong index);
[DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)]
public static extern bool CreateUnicastIP(AddressFamily inet, string address, byte cidr, ulong index);
[DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)]
public static extern bool RefreshIPTable(AddressFamily inet, ulong index);
[DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)]
public static extern bool CreateRoute(AddressFamily inet, string address, byte cidr, string gateway, ulong index, int metric);
[DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)]
public static extern bool DeleteRoute(AddressFamily inet, string address, byte cidr, string gateway, ulong index, int metric);
}
}

View File

@@ -3,7 +3,7 @@ using System.Text;
namespace Netch.Interops
{
public static class TUNInterop
public static class tun2socks
{
public enum NameList
{
@@ -35,12 +35,13 @@ namespace Netch.Interops
public static bool Dial(NameList name, string value)
{
Global.Logger.Debug($"Dial {name} {value}");
Global.Logger.Debug($"[tun2socks] Dial {name}: {value}");
return tun_dial(name, Encoding.UTF8.GetBytes(value));
}
public static bool Init()
{
Global.Logger.Debug($"[tun2socks] init");
return tun_init();
}

View File

@@ -87,7 +87,7 @@ namespace Netch.Models.GitHubRelease
if (versionComparison != 0)
return versionComparison;
var suffixExistComparison = (Suffix != null ? 1 : 0) - (other.Suffix != null ? 1 : 0);
var suffixExistComparison = (Suffix == null ? 1 : 0) - (other.Suffix == null ? 1 : 0);
if (suffixExistComparison != 0)
return suffixExistComparison;

View File

@@ -1,14 +0,0 @@
using System.Net;
using System.Net.NetworkInformation;
namespace Netch.Models
{
public interface IAdapter
{
ulong InterfaceIndex { get; }
IPAddress Gateway { get; }
NetworkInterface NetworkInterface { get; }
}
}

View File

@@ -4,138 +4,126 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Netch.Enums;
namespace Netch.Models
{
public class Mode
{
private readonly Lazy<List<string>> _lazyRule;
public string? FullName { get; private set; }
/// <summary>
///
/// </summary>
/// <param name="fullName">Mode File FullPath</param>
/// <exception cref="FormatException"></exception>
/// <exception cref="NotSupportedException"></exception>
public Mode(string? fullName)
{
_lazyRule = new Lazy<List<string>>(ReadRules);
if (fullName == null)
return;
FullName = fullName;
if (!File.Exists(FullName))
if (FullName == null || !File.Exists(FullName))
return;
var text = File.ReadLines(FullName).First();
// load head
if (text.First() != '#')
throw new Exception($"mode {FullName} head not found at Line 0");
var split = text.Substring(1).SplitTrimEntries(',');
Remark = split[0];
var typeResult = int.TryParse(split.ElementAtOrDefault(1), out var type);
Type = typeResult ? type : 0;
if (!ModeHelper.ModeTypes.Contains(Type))
throw new NotSupportedException($"not support mode \"[{Type}]{Remark}\".");
(Remark, Type) = ReadHead(FullName);
}
public string? FullName { get; }
/// <summary>
/// 规则
/// </summary>
public List<string> Rule => _lazyRule.Value;
public List<string> Content => _content ??= ReadContent();
private List<string>? _content;
/// <summary>
/// 备注
/// </summary>
public string Remark { get; set; } = "";
/// <summary>
/// 类型
/// <para />
/// 0. Socks5 + 进程加速
/// <para />
/// 1. Socks5 + TUN/TAP 规则内 IP CIDR 加速
/// <para />
/// 2. Socks5 + TUN/TAP 全局,绕过规则内 IP CIDR
/// <para />
/// 3. Socks5 + HTTP 代理(设置到系统代理)
/// <para />
/// 4. Socks5 代理(不设置到系统代理)
/// <para />
/// 5. Socks5 + HTTP 代理(不设置到系统代理)
/// <para />
/// </summary>
public int Type { get; set; } = 0;
public ModeType Type { get; set; } = ModeType.Process;
/// <summary>
/// 文件相对路径(必须是存在的文件)
/// </summary>
public string? RelativePath => FullName == null ? null : ModeHelper.GetRelativePath(FullName);
public List<string> FullRule
public IEnumerable<string> GetRules()
{
get
var result = new List<string>();
foreach (var s in Content)
{
var result = new List<string>();
foreach (var s in Rule)
if (string.IsNullOrWhiteSpace(s))
continue;
if (s.StartsWith("//"))
continue;
const string include = "#include";
if (s.StartsWith(include))
{
if (string.IsNullOrWhiteSpace(s))
continue;
var relativePath = new StringBuilder(s[include.Length..].Trim());
relativePath.Replace("<", "").Replace(">", "");
relativePath.Replace(".h", ".txt");
if (s.StartsWith("//"))
continue;
var mode = Global.Modes.FirstOrDefault(m => m.RelativePath?.Equals(relativePath.ToString()) ?? false) ??
throw new MessageException($"{relativePath} file included in {Remark} not found");
if (s.StartsWith("#include"))
{
var relativePath = new StringBuilder(s.Substring(8).Trim());
relativePath.Replace("<", "");
relativePath.Replace(">", "");
relativePath.Replace(".h", ".txt");
if (mode == this)
throw new MessageException("Can't self-reference");
var mode = Global.Modes.FirstOrDefault(m => m.FullName != null && m.RelativePath!.Equals(relativePath.ToString()));
if (mode.Type != Type)
throw new MessageException($"{mode.Remark}'s mode is not as same as {Remark}'s mode");
if (mode == null)
throw new MessageException($"{relativePath} file included in {Remark} not found");
if (mode.Content.Any(rule => rule.StartsWith(include)))
throw new Exception("Cannot reference mode that reference other mode");
if (mode == this)
throw new MessageException("Can't self-reference");
if (mode.Type != Type)
throw new MessageException($"{mode.Remark}'s mode is not as same as {Remark}'s mode");
if (mode.Rule.Any(rule => rule.StartsWith("#include")))
throw new Exception("Cannot reference mode that reference other mode");
result.AddRange(mode.FullRule);
}
else
{
result.Add(s);
}
result.AddRange(mode.GetRules());
}
else
{
result.Add(s);
}
return result;
}
return result;
}
private List<string> ReadRules()
private static (string, ModeType) ReadHead(string fileName)
{
var text = File.ReadLines(fileName).First();
if (text.First() != '#')
throw new FormatException($"{fileName} head not found at Line 0");
var split = text[1..].SplitTrimEntries(',');
var typeNumber = int.TryParse(split.ElementAtOrDefault(1), out var type) ? type : 0;
if (!Enum.GetValues(typeof(ModeType)).Cast<int>().Contains(typeNumber))
throw new NotSupportedException($"Not support mode \"{typeNumber}\".");
return (split[0], (ModeType)typeNumber);
}
private List<string> ReadContent()
{
if (FullName == null || !File.Exists(FullName))
return new List<string>();
return File.ReadLines(FullName!).Skip(1).ToList();
return File.ReadLines(FullName).Skip(1).ToList();
}
public void WriteFile(string? fullName = null)
public void ResetContent()
{
if (fullName != null)
throw new NotImplementedException();
_content = null;
}
public void WriteFile()
{
var dir = Path.GetDirectoryName(FullName)!;
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
var content = $"# {Remark}, {(int)Type}{Constants.EOF}{string.Join(Constants.EOF, Content)}";
// 写入到模式文件里
File.WriteAllText(FullName!, ToFileString());
File.WriteAllText(FullName!, content);
}
/// <summary>
@@ -144,16 +132,7 @@ namespace Netch.Models
/// <returns>备注</returns>
public override string ToString()
{
return $"[{Type + 1}] {i18N.Translate(Remark)}";
}
/// <summary>
/// 获取模式文件字符串
/// </summary>
/// <returns>模式文件字符串</returns>
public string ToFileString()
{
return $"# {Remark}, {Type}{Constants.EOF}{string.Join(Constants.EOF, Rule)}";
return $"[{(int)Type + 1}] {i18N.Translate(Remark)}";
}
}
@@ -162,7 +141,7 @@ namespace Netch.Models
/// 是否会转发 UDP
public static bool TestNatRequired(this Mode mode)
{
return mode.Type is 0 or 2;
return mode.Type is ModeType.Process or ModeType.BypassRuleIPs;
}
}
}

50
Netch/Models/NetRoute.cs Normal file
View File

@@ -0,0 +1,50 @@
using System;
using System.Net;
using Vanara.PInvoke;
namespace Netch.Models
{
public struct NetRoute
{
public static NetRoute TemplateBuilder(string gateway, int interfaceIndex, int metric = 0)
{
return new()
{
Gateway = gateway,
InterfaceIndex = interfaceIndex,
Metric = metric
};
}
public static (NetRoute, IPAddress address) GetBestRouteTemplate()
{
if (IpHlpApi.GetBestRoute(BitConverter.ToUInt32(IPAddress.Parse("114.114.114.114").GetAddressBytes(), 0), 0, out var route) != 0)
throw new MessageException("GetBestRoute 搜索失败");
var address = new IPAddress(route.dwForwardNextHop.S_addr);
var gateway = new IPAddress(route.dwForwardNextHop.S_un_b);
return (TemplateBuilder(gateway.ToString(), (int)route.dwForwardIfIndex), address);
}
public int InterfaceIndex;
public string Gateway;
public string Network;
public byte Cidr;
public int Metric;
public NetRoute FillTemplate(string network, byte cidr, int? metric = null)
{
var o = (NetRoute)MemberwiseClone();
o.Network = network;
o.Cidr = cidr;
if (metric != null)
o.Metric = (int)metric;
return o;
}
}
}

View File

@@ -1,12 +1,12 @@
namespace Netch.Models
{
public readonly struct Range
public readonly struct NumberRange
{
public int Start { get; }
public int End { get; }
public Range(int start, int end)
public NumberRange(int start, int end)
{
Start = start;
End = end;

View File

@@ -1,45 +0,0 @@
using System;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using Vanara.PInvoke;
namespace Netch.Models
{
public class OutboundAdapter : IAdapter
{
public OutboundAdapter()
{
// 寻找出口适配器
if (IpHlpApi.GetBestRoute(BitConverter.ToUInt32(IPAddress.Parse("114.114.114.114").GetAddressBytes(), 0), 0, out var pRoute) != 0)
{
throw new MessageException("GetBestRoute 搜索失败");
}
NetworkInterface = NetworkInterface.GetAllNetworkInterfaces()
.First(ni => ni.Supports(NetworkInterfaceComponent.IPv4) &&
ni.GetIPProperties().GetIPv4Properties().Index == pRoute.dwForwardIfIndex);
Address = new IPAddress(pRoute.dwForwardNextHop.S_addr);
InterfaceIndex = (ulong)pRoute.dwForwardIfIndex;
Gateway = new IPAddress(pRoute.dwForwardNextHop.S_un_b);
Global.Logger.Info($"出口 网关 地址:{Gateway}");
Global.Logger.Info($"出口适配器:{NetworkInterface.Name} {NetworkInterface.Id} {NetworkInterface.Description}, index: {InterfaceIndex}");
}
public IPAddress Address { get; }
/// <summary>
/// 索引
/// </summary>
public ulong InterfaceIndex { get; }
/// <summary>
/// 网关
/// </summary>
public IPAddress Gateway { get; }
public NetworkInterface NetworkInterface { get; }
}
}

View File

@@ -80,9 +80,7 @@ namespace Netch.Models
public string OtherDNS { get; set; } = "tcp://1.1.1.1:53";
public ushort ListenPort { get; set; } = 53;
public string RulePath { get; set; } = "bin\\aiodns.conf";
public ushort ListenPort { get; set; } = 253;
}
public class RedirectorConfig

View File

@@ -1,26 +0,0 @@
using Netch.Interops;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
namespace Netch.Models
{
public class TunAdapter : IAdapter
{
public TunAdapter()
{
InterfaceIndex = NativeMethods.ConvertLuidToIndex(TUNInterop.tun_luid());
NetworkInterface = NetworkInterface.GetAllNetworkInterfaces().First(i => i.GetIPProperties().GetIPv4Properties().Index == (int)InterfaceIndex);
Gateway = IPAddress.Parse(Global.Settings.TUNTAP.Gateway);
Global.Logger.Info($"WinTUN 适配器:{NetworkInterface.Name} {NetworkInterface.Id} {NetworkInterface.Description}, index: {InterfaceIndex}");
}
public ulong InterfaceIndex { get; }
public IPAddress Gateway { get; }
public NetworkInterface NetworkInterface { get; }
}
}

View File

@@ -1,5 +1,4 @@
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices;
namespace Netch
{
@@ -7,23 +6,5 @@ namespace Netch
{
[DllImport("dnsapi", EntryPoint = "DnsFlushResolverCache")]
public static extern uint RefreshDNSCache();
[DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)]
public static extern ulong ConvertLuidToIndex(ulong id);
[DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)]
public static extern bool CreateIPv4(string address, string netmask, ulong index);
[DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)]
public static extern bool CreateUnicastIP(AddressFamily inet, string address, byte cidr, ulong index);
[DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)]
public static extern bool RefreshIPTable(AddressFamily inet, ulong index);
[DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)]
public static extern bool CreateRoute(AddressFamily inet, string address, byte cidr, string gateway, ulong index, int metric);
[DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)]
public static extern bool DeleteRoute(AddressFamily inet, string address, byte cidr, string gateway, ulong index, int metric);
}
}

View File

@@ -1,6 +1,7 @@
using Netch.Controllers;
using Netch.Forms;
using Netch.Utils;
using Netch.Services;
using System;
using System.Collections.Generic;
using System.IO;
@@ -8,6 +9,7 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Vanara.PInvoke;
using static Vanara.PInvoke.Kernel32;
namespace Netch
@@ -16,17 +18,17 @@ namespace Netch
{
public static readonly SingleInstance.SingleInstance SingleInstance = new($"Global\\{nameof(Netch)}");
public static HWND ConsoleHwnd { get; private set; }
/// <summary>
/// 应用程序的主入口点
/// </summary>
[STAThread]
public static void Main(string[] args)
{
#if DEBUG
AttachAllocConsole();
#else
if (args.Contains(Constants.Parameter.Console))
AttachAllocConsole();
ConsoleHwnd = GetConsoleWindow();
#if RELEASE
User32.ShowWindow(ConsoleHwnd, ShowWindowCommand.SW_HIDE);
#endif
if (args.Contains(Constants.Parameter.ForceUpdate))
@@ -38,7 +40,7 @@ namespace Netch
Environment.SetEnvironmentVariable("PATH", $"{Environment.GetEnvironmentVariable("PATH")};{binPath}");
AddDllDirectory(binPath);
Updater.Updater.CleanOld(Global.NetchDir);
Updater.CleanOld(Global.NetchDir);
// 预创建目录
var directories = new[] { "mode\\Custom", "data", "i18n", "logging" };
@@ -93,12 +95,6 @@ namespace Netch
Application.Run(Global.MainForm);
}
private static void AttachAllocConsole()
{
if (!AttachConsole(ATTACH_PARENT_PROCESS))
AllocConsole();
}
public static void Application_OnException(object sender, ThreadExceptionEventArgs e)
{
Global.Logger.Error(e.Exception.ToString());

View File

@@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<OutputType>Exe</OutputType>
<DisableWinExeOutputInference>true</DisableWinExeOutputInference>
<UseWindowsForms>true</UseWindowsForms>
<UseWPF>true</UseWPF>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
@@ -38,16 +39,17 @@
<ItemGroup>
<PackageReference Include="HMBSbige.SingleInstance" Version="5.0.0" />
<PackageReference Include="MaxMind.GeoIP2" Version="4.0.1" />
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="2.0.66" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="2.0.69" GeneratePathProperty="true" />
<PackageReference Include="Nullable.Extended.Analyzer" Version="1.2.4089">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="System.Drawing.Common" Version="5.0.2" />
<PackageReference Include="System.Management" Version="5.0.0" />
<PackageReference Include="TaskScheduler" Version="2.9.1" />
<PackageReference Include="Vanara.PInvoke.IpHlpApi" Version="3.3.7" />
<PackageReference Include="Vanara.PInvoke.IpHlpApi" Version="3.3.9" />
<PackageReference Include="Microsoft-WindowsAPICodePack-Shell" Version="1.1.4" />
<PackageReference Include="Vanara.PInvoke.User32" Version="3.3.7" />
<PackageReference Include="Vanara.PInvoke.User32" Version="3.3.9" />
<PackageReference Include="WindowsFirewallHelper" Version="2.0.4.70-beta2" />
<PackageReference Include="System.ServiceProcess.ServiceController" Version="5.0.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="5.0.0" />

View File

@@ -15,8 +15,8 @@
"Stopping": "正在停止中",
"Stopped": "已停止",
"Starting {0}": "正在启动 {0}",
"Starting NatTester": "正在启动 NAT 测试",
"SetupBypass": "设置绕行规则",
"Testing NAT": "正在测试 NAT",
"Setup Route Table Rule": "配置路由规则",
"Test failed": "测试失败",
"Starting update subscription": "正在更新订阅",
"Subscription updated": "订阅更新完毕",
@@ -87,6 +87,7 @@
"Remove Netch Firewall Rules": "移除 Netch 防火墙规则",
"Open Directory": "打开目录",
"Show/Hide Console": "显示/隐藏控制台",
"About": "关于",
"FAQ": "常见问题",
@@ -151,9 +152,9 @@
"Handle process's DNS Hijack": "被代理进程 DNS 劫持",
"Global ICMP Hijack": "全局 ICMP 劫持",
"Child Process Handle": "子进程代理",
"ProfileCount": "快捷配置数量",
"Delay test after start": "启动后延迟测试",
"ServerPingType": "测速方式",
"Profile Count": "快捷配置数量",
"Delay test after start(sec)": "启动后延迟测试(秒)",
"Ping Protocol": "延迟测试协议",
"Detection Tick(sec)": "检测心跳(秒)",
"STUN Server": "STUN 服务器",
"Language": "语言",

View File

@@ -1,6 +1,7 @@
using Netch.Controllers;
using Netch.Models;
using System.Collections.Generic;
using Netch.Controllers;
using Netch.Interfaces;
using Netch.Models;
namespace Netch.Servers.Shadowsocks
{

View File

@@ -1,14 +1,14 @@
using Netch.Controllers;
using Netch.Models;
using Netch.Servers.Shadowsocks.Form;
using Netch.Servers.Shadowsocks.Models.SSD;
using Netch.Utils;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Web;
using Netch.Interfaces;
using Netch.Models;
using Netch.Servers.Shadowsocks.Form;
using Netch.Servers.Shadowsocks.Models.SSD;
using Netch.Utils;
namespace Netch.Servers.Shadowsocks
{

View File

@@ -1,6 +1,7 @@
using Netch.Controllers;
using Netch.Models;
using System.Collections.Generic;
using Netch.Controllers;
using Netch.Interfaces;
using Netch.Models;
namespace Netch.Servers.ShadowsocksR
{

View File

@@ -1,11 +1,11 @@
using Netch.Controllers;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Netch.Interfaces;
using Netch.Models;
using Netch.Servers.Shadowsocks;
using Netch.Servers.ShadowsocksR.Form;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace Netch.Servers.ShadowsocksR
{

View File

@@ -1,9 +1,9 @@
using Netch.Controllers;
using Netch.Models;
using Netch.Servers.Socks5.Form;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using Netch.Interfaces;
using Netch.Models;
using Netch.Servers.Socks5.Form;
namespace Netch.Servers.Socks5
{

View File

@@ -1,9 +1,10 @@
using Netch.Controllers;
using Netch.Models;
using Netch.Servers.Trojan.Models;
using System.Collections.Generic;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using Netch.Controllers;
using Netch.Interfaces;
using Netch.Models;
using Netch.Servers.Trojan.Models;
namespace Netch.Servers.Trojan
{

View File

@@ -1,10 +1,10 @@
using Netch.Controllers;
using Netch.Models;
using Netch.Servers.Trojan.Form;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Web;
using Netch.Interfaces;
using Netch.Models;
using Netch.Servers.Trojan.Form;
namespace Netch.Servers.Trojan
{

View File

@@ -3,6 +3,7 @@ using Netch.Servers.V2ray.Models;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Netch.Enums;
using V2rayConfig = Netch.Servers.V2ray.Models.V2rayConfig;
namespace Netch.Servers.V2ray.Utils
@@ -65,7 +66,7 @@ namespace Netch.Servers.V2ray.Utils
outboundTag = "block"
};
if (mode.Type is 0 or 1 or 2)
if (mode.Type is ModeType.Process or ModeType.ProxyRuleIPs or ModeType.BypassRuleIPs)
blockRuleObject.ip.Add("geoip:private");
static bool CheckRuleItem(ref RulesItem rulesItem)

View File

@@ -1,8 +1,9 @@
using Netch.Controllers;
using Netch.Models;
using Netch.Servers.V2ray.Utils;
using System.Collections.Generic;
using System.IO;
using Netch.Controllers;
using Netch.Interfaces;
using Netch.Models;
using Netch.Servers.V2ray.Utils;
namespace Netch.Servers.V2ray
{

View File

@@ -1,8 +1,8 @@
using Netch.Controllers;
using Netch.Models;
using Netch.Servers.V2ray;
using System;
using System.Collections.Generic;
using Netch.Interfaces;
using Netch.Models;
using Netch.Servers.V2ray;
namespace Netch.Servers.VLESS
{

View File

@@ -1,14 +1,14 @@
using Netch.Controllers;
using Netch.Models;
using Netch.Servers.V2ray;
using Netch.Servers.V2ray.Models;
using Netch.Servers.VMess.Form;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
using Netch.Interfaces;
using Netch.Models;
using Netch.Servers.V2ray;
using Netch.Servers.V2ray.Models;
using Netch.Servers.VMess.Form;
using Netch.Utils;
namespace Netch.Servers.VMess
{

View File

@@ -1,7 +1,3 @@
using Netch.Controllers;
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
@@ -10,8 +6,13 @@ using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Netch.Controllers;
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
namespace Netch.Updater
namespace Netch.Services
{
public class Updater
{
@@ -25,7 +26,7 @@ namespace Netch.Updater
/// <param name="onDownloadProgressChanged"></param>
/// <param name="keyword"></param>
/// <exception cref="MessageException"></exception>
public static void DownloadAndUpdate(string downloadDirectory,
public static async Task DownloadAndUpdate(string downloadDirectory,
string installDirectory,
DownloadProgressChangedEventHandler onDownloadProgressChanged,
string? keyword = null)
@@ -40,7 +41,7 @@ namespace Netch.Updater
{
if (Utils.Utils.SHA256CheckSum(updateFile) == sha256)
{
updater.ApplyUpdate();
await updater.ApplyUpdate();
return;
}
@@ -48,7 +49,7 @@ namespace Netch.Updater
}
DownloadUpdateFile(onDownloadProgressChanged, updateFile, sha256);
updater.ApplyUpdate();
await updater.ApplyUpdate();
}
/// <summary>
@@ -94,7 +95,7 @@ namespace Netch.Updater
private static readonly ImmutableArray<string> KeepDirectories = new List<string> { "data", "mode\\Custom", "logging" }.ToImmutableArray();
private void ApplyUpdate()
private async Task ApplyUpdate()
{
var mainForm = Global.MainForm;
@@ -102,7 +103,7 @@ namespace Netch.Updater
ModeHelper.SuspendWatcher = true;
// Stop and Save
mainForm.Stop();
await mainForm.Stop();
Configuration.Save();
// Backup Configuration file

View File

@@ -75,7 +75,8 @@ namespace Netch.Utils
if (!Directory.Exists(DataDirectoryFullName))
Directory.CreateDirectory(DataDirectoryFullName);
File.WriteAllBytes(SettingFileFullName, JsonSerializer.SerializeToUtf8Bytes(Global.Settings, JsonSerializerOptions));
using var fileStream = File.Create(SettingFileFullName);
JsonSerializer.SerializeAsync(fileStream, Global.Settings, JsonSerializerOptions).Wait();
}
}
}

View File

@@ -13,12 +13,7 @@ namespace Netch.Utils
/// </summary>
private static readonly Hashtable Cache = new();
/// <summary>
/// 查询
/// </summary>
/// <param name="hostname">主机名</param>
/// <returns></returns>
public static IPAddress? Lookup(string hostname)
public static IPAddress? Lookup(string hostname, int timeout = 3000)
{
try
{
@@ -26,7 +21,7 @@ namespace Netch.Utils
return Cache[hostname] as IPAddress;
var task = Dns.GetHostAddressesAsync(hostname);
if (!task.Wait(1000))
if (!task.Wait(timeout))
return null;
if (task.Result.Length == 0)

View File

@@ -1,10 +1,12 @@
using Netch.Controllers;
using Netch.Models;
using Netch.Servers.Shadowsocks;
using Netch.Servers.Socks5;
using System;
using System.IO;
using System.Linq;
using Netch.Controllers;
using Netch.Enums;
using Netch.Interfaces;
using Netch.Models;
using Netch.Servers.Shadowsocks;
using Netch.Servers.Socks5;
namespace Netch.Utils
{
@@ -111,35 +113,33 @@ namespace Netch.Utils
{
switch (mode.Type)
{
case 0:
case ModeType.Process:
return server switch
{
Socks5 => true,
Shadowsocks shadowsocks when !shadowsocks.HasPlugin() && Global.Settings.Redirector.RedirectorSS => true,
_ => false
};
case 1:
case 2:
case ModeType.ProxyRuleIPs:
case ModeType.BypassRuleIPs:
return server is Socks5;
default:
return false;
}
}
public static readonly int[] ModeTypes = { 0, 1, 2, 6 };
public static IModeController GetModeControllerByType(int type, out ushort? port, out string portName)
public static IModeController GetModeControllerByType(ModeType type, out ushort? port, out string portName)
{
port = null;
portName = string.Empty;
switch (type)
{
case 0:
case ModeType.Process:
return new NFController();
case 1:
case 2:
case ModeType.ProxyRuleIPs:
case ModeType.BypassRuleIPs:
return new TUNController();
case 6:
case ModeType.Pcap2Socks:
return new PcapController();
default:
Global.Logger.Error("未知模式类型");

View File

@@ -0,0 +1,96 @@
using System;
using System.Linq;
using System.Management;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using Netch.Models;
using Vanara.PInvoke;
namespace Netch.Utils
{
public static class NetworkInterfaceUtils
{
public static NetworkInterface GetBest(AddressFamily addressFamily = AddressFamily.InterNetwork)
{
var ipAddress = addressFamily switch
{
AddressFamily.InterNetwork => "114.114.114.114",
AddressFamily.InterNetworkV6 => throw new NotImplementedException(),
_ => throw new ArgumentOutOfRangeException(nameof(addressFamily), addressFamily, null)
};
if (IpHlpApi.GetBestRoute(BitConverter.ToUInt32(IPAddress.Parse(ipAddress).GetAddressBytes(), 0), 0, out var route) != 0)
throw new MessageException("GetBestRoute 搜索失败");
return Get((int)route.dwForwardIfIndex);
}
/// <summary>
/// </summary>
/// <param name="interfaceIndex"></param>
/// <exception cref="InvalidOperationException"></exception>
/// <returns></returns>
public static NetworkInterface Get(int interfaceIndex)
{
return NetworkInterface.GetAllNetworkInterfaces().First(n => n.GetIndex() == interfaceIndex);
}
public static NetworkInterface Get(string description)
{
return NetworkInterface.GetAllNetworkInterfaces().First(n => n.Description == description);
}
public static void SetInterfaceMetric(int interfaceIndex, int? metric = null)
{
var arguments = $"interface ip set interface {interfaceIndex} ";
if (metric != null)
arguments += $"metric={metric} ";
Utils.ProcessRunHiddenAsync("netsh", arguments).Wait();
}
}
public static class NetworkInterfaceExtension
{
public static int GetIndex(this NetworkInterface ni)
{
var ipProperties = ni.GetIPProperties();
if (ni.Supports(NetworkInterfaceComponent.IPv4))
return ipProperties.GetIPv4Properties().Index;
if (ni.Supports(NetworkInterfaceComponent.IPv6))
return ipProperties.GetIPv6Properties().Index;
throw new Exception();
}
public static void SetDns(this NetworkInterface ni, string primaryDns, string? secondDns = null)
{
void VerifyDns(ref string s)
{
s = s.Trim();
if (primaryDns.IsNullOrEmpty())
throw new ArgumentException("DNS format invalid", nameof(primaryDns));
}
VerifyDns(ref primaryDns);
if (secondDns != null)
VerifyDns(ref primaryDns);
var wmi = new ManagementClass("Win32_NetworkAdapterConfiguration");
var mos = wmi.GetInstances().Cast<ManagementObject>();
var mo = mos.First(m => m["Description"].ToString() == ni.Description);
var dns = new[] { primaryDns };
if (secondDns != null)
dns = dns.Append(secondDns).ToArray();
var inPar = mo.GetMethodParameters("SetDNSServerSearchOrder");
inPar["DNSServerSearchOrder"] = dns;
mo.InvokeMethod("SetDNSServerSearchOrder", inPar, null);
}
}
}

View File

@@ -3,16 +3,16 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.NetworkInformation;
using Netch.Models;
using static Vanara.PInvoke.IpHlpApi;
using static Vanara.PInvoke.Ws2_32;
using Range = Netch.Models.Range;
namespace Netch.Utils
{
public static class PortHelper
{
private static readonly List<Range> TCPReservedRanges = new();
private static readonly List<Range> UDPReservedRanges = new();
private static readonly List<NumberRange> TCPReservedRanges = new();
private static readonly List<NumberRange> UDPReservedRanges = new();
private static readonly IPGlobalProperties NetInfo = IPGlobalProperties.GetIPGlobalProperties();
static PortHelper()
@@ -38,7 +38,7 @@ namespace Netch.Utils
return row.Select(r => Process.GetProcessById((int)r.dwOwningPid));
}
private static void GetReservedPortRange(PortType portType, ref List<Range> targetList)
private static void GetReservedPortRange(PortType portType, ref List<NumberRange> targetList)
{
var process = new Process
{
@@ -64,7 +64,7 @@ namespace Netch.Utils
if (!ushort.TryParse(value[0], out var start) || !ushort.TryParse(value[1], out var end))
continue;
targetList.Add(new Range(start, end));
targetList.Add(new NumberRange(start, end));
}
}

69
Netch/Utils/RouteUtils.cs Normal file
View File

@@ -0,0 +1,69 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Net.Sockets;
using Netch.Interops;
using Netch.Models;
namespace Netch.Utils
{
public static class RouteUtils
{
public static void CreateRouteFill(NetRoute template, IEnumerable<string> rules, int? metric = null)
{
foreach (var rule in rules)
CreateRouteFill(template, rule, metric);
}
public static bool CreateRouteFill(NetRoute template, string rule, int? metric = null)
{
if (!TryParseIPNetwork(rule, out var network, out var cidr))
{
Global.Logger.Warning($"invalid rule {rule}");
return false;
}
return CreateRoute(template.FillTemplate(network, (byte)cidr, metric));
}
public static bool CreateRoute(NetRoute o)
{
return RouteHelper.CreateRoute(AddressFamily.InterNetwork, o.Network, o.Cidr, o.Gateway, (ulong)o.InterfaceIndex, o.Metric);
}
public static void DeleteRouteFill(NetRoute template, IEnumerable<string> rules, int? metric = null)
{
foreach (var rule in rules)
DeleteRouteFill(template, rule, metric);
}
public static bool DeleteRouteFill(NetRoute template, string rule, int? metric = null)
{
if (!TryParseIPNetwork(rule, out var network, out var cidr))
{
Global.Logger.Warning($"invalid rule {rule}");
return false;
}
return DeleteRoute(template.FillTemplate(network, (byte)cidr, metric));
}
public static bool DeleteRoute(NetRoute o)
{
return RouteHelper.DeleteRoute(AddressFamily.InterNetwork, o.Network, o.Cidr, o.Gateway, (ulong)o.InterfaceIndex, o.Metric);
}
public static bool TryParseIPNetwork(string ipNetwork, [NotNullWhen(true)] out string? ip, out int cidr)
{
ip = null;
cidr = 0;
var s = ipNetwork.Split('/');
if (s.Length != 2)
return false;
ip = s[0];
cidr = int.Parse(s[1]);
return true;
}
}
}

View File

@@ -1,11 +1,12 @@
using Netch.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using Range = Netch.Models.Range;
using Netch.Interfaces;
using Netch.Models;
using Timer = System.Timers.Timer;
namespace Netch.Utils
{
@@ -30,9 +31,9 @@ namespace Netch.Utils
public static class DelayTestHelper
{
private static readonly Timer Timer;
private static bool _mux;
private static readonly object TestAllLock = new();
public static readonly Range Range = new(0, int.MaxValue / 1000);
public static readonly NumberRange Range = new(0, int.MaxValue / 1000);
static DelayTestHelper()
{
@@ -68,20 +69,22 @@ namespace Netch.Utils
public static void TestAllDelay()
{
if (_mux)
if (!Monitor.TryEnter(TestAllLock))
return;
try
{
_mux = true;
Parallel.ForEach(Global.Settings.Server, new ParallelOptions { MaxDegreeOfParallelism = 16 }, server => { server.Test(); });
_mux = false;
TestDelayFinished?.Invoke(null, new EventArgs());
}
catch (Exception)
{
// ignored
}
finally
{
Monitor.Exit(TestAllLock);
}
}
public static void UpdateInterval()

View File

@@ -1,5 +1,3 @@
using MaxMind.GeoIP2;
using Microsoft.Win32.TaskScheduler;
using System;
using System.ComponentModel;
using System.Diagnostics;
@@ -13,6 +11,8 @@ using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using MaxMind.GeoIP2;
using Microsoft.Win32.TaskScheduler;
using Task = System.Threading.Tasks.Task;
namespace Netch.Utils
@@ -201,6 +201,9 @@ namespace Netch.Utils
td.Settings.ExecutionTimeLimit = TimeSpan.Zero;
td.Settings.DisallowStartIfOnBatteries = false;
td.Settings.StopIfGoingOnBatteries = false;
td.Settings.IdleSettings.StopOnIdleEnd = false;
td.Settings.IdleSettings.RestartOnIdle = false;
td.Settings.RunOnlyIfIdle = false;
td.Settings.Compatibility = TaskCompatibility.V2_1;
@@ -254,7 +257,7 @@ namespace Netch.Utils
Console.Write(error);
}
p.WaitForExit();
await p.WaitForExitAsync();
}
public static int SubnetToCidr(string value)
@@ -275,5 +278,15 @@ namespace Netch.Utils
return host;
}
public static string GetHostFromUri(string str)
{
var startIndex = str.LastIndexOf('/');
if (startIndex != -1)
str = str[(startIndex + 1)..];
var endIndex = str.IndexOf(':');
return endIndex == -1 ? str : str[..endIndex];
}
}
}

View File

@@ -1,70 +1,55 @@
<p align="center"><img src="https://cdn.jsdelivr.net/gh/netchx/netch/Netch/Resources/Netch.png" width="128" /></p>
<div align="center">
# Netch
[![Group](https://img.shields.io/badge/Telegram-Group-green)](https://t.me/Netch_Discuss_Group)
[![Channel](https://img.shields.io/badge/Telegram-Channel-blue)](https://t.me/Netch)
[![Platform](https://img.shields.io/badge/platform-windows-orange.svg)](https://github.com/NetchX/Netch)
[![Version](https://img.shields.io/github/v/release/NetchX/Netch)](https://github.com/NetchX/Netch/releases)
[![Downloads](https://img.shields.io/github/downloads/NetchX/Netch/total.svg)](https://github.com/NetchX/Netch/releases)
[![Netch CI](https://github.com/NetchX/Netch/workflows/Netch%20CI/badge.svg)](https://github.com/NetchX/Netch/actions)
[![License](https://img.shields.io/badge/license-MIT-yellow.svg)](LICENSE)
A simple proxy client
[文档网站](https://netch.org/) [常见问题](https://netch.org/#/docs/zh-CN/faq)
[![](https://img.shields.io/badge/telegram-group-green?style=flat-square)](https://t.me/netch_group)
[![](https://img.shields.io/badge/telegram-channel-blue?style=flat-square)](https://t.me/netch_channel)
[![](https://img.shields.io/github/downloads/netchx/netch/total.svg?style=flat-square)](https://github.com/netchx/netch/releases)
[![](https://img.shields.io/github/v/release/netchx/netch?style=flat-square)](https://github.com/netchx/netch/releases)
</div>
[中文说明](README.zh-CN.md)
## Features
Some features may not be implemented in version 1
Game network accelerator
### Modes
- ProcessMode - Use Netfilter driver to intercept process traffic
- ShareMode - Share your network based on WinPcap / Npcap
- TapMode - Use TAP-Windows driver to create virtual adapter
- TunMode - Use WinTUN driver to create virtual adapter
- WebMode - Web proxy mode
- WmpMode - Proxy forwarding (eg. OBS Streaming)
## TOC
- [Netch](#netch)
- [TOC](#toc)
- [Description](#description)
- [Sponsor](#sponsor)
- [Donate](#donate)
- [Screenshots](#screenshots)
- [Requirements](#requirements)
- [Quote](#quote)
### Protocols
- [Socks5](https://www.wikiwand.com/en/SOCKS)
- [Shadowsocks](https://github.com/shadowsocks/shadowsocks-libev)
- [ShadowsocksR](https://github.com/shadowsocksrr/shadowsocksr-libev)
- [Trojan](https://trojan-gfw.github.io/trojan/)
- [VLess](https://github.com/xtls/xray-core)
- [VMess](https://github.com/v2fly/v2ray-core)
## Description
Netch is an open source game network accelerator. Unlike SSTap, which needs to add rules to function as a blacklist proxy, Netch is more similar to SocksCap64, which can scan the game directory to get their process names specifically and forward their network traffic through the proxy server
Currently supports the following protocols
- Socks5
- Shadowsocks
- ShadowsocksR
- Trojan
- VMess
- VLESS
As well, Netch avoid the restricted NAT problem caused by SSTap. You can use an NATTypeTester to test out what your NAT type is. When using SSTap to speed up some P2P gaming connections or the game is required for that kind of open NAT type, you may experience some bad situations such as unable to join the game
### Others
- UDP NAT FullCone (May limited by your server)
- .NET 5.0 x64
## Sponsor
<a href="https://www.jetbrains.com/?from=Netch"><img src="jetbrains.svg" alt="JetBrains" width="200"/></a>
<a href="https://www.jetbrains.com/?from=Netch"><img src="https://cdn.jsdelivr.net/gh/netchx/netch/jetbrains.svg" alt="JetBrains" width="200"/></a>
- [RabbitHosts](https://rabbithosts.com/cart.php)
- [ManSora](https://www.mansora.co/cart.php)
- [NyanCat](https://nyancat.info/register)
- [NeroCloud](https://nerocloud.io)
## Donate
- XMR *48ju3ELNZEa6wwPBMexCJ9G218BGY2XwhH6B6bmkFuJ3QgM4hPw2Pra35jPtuBZSc7SLNWeBpiWJZWjQeMAiLnTx2tH2Efx*
- ETH *0x23dac0a93bcd71fec7a95833ad030338f167f185*
## Screenshots
![](screenshots/main.png)
## Requirements
- [.NET 5](https://dotnet.microsoft.com/download/dotnet/5.0/runtime)
## Quote
- [core](https://github.com/aiocloud/core)
- [aiodns](https://github.com/aiocloud/aiodns)
- [tun2socks](https://github.com/aiocloud/tun2socks)
- [Redirector](https://github.com/aiocloud/Redirector)
- [RouteHelper](https://github.com/aiocloud/RouteHelper)
- [NatTypeTester](https://github.com/HMBSbige/NatTypeTester)
- [NetFilter SDK](https://netfiltersdk.com)
- [pcap2socks](https://github.com/zhxie/pcap2socks)
- [shadowsocks-libev](https://github.com/shadowsocks/shadowsocks-libev)
- [shadowsocksr-libev](https://github.com/shadowsocksrr/shadowsocksr-libev)
- [trojan](https://github.com/trojan-gfw/trojan)
- [xray-core](https://github.com/XTLS/Xray-core)
- [dnsmasq-china-list](https://github.com/felixonmars/dnsmasq-china-list)
[![Stargazers over time](https://starchart.cc/NetchX/Netch.svg)](https://starchart.cc/NetchX/Netch)
## Credit
- [WinTUN](https://www.wintun.net)
- [aioCloud](https://github.com/aiocloud)
- [NetFilter](https://netfiltersdk.com)
- [TAP-Windows](https://github.com/OpenVPN/tap-windows6)
- [Shadowsocks](https://github.com/shadowsocks/shadowsocks-libev)
- [ShadowsocksR](https://github.com/shadowsocksrr/shadowsocksr-libev)
- [Trojan](https://github.com/trojan-gfw/trojan)
- [V2Ray](https://github.com/v2fly/v2ray-core)
- [XRay](https://github.com/xtls/xray-core)

View File

@@ -1,70 +0,0 @@
# Netch
[![群组](https://img.shields.io/badge/Telegram-群组-green)](https://t.me/Netch_Discuss_Group)
[![频道](https://img.shields.io/badge/Telegram-频道-blue)](https://t.me/Netch)
[![平台](https://img.shields.io/badge/平台-windows-orange.svg)](https://github.com/NetchX/Netch)
[![版本](https://img.shields.io/github/v/release/NetchX/Netch)](https://github.com/NetchX/Netch/releases)
[![下载](https://img.shields.io/github/downloads/NetchX/Netch/total.svg)](https://github.com/NetchX/Netch/releases)
[![Netch CI](https://github.com/NetchX/Netch/workflows/Netch%20CI/badge.svg)](https://github.com/NetchX/Netch/actions)
[![License](https://img.shields.io/badge/license-MIT-yellow.svg)](LICENSE)
[文档网站](https://netch.org/) [常见问题](https://netch.org/#/docs/zh-CN/faq)
游戏加速工具
## TOC
- [Netch](#netch)
- [TOC](#toc)
- [简介](#简介)
- [赞助商](#赞助商)
- [捐赠](#捐赠)
- [依赖](#依赖)
- [语言支持](#语言支持)
- [引用](#引用)
## 简介
Netch 是一款 Windows 平台的开源游戏加速工具Netch 可以实现类似 SocksCap64 那样的进程代理,也可以实现 SSTap 那样的全局 TUN/TAP 代理,和 Shadowsocks-Windows 那样的本地 Socks5HTTP 和系统代理
至于连接至远程服务器的代理协议,目前 Netch 支持以下代理协议
- Socks5
- Shadowsocks
- ShadowsocksR
- Trojan
- VMess
- VLESS
与此同时 Netch 避免了 SSTap 的 NAT 问题 ,检查 NAT 类型即可知道是否有 NAT 问题。使用 SSTap 加速部分 P2P 联机,对 NAT 类型有要求的游戏时,可能会因为 NAT 类型严格遇到无法加入联机,或者其他影响游戏体验的情况
## 赞助商
<a href="https://www.jetbrains.com/?from=Netch"><img src="jetbrains.svg" alt="JetBrains" width="200"/></a>
- [RabbitHosts](https://rabbithosts.com/cart.php)
- [ManSora](https://www.mansora.co/cart.php)
- [NyanCat](https://nyancat.info/register)
## 捐赠
- XMR *48ju3ELNZEa6wwPBMexCJ9G218BGY2XwhH6B6bmkFuJ3QgM4hPw2Pra35jPtuBZSc7SLNWeBpiWJZWjQeMAiLnTx2tH2Efx*
## 依赖
- [.NET 5](https://dotnet.microsoft.com/download/dotnet/5.0/runtime)
## 语言支持
Netch 内置 en-US 和 zh-CN外置 zh-TW 等,默认根据系统语言选择语言。
[Netch 外置语言仓库](https://github.com/NetchX/NetchTranslation) ,欢迎提供其他语言的翻译
## 引用
- [core](https://github.com/aiocloud/core)
- [aiodns](https://github.com/aiocloud/aiodns)
- [tun2socks](https://github.com/aiocloud/tun2socks)
- [Redirector](https://github.com/aiocloud/Redirector)
- [RouteHelper](https://github.com/aiocloud/RouteHelper)
- [NatTypeTester](https://github.com/HMBSbige/NatTypeTester)
- [NetFilter SDK](https://netfiltersdk.com)
- [pcap2socks](https://github.com/zhxie/pcap2socks)
- [shadowsocks-libev](https://github.com/shadowsocks/shadowsocks-libev)
- [shadowsocksr-libev](https://github.com/shadowsocksrr/shadowsocksr-libev)
- [trojan](https://github.com/trojan-gfw/trojan)
- [xray-core](https://github.com/XTLS/Xray-core)
- [dnsmasq-china-list](https://github.com/felixonmars/dnsmasq-china-list)
[![Stargazers over time](https://starchart.cc/NetchX/Netch.svg)](https://starchart.cc/NetchX/Netch)

View File

@@ -1,8 +1,8 @@
param([string]$OutputPath)
$NetchDataURL="https://github.com/NetchX/NetchData/archive/refs/heads/master.zip"
$NetchModeURL="https://github.com/NetchX/NetchMode/archive/refs/heads/master.zip"
$NetchI18NURL="https://github.com/NetchX/NetchI18N/archive/refs/heads/master.zip"
$NetchDataURL="https://github.com/netchx/netchdata/archive/refs/heads/master.zip"
$NetchModeURL="https://github.com/netchx/netchmode/archive/refs/heads/master.zip"
$NetchI18NURL="https://github.com/netchx/netchi18n/archive/refs/heads/master.zip"
$last=$(Get-Location)
New-Item -ItemType Directory -Name $OutputPath | Out-Null
@@ -20,19 +20,20 @@ New-Item -ItemType Directory -Name bin | Out-Null
New-Item -ItemType Directory -Name mode | Out-Null
New-Item -ItemType Directory -Name i18n | Out-Null
Copy-Item -Recurse -Force .\NetchData-master\* .\bin
Copy-Item -Recurse -Force .\NetchMode-master\mode\* .\mode
Copy-Item -Recurse -Force .\NetchI18N-master\i18n\* .\i18n
Copy-Item -Recurse -Force .\netchdata-master\* .\bin
Copy-Item -Recurse -Force .\netchmode-master\mode\* .\mode
Copy-Item -Recurse -Force .\netchi18n-master\i18n\* .\i18n
Remove-Item -Recurse -Force NetchData-master
Remove-Item -Recurse -Force NetchMode-master
Remove-Item -Recurse -Force NetchI18N-master
Remove-Item -Recurse -Force netchdata-master
Remove-Item -Recurse -Force netchmode-master
Remove-Item -Recurse -Force netchi18n-master
Remove-Item -Force data.zip
Remove-Item -Force mode.zip
Remove-Item -Force i18n.zip
..\scripts\downloads\cloak.ps1 -OutputPath bin
..\scripts\downloads\xray-core.ps1 -OutputPath bin
..\scripts\download\aiodns.ps1 -OutputPath bin
..\scripts\download\cloak.ps1 -OutputPath bin
..\scripts\download\xray-core.ps1 -OutputPath bin
Get-Item *
Set-Location $last

View File

@@ -0,0 +1,10 @@
param([string]$OutputPath)
$address="https://github.com/aiocloud/aiodns/releases/download/1.0.4/aiodns.bin"
$domains="https://raw.githubusercontent.com/aiocloud/aiodns/master/aiodns.conf"
Invoke-WebRequest -Uri $address -OutFile aiodns.bin
Invoke-WebRequest -Uri $domains -OutFile aiodns.conf
Move-Item -Force aiodns.bin $OutputPath
Move-Item -Force aiodns.conf $OutputPath
exit 0

View File

@@ -1,5 +1,5 @@
param([string]$OutputPath)
$address="https://github.com/cbeuw/Cloak/releases/download/v2.5.3/ck-client-windows-amd64-v2.5.3.exe"
$address="https://github.com/cbeuw/Cloak/releases/download/v2.5.4/ck-client-windows-amd64-v2.5.4.exe"
Invoke-WebRequest -Uri $address -OutFile ck-client.exe

View File

@@ -1,6 +1,2 @@
param([string]$file)
$hash = [Security.Cryptography.HashAlgorithm]::Create( "SHA256" )
$path = (Resolve-Path -Path $file).Path
$stream = ([IO.StreamReader]$path).BaseStream
-join ($hash.ComputeHash($stream) | ForEach-Object { "{0:x2}" -f $_ })
$stream.Close()
(Get-FileHash $file -Algorithm SHA256).Hash.ToLower()