├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── bug_report.zh-CN.yml │ ├── config.yml │ ├── feature_request.yml │ └── feature_request.zh-CN.yml ├── dependabot.yml └── workflows │ ├── build.yml │ ├── release.yml │ └── stale.yml ├── .gitignore ├── LICENSE ├── Netch.sln ├── Netch ├── .gitignore ├── App.manifest ├── Constants.cs ├── Controllers │ ├── DNSController.cs │ ├── Guard.cs │ ├── MainController.cs │ ├── NFController.cs │ ├── PcapController.cs │ ├── TUNController.cs │ └── UpdateChecker.cs ├── Enums │ ├── LogLevel.cs │ └── State.cs ├── Flags.cs ├── FodyWeavers.xml ├── Forms │ ├── AboutForm.Designer.cs │ ├── AboutForm.cs │ ├── AboutForm.resx │ ├── BindingForm.cs │ ├── BindingForm.resx │ ├── GlobalBypassIPForm.Designer.cs │ ├── GlobalBypassIPForm.cs │ ├── GlobalBypassIPForm.resx │ ├── LogForm.Designer.cs │ ├── LogForm.cs │ ├── LogForm.resx │ ├── MainForm.Designer.cs │ ├── MainForm.cs │ ├── MainForm.resx │ ├── MessageBoxX.cs │ ├── ModeForms │ │ ├── ModeEditorUtils.cs │ │ ├── ProcessForm.Designer.cs │ │ ├── ProcessForm.cs │ │ ├── ProcessForm.resx │ │ ├── RouteForm.Designer.cs │ │ ├── RouteForm.cs │ │ └── RouteForm.resx │ ├── ServerForm.cs │ ├── SettingForm.Designer.cs │ ├── SettingForm.cs │ ├── SettingForm.resx │ ├── SubscriptionForm.Designer.cs │ ├── SubscriptionForm.cs │ ├── SubscriptionForm.resx │ └── SyncGlobalCheckBox.cs ├── Global.cs ├── Interfaces │ ├── IController.cs │ ├── IModeController.cs │ ├── IServerController.cs │ └── IServerUtil.cs ├── Interops │ ├── AioDNS.cs │ ├── Redirector.cs │ ├── RouteHelper.cs │ └── tun2socks.cs ├── JsonConverter │ ├── ModeConverterWithTypeDiscriminator.cs │ └── ServerConverterWithTypeDiscriminator.cs ├── Models │ ├── Arguments.cs │ ├── GitHubRelease │ │ ├── Asset.cs │ │ ├── GitHubRelease.cs │ │ ├── GitHubUser.cs │ │ ├── Release.cs │ │ ├── SuffixVersion.cs │ │ └── VersionUtil.cs │ ├── MessageException.cs │ ├── Modes │ │ ├── Mode.cs │ │ ├── ModeFeature.cs │ │ ├── ModeType.cs │ │ ├── ProcessMode │ │ │ └── ProcessMode.cs │ │ ├── ShareMode │ │ │ └── ShareMode.cs │ │ └── TunMode │ │ │ └── TunMode.cs │ ├── NatTypeTestResult.cs │ ├── NetRoute.cs │ ├── NumberRange.cs │ ├── Profile.cs │ ├── Server.cs │ ├── Settings │ │ ├── AioDNSConfig.cs │ │ ├── KcpConfig.cs │ │ ├── RedirectorConfig.cs │ │ ├── Setting.cs │ │ ├── TUNConfig.cs │ │ └── V2rayConfig.cs │ ├── StatusText.cs │ ├── Subscription.cs │ └── TagItem.cs ├── NOTICE.txt ├── NativeMethods.cs ├── NativeMethods.txt ├── Netch.csproj ├── Program.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── PublishProfiles │ │ ├── FolderProfile.pubxml │ │ └── FolderProfile.pubxml.user │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── Resources │ ├── 7za.exe │ ├── CopyLink.png │ ├── Netch.ico │ ├── Netch.png │ ├── NetchTrayIcon.png │ ├── delete.png │ ├── edit.png │ ├── speed.png │ └── zh-CN ├── Servers │ ├── SSH │ │ ├── SSHForm.cs │ │ ├── SSHServer.cs │ │ └── SSHUtil.cs │ ├── Shadowsocks │ │ ├── ShadowsocksController.cs │ │ ├── ShadowsocksForm.cs │ │ ├── ShadowsocksServer.cs │ │ ├── ShadowsocksUtil.cs │ │ └── ShareModels │ │ │ ├── SSDJObject.cs │ │ │ ├── SSDServerJObject.cs │ │ │ └── ShadowsocksConfig.cs │ ├── ShadowsocksR │ │ ├── ShadowsocksRController.cs │ │ ├── ShadowsocksRForm.cs │ │ ├── ShadowsocksRServer.cs │ │ └── ShadowsocksRUtil.cs │ ├── Socks5 │ │ ├── Socks5Controller.cs │ │ ├── Socks5Form.cs │ │ ├── Socks5Server.cs │ │ └── Socks5Util.cs │ ├── Trojan │ │ ├── TrojanConfig.cs │ │ ├── TrojanController.cs │ │ ├── TrojanForm.cs │ │ ├── TrojanServer.cs │ │ └── TrojanUtil.cs │ ├── V2ray │ │ ├── ShareModels │ │ │ └── V2rayNJObject.cs │ │ ├── V2rayConfig.cs │ │ ├── V2rayConfigUtils.cs │ │ ├── V2rayController.cs │ │ └── V2rayUtils.cs │ ├── VLESS │ │ ├── VLESSForm.cs │ │ ├── VLESSServer.cs │ │ └── VLESSUtil.cs │ ├── VMess │ │ ├── VMessForm.cs │ │ ├── VMessServer.cs │ │ └── VMessUtil.cs │ ├── Vision │ │ ├── VisionForm.cs │ │ ├── VisionServer.cs │ │ └── VisionUtil.cs │ └── WireGuard │ │ ├── WireGuardForm.cs │ │ ├── WireGuardServer.cs │ │ └── WireGuardUtil.cs ├── Services │ ├── ModeService.cs │ └── Updater.cs ├── Utils │ ├── Bandwidth.cs │ ├── Configuration.cs │ ├── DelayTestHelper.cs │ ├── DnsUtils.cs │ ├── Firewall.cs │ ├── ModeHelper.cs │ ├── NetworkInterfaceUtils.cs │ ├── PortHelper.cs │ ├── RouteUtils.cs │ ├── ServerHelper.cs │ ├── ShareLink.cs │ ├── Socks5ServerTestUtils.cs │ ├── StringExtension.cs │ ├── SubscriptionUtil.cs │ ├── SystemInfo.cs │ ├── Utils.cs │ ├── WebUtil.cs │ └── i18N.cs └── runtimeconfig.template.json ├── Other ├── .gitignore ├── .must_build ├── _Archive │ ├── build.ps1 │ ├── chnip │ │ └── build.ps1 │ ├── chnsite │ │ └── build.ps1 │ ├── cloak │ │ └── build.ps1 │ ├── dnsproxy │ │ └── build.ps1 │ ├── geoip │ │ └── build.ps1 │ ├── geosite │ │ └── build.ps1 │ ├── tun2socks │ │ └── build.ps1 │ ├── v2ray-core │ │ └── build.ps1 │ └── v2ray-plugin │ │ └── build.ps1 ├── aiodns │ ├── build.ps1 │ ├── deps.ps1 │ ├── go.mod │ ├── go.sum │ └── main.go ├── build.ps1 ├── clean.ps1 ├── deps.ps1 ├── pcap2socks │ └── build.ps1 ├── wintun │ └── build.ps1 ├── xray-core │ └── build.ps1 └── xray-plugin │ └── build.ps1 ├── README.md ├── Redirector ├── .gitignore ├── .must_build ├── Based.cpp ├── Based.h ├── DNSHandler.cpp ├── DNSHandler.h ├── EventHandler.cpp ├── EventHandler.h ├── IPEventHandler.cpp ├── IPEventHandler.h ├── README.md ├── Redirector.cpp ├── Redirector.vcxproj ├── Redirector.vcxproj.filters ├── SocksHelper.cpp ├── SocksHelper.h ├── TCPHandler.cpp ├── TCPHandler.h ├── Utils.cpp ├── Utils.h ├── include │ ├── nfapi.h │ ├── nfdriver.h │ └── nfevents.h ├── lib │ └── nfapi.lib └── static │ └── nfapi.dll ├── RedirectorTester ├── .gitignore ├── App.config ├── App.manifest ├── Properties │ └── AssemblyInfo.cs ├── RedirectorTester.cs └── RedirectorTester.csproj ├── RouteHelper ├── .gitignore ├── .must_build ├── Based.h ├── README.md ├── RouteHelper.cpp ├── RouteHelper.vcxproj ├── RouteHelper.vcxproj.filters ├── WaitGroup.cpp └── WaitGroup.h ├── Storage ├── README.md ├── aiodns.conf ├── i18n │ ├── fa-IR │ ├── ja-JP │ └── zh-TW ├── mode │ ├── Battlenet.txt │ ├── Bypass LAN and China.txt │ ├── Bypass LAN and Vivox.txt │ ├── Bypass LAN.txt │ ├── Discord (with Steam Apps).txt │ ├── Discord.txt │ ├── EA Desktop Games (with EA Desktop).txt │ ├── EA Desktop Games.txt │ ├── EA Desktop.txt │ ├── Game │ │ ├── Age of Empires IV.json │ │ ├── COD18.json │ │ ├── Cube 2 Sauerbraten.txt │ │ ├── CyberDuck.txt │ │ ├── DLsite PlayDRM.txt │ │ ├── EVE Online.txt │ │ ├── Escape From Tarkov.txt │ │ ├── Etterna.txt │ │ ├── Faceit AC.txt │ │ ├── ForzaHorizon 4.txt │ │ ├── Grand Theft Auto V.txt │ │ ├── Halo The Master Chief Collection.txt │ │ ├── League of Legends (Japan) (with Riot Games).txt │ │ ├── League of Legends (Taiwan) (with Garena).txt │ │ ├── League of Legends (US).txt │ │ ├── Minecraft (Java).txt │ │ ├── Minecraft Bedrock (Win10 UWP).txt │ │ ├── Multi Theft Auto (MTA).txt │ │ ├── OSU.txt │ │ ├── PVZ Battle for Neighborville.json │ │ ├── PlayerUnknown's Battlegrounds Lite.txt │ │ ├── RAGE Multiplayer.txt │ │ ├── RayCity (Thailand) (Dark RayCity).txt │ │ ├── RayCity (Thailand) (Rebirth RayCity).txt │ │ ├── San Andreas Multiplayer (SA-MP).txt │ │ ├── Tom Clancy's Rainbow Six Siege.txt │ │ ├── VRChat.txt │ │ ├── Valorant.txt │ │ ├── Warframe.txt │ │ └── World of Warships.txt │ ├── Global.json │ ├── NatTypeTester.txt │ ├── Nexon Games.txt │ ├── Nexon.txt │ ├── Origin Games.txt │ ├── Origin.txt │ ├── Other │ │ ├── AMD Radeon.txt │ │ ├── Adobe Creative Cloud (No Apps).txt │ │ ├── Geforce Experience.txt │ │ ├── Git.txt │ │ ├── Google Drive Backup and Sync.txt │ │ ├── JetBrains ToolBox.txt │ │ ├── NVIDIA Corporation.json │ │ ├── NodeJS With NVM.txt │ │ ├── Unity Asset Store for Unity.txt │ │ ├── Unity Hub.txt │ │ ├── VMware.txt │ │ ├── Visual Studio Code.txt │ │ ├── Xftp 6.txt │ │ ├── Xshell 6.txt │ │ └── qBittorrent.txt │ ├── Rockstar Games Launcher.txt │ ├── Steam Games (with Steam).txt │ ├── Steam Games.txt │ ├── Steam.txt │ ├── TUNTAP │ │ ├── ARK Survival Evolved (Asia) - Tencent.txt │ │ ├── ARK Survival Evolved (US) - Tencent.txt │ │ ├── Among Us - UU.txt │ │ ├── Battlefield V - Tencent.txt │ │ ├── Black Desert (Taiwan) - Tencent.txt │ │ ├── Black Desert (US) - Tencent.txt │ │ ├── Counter-Strike Global Offensive -UU-.txt │ │ ├── DOOM Eternal.txt │ │ ├── Dead by Daylight - Tencent.txt │ │ ├── Destiny 2 - Tencent.txt │ │ ├── Destiny 2 - UU.txt │ │ ├── EVE Online - Tencent.txt │ │ ├── Escape From Tarkov (HK) - UU.txt │ │ ├── Fall Guys Ultimate Knockout - UU.txt │ │ ├── Fastly.txt │ │ ├── Forza Horizon 4 - Tencent.txt │ │ ├── Forza Motorsport 7 - Tencent.txt │ │ ├── Grand Theft Auto V - Tencent.txt │ │ ├── Grand Theft Auto V - UU.txt │ │ ├── Insurgency Sandstorm - Tencent.txt │ │ ├── Maple Story (Taiwan) - UU.txt │ │ ├── NBA 2K21 - UU.txt │ │ ├── Phasmophobia - UU.txt │ │ ├── PlayerUnknown's Battlegrounds - Tencent.txt │ │ ├── PlayerUnknown's Battlegrounds - UU.txt │ │ ├── Scum - Tencent.txt │ │ ├── Scum - UU.txt │ │ ├── Sea of Thieves - Tencent.txt │ │ ├── Sea of Thieves - UU.txt │ │ └── Tom Clancy's Rainbow Six Siege - UU.txt │ ├── Ubisoft Connect.txt │ ├── pcap2socks-Tencent.txt │ └── pcap2socks-UU.txt ├── nfdriver.sys ├── stun.txt └── tun2socks.bin ├── Tests ├── .gitignore ├── Global.cs └── Tests.csproj ├── build.ps1 ├── clean.ps1 ├── common.props ├── global.json ├── jetbrains.svg └── sha256.ps1 /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug report 2 | description: Create a report to help us improve 3 | labels: bug 4 | body: 5 | - type: textarea 6 | id: error 7 | attributes: 8 | label: Describe the bug 9 | description: A clear and concise description of what the bug is. 10 | validations: 11 | required: true 12 | - type: textarea 13 | id: reproduce 14 | attributes: 15 | label: To Reproduce 16 | placeholder: | 17 | 1. Open Netch 18 | 2. ... 19 | validations: 20 | required: true 21 | - type: textarea 22 | id: log 23 | attributes: 24 | label: Log 25 | description: Attaching any log files in the folder `logging` is strongly recommended. 26 | validations: 27 | required: true 28 | - type: textarea 29 | id: environment 30 | attributes: 31 | label: Environment 32 | render: txt 33 | placeholder: | 34 | - OS: [e.g. Windows 10 x64 Professional Workstation 20H2 19042.928] 35 | - Netch Version: [e.g. 1.0.0] 36 | validations: 37 | required: true 38 | - type: textarea 39 | id: info 40 | attributes: 41 | label: Additional information 42 | description: > 43 | If you have any additional information for us, use the field below. 44 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.zh-CN.yml: -------------------------------------------------------------------------------- 1 | name: 错误报告 2 | description: 创建错误报告以帮助我们改进 3 | labels: bug 4 | body: 5 | - type: textarea 6 | id: error 7 | attributes: 8 | label: 错误描述 9 | description: 对错误的清晰简洁描述 10 | validations: 11 | required: true 12 | - type: textarea 13 | id: reproduce 14 | attributes: 15 | label: 复现步骤 16 | placeholder: | 17 | 1. 打开 Netch 软件 18 | 2. ... 19 | validations: 20 | required: true 21 | - type: textarea 22 | id: log 23 | attributes: 24 | label: 日志 25 | description: 强烈建议附上任何在 `logging` 文件夹下面的日志 26 | validations: 27 | required: true 28 | - type: textarea 29 | id: environment 30 | attributes: 31 | label: 操作环境 32 | render: txt 33 | placeholder: | 34 | 操作系统:[Windows 10 x64 Professional Workstation 20H2 19042.928] 35 | 软件版本:[1.0.0] 36 | validations: 37 | required: true 38 | - type: textarea 39 | id: info 40 | attributes: 41 | label: 额外信息 42 | description: > 43 | 下面的文本框中你可以附上跟 issue 相关的截图、文件 44 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Telegram Channel 4 | url: https://t.me/netch_channel 5 | about: Telegram Channel 6 | 7 | - name: Telegram Group 8 | url: https://t.me/netch_group 9 | about: Telegram Group 10 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: Feature request 2 | description: Suggest an idea for this project 3 | labels: enhancement 4 | body: 5 | - type: textarea 6 | id: description 7 | attributes: 8 | label: Describe the feature you want 9 | description: A clear and concise description of what you want to happen. 10 | validations: 11 | required: true 12 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.zh-CN.yml: -------------------------------------------------------------------------------- 1 | name: 功能请求 2 | description: 建议这个项目的想法 3 | labels: enhancement 4 | body: 5 | - type: textarea 6 | id: description 7 | attributes: 8 | label: 功能描述 9 | description: 简明扼要地描述需要的功能 10 | validations: 11 | required: true 12 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | time: "00:00" 8 | timezone: "Asia/Shanghai" 9 | 10 | - package-ecosystem: "nuget" 11 | directory: "/" 12 | schedule: 13 | interval: "daily" 14 | time: "00:00" 15 | timezone: "Asia/Shanghai" 16 | labels: 17 | - "automatic" 18 | 19 | - package-ecosystem: "gomod" 20 | directory: "/" 21 | schedule: 22 | interval: "daily" 23 | time: "00:00" 24 | timezone: "Asia/Shanghai" 25 | labels: 26 | - "automatic" 27 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: Close stale issues and PRs 2 | on: 3 | schedule: 4 | - cron: "0 0 * * *" 5 | 6 | jobs: 7 | close-issues: 8 | runs-on: ubuntu-latest 9 | permissions: 10 | issues: write 11 | pull-requests: write 12 | steps: 13 | - uses: actions/stale@v7 14 | with: 15 | days-before-issue-stale: 30 16 | days-before-issue-close: 14 17 | days-before-pr-stale: 30 18 | days-before-pr-close: 14 19 | stale-issue-message: "This issue is stale because it has been open for 30 days with no activity." 20 | close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale." 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.vs 2 | /.idea 3 | /release 4 | /packages 5 | /TestResults 6 | -------------------------------------------------------------------------------- /Netch/.gitignore: -------------------------------------------------------------------------------- 1 | /bin 2 | /obj 3 | /*.csproj.user 4 | FodyWeavers.xsd -------------------------------------------------------------------------------- /Netch/App.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Netch/Constants.cs: -------------------------------------------------------------------------------- 1 | namespace Netch; 2 | 3 | public static class Constants 4 | { 5 | public const string TempConfig = "data\\last.json"; 6 | public const string TempRouteFile = "data\\route.txt"; 7 | 8 | public const string AioDnsRuleFile = "bin\\aiodns.conf"; 9 | public const string NFDriver = "bin\\nfdriver.sys"; 10 | public const string STUNServersFile = "bin\\stun.txt"; 11 | 12 | public const string LogFile = "logging\\application.log"; 13 | 14 | public const string OutputTemplate = @"[{Timestamp:yyyy-MM-dd HH:mm:ss}][{Level}] {Message:lj}{NewLine}{Exception}"; 15 | public const string EOF = "\r\n"; 16 | 17 | public const string DefaultGroup = "NONE"; 18 | 19 | public static class Parameter 20 | { 21 | public const string Show = "-show"; 22 | public const string ForceUpdate = "-forceUpdate"; 23 | } 24 | 25 | public const string WintunDllFile = "bin\\wintun.dll"; 26 | public const string DisableModeDirectoryFileName = "disabled"; 27 | 28 | public const string DefaultPrimaryDNS = "1.1.1.1"; 29 | public const string DefaultCNPrimaryDNS = "223.5.5.5"; 30 | } -------------------------------------------------------------------------------- /Netch/Controllers/DNSController.cs: -------------------------------------------------------------------------------- 1 | using Netch.Interfaces; 2 | using Netch.Models; 3 | using static Netch.Interops.AioDNS; 4 | 5 | namespace Netch.Controllers; 6 | 7 | public class DNSController : IController 8 | { 9 | public string Name => "DNS Service"; 10 | 11 | public static async Task StartAsync() 12 | { 13 | var aioDnsConfig = Global.Settings.AioDNS; 14 | 15 | Dial(NameList.TYPE_REST, ""); 16 | Dial(NameList.TYPE_LIST, Path.GetFullPath(Constants.AioDnsRuleFile)); 17 | // TODO remove ListenPort setting 18 | Dial(NameList.TYPE_LISN, $"127.0.0.1:{aioDnsConfig.ListenPort}"); 19 | Dial(NameList.TYPE_CDNS, $"{aioDnsConfig.ChinaDNS}"); 20 | Dial(NameList.TYPE_ODNS, $"{aioDnsConfig.OtherDNS}"); 21 | 22 | if (!await InitAsync()) 23 | throw new MessageException("AioDNS start failed."); 24 | } 25 | 26 | public Task StopAsync() 27 | { 28 | return FreeAsync(); 29 | } 30 | } -------------------------------------------------------------------------------- /Netch/Controllers/PcapController.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Microsoft.VisualStudio.Threading; 3 | using Netch.Forms; 4 | using Netch.Interfaces; 5 | using Netch.Models; 6 | using Netch.Models.Modes; 7 | using Netch.Models.Modes.ShareMode; 8 | using Netch.Servers; 9 | using Netch.Utils; 10 | 11 | namespace Netch.Controllers; 12 | 13 | public class PcapController : Guard, IModeController 14 | { 15 | private readonly LogForm _form; 16 | private ShareMode _mode = null!; 17 | private Socks5Server _server = null!; 18 | 19 | public PcapController() : base("pcap2socks.exe", encoding: Encoding.UTF8) 20 | { 21 | _form = new LogForm(Global.MainForm); 22 | _form.CreateControl(); 23 | } 24 | 25 | protected override IEnumerable StartedKeywords { get; } = new[] { "└" }; 26 | 27 | public override string Name => "pcap2socks"; 28 | 29 | public ModeFeature Features => ModeFeature.SupportSocks5Auth; 30 | 31 | public async Task StartAsync(Socks5Server server, Mode mode) 32 | { 33 | if (mode is not ShareMode shareMode) 34 | throw new InvalidOperationException(); 35 | 36 | _server = server; 37 | _mode = shareMode; 38 | 39 | var outboundNetworkInterface = NetworkInterfaceUtils.GetBest(); 40 | 41 | var arguments = new List 42 | { 43 | "--interface", $@"\Device\NPF_{outboundNetworkInterface.Id}", 44 | "--destination", $"{await _server.AutoResolveHostnameAsync()}:{_server.Port}", 45 | _mode.Argument, SpecialArgument.Flag 46 | }; 47 | 48 | if (_server.Auth()) 49 | arguments.AddRange(new[] 50 | { 51 | "--username", server.Username, 52 | "--password", server.Password 53 | }); 54 | 55 | await StartGuardAsync(Arguments.Format(arguments)); 56 | } 57 | 58 | public override async Task StopAsync() 59 | { 60 | Global.MainForm.Invoke(() => { _form.Close(); }); 61 | await StopGuardAsync(); 62 | } 63 | 64 | ~PcapController() 65 | { 66 | _form.Dispose(); 67 | } 68 | 69 | protected override void OnReadNewLine(string line) 70 | { 71 | Global.MainForm.BeginInvoke(() => 72 | { 73 | if (!_form.IsDisposed) 74 | _form.richTextBox1.AppendText(line + "\n"); 75 | }); 76 | } 77 | 78 | protected override void OnStarted() 79 | { 80 | Global.MainForm.BeginInvoke(() => _form.Show()); 81 | } 82 | 83 | protected override void OnStartFailed() 84 | { 85 | if (new FileInfo(LogPath).Length == 0) 86 | { 87 | Task.Run(() => 88 | { 89 | Thread.Sleep(1000); 90 | Utils.Utils.Open("https://github.com/zhxie/pcap2socks#dependencies"); 91 | }) 92 | .Forget(); 93 | 94 | throw new MessageException("Pleases install pcap2socks's dependency"); 95 | } 96 | 97 | Utils.Utils.Open(LogPath); 98 | } 99 | } -------------------------------------------------------------------------------- /Netch/Enums/LogLevel.cs: -------------------------------------------------------------------------------- 1 | namespace Netch.Enums; 2 | 3 | public enum LogLevel 4 | { 5 | INFO, 6 | WARNING, 7 | ERROR 8 | } -------------------------------------------------------------------------------- /Netch/Enums/State.cs: -------------------------------------------------------------------------------- 1 | namespace Netch.Enums; 2 | 3 | /// 4 | /// 状态 5 | /// 6 | public enum State 7 | { 8 | /// 9 | /// 等待命令中 10 | /// 11 | Waiting, 12 | 13 | /// 14 | /// 正在启动中 15 | /// 16 | Starting, 17 | 18 | /// 19 | /// 已启动 20 | /// 21 | Started, 22 | 23 | /// 24 | /// 正在停止中 25 | /// 26 | Stopping, 27 | 28 | /// 29 | /// 已停止 30 | /// 31 | Stopped, 32 | 33 | /// 34 | /// 退出中 35 | /// 36 | Terminating 37 | } 38 | 39 | public static class StateExtension 40 | { 41 | public static string GetStatusString(State state) 42 | { 43 | if (state == State.Waiting) 44 | return "Waiting for command"; 45 | 46 | return state.ToString(); 47 | } 48 | } -------------------------------------------------------------------------------- /Netch/Flags.cs: -------------------------------------------------------------------------------- 1 | namespace Netch; 2 | 3 | public static class Flags 4 | { 5 | public static readonly bool IsWindows10Upper = Environment.OSVersion.Version.Major >= 10; 6 | 7 | public static bool AlwaysShowNewVersionFound { get; set; } 8 | 9 | public static bool NoSupport { get; set; } 10 | } -------------------------------------------------------------------------------- /Netch/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /Netch/Forms/AboutForm.cs: -------------------------------------------------------------------------------- 1 | using Netch.Properties; 2 | using Netch.Utils; 3 | 4 | namespace Netch.Forms; 5 | 6 | [Fody.ConfigureAwait(true)] 7 | public partial class AboutForm : Form 8 | { 9 | public AboutForm() 10 | { 11 | InitializeComponent(); 12 | Icon = Resources.icon; 13 | } 14 | 15 | private void AboutForm_Load(object sender, EventArgs e) 16 | { 17 | i18N.TranslateForm(this); 18 | } 19 | 20 | private void NetchPictureBox_Click(object sender, EventArgs e) 21 | { 22 | Utils.Utils.Open("https://github.com/NetchX/Netch"); 23 | } 24 | 25 | private void ChannelLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) 26 | { 27 | Utils.Utils.Open("https://t.me/Netch"); 28 | } 29 | 30 | private void SponsorPictureBox_Click(object sender, EventArgs e) 31 | { 32 | Utils.Utils.Open("https://www.mansora.co"); 33 | } 34 | } -------------------------------------------------------------------------------- /Netch/Forms/AboutForm.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | text/microsoft-resx 50 | 51 | 52 | 2.0 53 | 54 | 55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 56 | 57 | 58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 59 | 60 | -------------------------------------------------------------------------------- /Netch/Forms/GlobalBypassIPForm.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using Netch.Properties; 3 | using Netch.Utils; 4 | 5 | namespace Netch.Forms; 6 | 7 | [Fody.ConfigureAwait(true)] 8 | public partial class GlobalBypassIPForm : Form 9 | { 10 | public GlobalBypassIPForm() 11 | { 12 | InitializeComponent(); 13 | Icon = Resources.icon; 14 | } 15 | 16 | private void GlobalBypassIPForm_Load(object sender, EventArgs e) 17 | { 18 | i18N.TranslateForm(this); 19 | 20 | IPListBox.Items.AddRange(Global.Settings.TUNTAP.BypassIPs.Cast().ToArray()); 21 | 22 | for (var i = 32; i >= 1; i--) 23 | PrefixComboBox.Items.Add(i); 24 | 25 | PrefixComboBox.SelectedIndex = 0; 26 | } 27 | 28 | private void AddButton_Click(object sender, EventArgs e) 29 | { 30 | if (!string.IsNullOrEmpty(IPTextBox.Text)) 31 | { 32 | if (IPAddress.TryParse(IPTextBox.Text, out var address)) 33 | IPListBox.Items.Add($"{address}/{PrefixComboBox.SelectedItem}"); 34 | else 35 | MessageBoxX.Show(i18N.Translate("Please enter a correct IP address")); 36 | } 37 | else 38 | { 39 | MessageBoxX.Show(i18N.Translate("Please enter an IP")); 40 | } 41 | } 42 | 43 | private void DeleteButton_Click(object sender, EventArgs e) 44 | { 45 | if (IPListBox.SelectedIndex != -1) 46 | IPListBox.Items.RemoveAt(IPListBox.SelectedIndex); 47 | else 48 | MessageBoxX.Show(i18N.Translate("Please select an IP")); 49 | } 50 | 51 | private async void ControlButton_Click(object sender, EventArgs e) 52 | { 53 | Global.Settings.TUNTAP.BypassIPs.Clear(); 54 | foreach (var ip in IPListBox.Items) 55 | Global.Settings.TUNTAP.BypassIPs.Add((string)ip); 56 | 57 | await Configuration.SaveAsync(); 58 | MessageBoxX.Show(i18N.Translate("Saved")); 59 | Close(); 60 | } 61 | } -------------------------------------------------------------------------------- /Netch/Forms/LogForm.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using Windows.Win32.Foundation; 3 | using Windows.Win32.UI.WindowsAndMessaging; 4 | using static Windows.Win32.PInvoke; 5 | 6 | namespace Netch.Forms; 7 | 8 | [Fody.ConfigureAwait(true)] 9 | public partial class LogForm : Form 10 | { 11 | private readonly Form _parent; 12 | 13 | public LogForm(Form parent) 14 | { 15 | InitializeComponent(); 16 | _parent = parent; 17 | } 18 | 19 | protected override void OnLoad(EventArgs? e) 20 | { 21 | base.OnLoad(e); 22 | Parent_Move(null!, null!); 23 | } 24 | 25 | private void Parent_Move(object? sender, EventArgs? e) 26 | { 27 | var cl = Location; 28 | var fl = _parent.Location; 29 | 30 | cl.X = fl.X + _parent.Width; 31 | cl.Y = fl.Y; 32 | Location = cl; 33 | } 34 | 35 | private void Parent_Activated(object? sender, EventArgs? e) 36 | { 37 | SetWindowPos(new HWND(Handle), 38 | new HWND(-1), 39 | 0, 40 | 0, 41 | 0, 42 | 0, 43 | SET_WINDOW_POS_FLAGS.SWP_NOACTIVATE | SET_WINDOW_POS_FLAGS.SWP_NOMOVE | SET_WINDOW_POS_FLAGS.SWP_NOSIZE | SET_WINDOW_POS_FLAGS.SWP_SHOWWINDOW); 44 | 45 | SetWindowPos(new HWND(Handle), 46 | new HWND(-2), 47 | 0, 48 | 0, 49 | 0, 50 | 0, 51 | SET_WINDOW_POS_FLAGS.SWP_NOACTIVATE | SET_WINDOW_POS_FLAGS.SWP_NOMOVE | SET_WINDOW_POS_FLAGS.SWP_NOSIZE | SET_WINDOW_POS_FLAGS.SWP_SHOWWINDOW); 52 | } 53 | 54 | private void RichTextBox1_TextChanged(object? sender, EventArgs? e) 55 | { 56 | if (!checkBox1.Checked) 57 | return; 58 | 59 | richTextBox1.SelectionStart = richTextBox1.Text.Length; 60 | richTextBox1.ScrollToCaret(); 61 | } 62 | 63 | private void LogForm_Load(object? sender, EventArgs? e) 64 | { 65 | _parent.LocationChanged += Parent_Move; 66 | _parent.SizeChanged += Parent_Move; 67 | _parent.Activated += Parent_Activated; 68 | _parent.VisibleChanged += Parent_VisibleChanged; 69 | } 70 | 71 | private void Parent_VisibleChanged(object? sender, EventArgs e) 72 | { 73 | Visible = _parent.Visible; 74 | } 75 | 76 | protected override void OnClosing(CancelEventArgs? e) 77 | { 78 | _parent.LocationChanged -= Parent_Move; 79 | _parent.SizeChanged -= Parent_Move; 80 | _parent.Activated -= Parent_Activated; 81 | _parent.VisibleChanged -= Parent_VisibleChanged; 82 | base.OnClosing(e!); 83 | } 84 | } -------------------------------------------------------------------------------- /Netch/Forms/LogForm.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | text/microsoft-resx 50 | 51 | 52 | 2.0 53 | 54 | 55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 56 | 57 | 58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 59 | 60 | -------------------------------------------------------------------------------- /Netch/Forms/MessageBoxX.cs: -------------------------------------------------------------------------------- 1 | using Netch.Enums; 2 | using Netch.Utils; 3 | 4 | namespace Netch.Forms; 5 | 6 | public static class MessageBoxX 7 | { 8 | /// 9 | /// 10 | /// 内容 11 | /// 自定义标题 12 | /// 弹窗等级 (标题, 图标) 13 | /// 需要确认 14 | /// 阻止 owner Focus() 直到 Messageox 被关闭 15 | public static DialogResult Show(string text, 16 | LogLevel level = LogLevel.INFO, 17 | string title = "", 18 | bool confirm = false, 19 | IWin32Window? owner = null) 20 | { 21 | MessageBoxIcon msgIcon; 22 | if (string.IsNullOrWhiteSpace(title)) 23 | title = level switch 24 | { 25 | LogLevel.INFO => "Information", 26 | LogLevel.WARNING => "Warning", 27 | LogLevel.ERROR => "Error", 28 | _ => throw new ArgumentOutOfRangeException(nameof(level), level, null) 29 | }; 30 | 31 | msgIcon = level switch 32 | { 33 | LogLevel.INFO => MessageBoxIcon.Information, 34 | LogLevel.WARNING => MessageBoxIcon.Warning, 35 | LogLevel.ERROR => MessageBoxIcon.Exclamation, 36 | _ => throw new ArgumentOutOfRangeException(nameof(level), level, null) 37 | }; 38 | 39 | return MessageBox.Show(owner, text, i18N.Translate(title), confirm ? MessageBoxButtons.OKCancel : MessageBoxButtons.OK, msgIcon); 40 | } 41 | } -------------------------------------------------------------------------------- /Netch/Forms/ModeForms/ModeEditorUtils.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace Netch.Forms.ModeForms; 4 | 5 | public static class ModeEditorUtils 6 | { 7 | public static string ToSafeFileName(string text) 8 | { 9 | var fileName = new StringBuilder(text); 10 | foreach (var c in Path.GetInvalidFileNameChars()) 11 | fileName.Replace(c, '_'); 12 | 13 | return fileName.ToString(); 14 | } 15 | 16 | public static string GetCustomModeRelativePath(string name) 17 | { 18 | if (name == string.Empty) 19 | return string.Empty; 20 | 21 | var safeFileName = ToSafeFileName(name); 22 | var relativePath = $"Custom\\{safeFileName}.json"; 23 | return relativePath; 24 | } 25 | } -------------------------------------------------------------------------------- /Netch/Forms/ModeForms/ProcessForm.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | text/microsoft-resx 50 | 51 | 52 | 2.0 53 | 54 | 55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 56 | 57 | 58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 59 | 60 | -------------------------------------------------------------------------------- /Netch/Forms/ModeForms/RouteForm.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | text/microsoft-resx 50 | 51 | 52 | 2.0 53 | 54 | 55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 56 | 57 | 58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 59 | 60 | -------------------------------------------------------------------------------- /Netch/Forms/SyncGlobalCheckBox.cs: -------------------------------------------------------------------------------- 1 | namespace Netch.Forms; 2 | 3 | public class SyncGlobalCheckBox : CheckBox 4 | { 5 | public SyncGlobalCheckBox() 6 | { 7 | AutoCheck = false; 8 | OnSyncGlobalChanged(); 9 | } 10 | 11 | private bool _syncGlobal; 12 | 13 | private bool _globalValue; 14 | 15 | public bool SyncGlobal 16 | { 17 | get => _syncGlobal; 18 | set 19 | { 20 | if (value == _syncGlobal) 21 | return; 22 | 23 | _syncGlobal = value; 24 | 25 | OnSyncGlobalChanged(); 26 | } 27 | } 28 | 29 | public bool GlobalValue 30 | { 31 | get => _globalValue; 32 | set 33 | { 34 | if (value == _globalValue) 35 | return; 36 | 37 | _globalValue = value; 38 | 39 | if (SyncGlobal) 40 | Checked = value; 41 | } 42 | } 43 | 44 | protected override void OnClick(EventArgs e) 45 | { 46 | if (Checked == GlobalValue) 47 | { 48 | SyncGlobal = !SyncGlobal; 49 | if (SyncGlobal) 50 | return; 51 | } 52 | 53 | Checked = !Checked; 54 | base.OnClick(e); 55 | } 56 | 57 | public bool? Value 58 | { 59 | get => _syncGlobal ? null : Checked; 60 | set 61 | { 62 | if (value == null) 63 | { 64 | SyncGlobal = true; 65 | } 66 | else 67 | { 68 | SyncGlobal = false; 69 | Checked = (bool)value; 70 | } 71 | } 72 | } 73 | 74 | private void OnSyncGlobalChanged() 75 | { 76 | if (_syncGlobal) 77 | { 78 | Font = new Font(Font, FontStyle.Regular); 79 | BackColor = SystemColors.Control; 80 | } 81 | else 82 | { 83 | Font = new Font(Font, FontStyle.Bold | FontStyle.Italic); 84 | BackColor = Color.Yellow; 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /Netch/Global.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Encodings.Web; 2 | using System.Text.Json; 3 | using System.Text.Json.Serialization; 4 | using Netch.Forms; 5 | using Netch.Models; 6 | using Netch.Models.Modes; 7 | using WindowsJobAPI; 8 | 9 | namespace Netch; 10 | 11 | public static class Global 12 | { 13 | /// 14 | /// 主窗体的静态实例 15 | /// 16 | private static readonly Lazy LazyMainForm = new(() => new MainForm()); 17 | 18 | /// 19 | /// 用于读取和写入的配置 20 | /// 21 | internal static Setting Settings = new(); 22 | 23 | public static readonly JobObject Job = new(); 24 | 25 | /// 26 | /// 用于存储模式 27 | /// 28 | public static readonly List Modes = new(); 29 | 30 | public static readonly string NetchDir; 31 | public static readonly string NetchExecutable; 32 | 33 | static Global() 34 | { 35 | NetchExecutable = Application.ExecutablePath; 36 | NetchDir = Application.StartupPath; 37 | } 38 | 39 | /// 40 | /// 主窗体的静态实例 41 | /// 42 | public static MainForm MainForm => LazyMainForm.Value; 43 | 44 | public static JsonSerializerOptions NewCustomJsonSerializerOptions() => new() 45 | { 46 | WriteIndented = true, 47 | DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, 48 | Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping 49 | }; 50 | } -------------------------------------------------------------------------------- /Netch/Interfaces/IController.cs: -------------------------------------------------------------------------------- 1 | namespace Netch.Interfaces; 2 | 3 | public interface IController 4 | { 5 | public string Name { get; } 6 | 7 | public Task StopAsync(); 8 | } -------------------------------------------------------------------------------- /Netch/Interfaces/IModeController.cs: -------------------------------------------------------------------------------- 1 | using Netch.Models.Modes; 2 | using Netch.Servers; 3 | 4 | namespace Netch.Interfaces; 5 | 6 | public interface IModeController : IController 7 | { 8 | public ModeFeature Features { get; } 9 | 10 | public Task StartAsync(Socks5Server server, Mode mode); 11 | } -------------------------------------------------------------------------------- /Netch/Interfaces/IServerController.cs: -------------------------------------------------------------------------------- 1 | using Netch.Models; 2 | using Netch.Servers; 3 | 4 | namespace Netch.Interfaces; 5 | 6 | public interface IServerController : IController 7 | { 8 | public ushort? Socks5LocalPort { get; set; } 9 | 10 | public string? LocalAddress { get; set; } 11 | 12 | public Task StartAsync(Server s); 13 | } 14 | 15 | public static class ServerControllerExtension 16 | { 17 | public static ushort Socks5LocalPort(this IServerController controller) 18 | { 19 | return controller.Socks5LocalPort ?? Global.Settings.Socks5LocalPort; 20 | } 21 | 22 | public static string LocalAddress(this IServerController controller) 23 | { 24 | return controller.LocalAddress ?? Global.Settings.LocalAddress; 25 | } 26 | } -------------------------------------------------------------------------------- /Netch/Interfaces/IServerUtil.cs: -------------------------------------------------------------------------------- 1 | using Netch.Models; 2 | 3 | namespace Netch.Interfaces; 4 | 5 | public interface IServerUtil 6 | { 7 | /// 8 | /// Collection order basis 9 | /// 10 | ushort Priority { get; } 11 | 12 | /// 13 | /// Server.Type 14 | /// 15 | string TypeName { get; } 16 | 17 | /// 18 | /// Protocol Name 19 | /// 20 | string FullName { get; } 21 | 22 | string ShortName { get; } 23 | 24 | /// 25 | /// Support URI 26 | /// 27 | string[] UriScheme { get; } 28 | 29 | public Type ServerType { get; } 30 | 31 | public void Edit(Server s); 32 | 33 | public void Create(); 34 | 35 | string GetShareLink(Server s); 36 | 37 | public IServerController GetController(); 38 | 39 | public IEnumerable ParseUri(string text); 40 | 41 | bool CheckServer(Server s); 42 | } -------------------------------------------------------------------------------- /Netch/Interops/AioDNS.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | using System.Text; 3 | 4 | namespace Netch.Interops; 5 | 6 | public static class AioDNS 7 | { 8 | private const string aiodns_bin = "aiodns.bin"; 9 | 10 | public static bool Dial(NameList name, string value) 11 | { 12 | Log.Verbose($"[aiodns] Dial {name}: {value}"); 13 | return aiodns_dial(name, Encoding.UTF8.GetBytes(value)); 14 | } 15 | 16 | public static Task InitAsync() 17 | { 18 | return Task.Run(Init); 19 | } 20 | 21 | public static Task FreeAsync() 22 | { 23 | return Task.Run(Free); 24 | } 25 | 26 | [DllImport(aiodns_bin, CallingConvention = CallingConvention.Cdecl)] 27 | private static extern bool aiodns_dial(NameList name, byte[] value); 28 | 29 | [DllImport(aiodns_bin, EntryPoint = "aiodns_init", CallingConvention = CallingConvention.Cdecl)] 30 | private static extern bool Init(); 31 | 32 | [DllImport(aiodns_bin, EntryPoint = "aiodns_free", CallingConvention = CallingConvention.Cdecl)] 33 | private static extern void Free(); 34 | 35 | public enum NameList 36 | { 37 | TYPE_REST, 38 | TYPE_LIST, 39 | TYPE_LISN, 40 | TYPE_CDNS, 41 | TYPE_ODNS 42 | } 43 | } -------------------------------------------------------------------------------- /Netch/Interops/Redirector.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace Netch.Interops; 4 | 5 | public static class Redirector 6 | { 7 | public enum NameList 8 | { 9 | AIO_FILTERLOOPBACK, 10 | AIO_FILTERINTRANET, // LAN 11 | AIO_FILTERPARENT, 12 | AIO_FILTERICMP, 13 | AIO_FILTERTCP, 14 | AIO_FILTERUDP, 15 | AIO_FILTERDNS, 16 | 17 | AIO_ICMPING, 18 | 19 | AIO_DNSONLY, 20 | AIO_DNSPROX, 21 | AIO_DNSHOST, 22 | AIO_DNSPORT, 23 | 24 | AIO_TGTHOST, 25 | AIO_TGTPORT, 26 | AIO_TGTUSER, 27 | AIO_TGTPASS, 28 | 29 | AIO_CLRNAME, 30 | AIO_ADDNAME, 31 | AIO_BYPNAME 32 | } 33 | 34 | public static bool Dial(NameList name, bool value) 35 | { 36 | Log.Verbose($"[Redirector] Dial {name}: {value}"); 37 | return aio_dial(name, value.ToString().ToLower()); 38 | } 39 | 40 | public static bool Dial(NameList name, string value) 41 | { 42 | Log.Verbose($"[Redirector] Dial {name}: {value}"); 43 | return aio_dial(name, value); 44 | } 45 | 46 | public static Task InitAsync() 47 | { 48 | return Task.Run(aio_init); 49 | } 50 | 51 | public static Task FreeAsync() 52 | { 53 | return Task.Run(aio_free); 54 | } 55 | 56 | private const string Redirector_bin = "Redirector.bin"; 57 | 58 | [DllImport(Redirector_bin, CallingConvention = CallingConvention.Cdecl)] 59 | internal static extern bool aio_register([MarshalAs(UnmanagedType.LPWStr)] string value); 60 | 61 | [DllImport(Redirector_bin, CallingConvention = CallingConvention.Cdecl)] 62 | internal static extern bool aio_unregister([MarshalAs(UnmanagedType.LPWStr)] string value); 63 | 64 | [DllImport(Redirector_bin, CallingConvention = CallingConvention.Cdecl)] 65 | private static extern bool aio_dial(NameList name, [MarshalAs(UnmanagedType.LPWStr)] string value); 66 | 67 | [DllImport(Redirector_bin, CallingConvention = CallingConvention.Cdecl)] 68 | private static extern bool aio_init(); 69 | 70 | [DllImport(Redirector_bin, CallingConvention = CallingConvention.Cdecl)] 71 | private static extern bool aio_free(); 72 | 73 | [DllImport(Redirector_bin, CallingConvention = CallingConvention.Cdecl)] 74 | private static extern ulong aio_getUP(); 75 | 76 | [DllImport(Redirector_bin, CallingConvention = CallingConvention.Cdecl)] 77 | private static extern ulong aio_getDL(); 78 | } -------------------------------------------------------------------------------- /Netch/Interops/tun2socks.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | using System.Text; 3 | using System.Threading.Tasks; 4 | using Serilog; 5 | 6 | namespace Netch.Interops 7 | { 8 | public static class Tun2socks 9 | { 10 | public enum NameList 11 | { 12 | TYPE_BYPBIND, 13 | TYPE_BYPLIST, 14 | TYPE_DNSADDR, 15 | TYPE_ADAPMTU, 16 | TYPE_TCPREST, 17 | TYPE_TCPTYPE, 18 | TYPE_TCPHOST, 19 | TYPE_TCPUSER, 20 | TYPE_TCPPASS, 21 | TYPE_TCPMETH, 22 | TYPE_TCPPROT, 23 | TYPE_TCPPRPA, 24 | TYPE_TCPOBFS, 25 | TYPE_TCPOBPA, 26 | TYPE_UDPREST, 27 | TYPE_UDPTYPE, 28 | TYPE_UDPHOST, 29 | TYPE_UDPUSER, 30 | TYPE_UDPPASS, 31 | TYPE_UDPMETH, 32 | TYPE_UDPPROT, 33 | TYPE_UDPPRPA, 34 | TYPE_UDPOBFS, 35 | TYPE_UDPOBPA 36 | } 37 | 38 | public static bool Dial(NameList name, string value) 39 | { 40 | Log.Verbose( $"[tun2socks] Dial {name}: {value}"); 41 | return tun_dial(name, Encoding.UTF8.GetBytes(value)); 42 | } 43 | 44 | public static bool Init() 45 | { 46 | Log.Verbose("[tun2socks] init"); 47 | return tun_init(); 48 | } 49 | 50 | public static async Task FreeAsync() 51 | { 52 | return await Task.Run(tun_free).ConfigureAwait(false); 53 | } 54 | 55 | private const string tun2socks_bin = "tun2socks.bin"; 56 | 57 | [DllImport(tun2socks_bin, CallingConvention = CallingConvention.Cdecl)] 58 | private static extern bool tun_dial(NameList name, byte[] value); 59 | 60 | [DllImport(tun2socks_bin, CallingConvention = CallingConvention.Cdecl)] 61 | private static extern bool tun_init(); 62 | 63 | [DllImport(tun2socks_bin, CallingConvention = CallingConvention.Cdecl)] 64 | private static extern bool tun_free(); 65 | 66 | [DllImport(tun2socks_bin, CallingConvention = CallingConvention.Cdecl)] 67 | internal static extern ulong tun_luid(); 68 | 69 | [DllImport(tun2socks_bin, CallingConvention = CallingConvention.Cdecl)] 70 | private static extern ulong tun_getUP(); 71 | 72 | [DllImport(tun2socks_bin, CallingConvention = CallingConvention.Cdecl)] 73 | private static extern ulong tun_getDL(); 74 | } 75 | } -------------------------------------------------------------------------------- /Netch/JsonConverter/ModeConverterWithTypeDiscriminator.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using System.Text.Json.Serialization; 3 | using Netch.Models.Modes; 4 | using Netch.Models.Modes.ProcessMode; 5 | using Netch.Models.Modes.ShareMode; 6 | using Netch.Models.Modes.TunMode; 7 | 8 | namespace Netch.JsonConverter; 9 | 10 | public class ModeConverterWithTypeDiscriminator : JsonConverter 11 | { 12 | public override Mode? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 13 | { 14 | var jsonElement = JsonSerializer.Deserialize(ref reader); 15 | 16 | var modeTypePropertyName = JsonNamingPolicy.CamelCase.ConvertName(nameof(Mode.Type)); 17 | if (!jsonElement.TryGetProperty(modeTypePropertyName, out var modeTypeToken)) 18 | throw new JsonException(); 19 | 20 | var modeTypeEnum = modeTypeToken.ValueKind switch 21 | { 22 | JsonValueKind.Number => (ModeType)modeTypeToken.GetInt32(), 23 | JsonValueKind.String => Enum.Parse(modeTypeToken.GetString()!), 24 | _ => throw new JsonException() 25 | }; 26 | 27 | var modeType = modeTypeEnum switch 28 | { 29 | ModeType.ProcessMode => typeof(Redirector), 30 | ModeType.TunMode => typeof(TunMode), 31 | ModeType.ShareMode => typeof(ShareMode), 32 | _ => throw new ArgumentOutOfRangeException(nameof(modeTypeEnum), "Invalid ModeType value.") 33 | }; 34 | 35 | return (Mode?)jsonElement.Deserialize(modeType, options); 36 | } 37 | 38 | public override void Write(Utf8JsonWriter writer, Mode value, JsonSerializerOptions options) 39 | { 40 | JsonSerializer.Serialize(writer, value, options); 41 | } 42 | } -------------------------------------------------------------------------------- /Netch/JsonConverter/ServerConverterWithTypeDiscriminator.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using System.Text.Json.Serialization; 3 | using Netch.Models; 4 | using Netch.Utils; 5 | 6 | namespace Netch.JsonConverter; 7 | 8 | public class ServerConverterWithTypeDiscriminator : JsonConverter 9 | { 10 | public override Server Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 11 | { 12 | var jsonElement = JsonSerializer.Deserialize(ref reader); 13 | var type = ServerHelper.GetTypeByTypeName(jsonElement.GetProperty("Type").GetString()!); 14 | return (Server)jsonElement.Deserialize(type)!; 15 | } 16 | 17 | public override void Write(Utf8JsonWriter writer, Server value, JsonSerializerOptions options) 18 | { 19 | JsonSerializer.Serialize(writer, value, options); 20 | } 21 | } -------------------------------------------------------------------------------- /Netch/Models/Arguments.cs: -------------------------------------------------------------------------------- 1 | using Netch.Utils; 2 | 3 | namespace Netch.Models; 4 | 5 | public static class Arguments 6 | { 7 | public static string Format(IEnumerable a) 8 | { 9 | var arguments = a.ToList(); 10 | if (arguments.Count % 2 != 0) 11 | throw new FormatException("missing last argument value"); 12 | 13 | var tokens = new List(); 14 | 15 | for (var i = 0; i < arguments.Count; i += 2) 16 | { 17 | var keyObj = arguments[i]; 18 | var valueObj = arguments[i + 1]; 19 | 20 | if (keyObj is not string key) 21 | throw new FormatException($"argument key at array index {i} is not string"); 22 | 23 | switch (valueObj) 24 | { 25 | case SpecialArgument.Flag: 26 | tokens.Add(key); 27 | break; 28 | case null: 29 | case string value when value.IsNullOrWhiteSpace(): 30 | continue; 31 | default: 32 | tokens.Add(key); 33 | tokens.Add(valueObj.ToString()!); 34 | break; 35 | } 36 | } 37 | 38 | return string.Join(' ', tokens); 39 | } 40 | } 41 | 42 | public enum SpecialArgument 43 | { 44 | Flag 45 | } -------------------------------------------------------------------------------- /Netch/Models/GitHubRelease/Asset.cs: -------------------------------------------------------------------------------- 1 | #nullable disable 2 | namespace Netch.Models.GitHubRelease; 3 | 4 | public class Asset 5 | { 6 | public string url { get; set; } 7 | 8 | public int id { get; set; } 9 | 10 | public string node_id { get; set; } 11 | 12 | public string name { get; set; } 13 | 14 | public object label { get; set; } 15 | 16 | public GitHubUser uploader { get; set; } 17 | 18 | public string content_type { get; set; } 19 | 20 | public string state { get; set; } 21 | 22 | public int size { get; set; } 23 | 24 | public int download_count { get; set; } 25 | 26 | public DateTime created_at { get; set; } 27 | 28 | public DateTime updated_at { get; set; } 29 | 30 | public string browser_download_url { get; set; } 31 | } -------------------------------------------------------------------------------- /Netch/Models/GitHubRelease/GitHubRelease.cs: -------------------------------------------------------------------------------- 1 | namespace Netch.Models.GitHubRelease; 2 | 3 | public class GitHubRelease 4 | { 5 | private readonly string _owner; 6 | private readonly string _repo; 7 | 8 | public GitHubRelease(string owner, string repo) 9 | { 10 | _owner = owner; 11 | _repo = repo; 12 | } 13 | 14 | public string AllReleaseUrl => $@"https://api.github.com/repos/{_owner}/{_repo}/releases"; 15 | } -------------------------------------------------------------------------------- /Netch/Models/GitHubRelease/GitHubUser.cs: -------------------------------------------------------------------------------- 1 | #nullable disable 2 | namespace Netch.Models.GitHubRelease; 3 | 4 | public class GitHubUser 5 | { 6 | public string login { get; set; } 7 | 8 | public int id { get; set; } 9 | 10 | public string node_id { get; set; } 11 | 12 | public string avatar_url { get; set; } 13 | 14 | public string gravatar_id { get; set; } 15 | 16 | public string url { get; set; } 17 | 18 | public string html_url { get; set; } 19 | 20 | public string followers_url { get; set; } 21 | 22 | public string following_url { get; set; } 23 | 24 | public string gists_url { get; set; } 25 | 26 | public string starred_url { get; set; } 27 | 28 | public string subscriptions_url { get; set; } 29 | 30 | public string organizations_url { get; set; } 31 | 32 | public string repos_url { get; set; } 33 | 34 | public string events_url { get; set; } 35 | 36 | public string received_events_url { get; set; } 37 | 38 | public string type { get; set; } 39 | 40 | public bool site_admin { get; set; } 41 | } -------------------------------------------------------------------------------- /Netch/Models/GitHubRelease/Release.cs: -------------------------------------------------------------------------------- 1 | #nullable disable 2 | namespace Netch.Models.GitHubRelease; 3 | 4 | public class Release 5 | { 6 | public string url { get; set; } 7 | 8 | public string assets_url { get; set; } 9 | 10 | public string upload_url { get; set; } 11 | 12 | public string html_url { get; set; } 13 | 14 | public int id { get; set; } 15 | 16 | public string node_id { get; set; } 17 | 18 | public string tag_name { get; set; } 19 | 20 | public string target_commitish { get; set; } 21 | 22 | public string name { get; set; } 23 | 24 | public bool draft { get; set; } 25 | 26 | public GitHubUser author { get; set; } 27 | 28 | public bool prerelease { get; set; } 29 | 30 | public DateTime created_at { get; set; } 31 | 32 | public DateTime published_at { get; set; } 33 | 34 | public Asset[] assets { get; set; } 35 | 36 | public string tarball_url { get; set; } 37 | 38 | public string zipball_url { get; set; } 39 | 40 | public string body { get; set; } 41 | } -------------------------------------------------------------------------------- /Netch/Models/GitHubRelease/VersionUtil.cs: -------------------------------------------------------------------------------- 1 | namespace Netch.Models.GitHubRelease; 2 | 3 | public static class VersionUtil 4 | { 5 | private static VersionComparer instance = new(); 6 | 7 | public static int CompareVersion(string x, string y) 8 | { 9 | return instance.Compare(x, y); 10 | } 11 | 12 | public class VersionComparer : IComparer 13 | { 14 | /// 15 | /// Greater than 0 newer 16 | /// 17 | /// 18 | /// 19 | /// 20 | public int Compare(string? x, string? y) 21 | { 22 | var xResult = SuffixVersion.TryParse(x, out var version1) ? 1 : 0; 23 | var yResult = SuffixVersion.TryParse(y, out var version2) ? 1 : 0; 24 | 25 | var parseResult = xResult - yResult; 26 | if (parseResult != 0) 27 | return parseResult; 28 | 29 | return version1.CompareTo(version2); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Netch/Models/MessageException.cs: -------------------------------------------------------------------------------- 1 | namespace Netch.Models; 2 | 3 | public class MessageException : Exception 4 | { 5 | public MessageException() 6 | { 7 | } 8 | 9 | public MessageException(string message) : base(message) 10 | { 11 | } 12 | } -------------------------------------------------------------------------------- /Netch/Models/Modes/Mode.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | using Netch.Utils; 3 | 4 | namespace Netch.Models.Modes; 5 | 6 | public abstract class Mode 7 | { 8 | [JsonPropertyOrder(int.MinValue)] 9 | public abstract ModeType Type { get; } 10 | 11 | public Dictionary Remark { get; set; } = new(); 12 | 13 | [JsonIgnore] 14 | // File FullName 15 | // TODO maybe make it becomes mode dictionary key 16 | public string FullName { get; set; } = string.Empty; 17 | 18 | public override string ToString() => $"[{(int)Type + 1}] {i18NRemark}"; 19 | 20 | [JsonIgnore] 21 | public string i18NRemark 22 | { 23 | // TODO i18N.Culture to support fallback 24 | get => Remark.GetValueOrDefault(i18N.LangCode) ?? Remark.GetValueOrDefault("en") ?? ""; 25 | set => Remark[i18N.LangCode] = value; 26 | } 27 | } -------------------------------------------------------------------------------- /Netch/Models/Modes/ModeFeature.cs: -------------------------------------------------------------------------------- 1 | namespace Netch.Models.Modes; 2 | 3 | [Flags] 4 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "CA1069:Enums values should not be duplicated", Justification = "Intentional duplication for specific scenario.")] 5 | public enum ModeFeature 6 | { 7 | SupportSocks5 = 0, 8 | SupportIPv4 = 0, 9 | SupportSocks5Auth = 0b_0001, 10 | SupportIPv6 = 0b_0100 11 | } -------------------------------------------------------------------------------- /Netch/Models/Modes/ModeType.cs: -------------------------------------------------------------------------------- 1 | namespace Netch.Models.Modes; 2 | 3 | public enum ModeType 4 | { 5 | /// 6 | /// 进程代理 7 | /// 8 | ProcessMode, 9 | 10 | /// 11 | /// 网络共享 12 | /// 13 | ShareMode, 14 | 15 | /// 16 | /// 网卡代理 17 | /// 18 | TunMode 19 | } -------------------------------------------------------------------------------- /Netch/Models/Modes/ProcessMode/ProcessMode.cs: -------------------------------------------------------------------------------- 1 | namespace Netch.Models.Modes.ProcessMode; 2 | 3 | public class Redirector : Mode 4 | { 5 | public override ModeType Type => ModeType.ProcessMode; 6 | 7 | #region Base 8 | 9 | public bool? FilterICMP { get; set; } 10 | 11 | public bool? FilterTCP { get; set; } 12 | 13 | public bool? FilterUDP { get; set; } 14 | 15 | public bool? FilterDNS { get; set; } 16 | 17 | public bool? FilterParent { get; set; } 18 | 19 | public int? ICMPDelay { get; set; } 20 | 21 | public bool? DNSProxy { get; set; } 22 | 23 | public bool? HandleOnlyDNS { get; set; } 24 | 25 | public string? DNSHost { get; set; } 26 | 27 | #endregion 28 | 29 | public bool FilterLoopback { get; set; } = false; 30 | 31 | public bool FilterIntranet { get; set; } = true; 32 | 33 | public List Bypass { get; set; } = new(); 34 | 35 | public List Handle { get; set; } = new(); 36 | } -------------------------------------------------------------------------------- /Netch/Models/Modes/ShareMode/ShareMode.cs: -------------------------------------------------------------------------------- 1 | namespace Netch.Models.Modes.ShareMode; 2 | 3 | public class ShareMode : Mode 4 | { 5 | public override ModeType Type => ModeType.ShareMode; 6 | 7 | public string Argument = "--preset uu"; 8 | } -------------------------------------------------------------------------------- /Netch/Models/Modes/TunMode/TunMode.cs: -------------------------------------------------------------------------------- 1 | namespace Netch.Models.Modes.TunMode; 2 | 3 | public class TunMode : Mode 4 | { 5 | public override ModeType Type => ModeType.TunMode; 6 | 7 | public List Bypass { get; set; } = new(); 8 | 9 | public List Handle { get; set; } = new(); 10 | } -------------------------------------------------------------------------------- /Netch/Models/NatTypeTestResult.cs: -------------------------------------------------------------------------------- 1 | namespace Netch.Models; 2 | 3 | public struct NatTypeTestResult 4 | { 5 | public string? Result; 6 | public string? LocalEnd; 7 | public string? PublicEnd; 8 | } -------------------------------------------------------------------------------- /Netch/Models/NetRoute.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using Windows.Win32; 3 | 4 | namespace Netch.Models; 5 | 6 | public struct NetRoute 7 | { 8 | public static NetRoute TemplateBuilder(string gateway, int interfaceIndex, int metric = 0) 9 | { 10 | return new() 11 | { 12 | Gateway = gateway, 13 | InterfaceIndex = interfaceIndex, 14 | Metric = metric 15 | }; 16 | } 17 | 18 | public static NetRoute GetBestRouteTemplate() 19 | { 20 | if (PInvoke.GetBestRoute(BitConverter.ToUInt32(IPAddress.Parse("114.114.114.114").GetAddressBytes(), 0), 0, out var route) != 0) 21 | throw new MessageException("GetBestRoute 搜索失败"); 22 | 23 | var gateway = new IPAddress(route.dwForwardNextHop); 24 | return TemplateBuilder(gateway.ToString(), (int)route.dwForwardIfIndex); 25 | } 26 | 27 | public int InterfaceIndex; 28 | 29 | public string Gateway; 30 | 31 | public string Network; 32 | 33 | public byte Cidr; 34 | 35 | public int Metric; 36 | 37 | public NetRoute FillTemplate(string network, byte cidr, int? metric = null) 38 | { 39 | var o = (NetRoute)MemberwiseClone(); 40 | o.Network = network; 41 | o.Cidr = cidr; 42 | //about why metric cannot be ZERO :) https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/route_ws2008 43 | o.Metric = (int)(metric == null ? 1 : metric); 44 | 45 | return o; 46 | } 47 | } -------------------------------------------------------------------------------- /Netch/Models/NumberRange.cs: -------------------------------------------------------------------------------- 1 | namespace Netch.Models; 2 | 3 | public readonly struct NumberRange 4 | { 5 | public int Start { get; } 6 | 7 | public int End { get; } 8 | 9 | public NumberRange(int start, int end) 10 | { 11 | Start = start; 12 | End = end; 13 | } 14 | 15 | public bool InRange(int num) 16 | { 17 | return Start <= num && num <= End; 18 | } 19 | } -------------------------------------------------------------------------------- /Netch/Models/Profile.cs: -------------------------------------------------------------------------------- 1 | using Netch.Models.Modes; 2 | 3 | namespace Netch.Models; 4 | 5 | public class Profile 6 | { 7 | public int Index { get; set; } 8 | 9 | public string ModeRemark { get; set; } 10 | 11 | public string ProfileName { get; set; } 12 | 13 | public string ServerRemark { get; set; } 14 | 15 | public Profile(Server server, Mode mode, string name, int index) 16 | { 17 | ServerRemark = server.Remark; 18 | ModeRemark = mode.i18NRemark; 19 | ProfileName = name; 20 | Index = index; 21 | } 22 | 23 | public Profile() 24 | { 25 | ServerRemark = string.Empty; 26 | ModeRemark = string.Empty; 27 | ProfileName = string.Empty; 28 | Index = 0; 29 | } 30 | } -------------------------------------------------------------------------------- /Netch/Models/Settings/AioDNSConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace Netch.Models; 4 | 5 | public class AioDNSConfig 6 | { 7 | public string ChinaDNS { get; set; } = $"tcp://{Constants.DefaultCNPrimaryDNS}:53"; 8 | 9 | public string OtherDNS { get; set; } = $"tcp://{Constants.DefaultPrimaryDNS}:53"; 10 | 11 | [JsonIgnore] 12 | public ushort ListenPort { get; set; } = 53; 13 | } -------------------------------------------------------------------------------- /Netch/Models/Settings/KcpConfig.cs: -------------------------------------------------------------------------------- 1 | namespace Netch.Models; 2 | 3 | public class KcpConfig 4 | { 5 | public bool congestion { get; set; } = false; 6 | 7 | public int downlinkCapacity { get; set; } = 100; 8 | 9 | public int mtu { get; set; } = 1350; 10 | 11 | public int readBufferSize { get; set; } = 2; 12 | 13 | public int tti { get; set; } = 50; 14 | 15 | public int uplinkCapacity { get; set; } = 12; 16 | 17 | public int writeBufferSize { get; set; } = 2; 18 | } -------------------------------------------------------------------------------- /Netch/Models/Settings/RedirectorConfig.cs: -------------------------------------------------------------------------------- 1 | namespace Netch.Models; 2 | 3 | public class RedirectorConfig 4 | { 5 | public bool FilterTCP { get; set; } = true; 6 | 7 | public bool FilterUDP { get; set; } = true; 8 | 9 | public bool FilterDNS { get; set; } = true; 10 | 11 | public bool FilterParent { get; set; } = false; 12 | 13 | public bool HandleOnlyDNS { get; set; } = true; 14 | 15 | public bool DNSProxy { get; set; } = true; 16 | 17 | public string DNSHost { get; set; } = $"{Constants.DefaultPrimaryDNS}:53"; 18 | 19 | public int ICMPDelay { get; set; } = 10; 20 | 21 | public bool FilterICMP { get; set; } = false; 22 | } -------------------------------------------------------------------------------- /Netch/Models/Settings/TUNConfig.cs: -------------------------------------------------------------------------------- 1 | namespace Netch.Models; 2 | 3 | /// 4 | /// TUN/TAP 适配器配置类 5 | /// 6 | public class TUNConfig 7 | { 8 | /// 9 | /// 地址 10 | /// 11 | public string Address { get; set; } = "10.0.236.10"; 12 | 13 | /// 14 | /// DNS 15 | /// 16 | public string DNS { get; set; } = Constants.DefaultPrimaryDNS; 17 | 18 | /// 19 | /// 网关 20 | /// 21 | public string Gateway { get; set; } = "10.0.236.1"; 22 | 23 | /// 24 | /// 掩码 25 | /// 26 | public string Netmask { get; set; } = "255.255.255.0"; 27 | 28 | /// 29 | /// 模式 2 下是否代理 DNS 30 | /// 31 | public bool ProxyDNS { get; set; } = false; 32 | 33 | /// 34 | /// 使用自定义 DNS 设置 35 | /// 36 | public bool UseCustomDNS { get; set; } = false; 37 | 38 | /// 39 | /// Global bypass IPs 40 | /// 41 | public List BypassIPs { get; set; } = new(); 42 | } -------------------------------------------------------------------------------- /Netch/Models/Settings/V2rayConfig.cs: -------------------------------------------------------------------------------- 1 | namespace Netch.Models; 2 | 3 | public class V2rayConfig 4 | { 5 | public bool UseMux { get; set; } = false; 6 | 7 | public bool Sniffing { get; set; } = false; 8 | 9 | public bool AllowHttp { get; set; } = false; 10 | 11 | public bool XrayFullCone { get; set; } = true; 12 | 13 | public bool TCPFastOpen { get; set; } = false; 14 | 15 | public bool AllowInsecure { get; set; } = false; 16 | 17 | public KcpConfig KcpConfig { get; set; } = new(); 18 | 19 | public bool V2rayNShareLink { get; set; } = true; 20 | 21 | public string Fingerprint { get; set; } = "chrome"; 22 | 23 | public string[] Alpn { get; set; } = { "h2", "http/1.1", "h2,http/1.1" }; 24 | } -------------------------------------------------------------------------------- /Netch/Models/StatusText.cs: -------------------------------------------------------------------------------- 1 | using Netch.Utils; 2 | 3 | namespace Netch.Models; 4 | 5 | public static class StatusPortInfoText 6 | { 7 | private static ushort? _socks5Port; 8 | private static ushort? _httpPort; 9 | private static bool _shareLan; 10 | 11 | public static ushort HttpPort 12 | { 13 | set => _httpPort = value; 14 | } 15 | 16 | public static ushort Socks5Port 17 | { 18 | set => _socks5Port = value; 19 | } 20 | 21 | public static string Value 22 | { 23 | get 24 | { 25 | var strings = new List(); 26 | 27 | if (_socks5Port != null) 28 | strings.Add($"Socks5 {i18N.Translate("Local Port", ": ")}{_socks5Port}"); 29 | 30 | if (_httpPort != null) 31 | strings.Add($"HTTP {i18N.Translate("Local Port", ": ")}{_httpPort}"); 32 | 33 | if (!strings.Any()) 34 | return string.Empty; 35 | 36 | return $" ({(_shareLan ? i18N.Translate("Allow other Devices to connect") + " " : "")}{string.Join(" | ", strings)})"; 37 | } 38 | } 39 | 40 | public static void UpdateShareLan() 41 | { 42 | _shareLan = Global.Settings.LocalAddress != "127.0.0.1"; 43 | } 44 | 45 | public static void Reset() 46 | { 47 | _httpPort = _socks5Port = null; 48 | } 49 | } -------------------------------------------------------------------------------- /Netch/Models/Subscription.cs: -------------------------------------------------------------------------------- 1 | namespace Netch.Models; 2 | 3 | public class Subscription 4 | { 5 | /// 6 | /// 启用状态 7 | /// 8 | public bool Enable { get; set; } = true; 9 | 10 | /// 11 | /// 链接 12 | /// 13 | public string Link { get; set; } = string.Empty; 14 | 15 | /// 16 | /// 备注 17 | /// 18 | public string Remark { get; set; } = string.Empty; 19 | 20 | /// 21 | /// User Agent 22 | /// 23 | public string UserAgent { get; set; } = string.Empty; 24 | } -------------------------------------------------------------------------------- /Netch/Models/TagItem.cs: -------------------------------------------------------------------------------- 1 | using Netch.Utils; 2 | 3 | namespace Netch.Models; 4 | 5 | internal class TagItem 6 | { 7 | private readonly string _text; 8 | 9 | public TagItem(T value, string text) 10 | { 11 | _text = text; 12 | Value = value; 13 | } 14 | 15 | public string Text => i18N.Translate(_text); 16 | 17 | public T Value { get; } 18 | } -------------------------------------------------------------------------------- /Netch/NOTICE.txt: -------------------------------------------------------------------------------- 1 | This program comes with ABSOLUTELY NO WARRANTY. 2 | This is free software, and you are welcome to redistribute it under certain conditions. 3 | Copyright (c) 2019 AmazingDM and Contributors 4 | 5 | Libraries that have been used in Netch are listed below (Not in order): 6 | Copyright (c) .NET Foundation and Contributors(@dotnet): .NET (MIT) 7 | Copyright (c) Microsoft Corporation(@microsoft): CsWin32 (MIT) 8 | Copyright (c) Microsoft Corporation(@microsoft): Microsoft.VisualStudio.Threading (MIT) 9 | Copyright (c) .NET Foundation and Contributors(@microsoft): Microsoft.Diagnostics.Tracing.TraceEvent (MIT) 10 | Copyright (c) 2013 Serilog Contributors(@serilog): Serilog (Apache-2.0) 11 | Copyright (c) 2020 Bruce Wayne(@HMBSbige): WindowsJobAPI (MIT) 12 | Copyright (c) 2018 Bruce Wayne(@HMBSbige): Stun.Net (MIT) 13 | Copyright (c) 2020 Bruce Wayne(@HMBSbige): HMBSbige.SingleInstance (MIT) 14 | Copyright (c) 2013 MaxMind, Inc.(@maxmind): MaxMind.GeoIP2 (Apache-2.0) 15 | Copyright (c) 1999 Igor Pavlov: 7-Zip (LGPL-2.1-or-later with unRAR restriction) 16 | Copyright (c) 2016 Soroush(@falahati): WindowsFirewallHelper (MIT) 17 | Copyright (c) 2003 David Hall(@dahall): TaskScheduler (MIT) 18 | Copyright (c) 2021 tom-englert.de(@tom-englert): Nullable.Extended.Analyzer (MIT) 19 | 20 | Copyright (c) 2009 The Go Authors(@golang): Go (BSD) 21 | Copyright (c) Vitaly Sidorov: NetFilterSDK 22 | Copyright (c) 2018 WireGuard LLC.(@WireGuard): Wintun Network Adapter (GPL-3.0) 23 | Copyright (c) 2019 xᴊᴀsᴏɴʟʏᴜ(@xjasonlyu): tun2socks (GPL-3.0) 24 | Copyright (c) 2010 Miek Gieben(@miekg): dns (BSD) 25 | Copyright (c) 2020 Xie Zhihao(@zhxie): pcap2socks (MIT) 26 | Copyright (c) MaxMind, Inc.: GeoLite2 Database (GeoLite2 EULA, CC BY-SA 4.0) 27 | Copyright (c) 2020 Project X Community(@XTLS): Xray-core (MPL-2.0) 28 | Copyright (c) 2020 Teddysun(@teddysun): v2ray-plugin (MIT) 29 | Copyright (c) 2021 Teddysun(@teddysun): xray-plugin (MIT) 30 | Copyright (c) 2017 Y. T. CHUNG(@shadowsocks): shadowsocks-rust (MIT) 31 | Copyright (c) 2016 Max Lv(@shadowsocks): simple-obfs (GPL-3.0) 32 | Copyright (c) ???(@shadowsocksrr): shadowscoksr-libev (???) 33 | Copyright (c) 2018 Andy Wang(@cbeuw): Cloak (GPL-3.0) 34 | Copyright (c) 2017 The Trojan Authors(@trojan-gfw): trojan (GPL-3.0) 35 | Copyright (c) 2013 Felix Yan(@felixonmars): dnsmasq-china-list (WTFPL) 36 | Copyright (c) IPIP.NET(@17mon): china_ip_list (CC-BY-NC-SA 4.0) 37 | 38 | Special thanks to: 39 | GitHub for project hosting and delivery releases 40 | JetBrains for the Licenses for Open Source Development to access all JetBrains tools 41 | Fody for weaving .net assemblies save us a lot of time 42 | -------------------------------------------------------------------------------- /Netch/NativeMethods.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace Netch; 4 | 5 | public static class NativeMethods 6 | { 7 | [DllImport("dnsapi", EntryPoint = "DnsFlushResolverCache")] 8 | internal static extern uint RefreshDNSCache(); 9 | } -------------------------------------------------------------------------------- /Netch/NativeMethods.txt: -------------------------------------------------------------------------------- 1 | // IpHlpApi.dll 2 | GetBestRoute 3 | GetExtendedTcpTable 4 | MIB_TCPTABLE_OWNER_PID 5 | ADDRESS_FAMILY 6 | MIB_UNICASTIPADDRESS_ROW 7 | InitializeUnicastIpAddressEntry 8 | CreateUnicastIpAddressEntry 9 | GetUnicastIpAddressEntry 10 | NotifyUnicastIpAddressChange 11 | CancelMibChangeNotify2 12 | 13 | // User32.dll 14 | SetWindowPos 15 | GetWindowLong 16 | ShowWindow 17 | WINDOW_STYLE 18 | 19 | // Kernel32.dll 20 | AllocConsole 21 | GetConsoleWindow 22 | 23 | // Ws2_32.dll 24 | ntohs 25 | inet_pton 26 | 27 | // Windows.h 28 | // WIN32_ERROR -------------------------------------------------------------------------------- /Netch/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | using Netch.Controllers; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle(UpdateChecker.Name)] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct(UpdateChecker.Name)] 13 | [assembly: AssemblyCopyright(UpdateChecker.Copyright)] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | [assembly: System.Runtime.Versioning.SupportedOSPlatformAttribute("Windows7.0")] 17 | [assembly: Fody.ConfigureAwait(false)] 18 | 19 | // 将 ComVisible 设置为 false 会使此程序集中的类型 20 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 21 | //请将此类型的 ComVisible 特性设置为 true。 22 | [assembly: ComVisible(false)] 23 | 24 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 25 | [assembly: Guid("4b041b91-5790-4571-8c58-c63ffe4bc9f8")] 26 | 27 | // 程序集的版本信息由下列四个值组成: 28 | // 29 | // 主版本 30 | // 次版本 31 | // 生成号 32 | // 修订号 33 | // 34 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 35 | //通过使用 "*",如下所示: 36 | // [assembly: AssemblyVersion("1.0.*")] 37 | [assembly: AssemblyVersion(UpdateChecker.AssemblyVersion)] 38 | // [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /Netch/Properties/PublishProfiles/FolderProfile.pubxml: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | Release 8 | x64 9 | bin\x64\publish\ 10 | FileSystem 11 | net6.0-windows 12 | win-x64 13 | false 14 | true 15 | false 16 | 17 | -------------------------------------------------------------------------------- /Netch/Properties/PublishProfiles/FolderProfile.pubxml.user: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | True|2023-11-15T09:43:09.9961522Z;True|2023-11-15T17:19:01.8838624+08:00;True|2023-11-15T16:21:09.2044696+08:00;True|2023-11-15T16:10:07.6586486+08:00;True|2023-11-15T16:04:12.2259902+08:00;True|2023-11-14T18:01:19.1169680+08:00;True|2023-11-14T17:07:38.4780258+08:00;True|2023-11-10T16:49:11.0977855+08:00;True|2023-11-10T16:19:11.7332870+08:00;False|2023-11-10T16:18:19.7157663+08:00;False|2023-11-10T16:17:59.8327716+08:00;True|2023-11-10T15:25:24.6514851+08:00; 8 | 9 | -------------------------------------------------------------------------------- /Netch/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本:4.0.30319.42000 5 | // 6 | // 对此文件的更改可能会导致不正确的行为,并且如果 7 | // 重新生成代码,这些更改将会丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Netch.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.2.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Netch/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Netch/Resources/7za.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarflows/netch/1b3559051c420173be3d23ad5540685f91f00be8/Netch/Resources/7za.exe -------------------------------------------------------------------------------- /Netch/Resources/CopyLink.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarflows/netch/1b3559051c420173be3d23ad5540685f91f00be8/Netch/Resources/CopyLink.png -------------------------------------------------------------------------------- /Netch/Resources/Netch.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarflows/netch/1b3559051c420173be3d23ad5540685f91f00be8/Netch/Resources/Netch.ico -------------------------------------------------------------------------------- /Netch/Resources/Netch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarflows/netch/1b3559051c420173be3d23ad5540685f91f00be8/Netch/Resources/Netch.png -------------------------------------------------------------------------------- /Netch/Resources/NetchTrayIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarflows/netch/1b3559051c420173be3d23ad5540685f91f00be8/Netch/Resources/NetchTrayIcon.png -------------------------------------------------------------------------------- /Netch/Resources/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarflows/netch/1b3559051c420173be3d23ad5540685f91f00be8/Netch/Resources/delete.png -------------------------------------------------------------------------------- /Netch/Resources/edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarflows/netch/1b3559051c420173be3d23ad5540685f91f00be8/Netch/Resources/edit.png -------------------------------------------------------------------------------- /Netch/Resources/speed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarflows/netch/1b3559051c420173be3d23ad5540685f91f00be8/Netch/Resources/speed.png -------------------------------------------------------------------------------- /Netch/Servers/SSH/SSHForm.cs: -------------------------------------------------------------------------------- 1 | using Netch.Forms; 2 | 3 | namespace Netch.Servers; 4 | 5 | [Fody.ConfigureAwait(true)] 6 | public class SSHForm : ServerForm 7 | { 8 | public SSHForm(SSHServer? server = default) 9 | { 10 | server ??= new SSHServer(); 11 | Server = server; 12 | CreateTextBox("User", "User", s => true, s => server.User = s, server.User); 13 | CreateTextBox("Password", "Password", s => true, s => server.Password = s, server.Password); 14 | CreateTextBox("PrivateKey", "Private Key", s => true, s => server.PrivateKey = s, server.PrivateKey); 15 | CreateTextBox("PublicKey", "Public Key", s => true, s => server.PublicKey = s, server.PublicKey); 16 | } 17 | 18 | protected override string TypeName { get; } = "SSH"; 19 | } -------------------------------------------------------------------------------- /Netch/Servers/SSH/SSHServer.cs: -------------------------------------------------------------------------------- 1 | using Netch.Models; 2 | 3 | namespace Netch.Servers; 4 | 5 | public class SSHServer : Server 6 | { 7 | public override string Type { get; } = "SSH"; 8 | 9 | public override string MaskedData() 10 | { 11 | return $"{User}"; 12 | } 13 | 14 | /// 15 | /// 用户 16 | /// 17 | public string User { get; set; } = "root"; 18 | 19 | /// 20 | /// 密码 21 | /// 22 | public string Password { get; set; } = string.Empty; 23 | 24 | /// 25 | /// 私钥 26 | /// 27 | public string? PrivateKey { get; set; } 28 | 29 | /// 30 | /// 主机公钥 31 | /// 32 | public string? PublicKey { get; set; } 33 | } 34 | -------------------------------------------------------------------------------- /Netch/Servers/SSH/SSHUtil.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Encodings.Web; 2 | using System.Text.Json; 3 | using System.Text.Json.Serialization; 4 | using Netch.Interfaces; 5 | using Netch.Models; 6 | using Netch.Utils; 7 | 8 | namespace Netch.Servers; 9 | 10 | public class SSHUtil : IServerUtil 11 | { 12 | public ushort Priority { get; } = 4; 13 | 14 | public string TypeName { get; } = "SSH"; 15 | 16 | public string FullName { get; } = "SSH"; 17 | 18 | public string ShortName { get; } = "SSH"; 19 | 20 | public string[] UriScheme { get; } = { "ssh" }; 21 | 22 | public Type ServerType { get; } = typeof(SSHServer); 23 | 24 | public void Edit(Server s) 25 | { 26 | new SSHForm((SSHServer)s).ShowDialog(); 27 | } 28 | 29 | public void Create() 30 | { 31 | new SSHForm().ShowDialog(); 32 | } 33 | 34 | public string GetShareLink(Server s) 35 | { 36 | return V2rayUtils.GetVShareLink(s, "ssh"); 37 | } 38 | 39 | public IServerController GetController() 40 | { 41 | return new V2rayController(); 42 | } 43 | 44 | public IEnumerable ParseUri(string text) 45 | { 46 | return V2rayUtils.ParseVUri(text); 47 | } 48 | 49 | public bool CheckServer(Server s) 50 | { 51 | return true; 52 | } 53 | } -------------------------------------------------------------------------------- /Netch/Servers/Shadowsocks/ShadowsocksController.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using System.Text; 3 | using Netch.Controllers; 4 | using Netch.Interfaces; 5 | using Netch.Models; 6 | 7 | namespace Netch.Servers; 8 | 9 | public class ShadowsocksController : Guard, IServerController 10 | { 11 | public ShadowsocksController() : base("Shadowsocks.exe", encoding: Encoding.UTF8) 12 | { 13 | } 14 | 15 | protected override IEnumerable StartedKeywords => new[] { "listening on" }; 16 | 17 | protected override IEnumerable FailedKeywords => new[] { "error", "failed to start plguin" }; 18 | 19 | public override string Name => "Shadowsocks"; 20 | 21 | public ushort? Socks5LocalPort { get; set; } 22 | 23 | public string? LocalAddress { get; set; } 24 | 25 | public async Task StartAsync(Server s) 26 | { 27 | var server = (ShadowsocksServer)s; 28 | 29 | var arguments = new object?[] 30 | { 31 | "-s", $"{await server.AutoResolveHostnameAsync()}:{server.Port}", 32 | "-b", $"{this.LocalAddress()}:{this.Socks5LocalPort()}", 33 | "-m", server.EncryptMethod, 34 | "-k", server.Password, 35 | "--plugin", server.Plugin, 36 | "--plugin-opts", server.PluginOption, 37 | "-U", SpecialArgument.Flag 38 | }; 39 | 40 | await StartGuardAsync(Arguments.Format(arguments)); 41 | return new Socks5Server(IPAddress.Loopback.ToString(), this.Socks5LocalPort(), server.Hostname); 42 | } 43 | } -------------------------------------------------------------------------------- /Netch/Servers/Shadowsocks/ShadowsocksForm.cs: -------------------------------------------------------------------------------- 1 | using Netch.Forms; 2 | using Netch.Utils; 3 | 4 | namespace Netch.Servers; 5 | 6 | [Fody.ConfigureAwait(true)] 7 | public class ShadowsocksForm : ServerForm 8 | { 9 | public ShadowsocksForm(ShadowsocksServer? server = default) 10 | { 11 | server ??= new ShadowsocksServer(); 12 | Server = server; 13 | CreateTextBox("Password", "Password", s => !s.IsNullOrWhiteSpace(), s => server.Password = s, server.Password); 14 | CreateComboBox("EncryptMethod", "Encrypt Method", SSGlobal.EncryptMethods, s => server.EncryptMethod = s, server.EncryptMethod); 15 | CreateTextBox("Plugin", "Plugin", s => true, s => server.Plugin = s, server.Plugin); 16 | CreateTextBox("PluginsOption", "Plugin Options", s => true, s => server.PluginOption = s, server.PluginOption); 17 | } 18 | 19 | protected override string TypeName { get; } = "Shadowsocks"; 20 | } -------------------------------------------------------------------------------- /Netch/Servers/Shadowsocks/ShadowsocksServer.cs: -------------------------------------------------------------------------------- 1 | using Netch.Models; 2 | 3 | namespace Netch.Servers; 4 | 5 | public class ShadowsocksServer : Server 6 | { 7 | public override string Type { get; } = "SS"; 8 | public override string MaskedData() 9 | { 10 | return $"{EncryptMethod} + {Plugin}"; 11 | } 12 | 13 | /// 14 | /// 加密方式 15 | /// 16 | public string EncryptMethod { get; set; } = SSGlobal.EncryptMethods[4]; 17 | 18 | /// 19 | /// 密码 20 | /// 21 | public string Password { get; set; } = string.Empty; 22 | 23 | /// 24 | /// 插件 25 | /// 26 | public string? Plugin { get; set; } 27 | 28 | /// 29 | /// 插件参数 30 | /// 31 | public string? PluginOption { get; set; } 32 | 33 | public bool HasPlugin() 34 | { 35 | return !string.IsNullOrWhiteSpace(Plugin) && !string.IsNullOrWhiteSpace(PluginOption); 36 | } 37 | } 38 | 39 | public static class SSGlobal 40 | { 41 | /// 42 | /// SS 加密列表 43 | /// 44 | public static readonly List EncryptMethods = new() 45 | { 46 | "none", 47 | 48 | // 2022 edition cipher 49 | "2022-blake3-aes-128-gcm", 50 | "2022-blake3-aes-256-gcm", 51 | "2022-blake3-chacha20-poly1305", 52 | 53 | // AEAD cipher 54 | "aes-128-gcm", 55 | "aes-192-gcm", 56 | "aes-256-gcm", 57 | "chacha20-ietf-poly1305", 58 | "xchacha20-ietf-poly1305", 59 | 60 | // stream cipher 61 | "rc4", 62 | "rc4-md5", 63 | "aes-128-ctr", 64 | "aes-192-ctr", 65 | "aes-256-ctr", 66 | "aes-128-cfb", 67 | "aes-192-cfb", 68 | "aes-256-cfb", 69 | "aes-128-cfb8", 70 | "aes-192-cfb8", 71 | "aes-256-cfb8", 72 | "aes-128-ofb", 73 | "aes-192-ofb", 74 | "aes-256-ofb", 75 | "bf-cfb", 76 | "cast5-cfb", 77 | "des-cfb", 78 | "idea-cfb", 79 | "rc2-cfb", 80 | "seed-cfb", 81 | "camellia-128-cfb", 82 | "camellia-192-cfb", 83 | "camellia-256-cfb", 84 | "camellia-128-cfb8", 85 | "camellia-192-cfb8", 86 | "camellia-256-cfb8", 87 | "salsa20", 88 | "chacha20", 89 | "chacha20-ietf", 90 | "xchacha20" 91 | }; 92 | } -------------------------------------------------------------------------------- /Netch/Servers/Shadowsocks/ShareModels/SSDJObject.cs: -------------------------------------------------------------------------------- 1 | #nullable disable 2 | namespace Netch.Servers; 3 | 4 | public class SSDJObject 5 | { 6 | /// 7 | /// 机场名 8 | /// 9 | public string airport; 10 | 11 | /// 12 | /// 加密方式 13 | /// 14 | public string encryption; 15 | 16 | /// 17 | /// 密码 18 | /// 19 | public string password; 20 | 21 | /// 22 | /// 插件 23 | /// 24 | public string plugin; 25 | 26 | /// 27 | /// 插件参数 28 | /// 29 | public string plugin_options; 30 | 31 | /// 32 | /// 端口 33 | /// 34 | public ushort port; 35 | 36 | /// 37 | /// 服务器数组 38 | /// 39 | public List servers; 40 | } -------------------------------------------------------------------------------- /Netch/Servers/Shadowsocks/ShareModels/SSDServerJObject.cs: -------------------------------------------------------------------------------- 1 | #nullable disable 2 | namespace Netch.Servers; 3 | 4 | public class SSDServerJObject 5 | { 6 | /// 7 | /// 加密方式 8 | /// 9 | public string encryption; 10 | 11 | /// 12 | /// 密码 13 | /// 14 | public string password; 15 | 16 | /// 17 | /// 插件 18 | /// 19 | public string plugin; 20 | 21 | /// 22 | /// 插件参数 23 | /// 24 | public string plugin_options; 25 | 26 | /// 27 | /// 端口 28 | /// 29 | public ushort port; 30 | 31 | /// 32 | /// 备注 33 | /// 34 | public string remarks; 35 | /// 36 | /// 服务器地址 37 | /// 38 | public string server; 39 | } -------------------------------------------------------------------------------- /Netch/Servers/Shadowsocks/ShareModels/ShadowsocksConfig.cs: -------------------------------------------------------------------------------- 1 | #nullable disable 2 | namespace Netch.Servers; 3 | 4 | /// 5 | /// Import Shadowsocks Server from Json Configuration 6 | /// 7 | /// 8 | public class ShadowsocksConfig 9 | { 10 | public string server { get; set; } 11 | 12 | public ushort server_port { get; set; } 13 | 14 | public string password { get; set; } 15 | 16 | public string method { get; set; } 17 | 18 | public string remarks { get; set; } 19 | 20 | public string plugin { get; set; } 21 | 22 | public string plugin_opts { get; set; } 23 | } -------------------------------------------------------------------------------- /Netch/Servers/ShadowsocksR/ShadowsocksRController.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using Netch.Controllers; 3 | using Netch.Interfaces; 4 | using Netch.Models; 5 | 6 | namespace Netch.Servers; 7 | 8 | public class ShadowsocksRController : Guard, IServerController 9 | { 10 | public ShadowsocksRController() : base("ShadowsocksR.exe") 11 | { 12 | } 13 | 14 | protected override IEnumerable StartedKeywords => new[] { "listening at" }; 15 | 16 | protected override IEnumerable FailedKeywords => new[] { "Invalid config path", "usage" }; 17 | 18 | public override string Name => "ShadowsocksR"; 19 | 20 | public ushort? Socks5LocalPort { get; set; } 21 | 22 | public string? LocalAddress { get; set; } 23 | 24 | public async Task StartAsync(Server s) 25 | { 26 | var server = (ShadowsocksRServer)s; 27 | 28 | var arguments = new object?[] 29 | { 30 | "-s", await server.AutoResolveHostnameAsync(), 31 | "-p", server.Port, 32 | "-k", server.Password, 33 | "-m", server.EncryptMethod, 34 | "-t", 120, 35 | "-O", server.Protocol, 36 | "-G", server.ProtocolParam, 37 | "-o", server.OBFS, 38 | "-g", server.OBFSParam, 39 | "-b", this.LocalAddress(), 40 | "-l", this.Socks5LocalPort(), 41 | "-u", SpecialArgument.Flag 42 | }; 43 | 44 | await StartGuardAsync(Arguments.Format(arguments)); 45 | return new Socks5Server(IPAddress.Loopback.ToString(), this.Socks5LocalPort(), server.Hostname); 46 | } 47 | } -------------------------------------------------------------------------------- /Netch/Servers/ShadowsocksR/ShadowsocksRForm.cs: -------------------------------------------------------------------------------- 1 | using Netch.Forms; 2 | using Netch.Utils; 3 | 4 | namespace Netch.Servers; 5 | 6 | [Fody.ConfigureAwait(true)] 7 | public class ShadowsocksRForm : ServerForm 8 | { 9 | public ShadowsocksRForm(ShadowsocksRServer? server = default) 10 | { 11 | server ??= new ShadowsocksRServer(); 12 | Server = server; 13 | CreateTextBox("Password", "Password", s => !s.IsNullOrWhiteSpace(), s => server.Password = s, server.Password); 14 | CreateComboBox("EncryptMethod", "Encrypt Method", SSRGlobal.EncryptMethods, s => server.EncryptMethod = s, server.EncryptMethod); 15 | CreateComboBox("Protocol", "Protocol", SSRGlobal.Protocols, s => server.Protocol = s, server.Protocol); 16 | CreateTextBox("ProtocolParam", "Protocol Param", s => true, s => server.ProtocolParam = s, server.ProtocolParam); 17 | CreateComboBox("OBFS", "OBFS", SSRGlobal.OBFSs, s => server.OBFS = s, server.OBFS); 18 | CreateTextBox("OBFSParam", "OBFS Param", s => true, s => server.OBFSParam = s, server.OBFSParam); 19 | } 20 | 21 | protected override string TypeName { get; } = "ShadowsocksR"; 22 | } -------------------------------------------------------------------------------- /Netch/Servers/ShadowsocksR/ShadowsocksRServer.cs: -------------------------------------------------------------------------------- 1 | using Netch.Models; 2 | 3 | namespace Netch.Servers; 4 | 5 | public class ShadowsocksRServer : Server 6 | { 7 | public override string Type { get; } = "SSR"; 8 | public override string MaskedData() 9 | { 10 | return $"{EncryptMethod} + {Protocol} + {OBFS}"; 11 | } 12 | 13 | /// 14 | /// 密码 15 | /// 16 | public string Password { get; set; } = string.Empty; 17 | 18 | /// 19 | /// 加密方式 20 | /// 21 | public string EncryptMethod { get; set; } = SSRGlobal.EncryptMethods[4]; 22 | 23 | /// 24 | /// 协议 25 | /// 26 | public string Protocol { get; set; } = SSRGlobal.Protocols[0]; 27 | 28 | /// 29 | /// 协议参数 30 | /// 31 | public string? ProtocolParam { get; set; } 32 | 33 | /// 34 | /// 混淆 35 | /// 36 | public string OBFS { get; set; } = SSRGlobal.OBFSs[0]; 37 | 38 | /// 39 | /// 混淆参数 40 | /// 41 | public string? OBFSParam { get; set; } 42 | } 43 | 44 | public class SSRGlobal 45 | { 46 | /// 47 | /// SSR 协议列表 48 | /// 49 | public static readonly List Protocols = new() 50 | { 51 | "origin", 52 | "auth_sha1_v4", 53 | "auth_aes128_md5", 54 | "auth_aes128_sha1", 55 | "auth_chain_a", 56 | "auth_chain_b" 57 | }; 58 | 59 | /// 60 | /// SSR 混淆列表 61 | /// 62 | public static readonly List OBFSs = new() 63 | { 64 | "plain", 65 | "http_simple", 66 | "http_post", 67 | "tls_simple", 68 | "tls1.2_ticket_auth", 69 | "tls1.2_ticket_fastauth", 70 | "random_head" 71 | }; 72 | 73 | /// 74 | /// SS/SSR 加密方式 75 | /// 76 | public static readonly List EncryptMethods = SSGlobal.EncryptMethods; 77 | } -------------------------------------------------------------------------------- /Netch/Servers/Socks5/Socks5Controller.cs: -------------------------------------------------------------------------------- 1 | using Netch.Models; 2 | 3 | namespace Netch.Servers; 4 | 5 | public class Socks5Controller : V2rayController 6 | { 7 | public override string Name { get; } = "Socks5"; 8 | 9 | public override Task StartAsync(Server s) 10 | { 11 | var server = (Socks5Server)s; 12 | if (!server.Auth()) 13 | throw new ArgumentException("Authentication failed. Provide a valid username and password."); 14 | 15 | return base.StartAsync(s); 16 | } 17 | } -------------------------------------------------------------------------------- /Netch/Servers/Socks5/Socks5Form.cs: -------------------------------------------------------------------------------- 1 | using Netch.Forms; 2 | using Netch.Utils; 3 | 4 | namespace Netch.Servers; 5 | 6 | [Fody.ConfigureAwait(true)] 7 | public class Socks5Form : ServerForm 8 | { 9 | public Socks5Form(Socks5Server? server = default) 10 | { 11 | server ??= new Socks5Server(); 12 | Server = server; 13 | CreateTextBox("Username", "Username", s => true, s => server.Username = s, server.Username.ValueOrDefault()); 14 | CreateTextBox("Password", "Password", s => true, s => server.Password = s, server.Password.ValueOrDefault()); 15 | CreateComboBox("Version", 16 | "Version", 17 | SOCKSGlobal.Versions, 18 | s => server.Version = s, 19 | server.Version); 20 | (_remoteHostnameLabel, _remoteHostnameTextBox) = CreateTextBox("RemoteHostname", 21 | "Remote Address", 22 | s => true, 23 | s => server.RemoteHostname = s, 24 | server.RemoteHostname.ValueOrDefault()); 25 | 26 | AddressTextBox.TextChanged += AddressTextBoxOnTextChanged; 27 | AddressTextBoxOnTextChanged(null!, null!); 28 | } 29 | 30 | private readonly Label _remoteHostnameLabel; 31 | private readonly TextBox _remoteHostnameTextBox; 32 | 33 | private void AddressTextBoxOnTextChanged(object? sender, EventArgs e) 34 | { 35 | _remoteHostnameLabel.Visible = _remoteHostnameTextBox.Visible = IsPrivateAddress(AddressTextBox.Text); 36 | } 37 | 38 | private static bool IsPrivateAddress(string address) 39 | { 40 | // https://en.wikipedia.org/wiki/Private_network#Private_IPv4_addresses 41 | return address.StartsWith("10.") || address.StartsWith("192.168.") || address.StartsWith("172.") || address.StartsWith("127."); 42 | } 43 | 44 | protected override string TypeName { get; } = "Socks5"; 45 | } -------------------------------------------------------------------------------- /Netch/Servers/Socks5/Socks5Server.cs: -------------------------------------------------------------------------------- 1 | using Netch.Models; 2 | 3 | namespace Netch.Servers; 4 | 5 | public class Socks5Server : Server 6 | { 7 | public override string Type { get; } = "SOCKS"; 8 | 9 | /// 10 | /// 密码 11 | /// 12 | public string? Password { get; set; } 13 | 14 | /// 15 | /// 账号 16 | /// 17 | public string? Username { get; set; } 18 | 19 | public string? RemoteHostname { get; set; } 20 | 21 | /// 22 | /// 版本 23 | /// 24 | public string Version { get; set; } = SOCKSGlobal.Versions[0]; 25 | 26 | public override string MaskedData() 27 | { 28 | return $"Auth: {Auth()}"; 29 | } 30 | 31 | public Socks5Server() 32 | { 33 | } 34 | 35 | public Socks5Server(string hostname, ushort port) 36 | { 37 | Hostname = hostname; 38 | Port = port; 39 | } 40 | 41 | public Socks5Server(string hostname, ushort port, string username, string password) : this(hostname, port) 42 | { 43 | Username = username; 44 | Password = password; 45 | } 46 | 47 | public Socks5Server(string hostname, ushort port, string remoteHostname) : this(hostname, port) 48 | { 49 | RemoteHostname = remoteHostname; 50 | } 51 | 52 | public bool Auth() 53 | { 54 | return !string.IsNullOrWhiteSpace(Username) && !string.IsNullOrWhiteSpace(Password); 55 | } 56 | } 57 | 58 | public class SOCKSGlobal 59 | { 60 | public static readonly List Versions = new() 61 | { 62 | "5", 63 | "4a", 64 | "4" 65 | }; 66 | } -------------------------------------------------------------------------------- /Netch/Servers/Socks5/Socks5Util.cs: -------------------------------------------------------------------------------- 1 | using Netch.Interfaces; 2 | using Netch.Models; 3 | 4 | namespace Netch.Servers; 5 | 6 | public class Socks5Util : IServerUtil 7 | { 8 | public ushort Priority { get; } = 0; 9 | 10 | public string TypeName { get; } = "SOCKS"; 11 | 12 | public string FullName { get; } = "SOCKS"; 13 | 14 | public string ShortName { get; } = "SOCKS"; 15 | 16 | public string[] UriScheme { get; } = Array.Empty(); 17 | 18 | public Type ServerType { get; } = typeof(Socks5Server); 19 | 20 | public void Edit(Server s) 21 | { 22 | new Socks5Form((Socks5Server)s).ShowDialog(); 23 | } 24 | 25 | public void Create() 26 | { 27 | new Socks5Form().ShowDialog(); 28 | } 29 | 30 | public string GetShareLink(Server s) 31 | { 32 | var server = (Socks5Server)s; 33 | // https://t.me/socks?server=1.1.1.1&port=443 34 | return $"https://t.me/socks?server={server.Hostname}&port={server.Port}" + 35 | $"{(!string.IsNullOrWhiteSpace(server.Username) ? $"&user={server.Username}" : "")}" + 36 | $"{(server.Auth() ? $"&user={server.Password}" : "")}"; 37 | } 38 | 39 | public IServerController GetController() 40 | { 41 | return new Socks5Controller(); 42 | } 43 | 44 | public IEnumerable ParseUri(string text) 45 | { 46 | var dict = text.Replace("tg://socks?", "") 47 | .Replace("https://t.me/socks?", "") 48 | .Split('&') 49 | .Select(str => str.Split('=')) 50 | .ToDictionary(splited => splited[0], splited => splited[1]); 51 | 52 | if (!dict.ContainsKey("server") || !dict.ContainsKey("port")) 53 | throw new FormatException(); 54 | 55 | var data = new Socks5Server 56 | { 57 | Hostname = dict["server"], 58 | Port = ushort.Parse(dict["port"]) 59 | }; 60 | 61 | if (dict.ContainsKey("user") && !string.IsNullOrWhiteSpace(dict["user"])) 62 | data.Username = dict["user"]; 63 | 64 | if (dict.ContainsKey("pass") && !string.IsNullOrWhiteSpace(dict["pass"])) 65 | data.Password = dict["pass"]; 66 | 67 | return new[] { data }; 68 | } 69 | 70 | public bool CheckServer(Server s) 71 | { 72 | return true; 73 | } 74 | } -------------------------------------------------------------------------------- /Netch/Servers/Trojan/TrojanConfig.cs: -------------------------------------------------------------------------------- 1 | namespace Netch.Servers; 2 | 3 | public class TrojanConfig 4 | { 5 | /// 6 | /// 监听地址 7 | /// 8 | public string local_addr { get; set; } = "127.0.0.1"; 9 | 10 | /// 11 | /// 监听端口 12 | /// 13 | public int local_port { get; set; } = 2801; 14 | 15 | /// 16 | /// 日志级别 17 | /// 18 | public int log_level { get; set; } = 1; 19 | 20 | /// 21 | /// 密码 22 | /// 23 | public List password { get; set; } = new List(); 24 | 25 | /// 26 | /// 远端地址 27 | /// 28 | public string remote_addr { get; set; } = string.Empty; 29 | 30 | /// 31 | /// 远端端口 32 | /// 33 | public int remote_port { get; set; } 34 | 35 | /// 36 | /// 启动类型 37 | /// 38 | public string run_type { get; set; } = "client"; 39 | 40 | public TrojanSSL ssl { get; set; } = new(); 41 | 42 | public TrojanTCP tcp { get; set; } = new(); 43 | } 44 | 45 | public class TrojanSSL 46 | { 47 | public List alpn { get; set; } = new() 48 | { 49 | "h2", 50 | "http/1.1", 51 | "h2,http/1.1" 52 | }; 53 | 54 | public string cert { get; set; } = string.Empty; 55 | 56 | public string cipher { get; set; } = 57 | "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA"; 58 | 59 | public string cipher_tls13 { get; set; } = "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384"; 60 | 61 | public string curves { get; set; } = string.Empty; 62 | 63 | public bool reuse_session { get; set; } = true; 64 | 65 | public bool session_ticket { get; set; } = true; 66 | 67 | public string sni { get; set; } = string.Empty; 68 | 69 | public bool verify { get; set; } = false; 70 | 71 | public bool verify_hostname { get; set; } = false; 72 | } 73 | 74 | public class TrojanTCP 75 | { 76 | public bool fast_open { get; set; } = true; 77 | 78 | public int fast_open_qlen { get; set; } = 20; 79 | 80 | public bool keep_alive { get; set; } = true; 81 | 82 | public bool no_delay { get; set; } = false; 83 | 84 | public bool reuse_port { get; set; } = false; 85 | } -------------------------------------------------------------------------------- /Netch/Servers/Trojan/TrojanController.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using System.Text.Json; 3 | using Netch.Controllers; 4 | using Netch.Interfaces; 5 | using Netch.Models; 6 | using Netch.Utils; 7 | 8 | namespace Netch.Servers; 9 | 10 | public class TrojanController : Guard, IServerController 11 | { 12 | public TrojanController() : base("Trojan.exe") 13 | { 14 | } 15 | 16 | protected override IEnumerable StartedKeywords => new[] { "listening" }; 17 | 18 | protected override IEnumerable FailedKeywords => new[] { "exiting" }; 19 | 20 | public override string Name => "Trojan"; 21 | 22 | public ushort? Socks5LocalPort { get; set; } 23 | 24 | public string? LocalAddress { get; set; } 25 | 26 | public async Task StartAsync(Server s) 27 | { 28 | var server = (TrojanServer)s; 29 | var trojanConfig = new TrojanConfig 30 | { 31 | local_addr = this.LocalAddress(), 32 | local_port = this.Socks5LocalPort(), 33 | remote_addr = await server.AutoResolveHostnameAsync(), 34 | remote_port = server.Port, 35 | password = new List 36 | { 37 | server.Password 38 | }, 39 | ssl = new TrojanSSL 40 | { 41 | sni = server.Host.ValueOrDefault() ?? server.Hostname 42 | } 43 | }; 44 | 45 | await using (var fileStream = new FileStream(Constants.TempConfig, FileMode.Create, FileAccess.Write, FileShare.Read)) 46 | { 47 | await JsonSerializer.SerializeAsync(fileStream, trojanConfig, Global.NewCustomJsonSerializerOptions()); 48 | } 49 | 50 | await StartGuardAsync("-config ..\\data\\last.json"); 51 | return new Socks5Server(IPAddress.Loopback.ToString(), this.Socks5LocalPort(), server.Hostname); 52 | } 53 | } -------------------------------------------------------------------------------- /Netch/Servers/Trojan/TrojanForm.cs: -------------------------------------------------------------------------------- 1 | using Netch.Forms; 2 | 3 | namespace Netch.Servers; 4 | 5 | [Fody.ConfigureAwait(true)] 6 | public class TrojanForm : ServerForm 7 | { 8 | public TrojanForm(TrojanServer? server = default) 9 | { 10 | server ??= new TrojanServer(); 11 | Server = server; 12 | CreateTextBox("Password", "Password", s => true, s => server.Password = s, server.Password); 13 | CreateTextBox("Host", "Host", s => true, s => server.Host = s, server.Host); 14 | CreateComboBox("TLSSecure", "TLS Secure", VLESSGlobal.TLSSecure, s => server.TLSSecureType = s, server.TLSSecureType); 15 | } 16 | 17 | protected override string TypeName { get; } = "Trojan"; 18 | } -------------------------------------------------------------------------------- /Netch/Servers/Trojan/TrojanServer.cs: -------------------------------------------------------------------------------- 1 | using Netch.Models; 2 | 3 | namespace Netch.Servers; 4 | 5 | public class TrojanServer : Server 6 | { 7 | private string _tlsSecureType = VLESSGlobal.TLSSecure[1]; 8 | 9 | public override string Type { get; } = "Trojan"; 10 | 11 | public override string MaskedData() 12 | { 13 | return ""; 14 | } 15 | 16 | /// 17 | /// 密码 18 | /// 19 | public string Password { get; set; } = string.Empty; 20 | 21 | /// 22 | /// 伪装域名 23 | /// 24 | public string? Host { get; set; } 25 | 26 | /// 27 | /// TLS 底层传输安全 28 | /// 29 | public string TLSSecureType 30 | { 31 | get => _tlsSecureType; 32 | set 33 | { 34 | if (value == "") 35 | value = VLESSGlobal.TLSSecure[1]; 36 | 37 | _tlsSecureType = value; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /Netch/Servers/Trojan/TrojanUtil.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using System.Web; 3 | using Netch.Interfaces; 4 | using Netch.Models; 5 | 6 | namespace Netch.Servers; 7 | 8 | public class TrojanUtil : IServerUtil 9 | { 10 | public ushort Priority { get; } = 3; 11 | 12 | public string TypeName { get; } = "Trojan"; 13 | 14 | public string FullName { get; } = "Trojan"; 15 | 16 | public string ShortName { get; } = "TR"; 17 | 18 | public string[] UriScheme { get; } = { "trojan" }; 19 | 20 | public Type ServerType { get; } = typeof(TrojanServer); 21 | 22 | public void Edit(Server s) 23 | { 24 | new TrojanForm((TrojanServer)s).ShowDialog(); 25 | } 26 | 27 | public void Create() 28 | { 29 | new TrojanForm().ShowDialog(); 30 | } 31 | 32 | public string GetShareLink(Server s) 33 | { 34 | var server = (TrojanServer)s; 35 | return $"trojan://{HttpUtility.UrlEncode(server.Password)}@{server.Hostname}:{server.Port}?sni={server.Host}#{server.Remark}"; 36 | } 37 | 38 | public IServerController GetController() 39 | { 40 | return new TrojanController(); 41 | } 42 | 43 | public IEnumerable ParseUri(string text) 44 | { 45 | var data = new TrojanServer(); 46 | 47 | text = text.Replace("/?", "?"); 48 | if (text.Contains('#')) 49 | { 50 | data.Remark = HttpUtility.UrlDecode(text.Split('#')[1]); 51 | text = text.Split('#')[0]; 52 | } 53 | 54 | if (text.Contains('?')) 55 | { 56 | var reg = new Regex(@"^(?.+?)\?(.+)$"); 57 | var regmatch = reg.Match(text); 58 | 59 | if (!regmatch.Success) 60 | throw new FormatException(); 61 | 62 | var peer = HttpUtility.UrlDecode(HttpUtility.ParseQueryString(new Uri(text).Query).Get("peer")); 63 | 64 | if (peer != null) { 65 | data.Host = peer; 66 | } else { 67 | peer = HttpUtility.UrlDecode(HttpUtility.ParseQueryString(new Uri(text).Query).Get("sni")); 68 | if (peer != null) 69 | data.Host = peer; 70 | } 71 | 72 | text = regmatch.Groups["data"].Value; 73 | } 74 | 75 | var finder = new Regex(@"^trojan://(?.+?)@(?.+):(?\d+)"); 76 | var match = finder.Match(text); 77 | if (!match.Success) 78 | throw new FormatException(); 79 | 80 | data.Password = HttpUtility.UrlDecode(match.Groups["psk"].Value); 81 | data.Hostname = match.Groups["server"].Value; 82 | data.Port = ushort.Parse(match.Groups["port"].Value); 83 | 84 | return new[] { data }; 85 | } 86 | 87 | public bool CheckServer(Server s) 88 | { 89 | return true; 90 | } 91 | } -------------------------------------------------------------------------------- /Netch/Servers/V2ray/ShareModels/V2rayNJObject.cs: -------------------------------------------------------------------------------- 1 | namespace Netch.Servers; 2 | 3 | public class V2rayNJObject 4 | { 5 | /// 6 | /// 链接版本 7 | /// 8 | public int v { get; set; } = 2; 9 | 10 | /// 11 | /// 备注 12 | /// 13 | public string ps { get; set; } = string.Empty; 14 | 15 | /// 16 | /// 地址 17 | /// 18 | public string add { get; set; } = string.Empty; 19 | 20 | /// 21 | /// 端口 22 | /// 23 | public ushort port { get; set; } 24 | 25 | /// 26 | /// 用户 ID 27 | /// 28 | public string id { get; set; } = string.Empty; 29 | 30 | /// 31 | /// 额外 ID 32 | /// 33 | public int aid { get; set; } 34 | 35 | /// 36 | /// 加密方式 (security) 37 | /// 38 | public string scy { get; set; } = "auto"; 39 | 40 | /// 41 | /// 传输协议 42 | /// 43 | public string net { get; set; } = string.Empty; 44 | 45 | /// 46 | /// 伪装类型 47 | /// 48 | public string type { get; set; } = string.Empty; 49 | 50 | /// 51 | /// 伪装域名(HTTP,WS) 52 | /// 53 | public string host { get; set; } = string.Empty; 54 | 55 | /// 56 | /// 伪装路径/服务名称 57 | /// 58 | public string path { get; set; } = string.Empty; 59 | 60 | /// 61 | /// 是否使用 TLS 62 | /// 63 | public string tls { get; set; } = string.Empty; 64 | 65 | /// 66 | /// serverName 67 | /// 68 | public string sni { get; set; } = string.Empty; 69 | } -------------------------------------------------------------------------------- /Netch/Servers/V2ray/V2rayController.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using System.Text.Json; 3 | using Netch.Controllers; 4 | using Netch.Interfaces; 5 | using Netch.Models; 6 | 7 | namespace Netch.Servers; 8 | 9 | public class V2rayController : Guard, IServerController 10 | { 11 | public V2rayController() : base("xray.exe") 12 | { 13 | //if (!Global.Settings.V2RayConfig.XrayCone) 14 | // Instance.StartInfo.Environment["XRAY_CONE_DISABLED"] = "true"; 15 | } 16 | 17 | protected override IEnumerable StartedKeywords => new[] { "started" }; 18 | 19 | protected override IEnumerable FailedKeywords => new[] { "config file not readable", "failed to" }; 20 | 21 | public override string Name => "system.core"; 22 | 23 | public ushort? Socks5LocalPort { get; set; } 24 | 25 | public string? LocalAddress { get; set; } 26 | 27 | public virtual async Task StartAsync(Server s) 28 | { 29 | await using (var fileStream = new FileStream(Constants.TempConfig, FileMode.Create, FileAccess.Write, FileShare.Read)) 30 | { 31 | await JsonSerializer.SerializeAsync(fileStream, await CoreConfig.GenerateClientConfigAsync(s), Global.NewCustomJsonSerializerOptions()); 32 | } 33 | 34 | await StartGuardAsync("run -c ..\\data\\last.json"); 35 | return new Socks5Server(IPAddress.Loopback.ToString(), this.Socks5LocalPort(), s.Hostname); 36 | } 37 | } -------------------------------------------------------------------------------- /Netch/Servers/VLESS/VLESSForm.cs: -------------------------------------------------------------------------------- 1 | using Netch.Forms; 2 | 3 | namespace Netch.Servers; 4 | 5 | [Fody.ConfigureAwait(true)] 6 | internal class VLESSForm : ServerForm 7 | { 8 | public VLESSForm(VLESSServer? server = default) 9 | { 10 | server ??= new VLESSServer(); 11 | Server = server; 12 | CreateTextBox("Sni", "ServerName(Sni)", s => true, s => server.ServerName = s, server.ServerName); 13 | CreateTextBox("UUID", "UUID", s => true, s => server.UserID = s, server.UserID); 14 | CreateTextBox("EncryptMethod", 15 | "Encrypt Method", 16 | s => true, 17 | s => server.EncryptMethod = !string.IsNullOrWhiteSpace(s) ? s : "none", 18 | server.EncryptMethod); 19 | 20 | CreateComboBox("TransferProtocol", 21 | "Transfer Protocol", 22 | VLESSGlobal.TransferProtocols, 23 | s => server.TransferProtocol = s, 24 | server.TransferProtocol); 25 | CreateComboBox("PacketEncoding", 26 | "Packet Encoding", 27 | VMessGlobal.PacketEncodings, 28 | s => server.PacketEncoding = s, 29 | server.PacketEncoding); 30 | 31 | CreateComboBox("FakeType", "Fake Type", VLESSGlobal.FakeTypes, s => server.FakeType = s, server.FakeType); 32 | CreateComboBox("Flow", "Flow Control", VLESSGlobal.FlowControl, s => server.FlowControl = s, server.FlowControl); 33 | CreateTextBox("Host", "Host", s => true, s => server.Host = s, server.Host); 34 | CreateTextBox("Path", "Path", s => true, s => server.Path = s, server.Path); 35 | CreateComboBox("QUICSecurity", "QUIC Security", VLESSGlobal.QUIC, s => server.QUICSecure = s, server.QUICSecure); 36 | CreateTextBox("QUICSecret", "QUIC Secret", s => true, s => server.QUICSecret = s, server.QUICSecret); 37 | CreateComboBox("UseMux", 38 | "Use Mux", 39 | new List { "", "true", "false" }, 40 | s => server.UseMux = s switch { "" => null, "true" => true, "false" => false, _ => null }, 41 | server.UseMux?.ToString().ToLower() ?? ""); 42 | 43 | CreateComboBox("TLSSecure", "TLS Secure", VLESSGlobal.TLSSecure, s => server.TLSSecureType = s, server.TLSSecureType); 44 | } 45 | 46 | protected override string TypeName { get; } = "VLESS"; 47 | } -------------------------------------------------------------------------------- /Netch/Servers/VLESS/VLESSServer.cs: -------------------------------------------------------------------------------- 1 | namespace Netch.Servers; 2 | 3 | public class VLESSServer : VMessServer 4 | { 5 | public override string Type { get; } = "VLESS"; 6 | 7 | /// 8 | /// 加密方式 9 | /// 10 | public override string EncryptMethod { get; set; } = "none"; 11 | 12 | /// 13 | /// 传输协议 14 | /// 15 | public override string TransferProtocol { get; set; } = VLESSGlobal.TransferProtocols[0]; 16 | 17 | /// 18 | /// 伪装类型 19 | /// 20 | public override string FakeType { get; set; } = VLESSGlobal.FakeTypes[0]; 21 | public string FlowControl { get; set; } = VLESSGlobal.FlowControl[0]; 22 | } 23 | 24 | public class VLESSGlobal 25 | { 26 | public static readonly List TLSSecure = new() 27 | { 28 | "none", 29 | "tls", 30 | "xtls" 31 | }; 32 | 33 | public static readonly List FlowControl = new() 34 | { 35 | "", 36 | "xtls-rprx-vision", 37 | "xtls-rprx-direct", 38 | "xtls-rprx-origin", 39 | "xtls-rprx-vision-443", 40 | "xtls-rprx-direct-443", 41 | "xtls-rprx-origin-443", 42 | }; 43 | 44 | public static List FakeTypes => VMessGlobal.FakeTypes; 45 | 46 | public static List TransferProtocols => VMessGlobal.TransferProtocols; 47 | 48 | public static List QUIC => VMessGlobal.QUIC; 49 | } -------------------------------------------------------------------------------- /Netch/Servers/VLESS/VLESSUtil.cs: -------------------------------------------------------------------------------- 1 | using Netch.Interfaces; 2 | using Netch.Models; 3 | 4 | namespace Netch.Servers; 5 | 6 | public class VLESSUtil : IServerUtil 7 | { 8 | public ushort Priority { get; } = 2; 9 | 10 | public string TypeName { get; } = "VLESS"; 11 | 12 | public string FullName { get; } = "VLESS"; 13 | 14 | public string ShortName { get; } = "VL"; 15 | 16 | public string[] UriScheme { get; } = { "vless" }; 17 | 18 | public Type ServerType { get; } = typeof(VLESSServer); 19 | 20 | public void Edit(Server s) 21 | { 22 | new VLESSForm((VLESSServer)s).ShowDialog(); 23 | } 24 | 25 | public void Create() 26 | { 27 | new VLESSForm().ShowDialog(); 28 | } 29 | 30 | public string GetShareLink(Server s) 31 | { 32 | return V2rayUtils.GetVShareLink(s, "vless"); 33 | } 34 | 35 | public IServerController GetController() 36 | { 37 | return new V2rayController(); 38 | } 39 | 40 | public IEnumerable ParseUri(string text) 41 | { 42 | return V2rayUtils.ParseVUri(text); 43 | } 44 | 45 | public bool CheckServer(Server s) 46 | { 47 | return true; 48 | } 49 | } -------------------------------------------------------------------------------- /Netch/Servers/VMess/VMessForm.cs: -------------------------------------------------------------------------------- 1 | using Netch.Forms; 2 | 3 | namespace Netch.Servers; 4 | 5 | [Fody.ConfigureAwait(true)] 6 | public class VMessForm : ServerForm 7 | { 8 | public VMessForm(VMessServer? server = default) 9 | { 10 | server ??= new VMessServer(); 11 | Server = server; 12 | CreateTextBox("Sni", "ServerName(Sni)", s => true, s => server.ServerName = s, server.ServerName); 13 | CreateTextBox("UserId", "User ID", s => true, s => server.UserID = s, server.UserID); 14 | CreateTextBox("AlterId", "Alter ID", s => int.TryParse(s, out _), s => server.AlterID = int.Parse(s), server.AlterID.ToString(), 76); 15 | CreateComboBox("EncryptMethod", "Encrypt Method", VMessGlobal.EncryptMethods, s => server.EncryptMethod = s, server.EncryptMethod); 16 | CreateComboBox("TransferProtocol", 17 | "Transfer Protocol", 18 | VMessGlobal.TransferProtocols, 19 | s => server.TransferProtocol = s, 20 | server.TransferProtocol); 21 | CreateComboBox("PacketEncoding", 22 | "Packet Encoding", 23 | VMessGlobal.PacketEncodings, 24 | s => server.PacketEncoding = s, 25 | server.PacketEncoding); 26 | 27 | 28 | CreateComboBox("FakeType", "Fake Type", VMessGlobal.FakeTypes, s => server.FakeType = s, server.FakeType); 29 | CreateTextBox("Host", "Host", s => true, s => server.Host = s, server.Host); 30 | CreateTextBox("Path", "Path", s => true, s => server.Path = s, server.Path); 31 | CreateComboBox("QUICSecurity", "QUIC Security", VMessGlobal.QUIC, s => server.QUICSecure = s, server.QUICSecure); 32 | CreateTextBox("QUICSecret", "QUIC Secret", s => true, s => server.QUICSecret = s, server.QUICSecret); 33 | CreateComboBox("UseMux", 34 | "Use Mux", 35 | new List { "", "true", "false" }, 36 | s => server.UseMux = s switch { "" => null, "true" => true, "false" => false, _ => null }, 37 | server.UseMux?.ToString().ToLower() ?? ""); 38 | 39 | CreateComboBox("TLSSecure", "TLS Secure", VMessGlobal.TLSSecure, s => server.TLSSecureType = s, server.TLSSecureType); 40 | } 41 | 42 | protected override string TypeName { get; } = "VMess"; 43 | } -------------------------------------------------------------------------------- /Netch/Servers/Vision/VisionServer.cs: -------------------------------------------------------------------------------- 1 | namespace Netch.Servers; 2 | 3 | public class VisionServer : VMessServer 4 | { 5 | public override string Type { get; } = "Vision"; 6 | 7 | public string SpiderX { get; set; } = string.Empty; 8 | 9 | public string ShortId { get; set; } = string.Empty; 10 | 11 | public string PublicKey { get; set; } = string.Empty; 12 | 13 | public string Flow { get; set; } = VisionGlobal.Flows[0]; 14 | 15 | public override string EncryptMethod { get; set; } = "none"; 16 | 17 | public string Fingerprint { get; set; } = VisionGlobal.Fingerprints[0]; 18 | 19 | public override string TransferProtocol { get; set; } = VisionGlobal.TransferProtocols[0]; 20 | } 21 | 22 | public class VisionGlobal 23 | { 24 | public static List TransferProtocols => new() { "tcp" }; 25 | 26 | public static readonly List TLSSecure = new() { "none", "tls", "reality" }; 27 | 28 | public static readonly List Alpns = new() { "h2", "http/1.1", "h2,http/1.1" }; 29 | 30 | public static readonly List Flows = new() { "xtls-rprx-vision", "xtls-rprx-vision-udp443" }; 31 | 32 | public static readonly List Fingerprints = new() { "chrome","firefox","safari","ios","android","edge","360","qq" }; 33 | } -------------------------------------------------------------------------------- /Netch/Servers/Vision/VisionUtil.cs: -------------------------------------------------------------------------------- 1 | using Netch.Interfaces; 2 | using Netch.Models; 3 | 4 | namespace Netch.Servers; 5 | 6 | public class VisionUtil : IServerUtil 7 | { 8 | public ushort Priority { get; } = 2; 9 | 10 | public string TypeName { get; } = "Vision"; 11 | 12 | public string FullName { get; } = "Vision"; 13 | 14 | public string ShortName { get; } = "Vi"; 15 | 16 | public string[] UriScheme { get; } = { "vision" }; 17 | 18 | public Type ServerType { get; } = typeof(VisionServer); 19 | 20 | public void Edit(Server s) 21 | { 22 | new VisionForm((VisionServer)s).ShowDialog(); 23 | } 24 | 25 | public void Create() 26 | { 27 | new VisionForm().ShowDialog(); 28 | } 29 | 30 | public string GetShareLink(Server s) 31 | { 32 | return V2rayUtils.GetVShareLink(s, "vision"); 33 | } 34 | 35 | public IServerController GetController() 36 | { 37 | return new V2rayController(); 38 | } 39 | 40 | public IEnumerable ParseUri(string text) 41 | { 42 | return V2rayUtils.ParseVUri(text); 43 | } 44 | 45 | public bool CheckServer(Server s) 46 | { 47 | return true; 48 | } 49 | } -------------------------------------------------------------------------------- /Netch/Servers/WireGuard/WireGuardForm.cs: -------------------------------------------------------------------------------- 1 | using Netch.Forms; 2 | 3 | namespace Netch.Servers; 4 | 5 | [Fody.ConfigureAwait(true)] 6 | public class WireGuardForm : ServerForm 7 | { 8 | public WireGuardForm(WireGuardServer? server = default) 9 | { 10 | server ??= new WireGuardServer(); 11 | Server = server; 12 | CreateTextBox("PeerPublicKey", "Public Key", s => true, s => server.PeerPublicKey = s, server.PeerPublicKey); 13 | CreateTextBox("LocalAddresses", "Local Addresses", s => true, s => server.LocalAddresses = s, server.LocalAddresses); 14 | CreateTextBox("PrivateKey", "Private Key", s => true, s => server.PrivateKey = s, server.PrivateKey); 15 | CreateTextBox("PreSharedKey", "PSK", s => true, s => server.PreSharedKey = s, server.PreSharedKey); 16 | CreateTextBox("MTU", "MTU", s => int.TryParse(s, out _), s => server.MTU = int.Parse(s), server.MTU.ToString(), 76); 17 | CreateTextBox("Reserved", "Reserved", s => CheckReserved(s), s => server.Reserved = s, server.Reserved, 76); 18 | CreateTextBox("Workers", "Workers", s => int.TryParse(s, out _), s => server.Workers = int.Parse(s), server.Workers.ToString(), 76); 19 | CreateTextBox("KeepAlive", "Keep Alive", s => int.TryParse(s, out _), s => server.KeepAlive = int.Parse(s),server.KeepAlive.ToString(), 76); 20 | CreateTextBox("AllowIPs", "Allow Ips", s => true, s => server.AllowIPs = s, server.AllowIPs); 21 | CreateComboBox("DomainStrategy", "Domain Strategy", server.GetDomainStrategyList(), s => server.DomainStrategy=s, server.DomainStrategy); 22 | } 23 | 24 | protected override string TypeName { get; } = "WireGuard"; 25 | 26 | private bool CheckReserved(string s) 27 | { 28 | var s_reserved = s.Split(","); 29 | var int_reserved = s_reserved.Select(x => int.TryParse(x, out _)).ToList(); 30 | return int_reserved.Count == 3; 31 | } 32 | } -------------------------------------------------------------------------------- /Netch/Servers/WireGuard/WireGuardServer.cs: -------------------------------------------------------------------------------- 1 | using Netch.Models; 2 | 3 | namespace Netch.Servers; 4 | 5 | public class WireGuardServer : Server 6 | { 7 | public override string Type { get; } = "WireGuard"; 8 | 9 | public override string MaskedData() 10 | { 11 | return $"{LocalAddresses} + {MTU}"; 12 | } 13 | 14 | /// 15 | /// 本地地址 16 | /// 17 | public string LocalAddresses { get; set; } = "172.16.0.2/32"; 18 | 19 | /// 20 | /// 节点公钥 21 | /// 22 | public string PeerPublicKey { get; set; } = string.Empty; 23 | 24 | /// 25 | /// 私钥 26 | /// 27 | public string PrivateKey { get; set; } 28 | 29 | /// 30 | /// 节点预共享密钥 31 | /// 32 | public string? PreSharedKey { get; set; } 33 | 34 | /// 35 | /// MTU 36 | /// 37 | public int MTU { get; set; } = 1420; 38 | 39 | /// 40 | /// Reserved 41 | /// 42 | public string Reserved { get; set; } = "0,0,0"; 43 | 44 | /// 45 | /// EDomainStrategy 46 | /// 47 | public enum EDomainStrategy 48 | { 49 | ForceIPv6v4, 50 | ForceIPv6, 51 | ForceIPv4v6, 52 | ForceIPv4, 53 | ForceIP 54 | } 55 | 56 | /// 57 | /// DomainStrategy 58 | /// 59 | public string DomainStrategy { get; set; } = EDomainStrategy.ForceIP.ToString(); 60 | 61 | /// 62 | /// GetDomainStrategyList 63 | /// 64 | public List GetDomainStrategyList() 65 | { 66 | return Enum.GetValues().OfType().Select(x => x.ToString()).ToList(); 67 | } 68 | 69 | /// 70 | /// KeepAlive 71 | /// 72 | public int KeepAlive { get; set; } = 25; 73 | 74 | /// 75 | /// AllowIPs 76 | /// 77 | public string AllowIPs { get; set; } = "0.0.0.0/0,127.0.0.1/32"; 78 | 79 | /// 80 | /// Workers 81 | /// 82 | public int Workers { get; set; } = 2; 83 | } 84 | -------------------------------------------------------------------------------- /Netch/Servers/WireGuard/WireGuardUtil.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | using System.Text.Encodings.Web; 3 | using System.Text.Json; 4 | using System.Text.Json.Serialization; 5 | using Netch.Interfaces; 6 | using Netch.Models; 7 | using Netch.Utils; 8 | 9 | namespace Netch.Servers; 10 | 11 | public class WireGuardUtil : IServerUtil 12 | { 13 | public ushort Priority { get; } = 4; 14 | 15 | public string TypeName { get; } = "WireGuard"; 16 | 17 | public string FullName { get; } = "WireGuard"; 18 | 19 | public string ShortName { get; } = "WG"; 20 | 21 | public string[] UriScheme { get; } = { "wireguard" }; 22 | 23 | public Type ServerType { get; } = typeof(WireGuardServer); 24 | 25 | public void Edit(Server s) 26 | { 27 | new WireGuardForm((WireGuardServer)s).ShowDialog(); 28 | } 29 | 30 | public void Create() 31 | { 32 | new WireGuardForm().ShowDialog(); 33 | } 34 | 35 | public string GetShareLink(Server s) 36 | { 37 | return V2rayUtils.GetVShareLink(s, "wireguard"); 38 | } 39 | 40 | public IServerController GetController() 41 | { 42 | return new V2rayController(); 43 | } 44 | 45 | public IEnumerable ParseUri(string text) 46 | { 47 | return V2rayUtils.ParseVUri(text); 48 | } 49 | 50 | public bool CheckServer(Server s) 51 | { 52 | return true; 53 | } 54 | } -------------------------------------------------------------------------------- /Netch/Utils/DelayTestHelper.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.Threading; 2 | using Netch.Models; 3 | using Timer = System.Timers.Timer; 4 | 5 | namespace Netch.Utils; 6 | 7 | public static class DelayTestHelper 8 | { 9 | private static readonly Timer Timer; 10 | 11 | private static readonly AsyncSemaphore Lock = new(1); 12 | 13 | private static readonly AsyncSemaphore PoolLock = new(16); 14 | 15 | public static readonly NumberRange Range = new(0, int.MaxValue / 1000); 16 | 17 | private static bool _enabled = true; 18 | 19 | static DelayTestHelper() 20 | { 21 | Timer = new Timer 22 | { 23 | Interval = 10000, 24 | AutoReset = true 25 | }; 26 | 27 | Timer.Elapsed += (_, _) => PerformTestAsync().Forget(); 28 | } 29 | 30 | public static bool Enabled 31 | { 32 | get => _enabled; 33 | set 34 | { 35 | _enabled = value; 36 | UpdateTick(); 37 | } 38 | } 39 | 40 | /// if does not get lock, block until last release 41 | public static async Task PerformTestAsync(bool waitFinish = false) 42 | { 43 | if (Lock.CurrentCount == 0) 44 | { 45 | if (waitFinish) 46 | (await Lock.EnterAsync()).Dispose(); 47 | 48 | return; 49 | } 50 | 51 | using var _ = await Lock.EnterAsync(); 52 | 53 | try 54 | { 55 | var tasks = Global.Settings.Server.Select(async s => 56 | { 57 | using (await PoolLock.EnterAsync()) 58 | { 59 | await s.PingAsync(); 60 | } 61 | }); 62 | 63 | await Task.WhenAll(tasks); 64 | } 65 | catch (Exception) 66 | { 67 | // ignored 68 | } 69 | } 70 | 71 | public static void UpdateTick(bool performTestAtOnce = false) 72 | { 73 | UpdateTick(Global.Settings.DetectionTick, performTestAtOnce); 74 | } 75 | 76 | /// interval(seconds), 0 disable, MaxValue int.MaxValue/1000 77 | /// 78 | private static void UpdateTick(int interval, bool performTestAtOnce = false) 79 | { 80 | Timer.Stop(); 81 | 82 | var enable = Enabled && interval > 0 && Range.InRange(interval); 83 | if (enable) 84 | { 85 | Timer.Interval = interval * 1000; 86 | Timer.Start(); 87 | if (performTestAtOnce) 88 | PerformTestAsync().Forget(); 89 | } 90 | } 91 | } -------------------------------------------------------------------------------- /Netch/Utils/DnsUtils.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Net; 3 | using System.Net.Sockets; 4 | using Microsoft.VisualStudio.Threading; 5 | 6 | namespace Netch.Utils; 7 | 8 | public static class DnsUtils 9 | { 10 | private static readonly AsyncSemaphore Lock = new(1); 11 | 12 | /// 13 | /// 缓存 14 | /// 15 | private static readonly Hashtable Cache = new(); 16 | private static readonly Hashtable Cache6 = new(); 17 | 18 | public static async Task LookupAsync(string hostname, AddressFamily inet = AddressFamily.Unspecified, int timeout = 3000) 19 | { 20 | using var _ = await Lock.EnterAsync(); 21 | try 22 | { 23 | var cacheResult = inet switch 24 | { 25 | AddressFamily.Unspecified => (IPAddress?)(Cache[hostname] ?? Cache6[hostname]), 26 | AddressFamily.InterNetwork => (IPAddress?)Cache[hostname], 27 | AddressFamily.InterNetworkV6 => (IPAddress?)Cache6[hostname], 28 | _ => throw new ArgumentOutOfRangeException(nameof(inet)) 29 | }; 30 | 31 | if (cacheResult != null) 32 | return cacheResult; 33 | 34 | return await LookupNoCacheAsync(hostname, inet, timeout); 35 | } 36 | catch (Exception e) 37 | { 38 | Log.Verbose(e, "Lookup hostname {Hostname} failed", hostname); 39 | return null; 40 | } 41 | } 42 | 43 | private static async Task LookupNoCacheAsync(string hostname, AddressFamily inet = AddressFamily.Unspecified, int timeout = 3000) 44 | { 45 | using var task = Dns.GetHostAddressesAsync(hostname); 46 | using var resTask = await Task.WhenAny(task, Task.Delay(timeout)); 47 | 48 | if (resTask == task) 49 | { 50 | var addresses = await task; 51 | 52 | var result = addresses.FirstOrDefault(i => inet == AddressFamily.Unspecified || inet == i.AddressFamily); 53 | if (result == null) 54 | return null; 55 | 56 | switch (result.AddressFamily) 57 | { 58 | case AddressFamily.InterNetwork: 59 | Cache.Add(hostname, result); 60 | break; 61 | case AddressFamily.InterNetworkV6: 62 | Cache6.Add(hostname, result); 63 | break; 64 | default: 65 | throw new ArgumentOutOfRangeException(nameof(inet)); 66 | } 67 | 68 | return result; 69 | } 70 | 71 | return null; 72 | } 73 | 74 | public static void ClearCache() 75 | { 76 | Cache.Clear(); 77 | Cache6.Clear(); 78 | } 79 | 80 | public static string AppendPort(string host, ushort port = 53) 81 | { 82 | if (!host.Contains(':')) 83 | return host + $":{port}"; 84 | 85 | return host; 86 | } 87 | } -------------------------------------------------------------------------------- /Netch/Utils/Firewall.cs: -------------------------------------------------------------------------------- 1 | using WindowsFirewallHelper; 2 | using WindowsFirewallHelper.FirewallRules; 3 | 4 | namespace Netch.Utils; 5 | 6 | public static class Firewall 7 | { 8 | private const string Netch = "Netch"; 9 | 10 | /// 11 | /// Netch 自带程序添加防火墙 12 | /// 13 | public static void AddNetchFwRules() 14 | { 15 | if (!FirewallWAS.IsLocallySupported) 16 | { 17 | Log.Warning("Windows Firewall Locally Unsupported"); 18 | return; 19 | } 20 | 21 | try 22 | { 23 | var rule = FirewallManager.Instance.Rules.FirstOrDefault(r => r.Name == Netch); 24 | if (rule != null) 25 | { 26 | if (rule.ApplicationName.StartsWith(Global.NetchDir)) 27 | return; 28 | 29 | RemoveNetchFwRules(); 30 | } 31 | 32 | foreach (var path in Directory.GetFiles(Global.NetchDir, "*.exe", SearchOption.AllDirectories)) 33 | AddFwRule(Netch, path); 34 | } 35 | catch (Exception e) 36 | { 37 | Log.Warning(e, "Create Netch Firewall rules error"); 38 | } 39 | } 40 | 41 | /// 42 | /// 清除防火墙规则 (Netch 自带程序) 43 | /// 44 | public static void RemoveNetchFwRules(bool showNotification = false) 45 | { 46 | if (!FirewallWAS.IsLocallySupported) 47 | return; 48 | 49 | try 50 | { 51 | foreach (var rule in FirewallManager.Instance.Rules.Where(r 52 | => r.ApplicationName?.StartsWith(Global.NetchDir, StringComparison.OrdinalIgnoreCase) ?? r.Name == Netch)) 53 | { 54 | FirewallManager.Instance.Rules.Remove(rule); 55 | } 56 | if (showNotification) 57 | { 58 | Global.MainForm.NotifyTip(i18N.Translate("Remove Netch Firewall Rules succeeded")); 59 | } 60 | } 61 | catch (Exception e) 62 | { 63 | Log.Warning(e, "Remove Netch Firewall rules error"); 64 | } 65 | } 66 | 67 | #region 封装 68 | 69 | private static void AddFwRule(string ruleName, string exeFullPath) 70 | { 71 | var rule = new FirewallWASRule(ruleName, 72 | exeFullPath, 73 | FirewallAction.Allow, 74 | FirewallDirection.Inbound, 75 | FirewallProfiles.Private | FirewallProfiles.Public | FirewallProfiles.Domain); 76 | 77 | FirewallManager.Instance.Rules.Add(rule); 78 | } 79 | 80 | #endregion 81 | } -------------------------------------------------------------------------------- /Netch/Utils/RouteUtils.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using System.Net.Sockets; 3 | using Netch.Interops; 4 | using Netch.Models; 5 | 6 | namespace Netch.Utils; 7 | 8 | // #define DEBUG_TUN 9 | public static class RouteUtils 10 | { 11 | public static void CreateRouteFill(NetRoute template, IEnumerable rules, int? metric = null) 12 | { 13 | foreach (var rule in rules) 14 | CreateRouteFill(template, rule, metric); 15 | } 16 | 17 | public static bool CreateRouteFill(NetRoute template, string rule, int? metric = null) 18 | { 19 | if (!TryParseIPNetwork(rule, out var network, out var cidr)) 20 | { 21 | Log.Warning("invalid rule {Rule}", rule); 22 | return false; 23 | } 24 | 25 | return CreateRoute(template.FillTemplate(network, (byte)cidr, metric)); 26 | } 27 | 28 | public static bool CreateRoute(NetRoute o) 29 | { 30 | var Result = RouteHelper.CreateRoute(AddressFamily.InterNetwork, o.Network, o.Cidr, o.Gateway, (ulong)o.InterfaceIndex, o.Metric); 31 | 32 | #if DEBUG_TUN 33 | Log.Verbose("CreateRoute {InterNetwork} {Address} {Cidr} {Gateway} {Interface} {Metric} Result: {Result}", 34 | AddressFamily.InterNetwork, 35 | o.Network, 36 | o.Cidr, 37 | o.Gateway, 38 | (ulong)o.InterfaceIndex, 39 | o.Metric, 40 | Result); 41 | #endif 42 | return Result; 43 | } 44 | 45 | public static void DeleteRouteFill(NetRoute template, IEnumerable rules, int? metric = null) 46 | { 47 | foreach (var rule in rules) 48 | DeleteRouteFill(template, rule, metric); 49 | } 50 | 51 | public static bool DeleteRouteFill(NetRoute template, string rule, int? metric = null) 52 | { 53 | if (!TryParseIPNetwork(rule, out var network, out var cidr)) 54 | { 55 | Log.Warning("invalid rule {Rule}", rule); 56 | return false; 57 | } 58 | 59 | return DeleteRoute(template.FillTemplate(network, (byte)cidr, metric)); 60 | } 61 | 62 | public static bool DeleteRoute(NetRoute o) 63 | { 64 | var Result = RouteHelper.DeleteRoute(AddressFamily.InterNetwork, o.Network, o.Cidr, o.Gateway, (ulong)o.InterfaceIndex, o.Metric); 65 | 66 | #if DEBUG_TUN 67 | Log.Verbose("DeleteRoute {InterNetwork} {Address} {Cidr} {Gateway} {Interface} {Metric} Result: {}", 68 | AddressFamily.InterNetwork, 69 | o.Network, 70 | o.Cidr, 71 | o.Gateway, 72 | (ulong)o.InterfaceIndex, 73 | o.Metric, 74 | Result); 75 | #endif 76 | return Result; 77 | } 78 | 79 | public static bool TryParseIPNetwork(string ipNetwork, [NotNullWhen(true)] out string? ip, out int cidr) 80 | { 81 | ip = null; 82 | cidr = 0; 83 | 84 | var s = ipNetwork.Split('/'); 85 | if (s.Length != 2) 86 | return false; 87 | 88 | ip = s[0]; 89 | cidr = int.Parse(s[1]); 90 | return true; 91 | } 92 | } -------------------------------------------------------------------------------- /Netch/Utils/ServerHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using Netch.Interfaces; 3 | 4 | namespace Netch.Utils; 5 | 6 | public static class ServerHelper 7 | { 8 | static ServerHelper() 9 | { 10 | var serversUtilsTypes = Assembly.GetExecutingAssembly() 11 | .GetExportedTypes() 12 | .Where(type => type.GetInterfaces().Contains(typeof(IServerUtil))); 13 | 14 | ServerUtilDictionary = serversUtilsTypes.Select(t => (IServerUtil)Activator.CreateInstance(t)!).ToDictionary(util => util.TypeName); 15 | } 16 | 17 | public static Dictionary ServerUtilDictionary { get; } 18 | 19 | public static IServerUtil GetUtilByTypeName(string typeName) 20 | { 21 | return ServerUtilDictionary.GetValueOrDefault(typeName) ?? throw new NotSupportedException("Specified server type is not supported."); 22 | } 23 | 24 | public static IServerUtil? GetUtilByUriScheme(string scheme) 25 | { 26 | return ServerUtilDictionary.Values.SingleOrDefault(i => i.UriScheme.Any(s => s.Equals(scheme))); 27 | } 28 | 29 | public static Type GetTypeByTypeName(string typeName) 30 | { 31 | return GetUtilByTypeName(typeName).ServerType; 32 | } 33 | } -------------------------------------------------------------------------------- /Netch/Utils/SubscriptionUtil.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using Netch.Models; 3 | 4 | namespace Netch.Utils; 5 | 6 | public static class SubscriptionUtil 7 | { 8 | private static readonly object ServerLock = new(); 9 | 10 | public static Task UpdateServersAsync(string? proxyServer = default) 11 | { 12 | return Task.WhenAll(Global.Settings.Subscription.Select(item => UpdateServerCoreAsync(item, proxyServer))); 13 | } 14 | 15 | private static async Task UpdateServerCoreAsync(Subscription item, string? proxyServer) 16 | { 17 | try 18 | { 19 | if (!item.Enable) 20 | return; 21 | 22 | var request = WebUtil.CreateRequest(item.Link); 23 | 24 | if (!string.IsNullOrEmpty(item.UserAgent)) 25 | request.UserAgent = item.UserAgent; 26 | 27 | if (!string.IsNullOrEmpty(proxyServer)) 28 | request.Proxy = new WebProxy(proxyServer); 29 | 30 | List servers; 31 | 32 | var (code, result) = await WebUtil.DownloadStringAsync(request); 33 | if (code == HttpStatusCode.OK) 34 | servers = ShareLink.ParseText(result); 35 | else 36 | throw new Exception($"{item.Remark} Response Status Code: {code}"); 37 | 38 | foreach (var server in servers) 39 | server.Group = item.Remark; 40 | 41 | lock (ServerLock) 42 | { 43 | Global.Settings.Server.RemoveAll(server => server.Group.Equals(item.Remark)); 44 | Global.Settings.Server.AddRange(servers); 45 | } 46 | 47 | Global.MainForm.NotifyTip(i18N.TranslateFormat("Update {1} server(s) from {0}", item.Remark, servers.Count)); 48 | } 49 | catch (Exception e) 50 | { 51 | Global.MainForm.NotifyTip($"{i18N.TranslateFormat("Update servers failed from {0}", item.Remark)}\n{e.Message}", info: false); 52 | Log.Warning(e, "Update servers failed"); 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /Netch/Utils/SystemInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Management; 3 | 4 | namespace Netch.Utils; 5 | 6 | public static class SystemInfo 7 | { 8 | public static IEnumerable SystemDrivers(bool allDriver) 9 | { 10 | var mc = new ManagementClass("Win32_SystemDriver"); 11 | foreach (var obj in mc.GetInstances().Cast()) 12 | { 13 | if (!(bool)obj["Started"]) 14 | continue; 15 | 16 | var path = obj["PathName"].ToString(); 17 | if (path == null) 18 | continue; 19 | 20 | var vendorExclude = new[] { "microsoft", "intel", "amd", "nvidia", "realtek" }; 21 | var vendorName = FileVersionInfo.GetVersionInfo(path).LegalCopyright ?? string.Empty; 22 | if (!allDriver && vendorExclude.Any(s => vendorName.Contains(s, StringComparison.OrdinalIgnoreCase))) 23 | continue; 24 | 25 | yield return $"{obj["Caption"]} [{obj["Description"]}]({vendorName})\n\t{obj["PathName"]}"; 26 | } 27 | } 28 | 29 | public static IEnumerable Processes(bool mask) 30 | { 31 | var sortedSet = new SortedSet(); 32 | var windowsFolder = Environment.GetFolderPath(Environment.SpecialFolder.Windows); 33 | var windowsAppsFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "WindowsApps"); 34 | var userProfileFolder = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); 35 | foreach (var process in Process.GetProcesses()) 36 | { 37 | try 38 | { 39 | var path = process.MainModule?.FileName; 40 | if (path == null) 41 | continue; 42 | 43 | if (path.StartsWith(windowsFolder, StringComparison.OrdinalIgnoreCase)) 44 | continue; 45 | 46 | if (path.StartsWith(windowsAppsFolder, StringComparison.OrdinalIgnoreCase)) 47 | continue; 48 | 49 | if (mask) 50 | sortedSet.Add(path.Replace(userProfileFolder, "%USERPROFILE%")); 51 | else 52 | sortedSet.Add(path); 53 | } 54 | catch (Exception) 55 | { 56 | // ignored 57 | } 58 | } 59 | 60 | return sortedSet; 61 | } 62 | } -------------------------------------------------------------------------------- /Netch/runtimeconfig.template.json: -------------------------------------------------------------------------------- 1 | { 2 | "rollForward": "Major" 3 | } -------------------------------------------------------------------------------- /Other/.gitignore: -------------------------------------------------------------------------------- 1 | /release 2 | -------------------------------------------------------------------------------- /Other/.must_build: -------------------------------------------------------------------------------- 1 | 3 -------------------------------------------------------------------------------- /Other/_Archive/build.ps1: -------------------------------------------------------------------------------- 1 | exit 0 -------------------------------------------------------------------------------- /Other/_Archive/chnip/build.ps1: -------------------------------------------------------------------------------- 1 | Set-Location (Split-Path $MyInvocation.MyCommand.Path -Parent) 2 | 3 | try { 4 | Invoke-WebRequest ` 5 | -Uri 'https://raw.githubusercontent.com/17mon/china_ip_list/master/china_ip_list.txt' ` 6 | -OutFile '..\..\release\bin\chnip.txt' 7 | } 8 | catch { 9 | exit 1 10 | } 11 | 12 | exit 0 -------------------------------------------------------------------------------- /Other/_Archive/chnsite/build.ps1: -------------------------------------------------------------------------------- 1 | Set-Location (Split-Path $MyInvocation.MyCommand.Path -Parent) 2 | 3 | try { 4 | Invoke-WebRequest ` 5 | -Uri 'https://raw.githubusercontent.com/felixonmars/dnsmasq-china-list/master/accelerated-domains.china.conf' ` 6 | -OutFile 'chnsite.txt' 7 | } 8 | catch { 9 | exit 1 10 | } 11 | 12 | foreach ( $data in (Get-Content -Path 'chnsite.txt') ) { 13 | $data = $data.Replace('server=/', '') 14 | $data = $data.Replace('/114.114.114.114', '') 15 | $data = $data.Trim() 16 | 17 | if ( $data.Length -gt 0 ) { 18 | Add-Content -Path 'newsite.txt' -Value $data 19 | } 20 | } 21 | 22 | mv -Force 'newsite.txt' '..\..\release\bin\chnsite.txt' 23 | exit 0 -------------------------------------------------------------------------------- /Other/_Archive/cloak/build.ps1: -------------------------------------------------------------------------------- 1 | Set-Location (Split-Path $MyInvocation.MyCommand.Path -Parent) 2 | 3 | git clone https://github.com/cbeuw/Cloak -b 'v2.5.5' src 4 | if ( -Not $? ) { 5 | exit $lastExitCode 6 | } 7 | Set-Location src 8 | 9 | $Env:CGO_ENABLED='0' 10 | $Env:GOROOT_FINAL='/usr' 11 | 12 | $Env:GOOS='windows' 13 | $Env:GOARCH='amd64' 14 | go build -a -trimpath -asmflags '-s -w' -ldflags '-s -w' -o '..\..\release\ck-client.exe' '.\cmd\ck-client' 15 | exit $lastExitCode -------------------------------------------------------------------------------- /Other/_Archive/dnsproxy/build.ps1: -------------------------------------------------------------------------------- 1 | Set-Location (Split-Path $MyInvocation.MyCommand.Path -Parent) 2 | 3 | git clone https://github.com/AdguardTeam/dnsproxy -b 'v0.39.9' src 4 | if ( -Not $? ) { 5 | exit $lastExitCode 6 | } 7 | Set-Location src 8 | 9 | $Env:CGO_ENABLED='0' 10 | $Env:GOROOT_FINAL='/usr' 11 | 12 | $Env:GOOS='windows' 13 | $Env:GOARCH='amd64' 14 | go build -a -trimpath -asmflags '-s -w' -ldflags '-s -w' -o '..\..\release\dnsproxy.exe' 15 | exit $lastExitCode -------------------------------------------------------------------------------- /Other/_Archive/geoip/build.ps1: -------------------------------------------------------------------------------- 1 | Set-Location (Split-Path $MyInvocation.MyCommand.Path -Parent) 2 | 3 | try { 4 | Invoke-WebRequest ` 5 | -Uri 'https://github.com/v2fly/geoip/releases/latest/download/geoip.dat' ` 6 | -OutFile '..\..\release\bin\geoip.dat' 7 | } 8 | catch { 9 | exit 1 10 | } 11 | 12 | exit 0 -------------------------------------------------------------------------------- /Other/_Archive/geosite/build.ps1: -------------------------------------------------------------------------------- 1 | Set-Location (Split-Path $MyInvocation.MyCommand.Path -Parent) 2 | 3 | try { 4 | Invoke-WebRequest ` 5 | -Uri 'https://github.com/v2fly/domain-list-community/releases/latest/download/dlc.dat' ` 6 | -OutFile '..\..\release\bin\geosite.dat' 7 | } 8 | catch { 9 | exit 1 10 | } 11 | 12 | exit 0 -------------------------------------------------------------------------------- /Other/_Archive/tun2socks/build.ps1: -------------------------------------------------------------------------------- 1 | Set-Location (Split-Path $MyInvocation.MyCommand.Path -Parent) 2 | 3 | git clone https://github.com/xjasonlyu/tun2socks -b 'v2.3.2' src 4 | if ( -Not $? ) { 5 | exit $lastExitCode 6 | } 7 | Set-Location src 8 | 9 | $Env:CGO_ENABLED='0' 10 | $Env:GOROOT_FINAL='/usr' 11 | 12 | $Env:GOOS='windows' 13 | $Env:GOARCH='amd64' 14 | go build -a -trimpath -asmflags '-s -w' -ldflags '-s -w' -o '..\..\release\tun2socks.exe' 15 | exit $lastExitCode -------------------------------------------------------------------------------- /Other/_Archive/v2ray-core/build.ps1: -------------------------------------------------------------------------------- 1 | Set-Location (Split-Path $MyInvocation.MyCommand.Path -Parent) 2 | 3 | git clone https://github.com/v2fly/v2ray-core -b 'v4.43.0' src 4 | if ( -Not $? ) { 5 | exit $lastExitCode 6 | } 7 | Set-Location src 8 | 9 | $Env:CGO_ENABLED='0' 10 | $Env:GOROOT_FINAL='/usr' 11 | 12 | $Env:GOOS='windows' 13 | $Env:GOARCH='amd64' 14 | go build -a -trimpath -asmflags '-s -w' -ldflags '-s -w -buildid=' -o '..\..\release\v2ray.exe' '.\main' 15 | if ( -Not $? ) { 16 | exit $lastExitCode 17 | } 18 | 19 | go build -a -trimpath -asmflags '-s -w' -ldflags '-s -w -buildid=' -tags confonly -o '..\..\release\v2ctl.exe' '.\infra\control\main' 20 | if ( -Not $? ) { 21 | exit $lastExitCode 22 | } 23 | 24 | go build -a -trimpath -asmflags '-s -w' -ldflags '-s -w -buildid= -H windowsgui' -o '..\..\release\wv2ray.exe' '.\main' 25 | exit $lastExitCode -------------------------------------------------------------------------------- /Other/_Archive/v2ray-plugin/build.ps1: -------------------------------------------------------------------------------- 1 | Set-Location (Split-Path $MyInvocation.MyCommand.Path -Parent) 2 | 3 | git clone https://github.com/teddysun/v2ray-plugin -b 'v4.43.0' src 4 | if ( -Not $? ) { 5 | exit $lastExitCode 6 | } 7 | Set-Location src 8 | 9 | $Env:CGO_ENABLED='0' 10 | $Env:GOROOT_FINAL='/usr' 11 | 12 | $Env:GOOS='windows' 13 | $Env:GOARCH='amd64' 14 | go build -a -trimpath -asmflags '-s -w' -ldflags '-s -w' -o '..\..\release\v2ray-plugin.exe' 15 | exit $lastExitCode -------------------------------------------------------------------------------- /Other/aiodns/build.ps1: -------------------------------------------------------------------------------- 1 | Set-Location (Split-Path $MyInvocation.MyCommand.Path -Parent) 2 | 3 | $Env:CGO_ENABLED='1' 4 | $Env:GOROOT_FINAL='/usr' 5 | 6 | $Env:GOOS='windows' 7 | $Env:GOARCH='amd64' 8 | go build -a -buildmode=c-shared -trimpath -asmflags '-s -w' -ldflags '-s -w' -o '..\release\aiodns.bin' 9 | exit $lastExitCode 10 | -------------------------------------------------------------------------------- /Other/aiodns/deps.ps1: -------------------------------------------------------------------------------- 1 | Push-Location (Split-Path $MyInvocation.MyCommand.Path -Parent) 2 | 3 | rm -Force go.* 4 | go mod init aiodns 5 | go mod tidy 6 | 7 | Pop-Location 8 | exit $lastExitCode 9 | -------------------------------------------------------------------------------- /Other/aiodns/go.mod: -------------------------------------------------------------------------------- 1 | module aiodns 2 | 3 | go 1.17 4 | 5 | require github.com/miekg/dns v1.1.43 6 | 7 | require ( 8 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect 9 | golang.org/x/sys v0.0.0-20210303074136-134d130e1a04 // indirect 10 | ) 11 | -------------------------------------------------------------------------------- /Other/aiodns/go.sum: -------------------------------------------------------------------------------- 1 | github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= 2 | github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= 3 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= 4 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 5 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= 6 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 7 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 8 | golang.org/x/sys v0.0.0-20210303074136-134d130e1a04 h1:cEhElsAv9LUt9ZUUocxzWe05oFLVd+AA2nstydTeI8g= 9 | golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 10 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 11 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 12 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 13 | -------------------------------------------------------------------------------- /Other/build.ps1: -------------------------------------------------------------------------------- 1 | Push-Location (Split-Path $MyInvocation.MyCommand.Path -Parent) 2 | 3 | .\clean.ps1 4 | 5 | Set-Location (Split-Path $MyInvocation.MyCommand.Path -Parent) 6 | Get-ChildItem -Path '.' -Directory | ForEach-Object { 7 | $name=$_.Name 8 | 9 | if ( Test-Path ".\$name\build.ps1" ) { 10 | Write-Host "Building $name" 11 | 12 | & ".\$name\build.ps1" 13 | if ( -Not $? ) { 14 | Write-Host "Build $name failed" 15 | exit $lastExitCode 16 | } 17 | } 18 | 19 | Set-Location (Split-Path $MyInvocation.MyCommand.Path -Parent) 20 | } 21 | 22 | Set-Location (Split-Path $MyInvocation.MyCommand.Path -Parent) 23 | Get-ChildItem -Path '.' -Directory | ForEach-Object { 24 | $name=$_.Name 25 | 26 | if ( Test-Path ".\$name\src" ) { 27 | rm -Recurse -Force ".\$name\src" 28 | } 29 | 30 | Set-Location (Split-Path $MyInvocation.MyCommand.Path -Parent) 31 | } 32 | 33 | Write-Host 34 | 35 | Set-Location (Split-Path $MyInvocation.MyCommand.Path -Parent) 36 | Get-ChildItem -Path '.\release' -File | ForEach-Object { 37 | $name=$_.Name 38 | $hash=(Get-FileHash ".\release\$name" -Algorithm SHA256).Hash.ToLower() 39 | 40 | Write-Host "$hash $name" 41 | } 42 | 43 | Pop-Location 44 | exit 0 45 | -------------------------------------------------------------------------------- /Other/clean.ps1: -------------------------------------------------------------------------------- 1 | Push-Location (Split-Path $MyInvocation.MyCommand.Path -Parent) 2 | 3 | if ( Test-Path 'build' ) { 4 | rm -Recurse -Force 'build' 5 | } 6 | 7 | if ( Test-Path 'release' ) { 8 | rm -Recurse -Force 'release' 9 | } 10 | 11 | Get-ChildItem -Path '.' -Directory | ForEach-Object { 12 | $name=$_.Name 13 | 14 | if ( Test-Path "$name\src" ) { 15 | rm -Recurse -Force "$name\src" 16 | } 17 | } 18 | 19 | Pop-Location 20 | exit 0 21 | -------------------------------------------------------------------------------- /Other/deps.ps1: -------------------------------------------------------------------------------- 1 | Push-Location (Split-Path $MyInvocation.MyCommand.Path -Parent) 2 | 3 | .\clean.ps1 4 | 5 | Get-ChildItem -Path '.' -Directory | ForEach-Object { 6 | Push-Location (Split-Path $MyInvocation.MyCommand.Path -Parent) 7 | 8 | $name=$_.Name 9 | 10 | if ( Test-Path ".\$name\deps.ps1" ) { 11 | & ".\$name\deps.ps1" 12 | 13 | if ( -Not $? ) { 14 | exit $lastExitCode 15 | } 16 | } 17 | } 18 | 19 | Pop-Location 20 | exit 0 21 | -------------------------------------------------------------------------------- /Other/pcap2socks/build.ps1: -------------------------------------------------------------------------------- 1 | Set-Location (Split-Path $MyInvocation.MyCommand.Path -Parent) 2 | 3 | try { 4 | Invoke-WebRequest ` 5 | -Uri 'https://github.com/zhxie/pcap2socks/releases/download/v0.6.2/pcap2socks-v0.6.2-windows-amd64.zip' ` 6 | -OutFile 'pcap2socks.zip' 7 | Expand-Archive -Force -Path pcap2socks.zip -DestinationPath pcap2socks 8 | } 9 | catch { 10 | exit 1 11 | } 12 | 13 | mv -Force 'pcap2socks\pcap2socks.exe' '..\release\pcap2socks.exe' 14 | exit 0 -------------------------------------------------------------------------------- /Other/wintun/build.ps1: -------------------------------------------------------------------------------- 1 | Set-Location (Split-Path $MyInvocation.MyCommand.Path -Parent) 2 | 3 | try { 4 | Invoke-WebRequest ` 5 | -Uri 'https://www.wintun.net/builds/wintun-0.13.zip' ` 6 | -OutFile 'wintun.zip' 7 | } 8 | catch { 9 | exit 1 10 | } 11 | 12 | 7z x 'wintun.zip' 13 | if ( -Not $? ) { exit $lastExitCode } 14 | 15 | mv -Force 'wintun\bin\amd64\wintun.dll' '..\release\wintun.dll' 16 | 17 | rm -Recurse -Force 'wintun' 18 | rm -Recurse -Force 'wintun.zip' 19 | exit 0 -------------------------------------------------------------------------------- /Other/xray-core/build.ps1: -------------------------------------------------------------------------------- 1 | Set-Location (Split-Path $MyInvocation.MyCommand.Path -Parent) 2 | 3 | git clone https://github.com/xtls/xray-core -b 'v1.8.7' src 4 | if ( -Not $? ) { 5 | exit $lastExitCode 6 | } 7 | Set-Location src 8 | 9 | $Env:CGO_ENABLED='0' 10 | $Env:GOROOT_FINAL='/usr' 11 | 12 | $Env:GOOS='windows' 13 | $Env:GOARCH='amd64' 14 | go build -a -trimpath -asmflags '-s -w' -ldflags '-s -w -buildid=' -o '..\..\release\xray.exe' '.\main' 15 | exit $lastExitCode 16 | -------------------------------------------------------------------------------- /Other/xray-plugin/build.ps1: -------------------------------------------------------------------------------- 1 | Set-Location (Split-Path $MyInvocation.MyCommand.Path -Parent) 2 | 3 | git clone https://github.com/teddysun/xray-plugin -b 'v1.8.7' src 4 | if ( -Not $? ) { 5 | exit $lastExitCode 6 | } 7 | Set-Location src 8 | 9 | $Env:CGO_ENABLED='0' 10 | $Env:GOROOT_FINAL='/usr' 11 | 12 | $Env:GOOS='windows' 13 | $Env:GOARCH='amd64' 14 | go build -a -trimpath -asmflags '-s -w' -ldflags '-s -w' -o '..\..\release\xray-plugin.exe' 15 | exit $lastExitCode 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `In preparation for 2.0, this repository will be cleared of all 1.0 related releases and code` 2 |

3 | 4 |
5 | 6 | # Netch 7 | A simple proxy client 8 | 9 | [![](https://img.shields.io/badge/telegram-group-green?style=flat-square)](https://t.me/netch_group) 10 | [![](https://img.shields.io/badge/telegram-channel-blue?style=flat-square)](https://t.me/netch_channel) 11 | [![](https://img.shields.io/github/downloads/netchx/netch/total.svg?style=flat-square)](https://github.com/netchx/netch/releases) 12 | [![](https://img.shields.io/github/v/release/netchx/netch?style=flat-square)](https://github.com/netchx/netch/releases) 13 |
14 | 15 | ## Features 16 | Some features may not be implemented in version 1 17 | 18 | ### Modes 19 | - `ProcessMode` - Use Netfilter driver to intercept process traffic 20 | - `ShareMode` - Share your network based on WinPcap / Npcap 21 | - `TunMode` - Use WinTUN driver to create virtual adapter 22 | - `WebMode` - Web proxy mode 23 | 24 | ### Protocols 25 | - [`Socks5`](https://www.wikiwand.com/en/SOCKS) 26 | - [`Shadowsocks`](https://shadowsocks.org) 27 | - [`ShadowsocksR`](https://github.com/shadowsocksrr/shadowsocksr-libev) 28 | - [`WireGuard`](https://www.wireguard.com) 29 | - [`Trojan`](https://trojan-gfw.github.io/trojan) 30 | - [`VMess`](https://www.v2fly.org) 31 | - [`VLESS`](https://xtls.github.io) 32 | 33 | ### Others 34 | - UDP NAT FullCone (Limited by your server) 35 | - .NET 6.0 x64 36 | 37 | ## Sponsor 38 | JetBrains 39 | 40 | ## License 41 | Netch is licensed under the [GPLv3](https://raw.githubusercontent.com/netchx/netch/main/LICENSE) license 42 | -------------------------------------------------------------------------------- /Redirector/.gitignore: -------------------------------------------------------------------------------- 1 | /bin 2 | /obj 3 | /*.vcxproj.user 4 | -------------------------------------------------------------------------------- /Redirector/.must_build: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /Redirector/Based.cpp: -------------------------------------------------------------------------------- 1 | #include "Based.h" 2 | 3 | bool filterLoopback = false; 4 | bool filterIntranet = false; 5 | bool filterParent = false; 6 | bool filterICMP = true; 7 | bool filterTCP = true; 8 | bool filterUDP = true; 9 | bool filterDNS = true; 10 | 11 | DWORD icmping = 0; 12 | 13 | bool dnsOnly = false; 14 | bool dnsProx = true; 15 | string dnsHost = "1.1.1.1"; 16 | USHORT dnsPort = 53; 17 | 18 | wstring tgtHost = L"127.0.0.1"; 19 | wstring tgtPort = L"1080"; 20 | string tgtUsername = ""; 21 | string tgtPassword = ""; 22 | 23 | vector bypassList; 24 | vector handleList; 25 | -------------------------------------------------------------------------------- /Redirector/Based.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef BASED_H 3 | #define BASED_H 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | 26 | using namespace std; 27 | 28 | typedef enum _AIO_TYPE { 29 | AIO_FILTERLOOPBACK, 30 | AIO_FILTERINTRANET, 31 | AIO_FILTERPARENT, 32 | AIO_FILTERICMP, 33 | AIO_FILTERTCP, 34 | AIO_FILTERUDP, 35 | AIO_FILTERDNS, 36 | 37 | AIO_ICMPING, 38 | 39 | AIO_DNSONLY, 40 | AIO_DNSPROX, 41 | AIO_DNSHOST, 42 | AIO_DNSPORT, 43 | 44 | AIO_TGTHOST, 45 | AIO_TGTPORT, 46 | AIO_TGTUSER, 47 | AIO_TGTPASS, 48 | 49 | AIO_CLRNAME, 50 | AIO_ADDNAME, 51 | AIO_BYPNAME 52 | } AIO_TYPE; 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /Redirector/DNSHandler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef DNSHANDLER_H 3 | #define DNSHANDLER_H 4 | #include "Based.h" 5 | 6 | namespace DNSHandler 7 | { 8 | bool INIT(); 9 | 10 | bool IsDNS(PSOCKADDR_IN6 target); 11 | 12 | void CreateHandler(ENDPOINT_ID id, PSOCKADDR_IN6 target, const char* packet, int length, PNF_UDP_OPTIONS options); 13 | } 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /Redirector/EventHandler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef EVENTHANDLER_H 3 | #define EVENTHANDLER_H 4 | #include "Based.h" 5 | #include "SocksHelper.h" 6 | 7 | bool eh_init(); 8 | void eh_free(); 9 | 10 | void threadStart(); 11 | void threadEnd(); 12 | void tcpConnectRequest(ENDPOINT_ID id, PNF_TCP_CONN_INFO info); 13 | void tcpConnected(ENDPOINT_ID id, PNF_TCP_CONN_INFO info); 14 | void tcpCanSend(ENDPOINT_ID id); 15 | void tcpSend(ENDPOINT_ID id, const char* buffer, int length); 16 | void tcpCanReceive(ENDPOINT_ID id); 17 | void tcpReceive(ENDPOINT_ID id, const char* buffer, int length); 18 | void tcpClosed(ENDPOINT_ID id, PNF_TCP_CONN_INFO info); 19 | void udpCreated(ENDPOINT_ID id, PNF_UDP_CONN_INFO info); 20 | void udpConnectRequest(ENDPOINT_ID id, PNF_UDP_CONN_REQUEST info); 21 | void udpCanSend(ENDPOINT_ID id); 22 | void udpSend(ENDPOINT_ID id, const unsigned char* target, const char* buffer, int length, PNF_UDP_OPTIONS options); 23 | void udpCanReceive(ENDPOINT_ID id); 24 | void udpReceive(ENDPOINT_ID id, const unsigned char* target, const char* buffer, int length, PNF_UDP_OPTIONS options); 25 | void udpClosed(ENDPOINT_ID id, PNF_UDP_CONN_INFO info); 26 | 27 | void udpReceiveHandler(ENDPOINT_ID id, SocksHelper::PUDP remote, PNF_UDP_OPTIONS options); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /Redirector/IPEventHandler.cpp: -------------------------------------------------------------------------------- 1 | #include "IPEventHandler.h" 2 | 3 | extern DWORD icmping; 4 | 5 | USHORT IPv4Checksum(PBYTE buffer, ULONG64 size) 6 | { 7 | UINT32 sum = 0; 8 | for (int i = 0; i < size; i += 2) 9 | { 10 | sum += (buffer[i] << 8) + buffer[i + 1]; 11 | } 12 | 13 | if ((size % 2) == 1) 14 | { 15 | sum += buffer[size - 1] << 8; 16 | } 17 | 18 | while (sum > 0xffff) 19 | { 20 | sum = (sum >> 16) + (sum & 0xffff); 21 | } 22 | 23 | return ~sum & 0xffff; 24 | } 25 | 26 | USHORT ICMPChecksum(PBYTE buffer, ULONG64 size) 27 | { 28 | UINT32 sum = 0; 29 | for (int i = 0; i < size; i += 2) 30 | { 31 | sum += buffer[i] + (buffer[i + 1] << 8); 32 | } 33 | 34 | if ((size % 2) == 1) 35 | { 36 | sum += buffer[size - 1]; 37 | } 38 | 39 | sum = (sum >> 16) + (sum & 0xffff); 40 | sum += (sum >> 16); 41 | 42 | return ~sum & 0xffff; 43 | } 44 | 45 | void ipSend(const char* buffer, int length, PNF_IP_PACKET_OPTIONS options) 46 | { 47 | if (options->ip_family != AF_INET || 48 | options->ipHeaderSize != 20 || 49 | length < 28 || 50 | buffer[options->ipHeaderSize] != 0x08) 51 | { 52 | nf_ipPostSend(buffer, length, options); 53 | return; 54 | } 55 | 56 | auto data = new BYTE[length](); 57 | memcpy(data, buffer, length); 58 | 59 | { 60 | BYTE src[4]; 61 | BYTE dst[4]; 62 | memcpy(src, data + 12, 4); 63 | memcpy(dst, data + 16, 4); 64 | memcpy(data + 12, dst, 4); 65 | memcpy(data + 16, src, 4); 66 | } 67 | 68 | data[10] = 0x00; 69 | data[11] = 0x00; 70 | auto ipv4sum = IPv4Checksum(data, options->ipHeaderSize); 71 | data[10] = (ipv4sum >> 8); 72 | data[11] = ipv4sum & 0xff; 73 | 74 | data[options->ipHeaderSize] = 0x00; 75 | data[options->ipHeaderSize + 2] = 0x00; 76 | data[options->ipHeaderSize + 3] = 0x00; 77 | auto icmpsum = ICMPChecksum(data + options->ipHeaderSize, (ULONG64)length - options->ipHeaderSize); 78 | data[options->ipHeaderSize + 2] = icmpsum & 0xff; 79 | data[options->ipHeaderSize + 3] = (icmpsum >> 8); 80 | 81 | if (icmping > 0) 82 | this_thread::sleep_for(chrono::milliseconds(icmping)); 83 | printf("[Redirector][IPEventHandler][ipSend] Fake ICMP response for %d.%d.%d.%d\n", data[12], data[13], data[14], data[15]); 84 | 85 | nf_ipPostReceive((char*)data, length, options); 86 | delete[] data; 87 | } 88 | 89 | void ipReceive(const char* buffer, int length, PNF_IP_PACKET_OPTIONS options) 90 | { 91 | nf_ipPostReceive(buffer, length, options); 92 | } 93 | -------------------------------------------------------------------------------- /Redirector/IPEventHandler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef IPEVENTHANDLER_H 3 | #define IPEVENTHANDLER_H 4 | #include "Based.h" 5 | 6 | void ipSend(const char* buffer, int length, PNF_IP_PACKET_OPTIONS options); 7 | void ipReceive(const char* buffer, int length, PNF_IP_PACKET_OPTIONS options); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /Redirector/README.md: -------------------------------------------------------------------------------- 1 | # Redirector 2 | ```c++ 3 | typedef enum _AIO_TYPE { 4 | AIO_FILTERLOOPBACK, 5 | AIO_FILTERINTRANET, 6 | AIO_FILTERPARENT, 7 | AIO_FILTERICMP, 8 | AIO_FILTERTCP, 9 | AIO_FILTERUDP, 10 | AIO_FILTERDNS, 11 | 12 | AIO_ICMPING, 13 | 14 | AIO_DNSONLY, 15 | AIO_DNSPROX, 16 | AIO_DNSHOST, 17 | AIO_DNSPORT, 18 | 19 | AIO_TGTHOST, 20 | AIO_TGTPORT, 21 | AIO_TGTUSER, 22 | AIO_TGTPASS, 23 | 24 | AIO_CLRNAME, 25 | AIO_ADDNAME, 26 | AIO_BYPNAME 27 | } AIO_TYPE; 28 | 29 | __declspec(dllexport) BOOL __cdecl aio_register(LPWSTR value); 30 | __declspec(dllexport) BOOL __cdecl aio_unregister(LPWSTR value); 31 | __declspec(dllexport) BOOL __cdecl aio_dial(int name, LPWSTR value); 32 | __declspec(dllexport) BOOL __cdecl aio_init(); 33 | __declspec(dllexport) void __cdecl aio_free(); 34 | __declspec(dllexport) ULONG64 __cdecl aio_getUP(); 35 | __declspec(dllexport) ULONG64 __cdecl aio_getDL(); 36 | ``` 37 | 38 | ```c# 39 | private enum NameList : int 40 | { 41 | AIO_FILTERLOOPBACK, 42 | AIO_FILTERINTRANET, 43 | AIO_FILTERPARENT, 44 | AIO_FILTERICMP, 45 | AIO_FILTERTCP, 46 | AIO_FILTERUDP, 47 | AIO_FILTERDNS, 48 | 49 | AIO_ICMPING, 50 | 51 | AIO_DNSONLY, 52 | AIO_DNSPROX, 53 | AIO_DNSHOST, 54 | AIO_DNSPORT, 55 | 56 | AIO_TGTHOST, 57 | AIO_TGTPORT, 58 | AIO_TGTUSER, 59 | AIO_TGTPASS, 60 | 61 | AIO_CLRNAME, 62 | AIO_ADDNAME, 63 | AIO_BYPNAME 64 | } 65 | 66 | [DllImport("Redirector.bin", CallingConvention = CallingConvention.Cdecl)] 67 | public static extern bool aio_register([MarshalAs(UnmanagedType.LPWStr)] string value); 68 | 69 | [DllImport("Redirector.bin", CallingConvention = CallingConvention.Cdecl)] 70 | public static extern bool aio_unregister([MarshalAs(UnmanagedType.LPWStr)] string value); 71 | 72 | [DllImport("Redirector.bin", CallingConvention = CallingConvention.Cdecl)] 73 | public static extern bool aio_dial(NameList name, [MarshalAs(UnmanagedType.LPWStr)] string value); 74 | 75 | [DllImport("Redirector.bin", CallingConvention = CallingConvention.Cdecl)] 76 | public static extern bool aio_init(); 77 | 78 | [DllImport("Redirector.bin", CallingConvention = CallingConvention.Cdecl)] 79 | public static extern void aio_free(); 80 | 81 | [DllImport("Redirector.bin", CallingConvention = CallingConvention.Cdecl)] 82 | public static extern ulong aio_getUP(); 83 | 84 | [DllImport("Redirector.bin", CallingConvention = CallingConvention.Cdecl)] 85 | public static extern ulong aio_getDL(); 86 | ``` 87 | -------------------------------------------------------------------------------- /Redirector/Redirector.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 6 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 7 | 8 | 9 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 10 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 11 | 12 | 13 | 14 | 15 | Source 16 | 17 | 18 | Source 19 | 20 | 21 | Source 22 | 23 | 24 | Source 25 | 26 | 27 | Source 28 | 29 | 30 | Source 31 | 32 | 33 | Source 34 | 35 | 36 | Source 37 | 38 | 39 | 40 | 41 | Header 42 | 43 | 44 | Header 45 | 46 | 47 | Header 48 | 49 | 50 | Header 51 | 52 | 53 | Header 54 | 55 | 56 | Header 57 | 58 | 59 | Header 60 | 61 | 62 | -------------------------------------------------------------------------------- /Redirector/SocksHelper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef SOCKSHELPER_H 3 | #define SOCKSHELPER_H 4 | #include "Based.h" 5 | 6 | namespace SocksHelper 7 | { 8 | SOCKET Connect(); 9 | bool Handshake(SOCKET client); 10 | bool SplitAddr(SOCKET client, PSOCKADDR_IN6 addr); 11 | 12 | typedef class TCP 13 | { 14 | public: 15 | ~TCP(); 16 | 17 | bool Connect(PSOCKADDR_IN6 target); 18 | 19 | int Send(const char* buffer, int length); 20 | int Read(char* buffer, int length); 21 | 22 | SOCKET tcpSocket = INVALID_SOCKET; 23 | } *PTCP; 24 | 25 | typedef class UDP 26 | { 27 | public: 28 | ~UDP(); 29 | 30 | static void Run(SOCKET tcpSocket, SOCKET udpSocket); 31 | 32 | bool Associate(); 33 | bool CreateUDP(); 34 | 35 | int Send(PSOCKADDR_IN6 target, const char* buffer, int length); 36 | int Read(PSOCKADDR_IN6 target, char* buffer, int length, PTIMEVAL timeout); 37 | 38 | SOCKET tcpSocket = INVALID_SOCKET; 39 | SOCKET udpSocket = INVALID_SOCKET; 40 | 41 | SOCKADDR_IN6 address = { 0 }; 42 | } *PUDP; 43 | }; 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /Redirector/TCPHandler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef TCPHANDLER_H 3 | #define TCPHANDLER_H 4 | #include "Based.h" 5 | #include "SocksHelper.h" 6 | 7 | namespace TCPHandler 8 | { 9 | bool INIT(); 10 | void FREE(); 11 | 12 | void CreateHandler(SOCKADDR_IN6 client, SOCKADDR_IN6 remote); 13 | void DeleteHandler(SOCKADDR_IN6 client); 14 | 15 | void Accept(); 16 | void Handle(SOCKET client); 17 | 18 | void Read(SOCKET client, SocksHelper::PTCP remote); 19 | void Send(SOCKET client, SocksHelper::PTCP remote); 20 | } 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /Redirector/Utils.cpp: -------------------------------------------------------------------------------- 1 | #include "Utils.h" 2 | 3 | string ws2s(wstring str) 4 | { 5 | auto length = WideCharToMultiByte(CP_ACP, 0, str.c_str(), static_cast(str.length()), NULL, 0, NULL, NULL); 6 | auto buffer = new char[length + 1](); 7 | 8 | WideCharToMultiByte(CP_ACP, 0, str.c_str(), static_cast(str.length()), buffer, length, NULL, NULL); 9 | 10 | auto data = string(buffer); 11 | delete[] buffer; 12 | 13 | return data; 14 | } 15 | 16 | wstring s2ws(string str) 17 | { 18 | auto length = MultiByteToWideChar(CP_ACP, 0, str.c_str(), static_cast(str.length()), NULL, 0); 19 | auto buffer = new wchar_t[length + 1](); 20 | 21 | MultiByteToWideChar(CP_ACP, 0, str.c_str(), static_cast(str.length()), buffer, length); 22 | 23 | auto data = wstring(buffer); 24 | delete[] buffer; 25 | 26 | return data; 27 | } 28 | -------------------------------------------------------------------------------- /Redirector/Utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef UTILS_H 3 | #define UTILS_H 4 | #include "Based.h" 5 | 6 | string ws2s(wstring str); 7 | wstring s2ws(string str); 8 | #endif 9 | -------------------------------------------------------------------------------- /Redirector/lib/nfapi.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarflows/netch/1b3559051c420173be3d23ad5540685f91f00be8/Redirector/lib/nfapi.lib -------------------------------------------------------------------------------- /Redirector/static/nfapi.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarflows/netch/1b3559051c420173be3d23ad5540685f91f00be8/Redirector/static/nfapi.dll -------------------------------------------------------------------------------- /RedirectorTester/.gitignore: -------------------------------------------------------------------------------- 1 | /bin 2 | /obj 3 | /*.csproj.user 4 | -------------------------------------------------------------------------------- /RedirectorTester/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /RedirectorTester/App.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /RedirectorTester/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // 有关程序集的一般信息由以下 5 | // 控制。更改这些特性值可修改 6 | // 与程序集关联的信息。 7 | [assembly: AssemblyTitle("RedirectorTester")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("RedirectorTester")] 12 | [assembly: AssemblyCopyright("Copyright © 2021")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // 将 ComVisible 设置为 false 会使此程序集中的类型 17 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 18 | //请将此类型的 ComVisible 特性设置为 true。 19 | [assembly: ComVisible(false)] 20 | 21 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 22 | [assembly: Guid("9142c528-9e42-448d-96b6-7e62e47b54f3")] 23 | 24 | // 程序集的版本信息由下列四个值组成: 25 | // 26 | // 主版本 27 | // 次版本 28 | // 生成号 29 | // 修订号 30 | // 31 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 32 | //通过使用 "*",如下所示: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /RouteHelper/.gitignore: -------------------------------------------------------------------------------- 1 | /bin 2 | /obj 3 | /*.vcxproj.user 4 | -------------------------------------------------------------------------------- /RouteHelper/.must_build: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /RouteHelper/Based.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef BASED_H 3 | #define BASED_H 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #endif 16 | -------------------------------------------------------------------------------- /RouteHelper/README.md: -------------------------------------------------------------------------------- 1 | # RouteHelper 2 | ```cpp 3 | ULONG ConvertLuidToIndex(ULONG64 id); 4 | void WaitForUnicastIP(); 5 | BOOL CreateIPv4(const char* address, const char* netmask, ULONG index); 6 | BOOL CreateUnicastIP(USHORT inet, const char* address, UINT8 cidr, ULONG index); 7 | BOOL CreateRoute(USHORT inet, const char* address, UINT8 cidr, const char* gateway, ULONG index, ULONG metric); 8 | BOOL DeleteRoute(USHORT inet, const char* address, UINT8 cidr, const char* gateway, ULONG index, ULONG metric); 9 | ``` 10 | 11 | ```csharp 12 | [DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)] 13 | public static extern uint ConvertLuidToIndex(ulong id); 14 | 15 | [DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)] 16 | public static extern void WaitForUnicastIP(); 17 | 18 | [DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)] 19 | public static extern bool CreateIPv4(string address, string netmask, uint index); 20 | 21 | [DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)] 22 | public static extern bool CreateUnicastIP(AddressFamily inet, string address, byte cidr, uint index); 23 | 24 | [DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)] 25 | public static extern bool CreateRoute(AddressFamily inet, string address, byte cidr, string gateway, uint index, uint metric); 26 | 27 | [DllImport("RouteHelper.bin", CallingConvention = CallingConvention.Cdecl)] 28 | public static extern bool CreateRoute(AddressFamily inet, string address, byte cidr, string gateway, uint index, uint metric); 29 | ``` 30 | -------------------------------------------------------------------------------- /RouteHelper/RouteHelper.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 6 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 7 | 8 | 9 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 10 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 11 | 12 | 13 | 14 | 15 | Source 16 | 17 | 18 | Source 19 | 20 | 21 | 22 | 23 | Header 24 | 25 | 26 | Header 27 | 28 | 29 | -------------------------------------------------------------------------------- /RouteHelper/WaitGroup.cpp: -------------------------------------------------------------------------------- 1 | #include "WaitGroup.h" 2 | 3 | void WaitGroup::Add(int size) 4 | { 5 | this->counter += size; 6 | } 7 | 8 | void WaitGroup::Done() 9 | { 10 | if (--this->counter <= 0) 11 | this->condition.notify_all(); 12 | } 13 | 14 | void WaitGroup::Wait() 15 | { 16 | std::unique_lock lock(this->mutex); 17 | 18 | condition.wait(lock, [&] { return counter <= 0; }); 19 | } 20 | -------------------------------------------------------------------------------- /RouteHelper/WaitGroup.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef WAITGROUP_H 3 | #define WAITGROUP_H 4 | #include "Based.h" 5 | 6 | class WaitGroup { 7 | public: 8 | void Add(int size); 9 | void Done(); 10 | void Wait(); 11 | 12 | private: 13 | std::mutex mutex; 14 | std::atomic_int counter; 15 | std::condition_variable condition; 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /Storage/README.md: -------------------------------------------------------------------------------- 1 | # Netch 2 | Prebuilt binaries for Netch version 1 3 | 4 | ## aiodns 5 | https://github.com/netchx/netch 6 | 7 | ## Redirector 8 | https://github.com/netchx/netch 9 | 10 | ## RouteHelper 11 | https://github.com/netchx/netch 12 | 13 | ## ck-client 14 | https://github.com/cbeuw/Cloak 15 | 16 | ## GeoLite2 17 | https://www.maxmind.com 18 | 19 | ## xray-core 20 | https://github.com/xtls/xray-core 21 | 22 | ## shadowsocks-libev 23 | https://github.com/shadowsocks/shadowsocks-rust 24 | 25 | ## shadowsocksr-libev 26 | https://github.com/shadowsocksrr/shadowsocksr-libev 27 | 28 | ## simple-obfs 29 | https://github.com/shadowsocks/simple-obfs 30 | 31 | ## tun2socks 32 | https://github.com/xjasonlyu/tun2socks 33 | 34 | ## v2ray-plugin 35 | https://github.com/teddysun/v2ray-plugin 36 | 37 | ## WinTUN 38 | https://www.wintun.net 39 | -------------------------------------------------------------------------------- /Storage/mode/Battlenet.txt: -------------------------------------------------------------------------------- 1 | # Battle 2 | Battle.net Launcher.exe 3 | BlizzardError.exe 4 | Loader64.exe 5 | SystemSurvey.exe 6 | Battle.net.exe 7 | Agent.exe -------------------------------------------------------------------------------- /Storage/mode/Bypass LAN and Vivox.txt: -------------------------------------------------------------------------------- 1 | # Bypass LAN and Vivox, 2 2 | 10.0.0.0/8 3 | 172.16.0.0/16 4 | 192.168.0.0/16 5 | 74.201.106.0/24 -------------------------------------------------------------------------------- /Storage/mode/Bypass LAN.txt: -------------------------------------------------------------------------------- 1 | # Bypass LAN, 2 2 | 10.0.0.0/8 3 | 172.16.0.0/16 4 | 192.168.0.0/16 -------------------------------------------------------------------------------- /Storage/mode/Discord (with Steam Apps).txt: -------------------------------------------------------------------------------- 1 | # Discord (with Steam Apps), 0 2 | Discord 3 | \\steamapps\\ -------------------------------------------------------------------------------- /Storage/mode/Discord.txt: -------------------------------------------------------------------------------- 1 | # Discord, 0 2 | Discord 3 | -------------------------------------------------------------------------------- /Storage/mode/EA Desktop Games (with EA Desktop).txt: -------------------------------------------------------------------------------- 1 | # EA Desktop Games (with EA Desktop), 0 2 | \\EA Games\\ 3 | EABackgroundService.exe 4 | EAConnect_microsoft.exe 5 | EACrashReporter.exe 6 | EADesktop.exe 7 | EAGEP.exe 8 | EALauncher.exe 9 | EALaunchHelper.exe 10 | EALocalHostSvc.exe 11 | ErrorReporter.exe 12 | GetGameToken32.exe 13 | GetGameToken64.exe 14 | IGOProxy32.exe 15 | OriginLegacyCompatibility.exe 16 | QtWebEngineProcess.exe -------------------------------------------------------------------------------- /Storage/mode/EA Desktop Games.txt: -------------------------------------------------------------------------------- 1 | # EA Desktop Games, 0 2 | \\EA Games\\ -------------------------------------------------------------------------------- /Storage/mode/EA Desktop.txt: -------------------------------------------------------------------------------- 1 | # EA Desktop, 0 2 | EABackgroundService.exe 3 | EAConnect_microsoft.exe 4 | EACrashReporter.exe 5 | EADesktop.exe 6 | EAGEP.exe 7 | EALauncher.exe 8 | EALaunchHelper.exe 9 | EALocalHostSvc.exe 10 | ErrorReporter.exe 11 | GetGameToken32.exe 12 | GetGameToken64.exe 13 | IGOProxy32.exe 14 | OriginLegacyCompatibility.exe 15 | QtWebEngineProcess.exe -------------------------------------------------------------------------------- /Storage/mode/Game/Age of Empires IV.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "ProcessMode", 3 | "remark": { 4 | "zh-CN": "Age of Empires IV" 5 | }, 6 | "handle": [ 7 | "RelicCardinal_ws.exe" 8 | ], 9 | "bypass": [], 10 | "filterIntranet": true, 11 | "filterLoopback": true, 12 | "dnsHost": "1.1.1.1:53", 13 | "handleOnlyDNS": false, 14 | "icmpDelay": 10, 15 | "filterParent": null, 16 | "filterDNS": false, 17 | "filterUDP": null, 18 | "filterTCP": null, 19 | "filterICMP": false, 20 | "dnsProxy": null 21 | } -------------------------------------------------------------------------------- /Storage/mode/Game/COD18.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "ProcessMode", 3 | "remark": { 4 | "zh-CN": "COD18" 5 | }, 6 | "handle": [ 7 | "\\\\Battlestate Games\\\\", 8 | "\\\\Battle.net\\\\" 9 | ], 10 | "bypass": [], 11 | "filterIntranet": true, 12 | "filterLoopback": false, 13 | "dnsHost": "1.1.1.1:53", 14 | "handleOnlyDNS": null, 15 | "icmpDelay": 100, 16 | "filterParent": true, 17 | "filterDNS": null, 18 | "filterUDP": null, 19 | "filterTCP": null, 20 | "filterICMP": true, 21 | "dnsProxy": null 22 | } -------------------------------------------------------------------------------- /Storage/mode/Game/Cube 2 Sauerbraten.txt: -------------------------------------------------------------------------------- 1 | # Cube 2: Sauerbraten 2 | sauerbraten.exe -------------------------------------------------------------------------------- /Storage/mode/Game/CyberDuck.txt: -------------------------------------------------------------------------------- 1 | # CyberDuck, 0 2 | Cyberduck.exe -------------------------------------------------------------------------------- /Storage/mode/Game/DLsite PlayDRM.txt: -------------------------------------------------------------------------------- 1 | # DLsite PlayDRM, 0 2 | startup.exe 3 | -------------------------------------------------------------------------------- /Storage/mode/Game/EVE Online.txt: -------------------------------------------------------------------------------- 1 | # EVE Online, 0 2 | eve.exe 3 | exefile.exe 4 | LogServer.exe 5 | evelauncher.exe 6 | fixpermissions.exe 7 | LogLite.exe 8 | QtWebEngineProcess.exe 9 | updater.exe -------------------------------------------------------------------------------- /Storage/mode/Game/Escape From Tarkov.txt: -------------------------------------------------------------------------------- 1 | # Escape From Tarkov, 0 2 | EscapeFromTarkov.exe 3 | EscapeFromTarkov_BE.exe 4 | BsgLauncher.exe 5 | -------------------------------------------------------------------------------- /Storage/mode/Game/Etterna.txt: -------------------------------------------------------------------------------- 1 | # Etterna 2 | Etterna.exe -------------------------------------------------------------------------------- /Storage/mode/Game/Faceit AC.txt: -------------------------------------------------------------------------------- 1 | # Faceit AC, 0 2 | faceitclient.exe 3 | faceitservice.exe -------------------------------------------------------------------------------- /Storage/mode/Game/ForzaHorizon 4.txt: -------------------------------------------------------------------------------- 1 | # ForzaHorizon 4 2 | ForzaHorizon4.exe 3 | XboxApp.exe -------------------------------------------------------------------------------- /Storage/mode/Game/Grand Theft Auto V.txt: -------------------------------------------------------------------------------- 1 | # Grand Theft Auto V, 0, 0 2 | \\Rockstar Games\\ 3 | \\Grand Theft Auto V\\ 4 | -------------------------------------------------------------------------------- /Storage/mode/Game/Halo The Master Chief Collection.txt: -------------------------------------------------------------------------------- 1 | # Halo The Master Chief Collection 2 | mcclauncher.exe 3 | MCC-Win64-Shipping.exe 4 | easyanticheat_setup.exe 5 | UnrealCEFSubProcess.exe -------------------------------------------------------------------------------- /Storage/mode/Game/League of Legends (Japan) (with Riot Games).txt: -------------------------------------------------------------------------------- 1 | # League of Legends (Japan) (with Riot Games), 0 2 | jpatch.exe 3 | RiotClientCrashHandler.exe 4 | RiotClientServices.exe 5 | RiotClientUx.exe 6 | RiotClientUxRender.exe 7 | BsSndRpt.exe 8 | LeagueClient.exe 9 | LeagueClientUx.exe 10 | LeagueClientUxRender.exe 11 | Uninstall League of Legends.exe 12 | League of Legends.exe 13 | LeagueCrashHandler.exe -------------------------------------------------------------------------------- /Storage/mode/Game/League of Legends (Taiwan) (with Garena).txt: -------------------------------------------------------------------------------- 1 | # League of Legends (Taiwan) (with Garena) 2 | wow_helper.exe 3 | CrashReporter.exe 4 | GarenaTV.exe 5 | gxxapphelper.exe 6 | gxxcef.exe 7 | gxxsvc.exe 8 | gxxsvcrev.exe 9 | gxxupdate.exe 10 | overlayhelper.exe 11 | capturehelper.exe 12 | uninst.exe 13 | voiceassist.exe 14 | Garena.exe 15 | BsSndRpt.exe 16 | League of Legends.exe 17 | LeagueCrashHandler.exe 18 | jpatch.exe 19 | LeagueClient.exe 20 | LeagueClientUx.exe 21 | LeagueClientUxRender.exe -------------------------------------------------------------------------------- /Storage/mode/Game/League of Legends (US).txt: -------------------------------------------------------------------------------- 1 | # League of Legends (US), 0 2 | BsSndRpt.exe 3 | jpatch.exe 4 | LeagueClient.exe 5 | LeagueClientUx.exe 6 | LeagueClientUxRender.exe 7 | Uninstall League of Legends.exe 8 | League of Legends.exe 9 | LeagueCrashHandler.exe 10 | RiotClientServices.exe 11 | RiotClientUx.exe 12 | RiotClientUxRender.exe 13 | RiotClientCrashHandler.exe 14 | -------------------------------------------------------------------------------- /Storage/mode/Game/Minecraft (Java).txt: -------------------------------------------------------------------------------- 1 | # Minecraft (Java) 2 | javaw.exe 3 | java.exe 4 | MinecraftLauncher.exe -------------------------------------------------------------------------------- /Storage/mode/Game/Minecraft Bedrock (Win10 UWP).txt: -------------------------------------------------------------------------------- 1 | # Minecraft Bedrock (Win10 UWP) 2 | Minecraft.Windows.exe -------------------------------------------------------------------------------- /Storage/mode/Game/Multi Theft Auto (MTA).txt: -------------------------------------------------------------------------------- 1 | # Multi Theft Auto (MTA), 0 2 | gta_sa.exe 3 | CEFLauncher.exe 4 | wow64_helper.exe 5 | MTA Server.exe 6 | Multi Theft Auto.exe 7 | -------------------------------------------------------------------------------- /Storage/mode/Game/OSU.txt: -------------------------------------------------------------------------------- 1 | # osu! 2 | osu!.exe -------------------------------------------------------------------------------- /Storage/mode/Game/PVZ Battle for Neighborville.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "ProcessMode", 3 | "remark": { 4 | "zh-CN": "PVZ Battle for Neighborville" 5 | }, 6 | "handle": [ 7 | "PVZ Battle for Neighborville" 8 | ], 9 | "bypass": [], 10 | "filterIntranet": true, 11 | "filterLoopback": false, 12 | "dnsHost": "1.1.1.1:53", 13 | "handleOnlyDNS": null, 14 | "icmpDelay": 10, 15 | "filterParent": null, 16 | "filterDNS": null, 17 | "filterUDP": null, 18 | "filterTCP": null, 19 | "filterICMP": null, 20 | "dnsProxy": null 21 | } -------------------------------------------------------------------------------- /Storage/mode/Game/PlayerUnknown's Battlegrounds Lite.txt: -------------------------------------------------------------------------------- 1 | # PlayerUnknown's Battlegrounds Lite 2 | CefSharp.BrowserSubprocess.exe 3 | UE4PrereqSetup_x64.exe 4 | PUBGLite.exe 5 | BroCrashReporter.exe 6 | PUBGLite-Win64-Shipping.exe 7 | ucldr_bgl_se.exe 8 | ucsvc.exe 9 | \\Launcher.exe 10 | \\LauncherAgent.exe 11 | unins000.exe -------------------------------------------------------------------------------- /Storage/mode/Game/RAGE Multiplayer.txt: -------------------------------------------------------------------------------- 1 | # RAGE Multiplayer, 0 2 | cef_process.exe 3 | ragemp_game_ui.exe 4 | ragemp_ui.exe 5 | ragemp-server.exe 6 | ragemp_v.exe 7 | updater.exe 8 | GTA5.exe 9 | PlayGTAV.exe -------------------------------------------------------------------------------- /Storage/mode/Game/RayCity (Thailand) (Dark RayCity).txt: -------------------------------------------------------------------------------- 1 | # RayCity (Thailand) (Dark RayCity), 0 2 | \\Launcher.exe 3 | Raycity.exe -------------------------------------------------------------------------------- /Storage/mode/Game/RayCity (Thailand) (Rebirth RayCity).txt: -------------------------------------------------------------------------------- 1 | # RayCity (Thailand) (Rebirth RayCity), 0 2 | \\Patcher.exe 3 | RebirtRaycity.exe -------------------------------------------------------------------------------- /Storage/mode/Game/San Andreas Multiplayer (SA-MP).txt: -------------------------------------------------------------------------------- 1 | # San Andreas Multiplayer (SA-MP), 0 2 | gta_sa.exe 3 | rcon.exe 4 | samp.exe 5 | samp_debug.exe 6 | -------------------------------------------------------------------------------- /Storage/mode/Game/Tom Clancy's Rainbow Six Siege.txt: -------------------------------------------------------------------------------- 1 | # Tom Clancy's Rainbow Six Siege, 0, 0 2 | \\Tom Clancy's Rainbow Six Siege\\ 3 | \\Ubisoft Game Launcher\\ 4 | -------------------------------------------------------------------------------- /Storage/mode/Game/VRChat.txt: -------------------------------------------------------------------------------- 1 | # VRChat, 0 2 | install.exe 3 | VRChat.exe 4 | UnityCrashHandler64.exe 5 | yt-dlp.exe 6 | -------------------------------------------------------------------------------- /Storage/mode/Game/Valorant.txt: -------------------------------------------------------------------------------- 1 | # Valorant, 0 2 | RiotClientCrashHandler.exe 3 | RiotClientServices.exe 4 | RiotClientUx.exe 5 | RiotClientUxRender.exe 6 | VALORANT.exe 7 | VALORANT-Win64-Shipping.exe 8 | CrashReportClient.exe 9 | UnrealCEFSubProcess.exe 10 | -------------------------------------------------------------------------------- /Storage/mode/Game/Warframe.txt: -------------------------------------------------------------------------------- 1 | # Warframe 2 | \\Launcher.exe 3 | RemoteCrashSender.exe 4 | Warframe.x64.exe -------------------------------------------------------------------------------- /Storage/mode/Game/World of Warships.txt: -------------------------------------------------------------------------------- 1 | # World Of Warships, 0, 0 2 | wgc_api.exe 3 | wgc.exe 4 | WorldOfWarships.exe 5 | WGCheck.exe 6 | WargamingErrorMonitor.exe 7 | WorldOfWarships64.exe 8 | cef_browser_process.exe 9 | cef_subprocess.exe 10 | WorldOfWarships32.exe -------------------------------------------------------------------------------- /Storage/mode/Global.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "ProcessMode", 3 | "remark": { 4 | "zh-CN": "Global" 5 | }, 6 | "handle": [ 7 | ".*" 8 | ], 9 | "bypass": [ 10 | "\\Netch\\" 11 | ], 12 | "filterIntranet": true, 13 | "filterLoopback": false, 14 | "dnsHost": "1.1.1.1:53", 15 | "handleOnlyDNS": null, 16 | "icmpDelay": 10, 17 | "filterParent": null, 18 | "filterDNS": true, 19 | "filterUDP": true, 20 | "filterTCP": true, 21 | "filterICMP": true, 22 | "dnsProxy": null 23 | } -------------------------------------------------------------------------------- /Storage/mode/NatTypeTester.txt: -------------------------------------------------------------------------------- 1 | # NatTypeTester 2 | NatTypeTester.exe -------------------------------------------------------------------------------- /Storage/mode/Nexon Games.txt: -------------------------------------------------------------------------------- 1 | # Nexon Games 2 | \\Nexon\\Library\\ -------------------------------------------------------------------------------- /Storage/mode/Nexon.txt: -------------------------------------------------------------------------------- 1 | # Nexon 2 | NexonPlug.exe 3 | NMService.exe 4 | NGM.exe 5 | NGCLIENT.AES 6 | NGM64.exe 7 | SIG.exe -------------------------------------------------------------------------------- /Storage/mode/Origin Games.txt: -------------------------------------------------------------------------------- 1 | # Origin Games 2 | \\OriginGames\\ -------------------------------------------------------------------------------- /Storage/mode/Origin.txt: -------------------------------------------------------------------------------- 1 | # Origin 2 | EAProxyInstaller.exe 3 | GetGameToken32.exe 4 | GetGameToken64.exe 5 | igoproxy.exe 6 | igoproxy64.exe 7 | EACoreServer.exe 8 | Login.exe 9 | MessageDlg.exe 10 | OriginLegacyCLI.exe 11 | OriginUninstall.exe 12 | PatchProgress.exe 13 | Origin.exe 14 | OriginClientService.exe 15 | OriginCrashReporter.exe 16 | OriginER.exe 17 | OriginThinSetupInternal.exe 18 | OriginWebHelperService.exe 19 | QtWebEngineProcess.exe 20 | UpdateTool.exe -------------------------------------------------------------------------------- /Storage/mode/Other/AMD Radeon.txt: -------------------------------------------------------------------------------- 1 | # AMD Radeon, 0 2 | AUEPLauncher.exe 3 | AUEPMaster.exe 4 | AUEPUF.exe 5 | AUEPRyzenMasterAC.exe 6 | amdow.exe 7 | AMDRSServ.exe 8 | AMDRSSrcExt.exe 9 | AutoOverClockGFXCLK.exe 10 | cncmd.exe 11 | gpuup.exe 12 | installShell64.exe 13 | MMLoadDrv.exe 14 | MMLoadDrvPXDiscrete.exe 15 | QtWebEngineProcess.exe 16 | RadeonSettings.exe 17 | RSServCmd.exe 18 | YoutubeAPIWrapper.exe 19 | YoukuWrapper.exe 20 | TwitterWrapperClient.exe 21 | TwitchClient.exe 22 | StreamableAPIWrapper.exe 23 | SinaWeiboWrapper.exe 24 | RestreamAPIWrapper.exe 25 | QuanminTVWrapper.exe 26 | MixerClient.exe 27 | GfycatWrapper.exe 28 | FacebookClient.exe 29 | AMDCleanupUtility.exe 30 | AMDInstallUEP.exe 31 | AMDSplashScreen.exe 32 | ATISetup.exe 33 | InstallManagerApp.exe 34 | RadeonInstaller.exe 35 | Setup.exe 36 | ccc2_install.exe -------------------------------------------------------------------------------- /Storage/mode/Other/Adobe Creative Cloud (No Apps).txt: -------------------------------------------------------------------------------- 1 | # Adobe Creative Cloud, 0 2 | Creative_Cloud_Set-Up.exe 3 | Adobe CEF Helper.exe 4 | Creative Cloud.exe 5 | Setup.exe 6 | Set-up.exe 7 | HDHelper.exe -------------------------------------------------------------------------------- /Storage/mode/Other/Geforce Experience.txt: -------------------------------------------------------------------------------- 1 | # Geforce Experience 2 | courgette.exe 3 | NVIDIA GeForce Experience.exe 4 | NVIDIA Notification.exe 5 | NVIDIA Share.exe 6 | -------------------------------------------------------------------------------- /Storage/mode/Other/Google Drive Backup and Sync.txt: -------------------------------------------------------------------------------- 1 | # Google Drive Backup and Sync, 0 2 | googledrivesync.exe 3 | nativeproxy.exe -------------------------------------------------------------------------------- /Storage/mode/Other/JetBrains ToolBox.txt: -------------------------------------------------------------------------------- 1 | # JetBrains, 0 2 | 7z.exe 3 | jetbrains-toolbox-helper.exe 4 | jetbrains-toolbox.exe 5 | Uninstall.exe -------------------------------------------------------------------------------- /Storage/mode/Other/NVIDIA Corporation.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "ProcessMode", 3 | "remark": { 4 | "zh-CN": "NVIDIA Corporation" 5 | }, 6 | "handle": [ 7 | "\\\\NVIDIA Corporation\\\\" 8 | ], 9 | "bypass": [], 10 | "filterIntranet": true, 11 | "filterLoopback": true, 12 | "dnsHost": "1.1.1.1:53", 13 | "handleOnlyDNS": null, 14 | "icmpDelay": 10, 15 | "filterParent": null, 16 | "filterDNS": null, 17 | "filterUDP": null, 18 | "filterTCP": null, 19 | "filterICMP": null, 20 | "dnsProxy": null 21 | } -------------------------------------------------------------------------------- /Storage/mode/Other/NodeJS With NVM.txt: -------------------------------------------------------------------------------- 1 | # NodeJS With NVM, 0 2 | nvm.exe 3 | unins000.exe 4 | node64.exe 5 | node.exe -------------------------------------------------------------------------------- /Storage/mode/Other/Unity Asset Store for Unity.txt: -------------------------------------------------------------------------------- 1 | # Unity Asset Store for Unity, 0 2 | Unity.exe -------------------------------------------------------------------------------- /Storage/mode/Other/Unity Hub.txt: -------------------------------------------------------------------------------- 1 | # Unity Hub, 0 2 | Unity Hub.exe 3 | Unity.exe -------------------------------------------------------------------------------- /Storage/mode/Other/VMware.txt: -------------------------------------------------------------------------------- 1 | # VMware, 0, 0 2 | vmnat.exe -------------------------------------------------------------------------------- /Storage/mode/Other/Visual Studio Code.txt: -------------------------------------------------------------------------------- 1 | # Visual Studio Code, 0 2 | Code.exe 3 | inno_updater.exe 4 | CodeHelper.exe 5 | rg.exe 6 | winpty-agent.exe 7 | ssh.exe 8 | -------------------------------------------------------------------------------- /Storage/mode/Other/Xftp 6.txt: -------------------------------------------------------------------------------- 1 | # Xftp 6, 0 2 | CrashSender.exe 3 | installanchorservice.exe 4 | LiveUpdate.exe 5 | nsregister.exe 6 | Xagent.exe 7 | Xftp.exe 8 | Xtransport.exe -------------------------------------------------------------------------------- /Storage/mode/Other/Xshell 6.txt: -------------------------------------------------------------------------------- 1 | # Xshell 6, 0 2 | CrashSender.exe 3 | installanchorservice.exe 4 | LiveUpdate.exe 5 | nsregister.exe 6 | RealCmdModule.exe 7 | SessionConverter.exe 8 | Xagent.exe 9 | Xshell.exe 10 | XshellCore.exe 11 | Xtransport.exe -------------------------------------------------------------------------------- /Storage/mode/Other/qBittorrent.txt: -------------------------------------------------------------------------------- 1 | # qBittorrent, 0 2 | qbittorrent.exe -------------------------------------------------------------------------------- /Storage/mode/Rockstar Games Launcher.txt: -------------------------------------------------------------------------------- 1 | # Rockstar Games Launcher 2 | \\Rockstar Games\\Launcher\\ -------------------------------------------------------------------------------- /Storage/mode/Steam Games (with Steam).txt: -------------------------------------------------------------------------------- 1 | # Steam Games (with Steam), 0 2 | \\steamapps\\ 3 | html5app_steam.exe 4 | steamwebhelper.exe 5 | gldriverquery.exe 6 | gldriverquery64.exe 7 | secure_desktop_capture.exe 8 | steamservice.exe 9 | steam_monitor.exe 10 | x64launcher.exe 11 | x86launcher.exe 12 | GameOverlayUI.exe 13 | steam.exe 14 | steamerrorreporter.exe 15 | steamerrorreporter64.exe 16 | streaming_client.exe 17 | WriteMiniDump.exe 18 | -------------------------------------------------------------------------------- /Storage/mode/Steam Games.txt: -------------------------------------------------------------------------------- 1 | # Steam Games, 0 2 | \\steamapps\\ -------------------------------------------------------------------------------- /Storage/mode/Steam.txt: -------------------------------------------------------------------------------- 1 | # Steam 2 | html5app_steam.exe 3 | steamwebhelper.exe 4 | gldriverquery.exe 5 | gldriverquery64.exe 6 | secure_desktop_capture.exe 7 | steamservice.exe 8 | steam_monitor.exe 9 | x64launcher.exe 10 | x86launcher.exe 11 | GameOverlayUI.exe 12 | steam.exe 13 | steamerrorreporter.exe 14 | steamerrorreporter64.exe 15 | streaming_client.exe 16 | WriteMiniDump.exe 17 | -------------------------------------------------------------------------------- /Storage/mode/TUNTAP/DOOM Eternal.txt: -------------------------------------------------------------------------------- 1 | # DOOM Eternal, 1 2 | 13.33.42.0/24 3 | 13.35.15.0/24 4 | 13.35.126.0/24 5 | 13.35.153.0/24 6 | 13.35.225.0/24 7 | 13.35.242.0/24 8 | 13.224.13.0/24 9 | 13.224.164.0/24 10 | 13.225.25.0/24 11 | 13.225.62.0/24 12 | 13.225.176.0/24 13 | 13.225.217.0/24 14 | 13.226.113.0/24 15 | 13.226.159.0/24 16 | 13.226.164.0/24 17 | 13.226.182.0/24 18 | 13.226.191.0/24 19 | 13.226.219.0/24 20 | 13.227.74.0/24 21 | 13.249.102.0/24 22 | 13.249.220.0/24 23 | 34.212.107.0/24 24 | 52.38.207.0/24 25 | 52.41.174.0/24 26 | 52.26.233.0/24 27 | 52.26.236.0/24 28 | 52.85.104.0/24 29 | 52.85.242.0/24 30 | 52.88.241.0/24 31 | 54.69.151.0/24 32 | 54.148.124.0/24 33 | 54.148.231.0/24 34 | 54.186.24.0/24 35 | 54.186.163.0/24 36 | 54.192.151.0/24 37 | 54.230.71.0/24 38 | 99.84.55.0/24 39 | 99.84.168.0/24 40 | 99.84.230.0/24 41 | 99.84.247.0/24 42 | 99.86.3.0/24 43 | 99.86.243.0/24 44 | 143.204.77.0/24 45 | 143.204.127.0/24 -------------------------------------------------------------------------------- /Storage/mode/TUNTAP/Fastly.txt: -------------------------------------------------------------------------------- 1 | # Fastly, 1 2 | 23.235.32.0/20 3 | 43.249.72.0/22 4 | 103.244.50.0/24 5 | 103.245.222.0/23 6 | 103.245.224.0/24 7 | 104.156.80.0/20 8 | 140.248.64.0/18 9 | 140.248.128.0/17 10 | 146.75.0.0/17 11 | 151.101.0.0/16 12 | 157.52.64.0/18 13 | 167.82.0.0/17 14 | 167.82.128.0/20 15 | 167.82.160.0/20 16 | 167.82.224.0/20 17 | 172.111.64.0/18 18 | 185.31.16.0/22 19 | 199.27.72.0/21 20 | 199.232.0.0/16 21 | -------------------------------------------------------------------------------- /Storage/mode/TUNTAP/Maple Story (Taiwan) - UU.txt: -------------------------------------------------------------------------------- 1 | # Maple Story (Taiwan) - UU, 1 2 | 3.36.27.126/32 3 | 13.112.12.29/32 4 | 13.114.207.73/32 5 | 13.124.52.215/32 6 | 13.209.108.125/32 7 | 15.165.162.52/32 8 | 18.176.45.69/32 9 | 35.72.177.113/32 10 | 44.235.13.236/32 11 | 52.68.238.52/32 12 | 52.197.41.237/32 13 | 52.198.154.243/32 14 | 54.65.226.144/32 15 | 54.68.85.27/32 16 | 54.92.53.20/32 17 | 54.150.73.3/32 18 | 54.178.174.167/32 19 | 54.248.164.147/32 20 | 54.249.45.198/32 21 | 112.121.124.0/24 22 | 112.121.124.11/32 23 | 112.121.124.26/32 24 | 163.163.0.0/16 25 | 168.95.245.0/24 26 | 168.95.245.1/32 27 | 168.95.245.2/32 28 | 168.95.245.3/32 29 | 168.95.245.4/32 30 | 168.95.246.1/32 31 | 168.95.246.2/32 32 | 168.95.246.3/32 33 | 168.95.246.4/32 34 | 175.24.127.9/32 35 | 202.80.104.0/24 36 | 202.80.104.24/32 37 | 202.80.104.25/32 38 | 202.80.104.26/32 39 | 202.80.104.27/32 40 | 202.80.104.28/32 41 | 202.80.104.29/32 42 | 202.80.107.0/24 43 | 202.80.107.11/32 44 | 202.80.107.13/32 45 | -------------------------------------------------------------------------------- /Storage/mode/TUNTAP/Phasmophobia - UU.txt: -------------------------------------------------------------------------------- 1 | # Phasmophobia - UU, 1 2 | 3.24.157.0/24 3 | 5.188.239.0/24 4 | 18.185.151.0/24 5 | 20.44.128.0/24 6 | 23.5.246.114/32 7 | 40.74.108.123/32 8 | 52.53.89.0/24 9 | 52.77.92.0/24 10 | 52.139.153.205/32 11 | 52.139.168.125/32 12 | 59.37.129.23/32 13 | 92.38.154.0/24 14 | 92.38.183.0/24 15 | 92.223.82.0/24 16 | 94.237.2.0/24 17 | 94.237.110.0/24 18 | 104.74.44.187/32 19 | 104.89.151.247/32 20 | 104.110.72.183/32 21 | 119.81.0.0/16 22 | 119.81.131.0/24 23 | 146.185.221.0/24 24 | 161.202.192.0/24 25 | 163.163.0.0/16 26 | 169.44.0.0/16 27 | 169.45.64.0/24 28 | 169.53.128.0/24 29 | 172.65.203.0/24 30 | 172.65.212.0/24 31 | 172.65.215.0/24 32 | 172.65.221.0/24 33 | 172.65.237.0/24 34 | 172.65.254.0/24 35 | 173.193.0.0/16 36 | 203.198.20.11/32 37 | 203.198.20.67/32 -------------------------------------------------------------------------------- /Storage/mode/TUNTAP/Scum - UU.txt: -------------------------------------------------------------------------------- 1 | # Scum - UU, 1 2 | 5.8.25.0/24 3 | 5.188.151.0/24 4 | 14.18.251.27/32 5 | 14.18.251.191/32 6 | 23.5.246.114/32 7 | 43.251.182.0/24 8 | 45.35.98.0/24 9 | 45.35.136.0/24 10 | 45.35.207.0/24 11 | 45.137.245.0/24 12 | 52.229.128.0/24 13 | 54.37.88.0/24 14 | 54.37.128.0/24 15 | 91.218.244.0/24 16 | 92.38.136.0/24 17 | 92.38.138.0/24 18 | 92.223.58.0/24 19 | 92.223.103.0/24 20 | 103.78.123.0/24 21 | 103.126.138.0/24 22 | 104.89.151.247/32 23 | 104.149.3.0/24 24 | 104.149.137.0/24 25 | 104.149.191.0/24 26 | 104.149.194.0/24 27 | 104.149.217.0/24 28 | 104.149.227.0/24 29 | 104.149.249.0/24 30 | 104.217.16.0/24 31 | 104.217.128.0/24 32 | 104.217.196.0/24 33 | 104.217.225.0/24 34 | 104.217.230.0/24 35 | 116.206.75.0/24 36 | 145.239.150.0/24 37 | 163.163.0.0/16 38 | 172.106.12.0/24 39 | 172.106.131.0/24 40 | 172.107.16.0/24 41 | 172.107.179.0/24 42 | 172.107.182.0/24 43 | 172.107.197.0/24 44 | 176.57.135.0/24 45 | 176.57.138.0/24 46 | 176.57.140.0/24 47 | 176.57.153.0/24 48 | 176.57.160.0/24 49 | 176.57.168.0/24 50 | 176.57.171.0/24 51 | 176.57.173.0/24 52 | 176.57.174.0/24 53 | 176.57.178.0/24 54 | 176.57.181.0/24 55 | 177.54.157.0/24 56 | 184.84.114.80/32 57 | 185.70.107.0/24 58 | 203.198.20.11/32 59 | 203.198.20.67/32 60 | 205.204.92.0/24 61 | 220.181.77.202/32 -------------------------------------------------------------------------------- /Storage/mode/Ubisoft Connect.txt: -------------------------------------------------------------------------------- 1 | # Ubisoft Connect 2 | UbisoftConnect.exe 3 | UbisoftGameLauncher.exe 4 | UbisoftGameLauncher64.exe 5 | upc.exe 6 | UplayCrashReporter.exe 7 | UplayService.exe 8 | UplayWebCore.exe -------------------------------------------------------------------------------- /Storage/mode/pcap2socks-Tencent.txt: -------------------------------------------------------------------------------- 1 | # [pcap2socks] Tencent(10.6.0.1) Preset, 6 2 | --preset tencent -------------------------------------------------------------------------------- /Storage/mode/pcap2socks-UU.txt: -------------------------------------------------------------------------------- 1 | # [pcap2socks] UU(172.24.?.?) Preset , 6 2 | --preset uu -------------------------------------------------------------------------------- /Storage/nfdriver.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarflows/netch/1b3559051c420173be3d23ad5540685f91f00be8/Storage/nfdriver.sys -------------------------------------------------------------------------------- /Storage/stun.txt: -------------------------------------------------------------------------------- 1 | stun.qq.com 2 | stun.bige0.com 3 | stun.miwifi.com 4 | stun.syncthing.net 5 | stunserver.stunprotocol.org 6 | iphone-stun.strato-iphone.de 7 | stun.voipstunt.com 8 | stun.xten.com 9 | stun.schlund.de 10 | numb.viagenie.ca 11 | stun.ekiga.net 12 | stun.sipgate.net 13 | stun.chat.bilibili.com 14 | turn.cloudflare.com 15 | fwa.lifesizecloud.com 16 | stun.isp.net.au 17 | stun.freeswitch.org 18 | stun.voip.blackberry.com 19 | stun.nextcloud.com 20 | stun.sipnet.com 21 | stun.radiojar.com 22 | stun.sonetel.com 23 | stun.voipgate.com 24 | -------------------------------------------------------------------------------- /Storage/tun2socks.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarflows/netch/1b3559051c420173be3d23ad5540685f91f00be8/Storage/tun2socks.bin -------------------------------------------------------------------------------- /Tests/.gitignore: -------------------------------------------------------------------------------- 1 | /bin 2 | /obj 3 | /*.csproj.user 4 | -------------------------------------------------------------------------------- /Tests/Global.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Security.Cryptography; 6 | using System.Text; 7 | 8 | namespace Tests 9 | { 10 | [TestClass] 11 | public class Global 12 | { 13 | [TestMethod] 14 | public void Test() 15 | { 16 | Console.WriteLine(AppDomain.CurrentDomain.BaseDirectory); 17 | } 18 | [TestMethod] 19 | public void VLESS_UUID5() 20 | { 21 | //https://github.com/XTLS/Xray-core/discussions/715 22 | 23 | byte[] bytes = new byte[16]; 24 | var str = "example"; 25 | 26 | SHA1 sha1 = new SHA1CryptoServiceProvider(); 27 | byte[] StrBytes = Encoding.UTF8.GetBytes(str); 28 | 29 | List byteSource = new(); 30 | byteSource.AddRange(bytes); 31 | byteSource.AddRange(StrBytes); 32 | 33 | byte[] Sha1Bytes = sha1.ComputeHash(byteSource.ToArray()).Skip(0).Take(16).ToArray(); 34 | sha1.Dispose(); 35 | 36 | //UUIDv5: [254 181 68 49 48 27 82 187 166 221 225 233 62 129 187 158] 37 | 38 | Sha1Bytes[6] = (byte)((Sha1Bytes[6] & 0x0f) | (5 << 4)); 39 | Sha1Bytes[8] = (byte)(Sha1Bytes[8] & (0xff >> 2) | (0x02 << 6)); 40 | 41 | var result = BitConverter.ToString(Sha1Bytes).Replace("-", "").Insert(8, "-").Insert(13, "-").Insert(18, "-").Insert(23, "-").ToLower(); 42 | Console.WriteLine(result); 43 | //UUIDv5: feb54431-301b-52bb-a6dd-e1e93e81bb9e 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Tests/Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net5.0 5 | 6 | false 7 | 8 | x64 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /clean.ps1: -------------------------------------------------------------------------------- 1 | Push-Location (Split-Path $MyInvocation.MyCommand.Path -Parent) 2 | 3 | function Delete { 4 | param ( 5 | [string] 6 | $Path 7 | ) 8 | 9 | if (Test-Path $Path) { 10 | rm -Recurse -Force $Path | Out-Null 11 | } 12 | } 13 | 14 | Delete '.vs' 15 | Delete 'release' 16 | Delete 'Netch\bin' 17 | Delete 'Netch\obj' 18 | Delete 'Tests\bin' 19 | Delete 'Tests\obj' 20 | Delete 'TestResults' 21 | Delete 'Redirector\bin' 22 | Delete 'Redirector\obj' 23 | Delete 'RedirectorTester\bin' 24 | Delete 'RedirectorTester\obj' 25 | Delete 'RouteHelper\bin' 26 | Delete 'RouteHelper\obj' 27 | 28 | Delete 'Netch\*.csproj.user' 29 | Delete 'Redirector\*.vcxproj.user' 30 | Delete 'RedirectorTester\*.csproj.user' 31 | Delete 'RouteHelper\*.vcxproj.user' 32 | 33 | .\other\clean.ps1 34 | 35 | Pop-Location 36 | exit $lastExitCode -------------------------------------------------------------------------------- /common.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | net6.0-windows 4 | win-x64 5 | x64 6 | latest 7 | enable 8 | 9 | -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "allowPrerelease": false 4 | } 5 | } -------------------------------------------------------------------------------- /sha256.ps1: -------------------------------------------------------------------------------- 1 | param ( 2 | [string] 3 | $Location = '' 4 | ) 5 | 6 | Push-Location $Location 7 | 8 | $global:data = '' 9 | function Scan { 10 | param ( 11 | [string] 12 | $path = '' 13 | ) 14 | 15 | foreach ( $item in ( Get-ChildItem -Path $path -File ) ) { 16 | $name = $item.Name 17 | 18 | $global:data += (Get-FileHash -Path ".\$path\$name" -Algorithm SHA256).Hash.ToLower() 19 | } 20 | 21 | foreach ( $item in ( Get-ChildItem -Path $path -Directory ) ) { 22 | $name = $item.Name 23 | 24 | Scan -Path ".\$path\$name" 25 | } 26 | } 27 | 28 | Scan -Path '.' 29 | Write-Output (Get-FileHash -InputStream ([System.IO.MemoryStream]::New([System.Text.Encoding]::UTF8.GetBytes($data)))).Hash.ToLower() 30 | 31 | Pop-Location 32 | exit 0 --------------------------------------------------------------------------------