mirror of
https://github.com/2dust/v2rayN.git
synced 2026-07-26 09:52:05 +03:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e9f78f831 | ||
|
|
8c4bd52389 | ||
|
|
fa61fedf11 | ||
|
|
ad12a6c456 | ||
|
|
66b48c231f | ||
|
|
52766d66bf | ||
|
|
e1a5c360ac | ||
|
|
0c570fcb38 | ||
|
|
a236fab27c | ||
|
|
f8e1186095 | ||
|
|
ca186e2636 | ||
|
|
1e8ba9ad9b | ||
|
|
31e32f174e | ||
|
|
bf376a8fac | ||
|
|
5a9a9b7ab1 | ||
|
|
e7a9aa66dc | ||
|
|
709b9a0958 | ||
|
|
191fe48257 | ||
|
|
48d58d482a |
112
.github/scripts/UpdateCert.cs
vendored
Normal file
112
.github/scripts/UpdateCert.cs
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
var client = new HttpClient { Timeout = TimeSpan.FromMinutes(2) };
|
||||
|
||||
var outputDir = args.Length > 0
|
||||
? args[0]
|
||||
: Path.Combine(Environment.CurrentDirectory, "v2rayN", "ServiceLib", "Sample");
|
||||
|
||||
Directory.CreateDirectory(outputDir);
|
||||
|
||||
Console.WriteLine("=== Mozilla + Chrome Root Store PEM Converter ===\n");
|
||||
Console.WriteLine($"Output directory: {outputDir}\n");
|
||||
|
||||
// Process Mozilla
|
||||
await ProcessMozillaAsync(outputDir);
|
||||
|
||||
// Process Chrome
|
||||
await ProcessChromeAsync(outputDir);
|
||||
|
||||
Console.WriteLine("\nAll done!");
|
||||
|
||||
async Task ProcessMozillaAsync(string outputDir)
|
||||
{
|
||||
const string certdataUrl = "https://raw.githubusercontent.com/mozilla-firefox/firefox/refs/heads/release/security/nss/lib/ckfw/builtins/certdata.txt";
|
||||
var outputFile = Path.Combine(outputDir, "mozilla_roots_pem");
|
||||
|
||||
Console.WriteLine("Downloading Mozilla certdata.txt...");
|
||||
var content = await client.GetStringAsync(certdataUrl);
|
||||
|
||||
Console.WriteLine("Parsing MULTILINE_OCTAL to PEM...");
|
||||
var pems = ParseMozillaCertData(content);
|
||||
|
||||
await File.WriteAllTextAsync(outputFile, string.Join("\n\n", pems));
|
||||
Console.WriteLine($"Mozilla roots saved to: {outputFile} ({pems.Count} certificates)");
|
||||
}
|
||||
|
||||
List<string> ParseMozillaCertData(string text)
|
||||
{
|
||||
var pems = new List<string>();
|
||||
|
||||
var matches = Regex.Matches(text,
|
||||
@"CKA_VALUE MULTILINE_OCTAL\s*([\s\S]*?)\s*END",
|
||||
RegexOptions.Multiline);
|
||||
|
||||
foreach (Match m in matches)
|
||||
{
|
||||
var octalBlock = m.Groups[1].Value.Trim();
|
||||
var der = OctalToBytes(octalBlock);
|
||||
if (der.Length > 0)
|
||||
{
|
||||
var pem = ConvertToPem(der);
|
||||
pems.Add(pem);
|
||||
}
|
||||
}
|
||||
return pems;
|
||||
}
|
||||
|
||||
byte[] OctalToBytes(string octalBlock)
|
||||
{
|
||||
var bytes = new List<byte>();
|
||||
var matches = Regex.Matches(octalBlock, @"\\(\d{1,3})");
|
||||
foreach (Match m in matches)
|
||||
{
|
||||
bytes.Add((byte)Convert.ToInt32(m.Groups[1].Value, 8));
|
||||
}
|
||||
return bytes.ToArray();
|
||||
}
|
||||
|
||||
string ConvertToPem(byte[] der)
|
||||
{
|
||||
var base64 = Convert.ToBase64String(der);
|
||||
var sb = new StringBuilder();
|
||||
sb.Append("-----BEGIN CERTIFICATE-----\n");
|
||||
|
||||
for (int i = 0; i < base64.Length; i += 64)
|
||||
{
|
||||
var length = Math.Min(64, base64.Length - i);
|
||||
sb.Append(base64.Substring(i, length));
|
||||
sb.Append("\n");
|
||||
}
|
||||
|
||||
sb.Append("-----END CERTIFICATE-----\n");
|
||||
return sb.ToString().TrimEnd();
|
||||
}
|
||||
|
||||
async Task ProcessChromeAsync(string outputDir)
|
||||
{
|
||||
const string chromeCertsUrl = "https://chromium.googlesource.com/chromium/src/+/main/net/data/ssl/chrome_root_store/root_store.certs?format=TEXT";
|
||||
var chromeOutput = Path.Combine(outputDir, "chrome_roots_pem");
|
||||
|
||||
Console.WriteLine("Downloading Chrome root_store.certs...");
|
||||
var base64Content = await client.GetStringAsync(chromeCertsUrl);
|
||||
var decoded = Convert.FromBase64String(base64Content.Replace("\n", ""));
|
||||
|
||||
var text = Encoding.UTF8.GetString(decoded);
|
||||
|
||||
var pemMatches = Regex.Matches(text, @"(-----BEGIN CERTIFICATE-----[\s\S]*?-----END CERTIFICATE-----)");
|
||||
var pems = new List<string>();
|
||||
foreach (Match m in pemMatches)
|
||||
{
|
||||
pems.Add(m.Groups[1].Value.Trim());
|
||||
}
|
||||
|
||||
await File.WriteAllTextAsync(chromeOutput, string.Join("\n\n", pems));
|
||||
Console.WriteLine($"Chrome roots saved to: {chromeOutput} ({pems.Count} certificates)");
|
||||
}
|
||||
8
.github/workflows/build-linux.yml
vendored
8
.github/workflows/build-linux.yml
vendored
@@ -214,7 +214,7 @@ jobs:
|
||||
QCOW2_IMAGE: debian13-loong64.qcow2
|
||||
EFI_CODE: edk2-loongarch64-code.fd
|
||||
EFI_VARS: edk2-loongarch64-vars.fd
|
||||
QEMU_VERSION: 10.2.3
|
||||
QEMU_VERSION: 10.2.4
|
||||
steps:
|
||||
- name: Prepare host tools
|
||||
shell: bash
|
||||
@@ -258,7 +258,7 @@ jobs:
|
||||
export VIRTIOFSD_SOCKET="$RUNNER_TEMP/virtiofs-deb-loong64.sock"
|
||||
rm -f "$VIRTIOFSD_SOCKET"
|
||||
|
||||
sudo virtiofsd --socket-path="$VIRTIOFSD_SOCKET" -o source="$GITHUB_WORKSPACE" -o cache=auto &
|
||||
sudo virtiofsd --socket-path="$VIRTIOFSD_SOCKET" --shared-dir="$GITHUB_WORKSPACE" --cache=auto &
|
||||
|
||||
VIRTIOFSD_PID=$!
|
||||
trap 'sudo kill "$VIRTIOFSD_PID" 2>/dev/null || true; rm -f "$VIRTIOFSD_SOCKET"' EXIT
|
||||
@@ -364,7 +364,7 @@ jobs:
|
||||
QCOW2_IMAGE: fedora43-loong64.qcow2
|
||||
EFI_CODE: edk2-loongarch64-code.fd
|
||||
EFI_VARS: edk2-loongarch64-vars.fd
|
||||
QEMU_VERSION: 10.2.3
|
||||
QEMU_VERSION: 10.2.4
|
||||
steps:
|
||||
- name: Prepare host tools
|
||||
shell: bash
|
||||
@@ -408,7 +408,7 @@ jobs:
|
||||
export VIRTIOFSD_SOCKET="$RUNNER_TEMP/virtiofs-rpm-loong64.sock"
|
||||
rm -f "$VIRTIOFSD_SOCKET"
|
||||
|
||||
sudo virtiofsd --socket-path="$VIRTIOFSD_SOCKET" -o source="$GITHUB_WORKSPACE" -o cache=auto &
|
||||
sudo virtiofsd --socket-path="$VIRTIOFSD_SOCKET" --shared-dir="$GITHUB_WORKSPACE" --cache=auto &
|
||||
|
||||
VIRTIOFSD_PID=$!
|
||||
trap 'sudo kill "$VIRTIOFSD_PID" 2>/dev/null || true; rm -f "$VIRTIOFSD_SOCKET"' EXIT
|
||||
|
||||
2
.github/workflows/build-windows-x86.yml
vendored
2
.github/workflows/build-windows-x86.yml
vendored
@@ -52,7 +52,7 @@ jobs:
|
||||
dotnet --list-sdks 2>$null; $LASTEXITCODE=0
|
||||
|
||||
- name: Setup .NET 10.0.1xx
|
||||
uses: actions/setup-dotnet@v5.3.0
|
||||
uses: actions/setup-dotnet@v5.4.0
|
||||
with:
|
||||
dotnet-version: 10.0.1xx
|
||||
|
||||
|
||||
5
.github/workflows/build.yml
vendored
5
.github/workflows/build.yml
vendored
@@ -22,6 +22,7 @@ jobs:
|
||||
case(
|
||||
inputs.target == 'macos', 'macos-latest',
|
||||
inputs.target == 'linux', 'ubuntu-24.04',
|
||||
inputs.target == 'windows', 'windows-latest',
|
||||
'ubuntu-latest'
|
||||
)
|
||||
}}
|
||||
@@ -68,15 +69,17 @@ jobs:
|
||||
dotnet --list-sdks 2>$null; $LASTEXITCODE=0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v5.3.0
|
||||
uses: actions/setup-dotnet@v5.4.0
|
||||
with:
|
||||
dotnet-version: '10.0.1xx'
|
||||
|
||||
- name: Build v2rayN
|
||||
shell: bash
|
||||
working-directory: ./v2rayN
|
||||
run: dotnet publish $Project -c Release -r $RID -p:SelfContained=true $ExtOpt -o $Output
|
||||
|
||||
- name: Build AmazTool
|
||||
shell: bash
|
||||
working-directory: ./v2rayN
|
||||
run: dotnet publish ./AmazTool/AmazTool.csproj -c Release -r $RID -p:SelfContained=true -p:PublishTrimmed=true $ExtOpt -o $Output
|
||||
|
||||
|
||||
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
||||
fetch-depth: '0'
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v5.3.0
|
||||
uses: actions/setup-dotnet@v5.4.0
|
||||
with:
|
||||
dotnet-version: '8.0.x'
|
||||
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,6 +1,3 @@
|
||||
[submodule "v2rayN/GlobalHotKeys"]
|
||||
path = v2rayN/GlobalHotKeys
|
||||
url = https://github.com/2dust/GlobalHotKeys
|
||||
[submodule "v2rayN/NetBridge"]
|
||||
path = v2rayN/NetBridge
|
||||
url = https://github.com/2dust/NetBridge
|
||||
|
||||
@@ -23,6 +23,13 @@ Download the latest release here:
|
||||
|
||||
[https://github.com/2dust/v2rayN/releases](https://github.com/2dust/v2rayN/releases)
|
||||
|
||||
|
||||
> [!TIP]
|
||||
> v2rayN is the desktop version. For the mobile version, please visit the v2rayNG \
|
||||
> v2rayN 是电脑版,手机版请访问 v2rayNG
|
||||
>
|
||||
> https://github.com/2dust/v2rayNG
|
||||
|
||||
---
|
||||
|
||||
## Documentation / 使用文档
|
||||
|
||||
@@ -8,7 +8,7 @@ BUILD_FROM=""
|
||||
XRAY_VER="${XRAY_VER:-}"
|
||||
SING_VER="${SING_VER:-}"
|
||||
|
||||
MIN_KERNEL="5.10"
|
||||
MIN_KERNEL="6.12"
|
||||
PKGROOT="v2rayN-publish"
|
||||
PROJECT_HINT="v2rayN.Desktop/v2rayN.Desktop.csproj"
|
||||
OUTPUT_DIR="${HOME}/debbuild"
|
||||
@@ -116,20 +116,7 @@ install_dependencies() {
|
||||
|
||||
export PATH="$HOME/.dotnet:$PATH"
|
||||
export DOTNET_ROOT="$HOME/.dotnet"
|
||||
|
||||
mkdir -p "$HOME/.nuget/NuGet"
|
||||
|
||||
cat > "$HOME/.nuget/NuGet/NuGet.Config" <<EOF
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
<add key="loongnix" value="https://lnuget.loongnix.cn/v3/index.json" allowInsecureConnections="true" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
EOF
|
||||
|
||||
|
||||
dotnet --info >/dev/null 2>&1 && install_ok=1
|
||||
fi
|
||||
|
||||
@@ -610,7 +597,7 @@ package_binary() {
|
||||
write_desktop_file "$stage"
|
||||
write_maintainer_scripts "$debian_dir"
|
||||
|
||||
extra_depends="libc6 (>= 2.34), fontconfig (>= 2.13.1), desktop-file-utils (>= 0.26), xdg-utils (>= 1.1.3), coreutils (>= 8.32), bash (>= 5.1), libfreetype6 (>= 2.11)"
|
||||
extra_depends="libc6 (>= 2.39), fontconfig (>= 2.15.0), desktop-file-utils (>= 0.26), xdg-utils (>= 1.2.0), coreutils (>= 9.5), bash (>= 5.2.26), libfreetype6 (>= 2.13)"
|
||||
|
||||
mkdir -p "$workdir/debian"
|
||||
cat > "$workdir/debian/control" <<EOF
|
||||
|
||||
@@ -595,7 +595,7 @@ package_binary() {
|
||||
write_desktop_file "$stage"
|
||||
write_maintainer_scripts "$debian_dir"
|
||||
|
||||
extra_depends="libc6 (>= 2.34), fontconfig (>= 2.13.1), desktop-file-utils (>= 0.26), xdg-utils (>= 1.1.3), coreutils (>= 8.32), bash (>= 5.1), libfreetype6 (>= 2.11)"
|
||||
extra_depends="libc6 (>= 2.39), fontconfig (>= 2.15.0), desktop-file-utils (>= 0.26), xdg-utils (>= 1.2.0), coreutils (>= 9.5), bash (>= 5.2.26), libfreetype6 (>= 2.13)"
|
||||
|
||||
mkdir -p "$workdir/debian"
|
||||
cat > "$workdir/debian/control" <<EOF
|
||||
|
||||
@@ -609,7 +609,7 @@ package_binary() {
|
||||
write_desktop_file "$stage"
|
||||
write_maintainer_scripts "$debian_dir"
|
||||
|
||||
extra_depends="libc6 (>= 2.34), fontconfig (>= 2.13.1), desktop-file-utils (>= 0.26), xdg-utils (>= 1.1.3), coreutils (>= 8.32), bash (>= 5.1), libfreetype6 (>= 2.11)"
|
||||
extra_depends="libc6 (>= 2.39), fontconfig (>= 2.15.0), desktop-file-utils (>= 0.26), xdg-utils (>= 1.2.0), coreutils (>= 9.5), bash (>= 5.2.26), libfreetype6 (>= 2.13)"
|
||||
|
||||
mkdir -p "$workdir/debian"
|
||||
cat > "$workdir/debian/control" <<EOF
|
||||
@@ -753,4 +753,4 @@ main() {
|
||||
print_summary
|
||||
}
|
||||
|
||||
main "$@"
|
||||
main "$@"
|
||||
|
||||
@@ -54,7 +54,7 @@ cat >"$PackagePath/v2rayN.app/Contents/Info.plist" <<-EOF
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<true/>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>12.7</string>
|
||||
<string>13.7</string>
|
||||
</dict>
|
||||
</plist>
|
||||
EOF
|
||||
|
||||
@@ -8,7 +8,7 @@ BUILD_FROM=""
|
||||
XRAY_VER="${XRAY_VER:-}"
|
||||
SING_VER="${SING_VER:-}"
|
||||
|
||||
MIN_KERNEL="5.10"
|
||||
MIN_KERNEL="6.12"
|
||||
PKGROOT="v2rayN-publish"
|
||||
PROJECT_HINT="v2rayN.Desktop/v2rayN.Desktop.csproj"
|
||||
RPM_TOPDIR="${HOME}/rpmbuild"
|
||||
@@ -112,20 +112,7 @@ install_dependencies() {
|
||||
|
||||
export PATH="$HOME/.dotnet:$PATH"
|
||||
export DOTNET_ROOT="$HOME/.dotnet"
|
||||
|
||||
mkdir -p "$HOME/.nuget/NuGet"
|
||||
|
||||
cat > "$HOME/.nuget/NuGet/NuGet.Config" <<EOF
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
<add key="loongnix" value="https://lnuget.loongnix.cn/v3/index.json" allowInsecureConnections="true" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
EOF
|
||||
|
||||
|
||||
dotnet --info >/dev/null 2>&1 || install_ok=0
|
||||
fi
|
||||
|
||||
@@ -523,13 +510,13 @@ ExclusiveArch: loongarch64
|
||||
Source0: __PKGROOT__.tar.gz
|
||||
|
||||
Requires: cairo, pango, openssl, mesa-libEGL, mesa-libGL
|
||||
Requires: glibc >= 2.34
|
||||
Requires: fontconfig >= 2.13.1
|
||||
Requires: glibc >= 2.39
|
||||
Requires: fontconfig >= 2.15.0
|
||||
Requires: desktop-file-utils >= 0.26
|
||||
Requires: xdg-utils >= 1.1.3
|
||||
Requires: coreutils >= 8.32
|
||||
Requires: bash >= 5.1
|
||||
Requires: freetype >= 2.10
|
||||
Requires: xdg-utils >= 1.2.0
|
||||
Requires: coreutils >= 9.5
|
||||
Requires: bash >= 5.2.26
|
||||
Requires: freetype >= 2.13
|
||||
|
||||
%description
|
||||
v2rayN Linux for Red Hat Enterprise Linux
|
||||
|
||||
@@ -509,13 +509,13 @@ ExclusiveArch: riscv64
|
||||
Source0: __PKGROOT__.tar.gz
|
||||
|
||||
Requires: cairo, pango, openssl, mesa-libEGL, mesa-libGL
|
||||
Requires: glibc >= 2.34
|
||||
Requires: fontconfig >= 2.13.1
|
||||
Requires: glibc >= 2.39
|
||||
Requires: fontconfig >= 2.15.0
|
||||
Requires: desktop-file-utils >= 0.26
|
||||
Requires: xdg-utils >= 1.1.3
|
||||
Requires: coreutils >= 8.32
|
||||
Requires: bash >= 5.1
|
||||
Requires: freetype >= 2.10
|
||||
Requires: xdg-utils >= 1.2.0
|
||||
Requires: coreutils >= 9.5
|
||||
Requires: bash >= 5.2.26
|
||||
Requires: freetype >= 2.13
|
||||
|
||||
%description
|
||||
v2rayN Linux for Red Hat Enterprise Linux
|
||||
|
||||
@@ -498,13 +498,13 @@ ExclusiveArch: aarch64 x86_64
|
||||
Source0: __PKGROOT__.tar.gz
|
||||
|
||||
Requires: cairo, pango, openssl, mesa-libEGL, mesa-libGL
|
||||
Requires: glibc >= 2.34
|
||||
Requires: fontconfig >= 2.13.1
|
||||
Requires: glibc >= 2.39
|
||||
Requires: fontconfig >= 2.15.0
|
||||
Requires: desktop-file-utils >= 0.26
|
||||
Requires: xdg-utils >= 1.1.3
|
||||
Requires: coreutils >= 8.32
|
||||
Requires: bash >= 5.1
|
||||
Requires: freetype >= 2.10
|
||||
Requires: xdg-utils >= 1.2.0
|
||||
Requires: coreutils >= 9.5
|
||||
Requires: bash >= 5.2.26
|
||||
Requires: freetype >= 2.13
|
||||
|
||||
%description
|
||||
v2rayN Linux for Red Hat Enterprise Linux
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<Version>7.23.0</Version>
|
||||
<Version>7.23.3</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
|
||||
<CentralPackageVersionOverrideEnabled>false</CentralPackageVersionOverrideEnabled>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="Avalonia.AvaloniaEdit" Version="11.4.1" />
|
||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.13" />
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="11.3.17" />
|
||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.17" />
|
||||
<PackageVersion Include="AwesomeAssertions" Version="9.4.0" />
|
||||
<PackageVersion Include="DialogHost.Avalonia" Version="0.11.0" />
|
||||
<PackageVersion Include="IPNetwork2" Version="4.3.0" />
|
||||
<PackageVersion Include="ReactiveUI.Avalonia" Version="11.4.13" />
|
||||
<PackageVersion Include="CliWrap" Version="3.10.1" />
|
||||
<PackageVersion Include="Downloader" Version="5.7.0" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.6.0" />
|
||||
<PackageVersion Include="H.NotifyIcon.Wpf" Version="2.4.1" />
|
||||
<PackageVersion Include="MaterialDesignThemes" Version="5.3.2" />
|
||||
<PackageVersion Include="QRCoder" Version="1.8.0" />
|
||||
<PackageVersion Include="ReactiveUI" Version="23.2.28" />
|
||||
<PackageVersion Include="ReactiveUI.Fody" Version="19.5.41" />
|
||||
<PackageVersion Include="ReactiveUI.WPF" Version="23.2.28" />
|
||||
<PackageVersion Include="Semi.Avalonia" Version="11.3.14" />
|
||||
<PackageVersion Include="Semi.Avalonia.AvaloniaEdit" Version="11.2.0.2" />
|
||||
<PackageVersion Include="Semi.Avalonia.DataGrid" Version="11.3.7.3" />
|
||||
<PackageVersion Include="NLog" Version="6.1.3" />
|
||||
<PackageVersion Include="sqlite-net-e" Version="1.11.0" />
|
||||
<PackageVersion Include="Repobot.SQLite.Unofficial" Version="3.53.2" />
|
||||
<PackageVersion Include="TaskScheduler" Version="2.12.2" />
|
||||
<PackageVersion Include="WebDav.Client" Version="2.9.0" />
|
||||
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
|
||||
<PackageVersion Include="xunit.v3" Version="3.2.2" />
|
||||
<PackageVersion Include="YamlDotNet" Version="18.0.0" />
|
||||
<PackageVersion Include="ZXing.Net.Bindings.SkiaSharp" Version="0.16.22" />
|
||||
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="3.119.4" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
|
||||
<CentralPackageVersionOverrideEnabled>false</CentralPackageVersionOverrideEnabled>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="Avalonia.AvaloniaEdit" Version="11.4.1" />
|
||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.13" />
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="11.3.18" />
|
||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.18" />
|
||||
<PackageVersion Include="AwesomeAssertions" Version="9.4.0" />
|
||||
<PackageVersion Include="DialogHost.Avalonia" Version="0.11.0" />
|
||||
<PackageVersion Include="IPNetwork2" Version="4.3.0" />
|
||||
<PackageVersion Include="ReactiveUI.Avalonia" Version="11.4.13" />
|
||||
<PackageVersion Include="CliWrap" Version="3.10.2" />
|
||||
<PackageVersion Include="Downloader" Version="5.9.0" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.7.0" />
|
||||
<PackageVersion Include="H.NotifyIcon.Wpf" Version="2.4.1" />
|
||||
<PackageVersion Include="MaterialDesignThemes" Version="5.3.2" />
|
||||
<PackageVersion Include="QRCoder" Version="1.8.0" />
|
||||
<PackageVersion Include="ReactiveUI" Version="23.2.28" />
|
||||
<PackageVersion Include="ReactiveUI.Fody" Version="19.5.41" />
|
||||
<PackageVersion Include="ReactiveUI.WPF" Version="23.2.28" />
|
||||
<PackageVersion Include="Semi.Avalonia" Version="11.3.14" />
|
||||
<PackageVersion Include="Semi.Avalonia.AvaloniaEdit" Version="11.2.0.2" />
|
||||
<PackageVersion Include="Semi.Avalonia.DataGrid" Version="11.3.7.3" />
|
||||
<PackageVersion Include="NLog" Version="6.1.3" />
|
||||
<PackageVersion Include="sqlite-net-e" Version="1.11.0" />
|
||||
<PackageVersion Include="Repobot.SQLite.Unofficial" Version="3.53.3" />
|
||||
<PackageVersion Include="TaskScheduler" Version="2.12.2" />
|
||||
<PackageVersion Include="WebDav.Client" Version="2.9.0" />
|
||||
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
|
||||
<PackageVersion Include="xunit.v3" Version="3.2.2" />
|
||||
<PackageVersion Include="YamlDotNet" Version="18.0.0" />
|
||||
<PackageVersion Include="ZXing.Net.Bindings.SkiaSharp" Version="0.16.22" />
|
||||
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="3.119.4" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
Submodule v2rayN/GlobalHotKeys updated: 569a95bb0f...162d401dfe
Submodule v2rayN/NetBridge deleted from e9b16cd187
@@ -1,8 +1,10 @@
|
||||
using AwesomeAssertions;
|
||||
using ServiceLib.Common;
|
||||
using ServiceLib.Enums;
|
||||
using ServiceLib.Handler.Fmt;
|
||||
using ServiceLib.Manager;
|
||||
using ServiceLib.Models;
|
||||
using ServiceLib.Models.Dto;
|
||||
using ServiceLib.Services.CoreConfig;
|
||||
using Xunit;
|
||||
|
||||
@@ -557,4 +559,37 @@ public class CoreConfigSingboxServiceTests
|
||||
cfg.dns.rules.Should().Contain(r => r.clash_mode == nameof(ERuleMode.Global));
|
||||
cfg.dns.rules.Should().Contain(r => r.clash_mode == nameof(ERuleMode.Direct));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GenerateClientConfigContent_Hysteria2Realm_ShouldEmitHttpsServerUrl()
|
||||
{
|
||||
var shareLink =
|
||||
"hysteria2+realm://public@realm.hy2.io/my-realm-id?auth=uuid&stun=turn.cloudflare.com%3A3478&sni=cloudflare.com&pinSHA256=xxx#Realm-Test";
|
||||
var node = Hysteria2Fmt.ResolveRealm(shareLink, out _);
|
||||
node.Should().NotBeNull();
|
||||
node!.CoreType = ECoreType.sing_box;
|
||||
|
||||
var config = CoreConfigTestFactory.CreateConfig(ECoreType.sing_box);
|
||||
config.CoreTypeItem =
|
||||
[
|
||||
new CoreTypeItem { ConfigType = EConfigType.Hysteria2, CoreType = ECoreType.sing_box }
|
||||
];
|
||||
CoreConfigTestFactory.BindAppManagerConfig(config);
|
||||
var context = CoreConfigTestFactory.CreateContext(config, node, ECoreType.sing_box);
|
||||
|
||||
var result = new CoreConfigSingboxService(context).GenerateClientConfigContent();
|
||||
|
||||
result.Success.Should().BeTrue($"ret msg: {result.Msg}");
|
||||
var cfg = JsonUtils.Deserialize<SingboxConfig>(result.Data!.ToString())!;
|
||||
var proxy = cfg.outbounds.First(o => o.tag == Global.ProxyTag);
|
||||
|
||||
proxy.type.Should().Be("hysteria2");
|
||||
proxy.realm.Should().NotBeNull();
|
||||
proxy.realm!.server_url.Should().StartWith("https://");
|
||||
proxy.realm.server_url.Should().Contain("realm.hy2.io");
|
||||
proxy.realm.token.Should().Be("public");
|
||||
proxy.realm.realm_id.Should().Be("my-realm-id");
|
||||
proxy.realm.stun_servers.Should().Contain("turn.cloudflare.com:3478");
|
||||
proxy.server.Should().BeNull();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using AwesomeAssertions;
|
||||
using ServiceLib.Handler.Fmt;
|
||||
using ServiceLib.Models.Dto;
|
||||
using Xunit;
|
||||
|
||||
namespace ServiceLib.Tests.Fmt;
|
||||
@@ -58,4 +60,32 @@ public class HyRealmTests
|
||||
uri.Should().Contain("hysteria2+realm://mytoken@rendezvous.example.com");
|
||||
uri.Should().EndWith("#remark");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToServerUrl_ShouldIncludeSchemeForSingbox()
|
||||
{
|
||||
var realm = new HyRealm(
|
||||
IsHttp: false,
|
||||
Token: "public",
|
||||
RendezvousHost: "realm.hy2.io",
|
||||
RendezvousPort: 443,
|
||||
RealmName: "my-realm-id",
|
||||
StunList: ["turn.cloudflare.com:3478"]
|
||||
);
|
||||
|
||||
realm.ToServerUrl().Should().Be("https://realm.hy2.io:443");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ResolveRealm_Issue9635_ShouldProduceHttpsServerUrl()
|
||||
{
|
||||
var str = "hysteria2+realm://public@realm.hy2.io/my-realm-id?auth=uuid&stun=turn.cloudflare.com%3A3478&sni=cloudflare.com&pinSHA256=xxx#Realm-Test";
|
||||
var resolved = Hysteria2Fmt.ResolveRealm(str, out _);
|
||||
resolved.Should().NotBeNull();
|
||||
|
||||
HyRealm.TryParse(resolved!.GetProtocolExtra().Hy2RealmUrl, out var realm).Should().BeTrue();
|
||||
realm!.ToServerUrl().Should().StartWith("https://");
|
||||
realm.ToServerUrl().Should().Contain("realm.hy2.io");
|
||||
realm.StunList.Should().Contain("turn.cloudflare.com:3478");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,11 @@ public class Global
|
||||
public const string KillAsSudoOSXShellFileName = NamespaceSample + "kill_as_sudo_osx_sh";
|
||||
public const string KillAsSudoLinuxShellFileName = NamespaceSample + "kill_as_sudo_linux_sh";
|
||||
public const string SingboxFakeIPFilterFileName = NamespaceSample + "singbox_fakeip_filter";
|
||||
public const string ChromeRootCertFileName = NamespaceSample + "chrome_roots_pem";
|
||||
public const string MozillaRootCertFileName = NamespaceSample + "mozilla_roots_pem";
|
||||
|
||||
public const string ChromeRootProvider = "chrome";
|
||||
public const string MozillaRootProvider = "mozilla";
|
||||
|
||||
public const string DefaultSecurity = "auto";
|
||||
public const string DefaultNetwork = "raw";
|
||||
@@ -92,6 +97,7 @@ public class Global
|
||||
public const string LinuxBash = "/bin/bash";
|
||||
public const string StringTrue = "true";
|
||||
public const string StringFalse = "false";
|
||||
public const int SqliteMaxBatchSize = 10000;
|
||||
|
||||
public const string SingboxDirectDNSTag = "direct_dns";
|
||||
public const string SingboxRemoteDNSTag = "remote_dns";
|
||||
@@ -731,5 +737,12 @@ public class Global
|
||||
"reply",
|
||||
];
|
||||
|
||||
public static readonly List<string> RootCertProviders =
|
||||
[
|
||||
"system",
|
||||
ChromeRootProvider,
|
||||
MozillaRootProvider,
|
||||
];
|
||||
|
||||
#endregion const
|
||||
}
|
||||
|
||||
@@ -95,6 +95,10 @@ public static class ConfigHandler
|
||||
EnableLegacyProtect = false,
|
||||
};
|
||||
config.GuiItem ??= new();
|
||||
if (!Global.RootCertProviders.Contains(config.GuiItem.RootCertProvider))
|
||||
{
|
||||
config.GuiItem.RootCertProvider = Global.RootCertProviders.First();
|
||||
}
|
||||
config.MsgUIItem ??= new();
|
||||
|
||||
config.UiItem ??= new();
|
||||
@@ -160,11 +164,7 @@ public static class ConfigHandler
|
||||
config.ClashUIItem.ConnectionsColumnItem ??= [];
|
||||
config.SystemProxyItem ??= new();
|
||||
config.WebDavItem ??= new();
|
||||
config.CheckUpdateItem ??= new();
|
||||
config.NetBridgeItem ??= new()
|
||||
{
|
||||
RuleProcess = string.Empty
|
||||
};
|
||||
config.CheckUpdateItem ??= new();
|
||||
config.Fragment4RayItem ??= new()
|
||||
{
|
||||
Packets = "tlshello",
|
||||
|
||||
@@ -38,7 +38,7 @@ public static class ConnectionHandler
|
||||
|
||||
for (var i = 0; i < 2; i++)
|
||||
{
|
||||
responseTime = await GetRealPingTime(webProxy, 10);
|
||||
responseTime = await GetRealPingTime(webProxy);
|
||||
if (responseTime > 0)
|
||||
{
|
||||
break;
|
||||
@@ -66,7 +66,7 @@ public static class ConnectionHandler
|
||||
/// <summary>
|
||||
/// Measures response time by sending HTTP requests through proxy.
|
||||
/// </summary>
|
||||
public static async Task<int> GetRealPingTime(IWebProxy? webProxy, int downloadTimeout)
|
||||
public static async Task<int> GetRealPingTime(IWebProxy? webProxy, int downloadTimeout = 9)
|
||||
{
|
||||
var url = AppManager.Instance.Config.SpeedTestItem.SpeedPingTestUrl;
|
||||
var responseTime = -1;
|
||||
@@ -77,7 +77,8 @@ public static class ConnectionHandler
|
||||
using var client = new HttpClient(new SocketsHttpHandler()
|
||||
{
|
||||
Proxy = webProxy,
|
||||
UseProxy = webProxy != null
|
||||
UseProxy = webProxy != null,
|
||||
ConnectTimeout = TimeSpan.FromSeconds(3)
|
||||
});
|
||||
|
||||
List<int> oneTime = [];
|
||||
|
||||
@@ -110,6 +110,7 @@ public class Hysteria2Fmt : BaseFmt
|
||||
Hy2RealmUrl = realm.ToUri(),
|
||||
});
|
||||
|
||||
msg = string.Empty;
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Security.Authentication;
|
||||
using Downloader;
|
||||
|
||||
namespace ServiceLib.Helper;
|
||||
@@ -14,6 +15,8 @@ public class DownloaderHelper
|
||||
return null;
|
||||
}
|
||||
|
||||
var connectTimeout = Math.Clamp(timeout / 5, 2, 5);
|
||||
|
||||
Uri uri = new(url);
|
||||
//Authorization Header
|
||||
var headers = new WebHeaderCollection();
|
||||
@@ -22,17 +25,19 @@ public class DownloaderHelper
|
||||
headers.Add(HttpRequestHeader.Authorization, "Basic " + Utils.Base64Encode(uri.UserInfo));
|
||||
}
|
||||
|
||||
var requestConfiguration = new RequestConfiguration()
|
||||
{
|
||||
Headers = headers,
|
||||
UserAgent = userAgent,
|
||||
ConnectTimeout = connectTimeout * 1000,
|
||||
Proxy = webProxy
|
||||
};
|
||||
var downloadOpt = new DownloadConfiguration()
|
||||
{
|
||||
BlockTimeout = timeout * 1000,
|
||||
MaxTryAgainOnFailure = 2,
|
||||
RequestConfiguration =
|
||||
{
|
||||
Headers = headers,
|
||||
UserAgent = userAgent,
|
||||
ConnectTimeout = timeout * 1000,
|
||||
Proxy = webProxy
|
||||
}
|
||||
RequestConfiguration = requestConfiguration,
|
||||
CustomHttpMessageHandlerFactory = () => GetSocketsHttpHandler(requestConfiguration),
|
||||
};
|
||||
|
||||
await using var downloader = new Downloader.DownloadService(downloadOpt);
|
||||
@@ -45,7 +50,9 @@ public class DownloaderHelper
|
||||
};
|
||||
|
||||
using var cts = new CancellationTokenSource();
|
||||
await using var stream = await downloader.DownloadFileTaskAsync(address: url, cts.Token).WaitAsync(TimeSpan.FromSeconds(timeout), cts.Token);
|
||||
cts.CancelAfter(TimeSpan.FromSeconds(timeout));
|
||||
|
||||
await using var stream = await downloader.DownloadFileTaskAsync(address: url, cts.Token);
|
||||
using StreamReader reader = new(stream);
|
||||
|
||||
downloadOpt = null;
|
||||
@@ -60,15 +67,18 @@ public class DownloaderHelper
|
||||
throw new ArgumentNullException(nameof(url));
|
||||
}
|
||||
|
||||
var connectTimeout = Math.Clamp(timeout / 5, 2, 5);
|
||||
var requestConfiguration = new RequestConfiguration()
|
||||
{
|
||||
ConnectTimeout = connectTimeout * 1000,
|
||||
Proxy = webProxy
|
||||
};
|
||||
var downloadOpt = new DownloadConfiguration()
|
||||
{
|
||||
BlockTimeout = timeout * 1000,
|
||||
MaxTryAgainOnFailure = 2,
|
||||
RequestConfiguration =
|
||||
{
|
||||
ConnectTimeout= timeout * 1000,
|
||||
Proxy = webProxy
|
||||
}
|
||||
RequestConfiguration = requestConfiguration,
|
||||
CustomHttpMessageHandlerFactory = () => GetSocketsHttpHandler(requestConfiguration),
|
||||
};
|
||||
|
||||
var lastUpdateTime = DateTime.Now;
|
||||
@@ -116,7 +126,7 @@ public class DownloaderHelper
|
||||
};
|
||||
//progress.Report("......");
|
||||
using var cts = new CancellationTokenSource();
|
||||
cts.CancelAfter(timeout * 1000);
|
||||
cts.CancelAfter(TimeSpan.FromSeconds(timeout));
|
||||
await using var stream = await downloader.DownloadFileTaskAsync(address: url, cts.Token);
|
||||
|
||||
downloadOpt = null;
|
||||
@@ -137,15 +147,18 @@ public class DownloaderHelper
|
||||
File.Delete(fileName);
|
||||
}
|
||||
|
||||
var connectTimeout = Math.Clamp(timeout / 5, 2, 5);
|
||||
var requestConfiguration = new RequestConfiguration()
|
||||
{
|
||||
ConnectTimeout = connectTimeout * 1000,
|
||||
Proxy = webProxy
|
||||
};
|
||||
var downloadOpt = new DownloadConfiguration()
|
||||
{
|
||||
BlockTimeout = timeout * 1000,
|
||||
MaxTryAgainOnFailure = 2,
|
||||
RequestConfiguration =
|
||||
{
|
||||
ConnectTimeout= timeout * 1000,
|
||||
Proxy = webProxy
|
||||
}
|
||||
RequestConfiguration = requestConfiguration,
|
||||
CustomHttpMessageHandlerFactory = () => GetSocketsHttpHandler(requestConfiguration),
|
||||
};
|
||||
|
||||
var progressPercentage = 0;
|
||||
@@ -182,4 +195,75 @@ public class DownloaderHelper
|
||||
|
||||
downloadOpt = null;
|
||||
}
|
||||
|
||||
// https://github.com/bezzad/Downloader/blob/a75a6e431acd6cbba6293f7afdcf676544a09174/src/Downloader/SocketClient.cs#L45
|
||||
// There is a risk of MITM attacks
|
||||
// https://github.com/bezzad/Downloader/blob/a75a6e431acd6cbba6293f7afdcf676544a09174/src/Downloader/Extensions/ExceptionHelper.cs#L111
|
||||
private static SocketsHttpHandler GetSocketsHttpHandler(RequestConfiguration config)
|
||||
{
|
||||
SocketsHttpHandler handler = new()
|
||||
{
|
||||
AllowAutoRedirect = config.AllowAutoRedirect,
|
||||
MaxAutomaticRedirections = config.MaximumAutomaticRedirections,
|
||||
AutomaticDecompression = config.AutomaticDecompression,
|
||||
PreAuthenticate = config.PreAuthenticate,
|
||||
UseCookies = config.CookieContainer != null,
|
||||
UseProxy = config.Proxy != null,
|
||||
MaxConnectionsPerServer = 1000,
|
||||
PooledConnectionIdleTimeout = config.KeepAliveTimeout,
|
||||
PooledConnectionLifetime = Timeout.InfiniteTimeSpan,
|
||||
EnableMultipleHttp2Connections = true,
|
||||
ConnectTimeout = TimeSpan.FromMilliseconds(config.ConnectTimeout)
|
||||
};
|
||||
|
||||
// Set up the SslClientAuthenticationOptions for custom certificate validation
|
||||
if (config.ClientCertificates?.Count > 0)
|
||||
{
|
||||
handler.SslOptions.ClientCertificates = config.ClientCertificates;
|
||||
}
|
||||
|
||||
handler.SslOptions.EnabledSslProtocols = SslProtocols.Tls13 | SslProtocols.Tls12;
|
||||
//handler.SslOptions.RemoteCertificateValidationCallback = ExceptionHelper.CertificateValidationCallBack;
|
||||
|
||||
var certificateChainPolicy = CertPemManager.Instance.BuildCertificateChainPolicy();
|
||||
if (certificateChainPolicy != null)
|
||||
{
|
||||
handler.SslOptions.CertificateChainPolicy = certificateChainPolicy;
|
||||
handler.SslOptions.RemoteCertificateValidationCallback = null;
|
||||
}
|
||||
|
||||
// Configure keep-alive
|
||||
if (config.KeepAlive)
|
||||
{
|
||||
handler.KeepAlivePingTimeout = config.KeepAliveTimeout;
|
||||
handler.KeepAlivePingPolicy = HttpKeepAlivePingPolicy.WithActiveRequests;
|
||||
}
|
||||
|
||||
// Configure credentials
|
||||
if (config.Credentials != null)
|
||||
{
|
||||
handler.Credentials = config.Credentials;
|
||||
handler.PreAuthenticate = config.PreAuthenticate;
|
||||
}
|
||||
|
||||
// Configure cookies
|
||||
if (handler.UseCookies && config.CookieContainer != null)
|
||||
{
|
||||
handler.CookieContainer = config.CookieContainer;
|
||||
}
|
||||
|
||||
// Configure proxy
|
||||
if (handler.UseProxy && config.Proxy != null)
|
||||
{
|
||||
handler.Proxy = config.Proxy;
|
||||
}
|
||||
|
||||
// Add expect header
|
||||
if (!string.IsNullOrWhiteSpace(config.Expect))
|
||||
{
|
||||
handler.Expect100ContinueTimeout = TimeSpan.FromSeconds(1);
|
||||
}
|
||||
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,9 +244,26 @@ public sealed class AppManager
|
||||
{
|
||||
return [];
|
||||
}
|
||||
return await SQLiteHelper.Instance.TableAsync<ProfileItem>()
|
||||
.Where(it => ids.Contains(it.IndexId))
|
||||
.ToListAsync();
|
||||
|
||||
if (ids.Count <= Global.SqliteMaxBatchSize)
|
||||
{
|
||||
return await SQLiteHelper.Instance.TableAsync<ProfileItem>()
|
||||
.Where(it => ids.Contains(it.IndexId))
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
var items = new List<ProfileItem>();
|
||||
for (var size = 0; size < ids.Count; size += Global.SqliteMaxBatchSize)
|
||||
{
|
||||
var chunk = ids.Skip(size).Take(Global.SqliteMaxBatchSize).ToList();
|
||||
var chunkItems = await SQLiteHelper.Instance.TableAsync<ProfileItem>()
|
||||
.Where(it => chunk.Contains(it.IndexId))
|
||||
.ToListAsync();
|
||||
|
||||
items.AddRange(chunkItems);
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
public async Task<Dictionary<string, ProfileItem>> GetProfileItemsByIndexIdsAsMap(IEnumerable<string> indexIds)
|
||||
@@ -257,18 +274,11 @@ public sealed class AppManager
|
||||
|
||||
public async Task<List<ProfileItem>> GetProfileItemsOrderedByIndexIds(IEnumerable<string> indexIds)
|
||||
{
|
||||
var idList = indexIds.Where(id => !id.IsNullOrEmpty()).Distinct().ToList();
|
||||
if (idList.Count == 0)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
var items = await SQLiteHelper.Instance.TableAsync<ProfileItem>()
|
||||
.Where(it => idList.Contains(it.IndexId))
|
||||
.ToListAsync();
|
||||
var ids = indexIds.Where(id => !id.IsNullOrEmpty()).Distinct().ToList();
|
||||
var items = await GetProfileItemsByIndexIds(ids);
|
||||
var itemMap = items.ToDictionary(it => it.IndexId);
|
||||
|
||||
return idList.Select(itemMap.GetValueOrDefault)
|
||||
return ids.Select(itemMap.GetValueOrDefault)
|
||||
.Where(item => item != null)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
@@ -10,180 +10,17 @@ public class CertPemManager
|
||||
{
|
||||
private static readonly string _tag = "CertPemManager";
|
||||
private static readonly Lazy<CertPemManager> _instance = new(() => new());
|
||||
private Config _config;
|
||||
|
||||
/// <summary>
|
||||
/// Trusted CA certificate thumbprints (SHA256) to prevent MITM attacks
|
||||
/// </summary>
|
||||
private static readonly HashSet<string> TrustedCaThumbprints = new(StringComparer.OrdinalIgnoreCase)
|
||||
public async Task Init(Config config)
|
||||
{
|
||||
"EBD41040E4BB3EC742C9E381D31EF2A41A48B6685C96E7CEF3C1DF6CD4331C99", // GlobalSign Root CA
|
||||
"6DC47172E01CBCB0BF62580D895FE2B8AC9AD4F873801E0C10B9C837D21EB177", // Entrust.net Premium 2048 Secure Server CA
|
||||
"73C176434F1BC6D5ADF45B0E76E727287C8DE57616C1E6E6141A2B2CBC7D8E4C", // Entrust Root Certification Authority
|
||||
"D8E0FEBC1DB2E38D00940F37D27D41344D993E734B99D5656D9778D4D8143624", // Certum Root CA
|
||||
"D7A7A0FB5D7E2731D771E9484EBCDEF71D5F0C3E0A2948782BC83EE0EA699EF4", // Comodo AAA Services root
|
||||
"85A0DD7DD720ADB7FF05F83D542B209DC7FF4528F7D677B18389FEA5E5C49E86", // QuoVadis Root CA 2
|
||||
"18F1FC7F205DF8ADDDEB7FE007DD57E3AF375A9C4D8D73546BF4F1FED1E18D35", // QuoVadis Root CA 3
|
||||
"C3846BF24B9E93CA64274C0EC67C1ECC5E024FFCACD2D74019350E81FE546AE4", // Go Daddy Class 2 CA
|
||||
"1465FA205397B876FAA6F0A9958E5590E40FCC7FAA4FB7C2C8677521FB5FB658", // Starfield Class 2 CA
|
||||
"3E9099B5015E8F486C00BCEA9D111EE721FABA355A89BCF1DF69561E3DC6325C", // DigiCert Assured ID Root CA
|
||||
"4348A0E9444C78CB265E058D5E8944B4D84F9662BD26DB257F8934A443C70161", // DigiCert Global Root CA
|
||||
"7431E5F4C3C1CE4690774F0B61E05440883BA9A01ED00BA6ABD7806ED3B118CF", // DigiCert High Assurance EV Root CA
|
||||
"62DD0BE9B9F50A163EA0F8E75C053B1ECA57EA55C8688F647C6881F2C8357B95", // SwissSign Gold CA - G2
|
||||
"0C2CD63DF7806FA399EDE809116B575BF87989F06518F9808C860503178BAF66", // COMODO Certification Authority
|
||||
"1793927A0614549789ADCE2F8F34F7F0B66D0F3AE3A3B84D21EC15DBBA4FADC7", // COMODO ECC Certification Authority
|
||||
"41C923866AB4CAD6B7AD578081582E020797A6CBDF4FFF78CE8396B38937D7F5", // OISTE WISeKey Global Root GA CA
|
||||
"E3B6A2DB2ED7CE48842F7AC53241C7B71D54144BFB40C11F3F1D0B42F5EEA12D", // Certigna
|
||||
"C0A6F4DC63A24BFDCF54EF2A6A082A0A72DE35803E2FF5FF527AE5D87206DFD5", // ePKI Root Certification Authority
|
||||
"6C61DAC3A2DEF031506BE036D2A6FE401994FBD13DF9C8D466599274C446EC98", // NetLock Arany (Class Gold) Főtanúsítvány
|
||||
"3C5F81FEA5FAB82C64BFA2EAECAFCDE8E077FC8620A7CAE537163DF36EDBF378", // Microsec e-Szigno Root CA 2009
|
||||
"CBB522D7B7F127AD6A0113865BDF1CD4102E7D0759AF635A7CF4720DC963C53B", // GlobalSign Root CA - R3
|
||||
"2530CC8E98321502BAD96F9B1FBA1B099E2D299E0F4548BB914F363BC0D4531F", // Izenpe.com
|
||||
"45140B3247EB9CC8C5B4F0D7B53091F73292089E6E5A63E2749DD3ACA9198EDA", // Go Daddy Root Certificate Authority - G2
|
||||
"2CE1CB0BF9D2F9E102993FBE215152C3B2DD0CABDE1C68E5319B839154DBB7F5", // Starfield Root Certificate Authority - G2
|
||||
"568D6905A2C88708A4B3025190EDCFEDB1974A606A13C6E5290FCB2AE63EDAB5", // Starfield Services Root Certificate Authority - G2
|
||||
"5C58468D55F58E497E743982D2B50010B6D165374ACF83A7D4A32DB768C4408E", // Certum Trusted Network CA
|
||||
"BFD88FE1101C41AE3E801BF8BE56350EE9BAD1A6B9BD515EDC5C6D5B8711AC44", // TWCA Root Certification Authority
|
||||
"513B2CECB810D4CDE5DD85391ADFC6C2DD60D87BB736D2B521484AA47A0EBEF6", // Security Communication RootCA2
|
||||
"55926084EC963A64B96E2ABE01CE0BA86A64FBFEBCC7AAB5AFC155B37FD76066", // Actalis Authentication Root CA
|
||||
"9A114025197C5BB95D94E63D55CD43790847B646B23CDF11ADA4A00EFF15FB48", // Buypass Class 2 Root CA
|
||||
"EDF7EBBCA27A2A384D387B7D4010C666E2EDB4843E4C29B4AE1D5B9332E6B24D", // Buypass Class 3 Root CA
|
||||
"FD73DAD31C644FF1B43BEF0CCDDA96710B9CD9875ECA7E31707AF3E96D522BBD", // T-TeleSec GlobalRoot Class 3
|
||||
"49E7A442ACF0EA6287050054B52564B650E4F49E42E348D6AA38E039E957B1C1", // D-TRUST Root Class 3 CA 2 2009
|
||||
"EEC5496B988CE98625B934092EEC2908BED0B0F316C2D4730C84EAF1F3D34881", // D-TRUST Root Class 3 CA 2 EV 2009
|
||||
"E23D4A036D7B70E9F595B1422079D2B91EDFBB1FB651A0633EAA8A9DC5F80703", // CA Disig Root R2
|
||||
"9A6EC012E1A7DA9DBE34194D478AD7C0DB1822FB071DF12981496ED104384113", // ACCVRAIZ1
|
||||
"59769007F7685D0FCD50872F9F95D5755A5B2B457D81F3692B610A98672F0E1B", // TWCA Global Root CA
|
||||
"91E2F5788D5810EBA7BA58737DE1548A8ECACD014598BC0B143E041B17052552", // T-TeleSec GlobalRoot Class 2
|
||||
"F356BEA244B7A91EB35D53CA9AD7864ACE018E2D35D5F8F96DDF68A6F41AA474", // Atos TrustedRoot 2011
|
||||
"8A866FD1B276B57E578E921C65828A2BED58E9F2F288054134B7F1F4BFC9CC74", // QuoVadis Root CA 1 G3
|
||||
"8FE4FB0AF93A4D0D67DB0BEBB23E37C71BF325DCBCDD240EA04DAF58B47E1840", // QuoVadis Root CA 2 G3
|
||||
"88EF81DE202EB018452E43F864725CEA5FBD1FC2D9D205730709C5D8B8690F46", // QuoVadis Root CA 3 G3
|
||||
"7D05EBB682339F8C9451EE094EEBFEFA7953A114EDB2F44949452FAB7D2FC185", // DigiCert Assured ID Root G2
|
||||
"7E37CB8B4C47090CAB36551BA6F45DB840680FBA166A952DB100717F43053FC2", // DigiCert Assured ID Root G3
|
||||
"CB3CCBB76031E5E0138F8DD39A23F9DE47FFC35E43C1144CEA27D46A5AB1CB5F", // DigiCert Global Root G2
|
||||
"31AD6648F8104138C738F39EA4320133393E3A18CC02296EF97C2AC9EF6731D0", // DigiCert Global Root G3
|
||||
"552F7BDCF1A7AF9E6CE672017F4F12ABF77240C78E761AC203D1D9D20AC89988", // DigiCert Trusted Root G4
|
||||
"52F0E1C4E58EC629291B60317F074671B85D7EA80D5B07273463534B32B40234", // COMODO RSA Certification Authority
|
||||
"E793C9B02FD8AA13E21C31228ACCB08119643B749C898964B1746D46C3D4CBD2", // USERTrust RSA Certification Authority
|
||||
"4FF460D54B9C86DABFBCFC5712E0400D2BED3FBC4D4FBDAA86E06ADCD2A9AD7A", // USERTrust ECC Certification Authority
|
||||
"179FBC148A3DD00FD24EA13458CC43BFA7F59C8182D783A513F6EBEC100C8924", // GlobalSign ECC Root CA - R5
|
||||
"3C4FB0B95AB8B30032F432B86F535FE172C185D0FD39865837CF36187FA6F428", // Staat der Nederlanden Root CA - G3
|
||||
"5D56499BE4D2E08BCFCAD08A3E38723D50503BDE706948E42F55603019E528AE", // IdenTrust Commercial Root CA 1
|
||||
"30D0895A9A448A262091635522D1F52010B5867ACAE12C78EF958FD4F4389F2F", // IdenTrust Public Sector Root CA 1
|
||||
"43DF5774B03E7FEF5FE40D931A7BEDF1BB2E6B42738C4E6D3841103D3AA7F339", // Entrust Root Certification Authority - G2
|
||||
"02ED0EB28C14DA45165C566791700D6451D7FB56F0B2AB1D3B8EB070E56EDFF5", // Entrust Root Certification Authority - EC1
|
||||
"5CC3D78E4E1D5E45547A04E6873E64F90CF9536D1CCC2EF800F355C4C5FD70FD", // CFCA EV ROOT
|
||||
"6B9C08E86EB0F767CFAD65CD98B62149E5494A67F5845E7BD1ED019F27B86BD6", // OISTE WISeKey Global Root GB CA
|
||||
"A1339D33281A0B56E557D3D32B1CE7F9367EB094BD5FA72A7E5004C8DED7CAFE", // SZAFIR ROOT CA2
|
||||
"B676F2EDDAE8775CD36CB0F63CD1D4603961F49E6265BA013A2F0307B6D0B804", // Certum Trusted Network CA 2
|
||||
"A040929A02CE53B4ACF4F2FFC6981CE4496F755E6D45FE0B2A692BCD52523F36", // Hellenic Academic and Research Institutions RootCA 2015
|
||||
"44B545AA8A25E65A73CA15DC27FC36D24C1CB9953A066539B11582DC487B4833", // Hellenic Academic and Research Institutions ECC RootCA 2015
|
||||
"96BCEC06264976F37460779ACF28C5A7CFE8A3C0AAE11A8FFCEE05C0BDDF08C6", // ISRG Root X1
|
||||
"EBC5570C29018C4D67B1AA127BAF12F703B4611EBC17B7DAB5573894179B93FA", // AC RAIZ FNMT-RCM
|
||||
"8ECDE6884F3D87B1125BA31AC3FCB13D7016DE7F57CC904FE1CB97C6AE98196E", // Amazon Root CA 1
|
||||
"1BA5B2AA8C65401A82960118F80BEC4F62304D83CEC4713A19C39C011EA46DB4", // Amazon Root CA 2
|
||||
"18CE6CFE7BF14E60B2E347B8DFE868CB31D02EBB3ADA271569F50343B46DB3A4", // Amazon Root CA 3
|
||||
"E35D28419ED02025CFA69038CD623962458DA5C695FBDEA3C22B0BFB25897092", // Amazon Root CA 4
|
||||
"A1A86D04121EB87F027C66F53303C28E5739F943FC84B38AD6AF009035DD9457", // D-TRUST Root CA 3 2013
|
||||
"46EDC3689046D53A453FB3104AB80DCAEC658B2660EA1629DD7E867990648716", // TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1
|
||||
"BFFF8FD04433487D6A8AA60C1A29767A9FC2BBB05E420F713A13B992891D3893", // GDCA TrustAUTH R5 ROOT
|
||||
"85666A562EE0BE5CE925C1D8890A6F76A87EC16D4D7D5F29EA7419CF20123B69", // SSL.com Root Certification Authority RSA
|
||||
"3417BB06CC6007DA1B961C920B8AB4CE3FAD820E4AA30B9ACBC4A74EBDCEBC65", // SSL.com Root Certification Authority ECC
|
||||
"2E7BF16CC22485A7BBE2AA8696750761B0AE39BE3B2FE9D0CC6D4EF73491425C", // SSL.com EV Root Certification Authority RSA R2
|
||||
"22A2C1F7BDED704CC1E701B5F408C310880FE956B5DE2A4A44F99C873A25A7C8", // SSL.com EV Root Certification Authority ECC
|
||||
"2CABEAFE37D06CA22ABA7391C0033D25982952C453647349763A3AB5AD6CCF69", // GlobalSign Root CA - R6
|
||||
"8560F91C3624DABA9570B5FEA0DBE36FF11A8323BE9486854FB3F34A5571198D", // OISTE WISeKey Global Root GC CA
|
||||
"9BEA11C976FE014764C1BE56A6F914B5A560317ABD9988393382E5161AA0493C", // UCA Global G2 Root
|
||||
"D43AF9B35473755C9684FC06D7D8CB70EE5C28E773FB294EB41EE71722924D24", // UCA Extended Validation Root
|
||||
"D48D3D23EEDB50A459E55197601C27774B9D7B18C94D5A059511A10250B93168", // Certigna Root CA
|
||||
"40F6AF0346A99AA1CD1D555A4E9CCE62C7F9634603EE406615833DC8C8D00367", // emSign Root CA - G1
|
||||
"86A1ECBA089C4A8D3BBE2734C612BA341D813E043CF9E8A862CD5C57A36BBE6B", // emSign ECC Root CA - G3
|
||||
"125609AA301DA0A249B97A8239CB6A34216F44DCAC9F3954B14292F2E8C8608F", // emSign Root CA - C1
|
||||
"BC4D809B15189D78DB3E1D8CF4F9726A795DA1643CA5F1358E1DDB0EDC0D7EB3", // emSign ECC Root CA - C3
|
||||
"5A2FC03F0C83B090BBFA40604B0988446C7636183DF9846E17101A447FB8EFD6", // Hongkong Post Root CA 3
|
||||
"DB3517D1F6732A2D5AB97C533EC70779EE3270A62FB4AC4238372460E6F01E88", // Entrust Root Certification Authority - G4
|
||||
"358DF39D764AF9E1B766E9C972DF352EE15CFAC227AF6AD1D70E8E4A6EDCBA02", // Microsoft ECC Root Certificate Authority 2017
|
||||
"C741F70F4B2A8D88BF2E71C14122EF53EF10EBA0CFA5E64CFA20F418853073E0", // Microsoft RSA Root Certificate Authority 2017
|
||||
"BEB00B30839B9BC32C32E4447905950641F26421B15ED089198B518AE2EA1B99", // e-Szigno Root CA 2017
|
||||
"657CFE2FA73FAA38462571F332A2363A46FCE7020951710702CDFBB6EEDA3305", // certSIGN Root CA G2
|
||||
"88F438DCF8FFD1FA8F429115FFE5F82AE1E06E0C70C375FAAD717B34A49E7265", // NAVER Global Root Certification Authority
|
||||
"554153B13D2CF9DDB753BFBE1A4E0AE08D0AA4187058FE60A2B862B2E4B87BCB", // AC RAIZ FNMT-RCM SERVIDORES SEGUROS
|
||||
"319AF0A7729E6F89269C131EA6A3A16FCD86389FDCAB3C47A4A675C161A3F974", // GlobalSign Secure Mail Root R45
|
||||
"5CBF6FB81FD417EA4128CD6F8172A3C9402094F74AB2ED3A06B4405D04F30B19", // GlobalSign Secure Mail Root E45
|
||||
"4FA3126D8D3A11D1C4855A4F807CBAD6CF919D3A5A88B03BEA2C6372D93C40C9", // GlobalSign Root R46
|
||||
"CBB9C44D84B8043E1050EA31A69F514955D7BFD2E2C6B49301019AD61D9F5058", // GlobalSign Root E46
|
||||
"FB8FEC759169B9106B1E511644C618C51304373F6C0643088D8BEFFD1B997599", // ANF Secure Server Root CA
|
||||
"6B328085625318AA50D173C98D8BDA09D57E27413D114CF787A0F5D06C030CF6", // Certum EC-384 CA
|
||||
"FE7696573855773E37A95E7AD4D9CC96C30157C15D31765BA9B15704E1AE78FD", // Certum Trusted Root CA
|
||||
"2E44102AB58CB85419451C8E19D9ACF3662CAFBC614B6A53960A30F7D0E2EB41", // TunTrust Root CA
|
||||
"D95D0E8EDA79525BF9BEB11B14D2100D3294985F0C62D9FABD9CD999ECCB7B1D", // HARICA TLS RSA Root CA 2021
|
||||
"3F99CC474ACFCE4DFED58794665E478D1547739F2E780F1BB4CA9B133097D401", // HARICA TLS ECC Root CA 2021
|
||||
"1BE7ABE30686B16348AFD1C61B6866A0EA7F4821E67D5E8AF937CF8011BC750D", // HARICA Client RSA Root CA 2021
|
||||
"8DD4B5373CB0DE36769C12339280D82746B3AA6CD426E797A31BABE4279CF00B", // HARICA Client ECC Root CA 2021
|
||||
"57DE0583EFD2B26E0361DA99DA9DF4648DEF7EE8441C3B728AFA9BCDE0F9B26A", // Autoridad de Certificacion Firmaprofesional CIF A62634068
|
||||
"30FBBA2C32238E2A98547AF97931E550428B9B3F1C8EEB6633DCFA86C5B27DD3", // vTrus ECC Root CA
|
||||
"8A71DE6559336F426C26E53880D00D88A18DA4C6A91F0DCB6194E206C5C96387", // vTrus Root CA
|
||||
"69729B8E15A86EFC177A57AFB7171DFC64ADD28C2FCA8CF1507E34453CCB1470", // ISRG Root X2
|
||||
"F015CE3CC239BFEF064BE9F1D2C417E1A0264A0A94BE1F0C8D121864EB6949CC", // HiPKI Root CA - G1
|
||||
"B085D70B964F191A73E4AF0D54AE7A0E07AAFDAF9B71DD0862138AB7325A24A2", // GlobalSign ECC Root CA - R4
|
||||
"D947432ABDE7B7FA90FC2E6B59101B1280E0E1C7E4E40FA3C6887FFF57A7F4CF", // GTS Root R1
|
||||
"8D25CD97229DBF70356BDA4EB3CC734031E24CF00FAFCFD32DC76EB5841C7EA8", // GTS Root R2
|
||||
"34D8A73EE208D9BCDB0D956520934B4E40E69482596E8B6F73C8426B010A6F48", // GTS Root R3
|
||||
"349DFA4058C5E263123B398AE795573C4E1313C83FE68F93556CD5E8031B3C7D", // GTS Root R4
|
||||
"242B69742FCB1E5B2ABF98898B94572187544E5B4D9911786573621F6A74B82C", // Telia Root CA v2
|
||||
"E59AAA816009C22BFF5B25BAD37DF306F049797C1F81D85AB089E657BD8F0044", // D-TRUST BR Root CA 1 2020
|
||||
"08170D1AA36453901A2F959245E347DB0C8D37ABAABC56B81AA100DC958970DB", // D-TRUST EV Root CA 1 2020
|
||||
"018E13F0772532CF809BD1B17281867283FC48C6E13BE9C69812854A490C1B05", // DigiCert TLS ECC P384 Root G5
|
||||
"371A00DC0533B3721A7EEB40E8419E70799D2B0A0F2C1D80693165F7CEC4AD75", // DigiCert TLS RSA4096 Root G5
|
||||
"E8E8176536A60CC2C4E10187C3BEFCA20EF263497018F566D5BEA0F94D0C111B", // DigiCert SMIME ECC P384 Root G5
|
||||
"90370D3EFA88BF58C30105BA25104A358460A7FA52DFC2011DF233A0F417912A", // DigiCert SMIME RSA4096 Root G5
|
||||
"77B82CD8644C4305F7ACC5CB156B45675004033D51C60C6202A8E0C33467D3A0", // Certainly Root R1
|
||||
"B4585F22E4AC756A4E8612A1361C5D9D031A93FD84FEBB778FA3068B0FC42DC2", // Certainly Root E1
|
||||
"82BD5D851ACF7F6E1BA7BFCBC53030D0E7BC3C21DF772D858CAB41D199BDF595", // DIGITALSIGN GLOBAL ROOT RSA CA
|
||||
"261D7114AE5F8FF2D8C7209A9DE4289E6AFC9D717023D85450909199F1857CFE", // DIGITALSIGN GLOBAL ROOT ECDSA CA
|
||||
"E74FBDA55BD564C473A36B441AA799C8A68E077440E8288B9FA1E50E4BBACA11", // Security Communication ECC RootCA1
|
||||
"F3896F88FE7C0A882766A7FA6AD2749FB57A7F3E98FB769C1FA7B09C2C44D5AE", // BJCA Global Root CA1
|
||||
"574DF6931E278039667B720AFDC1600FC27EB66DD3092979FB73856487212882", // BJCA Global Root CA2
|
||||
"48E1CF9E43B688A51044160F46D773B8277FE45BEAAD0E4DF90D1974382FEA99", // LAWtrust Root CA2 (4096)
|
||||
"22D9599234D60F1D4BC7C7E96F43FA555B07301FD475175089DAFB8C25E477B3", // Sectigo Public Email Protection Root E46
|
||||
"D5917A7791EB7CF20A2E57EB98284A67B28A57E89182DA53D546678C9FDE2B4F", // Sectigo Public Email Protection Root R46
|
||||
"C90F26F0FB1B4018B22227519B5CA2B53E2CA5B3BE5CF18EFE1BEF47380C5383", // Sectigo Public Server Authentication Root E46
|
||||
"7BB647A62AEEAC88BF257AA522D01FFEA395E0AB45C73F93F65654EC38F25A06", // Sectigo Public Server Authentication Root R46
|
||||
"8FAF7D2E2CB4709BB8E0B33666BF75A5DD45B5DE480F8EA8D4BFE6BEBC17F2ED", // SSL.com TLS RSA Root CA 2022
|
||||
"C32FFD9F46F936D16C3673990959434B9AD60AAFBB9E7CF33654F144CC1BA143", // SSL.com TLS ECC Root CA 2022
|
||||
"AD7DD58D03AEDB22A30B5084394920CE12230C2D8017AD9B81AB04079BDD026B", // SSL.com Client ECC Root CA 2022
|
||||
"1D4CA4A2AB21D0093659804FC0EB2175A617279B56A2475245C9517AFEB59153", // SSL.com Client RSA Root CA 2022
|
||||
"E38655F4B0190C84D3B3893D840A687E190A256D98052F159E6D4A39F589A6EB", // Atos TrustedRoot Root CA ECC G2 2020
|
||||
"78833A783BB2986C254B9370D3C20E5EBA8FA7840CBF63FE17297A0B0119685E", // Atos TrustedRoot Root CA RSA G2 2020
|
||||
"B2FAE53E14CCD7AB9212064701AE279C1D8988FACB775FA8A008914E663988A8", // Atos TrustedRoot Root CA ECC TLS 2021
|
||||
"81A9088EA59FB364C548A6F85559099B6F0405EFBF18E5324EC9F457BA00112F", // Atos TrustedRoot Root CA RSA TLS 2021
|
||||
"E0D3226AEB1163C2E48FF9BE3B50B4C6431BE7BB1EACC5C36B5D5EC509039A08", // TrustAsia Global Root CA G3
|
||||
"BE4B56CB5056C0136A526DF444508DAA36A0B54F42E4AC38F72AF470E479654C", // TrustAsia Global Root CA G4
|
||||
"D92C171F5CF890BA428019292927FE22F3207FD2B54449CB6F675AF4922146E2", // D-Trust SBR Root CA 1 2022
|
||||
"DBA84DD7EF622D485463A90137EA4D574DF8550928F6AFA03B4D8B1141E636CC", // D-Trust SBR Root CA 2 2022
|
||||
"3AE6DF7E0D637A65A8C81612EC6F9A142F85A16834C10280D88E707028518755", // Telekom Security SMIME ECC Root 2021
|
||||
"578AF4DED0853F4E5998DB4AEAF9CBEA8D945F60B620A38D1A3C13B2BC7BA8E1", // Telekom Security TLS ECC Root 2020
|
||||
"78A656344F947E9CC0F734D9053D32F6742086B6B9CD2CAE4FAE1A2E4EFDE048", // Telekom Security SMIME RSA Root 2023
|
||||
"EFC65CADBB59ADB6EFE84DA22311B35624B71B3B1EA0DA8B6655174EC8978646", // Telekom Security TLS RSA Root 2023
|
||||
"3F63BB2814BE174EC8B6439CF08D6D56F0B7C405883A5648A334424D6B3EC558", // TWCA CYBER Root CA
|
||||
"3A0072D49FFC04E996C59AEB75991D3C340F3615D6FD4DCE90AC0B3D88EAD4F4", // TWCA Global Root CA G2
|
||||
"3F034BB5704D44B2D08545A02057DE93EBF3905FCE721ACBC730C06DDAEE904E", // SecureSign Root CA12
|
||||
"4B009C1034494F9AB56BBA3BA1D62731FC4D20D8955ADCEC10A925607261E338", // SecureSign Root CA14
|
||||
"E778F0F095FE843729CD1A0082179E5314A9C291442805E1FB1D8FB6B8886C3A", // SecureSign Root CA15
|
||||
"0552E6F83FDF65E8FA9670E666DF28A4E21340B510CBE52566F97C4FB94B2BD1", // D-TRUST BR Root CA 2 2023
|
||||
"436472C1009A325C54F1A5BBB5468A7BAEECCBE05DE5F099CB70D3FE41E13C16", // TrustAsia SMIME ECC Root CA
|
||||
"C7796BEB62C101BB143D262A7C96A0C6168183223EF50D699632D86E03B8CC9B", // TrustAsia SMIME RSA Root CA
|
||||
"C0076B9EF0531FB1A656D67C4EBE97CD5DBAA41EF44598ACC2489878C92D8711", // TrustAsia TLS ECC Root CA
|
||||
"06C08D7DAFD876971EB1124FE67F847EC0C7A158D3EA53CBE940E2EA9791F4C3", // TrustAsia TLS RSA Root CA
|
||||
"8E8221B2E7D4007836A1672F0DCC299C33BC07D316F132FA1A206D587150F1CE", // D-TRUST EV Root CA 2 2023
|
||||
"9A12C392BFE57891A0C545309D4D9FD567E480CB613D6342278B195C79A7931F", // SwissSign RSA SMIME Root CA 2022 - 1
|
||||
"193144F431E0FDDB740717D4DE926A571133884B4360D30E272913CBE660CE41", // SwissSign RSA TLS Root CA 2022 - 1
|
||||
"D9A32485A8CCA85539CEF12FFFFF711378A17851D73DA2732AB4302D763BD62B", // OISTE Client Root ECC G1
|
||||
"D02A0F994A868C66395F2E7A880DF509BD0C29C96DE16015A0FD501EDA4F96A9", // OISTE Client Root RSA G1
|
||||
"EEC997C0C30F216F7E3B8B307D2BAE42412D753FC8219DAFD1520B2572850F49", // OISTE Server Root ECC G1
|
||||
"9AE36232A5189FFDDB353DFD26520C015395D22777DAC59DB57B98C089A651E6", // OISTE Server Root RSA G1
|
||||
"B49141502D00663D740F2E7EC340C52800962666121A36D09CF7DD2B90384FB4", // e-Szigno TLS Root CA 2023
|
||||
};
|
||||
if (_config != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_config = config;
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
public static CertPemManager Instance => _instance.Value;
|
||||
|
||||
@@ -292,7 +129,7 @@ public class CertPemManager
|
||||
/// <summary>
|
||||
/// Validate server certificate with CA pinning
|
||||
/// </summary>
|
||||
private static bool ValidateServerCertificate(
|
||||
private bool ValidateServerCertificate(
|
||||
object _,
|
||||
X509Certificate? certificate,
|
||||
X509Chain? chain,
|
||||
@@ -327,9 +164,10 @@ public class CertPemManager
|
||||
}
|
||||
|
||||
var rootCert = certChain.ChainElements[^1].Certificate;
|
||||
var rootThumbprint = rootCert.GetCertHashString(HashAlgorithmName.SHA256);
|
||||
|
||||
if (!TrustedCaThumbprints.Contains(rootThumbprint))
|
||||
var trustedCerts = BuildTrustedCertificateCollection();
|
||||
|
||||
if (!trustedCerts.Contains(rootCert))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -442,4 +280,48 @@ public class CertPemManager
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Lazy<X509Certificate2Collection> _chromeRootCerts = new(() =>
|
||||
{
|
||||
var pemText = EmbedUtils.GetEmbedText(Global.ChromeRootCertFileName);
|
||||
var collection = new X509Certificate2Collection();
|
||||
collection.ImportFromPem(pemText);
|
||||
return collection;
|
||||
});
|
||||
private static readonly Lazy<X509Certificate2Collection> _mozillaRootCerts = new(() =>
|
||||
{
|
||||
var pemText = EmbedUtils.GetEmbedText(Global.MozillaRootCertFileName);
|
||||
var collection = new X509Certificate2Collection();
|
||||
collection.ImportFromPem(pemText);
|
||||
return collection;
|
||||
});
|
||||
private X509Certificate2Collection BuildTrustedCertificateCollection()
|
||||
{
|
||||
if (_config.GuiItem.RootCertProvider == Global.ChromeRootProvider)
|
||||
{
|
||||
return _chromeRootCerts.Value;
|
||||
}
|
||||
return _mozillaRootCerts.Value;
|
||||
}
|
||||
|
||||
private bool IsSystemRootCertProvider()
|
||||
{
|
||||
return _config.GuiItem.RootCertProvider != Global.ChromeRootProvider && _config.GuiItem.RootCertProvider != Global.MozillaRootProvider;
|
||||
}
|
||||
|
||||
public X509ChainPolicy? BuildCertificateChainPolicy()
|
||||
{
|
||||
if (IsSystemRootCertProvider())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var trustedCerts = BuildTrustedCertificateCollection();
|
||||
var chainPolicy = new X509ChainPolicy
|
||||
{
|
||||
TrustMode = X509ChainTrustMode.CustomRootTrust,
|
||||
RevocationMode = X509RevocationMode.NoCheck,
|
||||
};
|
||||
chainPolicy.CustomTrustStore.AddRange(trustedCerts);
|
||||
return chainPolicy;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,6 +90,7 @@ public class CoreManager
|
||||
}
|
||||
|
||||
await CoreStart(mainContext);
|
||||
await WaitForProxyPort(preContext);
|
||||
await CoreStartPreService(preContext);
|
||||
|
||||
AppManager.Instance.RunningCoreType = preContext?.RunCoreType ?? mainContext.RunCoreType;
|
||||
@@ -213,6 +214,75 @@ public class CoreManager
|
||||
await _updateFunc?.Invoke(notify, msg);
|
||||
}
|
||||
|
||||
private static async Task WaitForProxyPort(CoreConfigContext? preContext, int timeoutMs = 5000)
|
||||
{
|
||||
if (preContext is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!preContext.AppConfig.TunModeItem.EnableTun)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using var rootCts = new CancellationTokenSource(TimeSpan.FromMilliseconds(timeoutMs));
|
||||
var rootToken = rootCts.Token;
|
||||
|
||||
var port = preContext.Node.Port;
|
||||
// SOCKS5 client greeting: VER=5, NMETHODS=1, METHOD=0x00 (no auth)
|
||||
ReadOnlyMemory<byte> greeting = new byte[] { 0x05, 0x01, 0x00 };
|
||||
var buf = new byte[2];
|
||||
|
||||
while (!rootToken.IsCancellationRequested)
|
||||
{
|
||||
using var tcp = new TcpClient();
|
||||
using var attemptCts = new CancellationTokenSource(TimeSpan.FromMilliseconds(50));
|
||||
using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(rootToken, attemptCts.Token);
|
||||
var linkedToken = linkedCts.Token;
|
||||
try
|
||||
{
|
||||
await tcp.ConnectAsync(Global.Loopback, port, linkedToken);
|
||||
var stream = tcp.GetStream();
|
||||
|
||||
await stream.WriteAsync(greeting, linkedToken);
|
||||
|
||||
var read = await stream.ReadAsync(buf.AsMemory(0, 2), linkedToken);
|
||||
|
||||
// Server selection: VER=5, METHOD=0x00 — proxy is fully ready
|
||||
if (read == 2 && buf[0] == 0x05)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
if (!rootToken.IsCancellationRequested)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Logging.SaveLog($"WaitForProxyPort Timeout waiting for proxy port {port} to be ready.");
|
||||
return;
|
||||
}
|
||||
catch (SocketException ex) when (ex.SocketErrorCode == SocketError.ConnectionRefused)
|
||||
{
|
||||
// Connection refused, proxy not ready yet, wait 50ms before retrying
|
||||
try
|
||||
{
|
||||
await Task.Delay(50, rootToken);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
Logging.SaveLog($"WaitForProxyPort Timeout waiting for proxy port {port} to be ready.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore other exceptions and continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Private
|
||||
|
||||
#region Process
|
||||
|
||||
@@ -1,239 +0,0 @@
|
||||
using NetBridgeLib.Services;
|
||||
|
||||
namespace ServiceLib.Manager;
|
||||
|
||||
public sealed class NetBridgeManager
|
||||
{
|
||||
private static readonly Lazy<NetBridgeManager> _instance = new(() => new());
|
||||
public static NetBridgeManager Instance => _instance.Value;
|
||||
private readonly Config _config = AppManager.Instance.Config;
|
||||
private NetBridgeService? _netBridgeService;
|
||||
private bool _isProxyRunning;
|
||||
private bool _isInitialized;
|
||||
private List<NetBridgeRuleConfig> _ruleConfigs = [];
|
||||
private Func<bool, string, Task>? _updateFunc;
|
||||
private uint _proxyConfigId;
|
||||
|
||||
public async Task Init(Func<bool, string, Task>? updateFunc = null)
|
||||
{
|
||||
if (_isInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_updateFunc = updateFunc;
|
||||
|
||||
try
|
||||
{
|
||||
_netBridgeService = new NetBridgeService();
|
||||
_netBridgeService.LogReceived += msg =>
|
||||
{
|
||||
var message = $"NetBridge Log: {msg}";
|
||||
_ = _updateFunc?.Invoke(false, message);
|
||||
};
|
||||
|
||||
_netBridgeService.ConnectionReceived += (processName, pid, destIp, destPort, proxyInfo) =>
|
||||
{
|
||||
var message = $"NetBridge Connection: {processName} (PID: {pid}) -> {destIp}:{destPort} -> {proxyInfo}";
|
||||
_ = _updateFunc?.Invoke(false, message);
|
||||
};
|
||||
|
||||
_ruleConfigs = BuildRuleConfigs(_config.NetBridgeItem?.RuleProcess);
|
||||
_isInitialized = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var error = $"Failed to initialize NetBridgeService: {ex.Message}";
|
||||
await _updateFunc?.Invoke(true, error);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> Start()
|
||||
{
|
||||
if (_isProxyRunning)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (_netBridgeService == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var started = _netBridgeService.Start();
|
||||
if (!started)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_isProxyRunning = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var error = $"Failed to start NetBridgeService: {ex.Message}";
|
||||
await _updateFunc?.Invoke(true, error);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<bool> Stop()
|
||||
{
|
||||
if (!_isProxyRunning)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (_netBridgeService == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var stopped = _netBridgeService.Stop();
|
||||
if (!stopped)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_isProxyRunning = false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var error = $"Failed to stop NetBridgeService: {ex.Message}";
|
||||
await _updateFunc?.Invoke(true, error);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateRoutes(string? ruleProcess)
|
||||
{
|
||||
var newRuleConfigs = BuildRuleConfigs(ruleProcess);
|
||||
|
||||
_ruleConfigs = newRuleConfigs;
|
||||
|
||||
if (!_isProxyRunning)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return await ApplyRoutesInternal();
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateProxyConfig(string proxyHost, int proxyPort)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_netBridgeService == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var proxyType = "SOCKS5";
|
||||
var username = "";
|
||||
var password = "";
|
||||
|
||||
if (_proxyConfigId > 0)
|
||||
{
|
||||
var edited = _netBridgeService.EditProxyConfig(_proxyConfigId, proxyType, proxyHost, (ushort)proxyPort, username, password);
|
||||
if (!edited)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_proxyConfigId = _netBridgeService.AddProxyConfig(proxyType, proxyHost, (ushort)proxyPort, username, password);
|
||||
if (_proxyConfigId == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return await Task.FromResult(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var error = $"Failed to update proxy config: {ex.Message}";
|
||||
await _updateFunc?.Invoke(true, error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> SetDnsViaProxy(bool enable)
|
||||
{
|
||||
if (_netBridgeService == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_netBridgeService.SetDnsViaProxy(enable);
|
||||
|
||||
return await Task.FromResult(true);
|
||||
}
|
||||
|
||||
private async Task<bool> ApplyRoutesInternal()
|
||||
{
|
||||
if (_netBridgeService == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
List<NetBridgeRuleConfig> rules;
|
||||
|
||||
rules = _ruleConfigs.Select(JsonUtils.DeepCopy).ToList();
|
||||
|
||||
foreach (var rule in rules.Where(x => x.RuleId > 0))
|
||||
{
|
||||
try
|
||||
{
|
||||
_ = _netBridgeService.DeleteRule(rule.RuleId);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < rules.Count; i++)
|
||||
{
|
||||
var rule = rules[i];
|
||||
var newRuleId = _netBridgeService.AddRule(rule.ProcessName, rule.TargetHosts, rule.TargetPorts, rule.Protocol, rule.Action, rule.ProxyConfigId);
|
||||
if (newRuleId == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
rules[i].RuleId = newRuleId;
|
||||
}
|
||||
|
||||
_ruleConfigs = rules;
|
||||
|
||||
return await Task.FromResult(true);
|
||||
}
|
||||
|
||||
private static List<NetBridgeRuleConfig> BuildRuleConfigs(string? ruleProcess)
|
||||
{
|
||||
if (ruleProcess.IsNullOrEmpty())
|
||||
{
|
||||
return new();
|
||||
}
|
||||
|
||||
var processNames = Utils.String2List(Utils.Convert2Comma(ruleProcess));
|
||||
return processNames.Select(processName => new NetBridgeRuleConfig
|
||||
{
|
||||
ProcessName = processName,
|
||||
TargetHosts = "*",
|
||||
TargetPorts = "*",
|
||||
Protocol = "BOTH",
|
||||
Action = "PROXY",
|
||||
ProxyConfigId = 0
|
||||
}).ToList();
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,6 @@ public class Config
|
||||
public SystemProxyItem SystemProxyItem { get; set; }
|
||||
public WebDavItem WebDavItem { get; set; }
|
||||
public CheckUpdateItem CheckUpdateItem { get; set; }
|
||||
public NetBridgeItem NetBridgeItem { get; set; }
|
||||
public Fragment4RayItem? Fragment4RayItem { get; set; }
|
||||
public List<InItem> Inbound { get; set; }
|
||||
public List<KeyEventItem> GlobalHotkeys { get; set; }
|
||||
|
||||
@@ -74,6 +74,7 @@ public class GUIItem
|
||||
public int TrayMenuServersLimit { get; set; } = 20;
|
||||
public bool EnableHWA { get; set; } = false;
|
||||
public bool EnableLog { get; set; } = true;
|
||||
public string? RootCertProvider { get; set; }
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
@@ -278,10 +279,3 @@ public class SimpleDNSItem
|
||||
public string? Hosts { get; set; }
|
||||
public string? DirectExpectedIPs { get; set; }
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class NetBridgeItem
|
||||
{
|
||||
public string? RuleProcess { get; set; }
|
||||
public bool EnableDnsViaProxy { get; set; }
|
||||
}
|
||||
|
||||
@@ -257,6 +257,7 @@ public class HyRealm4Sbox
|
||||
public string? server_url { get; set; }
|
||||
public string? token { get; set; }
|
||||
public string? realm_id { get; set; }
|
||||
public List<string>? stun_servers { get; set; }
|
||||
}
|
||||
|
||||
public class Server4Sbox : BaseServer4Sbox
|
||||
|
||||
@@ -289,16 +289,7 @@ public class BalancersStrategySettings4Ray
|
||||
{
|
||||
public int? expected { get; set; }
|
||||
public string? maxRTT { get; set; }
|
||||
public float? tolerance { get; set; }
|
||||
public List<string>? baselines { get; set; }
|
||||
public List<BalancersStrategySettingsCosts4Ray>? costs { get; set; }
|
||||
}
|
||||
|
||||
public class BalancersStrategySettingsCosts4Ray
|
||||
{
|
||||
public bool? regexp { get; set; }
|
||||
public string? match { get; set; }
|
||||
public float? value { get; set; }
|
||||
public double? tolerance { get; set; }
|
||||
}
|
||||
|
||||
public class Observatory4Ray
|
||||
|
||||
@@ -15,6 +15,15 @@ public record HyRealm(
|
||||
{
|
||||
public string RendezvousHostPort => RendezvousPort > 0 ? $"{RendezvousHost}:{RendezvousPort}" : RendezvousHost;
|
||||
|
||||
/// <summary>
|
||||
/// sing-box realm.server_url requires a scheme (https:// or http://).
|
||||
/// </summary>
|
||||
public string ToServerUrl()
|
||||
{
|
||||
var scheme = IsHttp ? "http" : "https";
|
||||
return $"{scheme}://{RendezvousHostPort}";
|
||||
}
|
||||
|
||||
public static bool TryParse(string? str, out HyRealm? realm)
|
||||
{
|
||||
realm = null;
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
namespace ServiceLib.Models.Dto;
|
||||
|
||||
public sealed class NetBridgeRuleConfig
|
||||
{
|
||||
public uint RuleId { get; set; }
|
||||
public string ProcessName { get; set; }
|
||||
public string TargetHosts { get; set; }
|
||||
public string TargetPorts { get; set; }
|
||||
public string Protocol { get; set; }
|
||||
public string Action { get; set; }
|
||||
public uint ProxyConfigId { get; set; }
|
||||
}
|
||||
65
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
65
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
@@ -1329,15 +1329,6 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Process traffic hijacking (experimental) 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string menuNetBridge {
|
||||
get {
|
||||
return ResourceManager.GetString("menuNetBridge", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 New Update 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2328,15 +2319,6 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 The process names that need to be proxied; separate multiple processes with commas. Processes not in the list will also be hijacked, but will connect directly. 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string NetBridgeRuleTips {
|
||||
get {
|
||||
return ResourceManager.GetString("NetBridgeRuleTips", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Non-VMess or SS protocol 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -3069,15 +3051,6 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Enables process traffic hijacking (experimental), similar to Proxifer; can coexist with system proxy; conflicts with TUN mode, please do not enable them simultaneously;please allow v2rayN to use a private network in your firewall. 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbEnableNetBridge {
|
||||
get {
|
||||
return ResourceManager.GetString("TbEnableNetBridge", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 DNS via Bridge 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -3366,6 +3339,15 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 If enabled, use sing-box TUN; otherwise, use xray TUN. 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbLegacyProtectTip {
|
||||
get {
|
||||
return ResourceManager.GetString("TbLegacyProtectTip", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Address (IPv4, IPv6) 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -3627,6 +3609,24 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Root Certificate Provider 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbRootCertificateProvider {
|
||||
get {
|
||||
return ResourceManager.GetString("TbRootCertificateProvider", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Only applies to the v2rayN GUI's downloads and network requests. Does not affect the core's certificate validation. 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbRootCertificateProviderTip {
|
||||
get {
|
||||
return ResourceManager.GetString("TbRootCertificateProviderTip", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Round Robin 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -3753,15 +3753,6 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Save rules 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSaveNetBridgeRule {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSaveNetBridgeRule", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 sing-box Full Config Template 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -3898,7 +3889,7 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 For multi-interface environments, enter the name of the interface to bind. Only effective on Windows systems or TUN mode 的本地化字符串。
|
||||
/// 查找类似 For multi-interface environments, enter the interface name for outbound connections. On Linux/macOS, it only works when TUN mode is enabled. 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsBindInterfaceTip {
|
||||
get {
|
||||
|
||||
@@ -1750,7 +1750,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if
|
||||
<value>Bind Interface</value>
|
||||
</data>
|
||||
<data name="TbSettingsBindInterfaceTip" xml:space="preserve">
|
||||
<value>For multi-interface environments, enter the name of the interface to bind. Only effective on Windows systems or TUN mode</value>
|
||||
<value>For multi-interface environments, enter the interface name for outbound connections. On Linux/macOS, it only works when TUN mode is enabled.</value>
|
||||
</data>
|
||||
<data name="TbPreSharedKey" xml:space="preserve">
|
||||
<value>PreSharedKey</value>
|
||||
@@ -1794,21 +1794,9 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if
|
||||
<data name="TbEnableFinalFragmentTip" xml:space="preserve">
|
||||
<value>Split the tail of packets into smaller fragments. This may affect throughput and latency.</value>
|
||||
</data>
|
||||
<data name="TbEnableNetBridge" xml:space="preserve">
|
||||
<value>Enables process traffic hijacking (experimental), similar to Proxifer; can coexist with system proxy; conflicts with TUN mode, please do not enable them simultaneously;please allow v2rayN to use a private network in your firewall.</value>
|
||||
</data>
|
||||
<data name="NetBridgeRuleTips" xml:space="preserve">
|
||||
<value>The process names that need to be proxied; separate multiple processes with commas. Processes not in the list will also be hijacked, but will connect directly.</value>
|
||||
</data>
|
||||
<data name="menuNetBridge" xml:space="preserve">
|
||||
<value>Process traffic hijacking (experimental)</value>
|
||||
</data>
|
||||
<data name="TbEnabletDnsViaProxy" xml:space="preserve">
|
||||
<value>DNS via Bridge</value>
|
||||
</data>
|
||||
<data name="TbSaveNetBridgeRule" xml:space="preserve">
|
||||
<value>Save rules</value>
|
||||
</data>
|
||||
<data name="MsgInsecureConfiguration" xml:space="preserve">
|
||||
<value>Insecure configuration detected: AllowInsecure is enabled but no certificate is provided. This may cause MITM attacks.</value>
|
||||
</data>
|
||||
@@ -1824,4 +1812,13 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if
|
||||
<data name="TbGeckoPacketSize" xml:space="preserve">
|
||||
<value>Gecko Packet Size (min/max)</value>
|
||||
</data>
|
||||
<data name="TbLegacyProtectTip" xml:space="preserve">
|
||||
<value>If enabled, use sing-box TUN; otherwise, use xray TUN.</value>
|
||||
</data>
|
||||
<data name="TbRootCertificateProvider" xml:space="preserve">
|
||||
<value>Root Certificate Provider</value>
|
||||
</data>
|
||||
<data name="TbRootCertificateProviderTip" xml:space="preserve">
|
||||
<value>Only applies to the v2rayN GUI's downloads and network requests. Does not affect the core's certificate validation.</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1747,7 +1747,7 @@
|
||||
<value>Привязать интерфейс</value>
|
||||
</data>
|
||||
<data name="TbSettingsBindInterfaceTip" xml:space="preserve">
|
||||
<value>Для среды с несколькими сетевыми интерфейсами укажите имя интерфейса для привязки. Работает только в Windows и режиме TUN</value>
|
||||
<value>Для среды с несколькими сетевыми интерфейсами укажите имя интерфейса для исходящих подключений. На Linux/macOS работает только при включённом TUN.</value>
|
||||
</data>
|
||||
<data name="TbPreSharedKey" xml:space="preserve">
|
||||
<value>Общий ключ (PSK)</value>
|
||||
|
||||
@@ -1791,21 +1791,9 @@
|
||||
<data name="TbEnableFinalFragmentTip" xml:space="preserve">
|
||||
<value>将数据包末端拆分为更小片段发送,可能影响吞吐与延迟。</value>
|
||||
</data>
|
||||
<data name="TbEnableNetBridge" xml:space="preserve">
|
||||
<value>启用进程流量劫持(实验性),类似 Proxifer 功能;可以和系统代理并存;和 TUN 模式冲突,请不要同时开启;请在防火墙中允许 v2rayN 使用专用网络</value>
|
||||
</data>
|
||||
<data name="NetBridgeRuleTips" xml:space="preserve">
|
||||
<value>需要代理的进程名,多个进程请用逗号分隔;不在列表中的进程也会被劫持,但是会直连</value>
|
||||
</data>
|
||||
<data name="menuNetBridge" xml:space="preserve">
|
||||
<value>进程流量劫持(实验性)</value>
|
||||
</data>
|
||||
<data name="TbEnabletDnsViaProxy" xml:space="preserve">
|
||||
<value>DNS 通过 Bridge</value>
|
||||
</data>
|
||||
<data name="TbSaveNetBridgeRule" xml:space="preserve">
|
||||
<value>保存规则</value>
|
||||
</data>
|
||||
<data name="MsgInsecureConfiguration" xml:space="preserve">
|
||||
<value>检测到不安全配置:AllowInsecure 已启用,但未提供证书。这可能会导致中间人攻击。</value>
|
||||
</data>
|
||||
@@ -1821,4 +1809,13 @@
|
||||
<data name="TbGeckoPacketSize" xml:space="preserve">
|
||||
<value>Gecko 包大小 (最小/最大)</value>
|
||||
</data>
|
||||
<data name="TbLegacyProtectTip" xml:space="preserve">
|
||||
<value>启用则使用 sing-box TUN ,否则使用 xray TUN</value>
|
||||
</data>
|
||||
<data name="TbRootCertificateProvider" xml:space="preserve">
|
||||
<value>根证书提供者</value>
|
||||
</data>
|
||||
<data name="TbRootCertificateProviderTip" xml:space="preserve">
|
||||
<value>仅用于 v2rayN 界面程序的下载及网络请求,不影响核心的证书验证。</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1791,19 +1791,10 @@
|
||||
<data name="TbEnableFinalFragmentTip" xml:space="preserve">
|
||||
<value>將封包末端拆分為更小的片段進行傳送,可能會影響吞吐量與延遲</value>
|
||||
</data>
|
||||
<data name="TbEnableNetBridge" xml:space="preserve">
|
||||
<value>啟用進程流量劫持(實驗性),類似 Proxifer 功能;可以和系統代理並存;和 TUN 模式衝突,請不要同時開啟;請在防火牆中允許 v2rayN 使用專用網絡</value>
|
||||
</data>
|
||||
<data name="NetBridgeRuleTips" xml:space="preserve">
|
||||
<value>需要代理程式的進程名,多個進程請用逗號分隔;不在清單中的進程也會被劫持,但是會直連</value>
|
||||
</data>
|
||||
<data name="menuNetBridge" xml:space="preserve">
|
||||
<value>進程流量劫持(實驗性)</value>
|
||||
</data>
|
||||
<data name="TbEnabletDnsViaProxy" xml:space="preserve">
|
||||
<value>DNS 透過 Bridge</value>
|
||||
</data>
|
||||
<data name="TbSaveNetBridgeRule" xml:space="preserve">
|
||||
<value>保存規則</value>
|
||||
<data name="TbLegacyProtectTip" xml:space="preserve">
|
||||
<value>啟用則使用 sing-box TUN ,否則使用 xray TUN</value>
|
||||
</data>
|
||||
</root>
|
||||
2697
v2rayN/ServiceLib/Sample/chrome_roots_pem
Normal file
2697
v2rayN/ServiceLib/Sample/chrome_roots_pem
Normal file
File diff suppressed because it is too large
Load Diff
4322
v2rayN/ServiceLib/Sample/mozilla_roots_pem
Normal file
4322
v2rayN/ServiceLib/Sample/mozilla_roots_pem
Normal file
File diff suppressed because it is too large
Load Diff
@@ -23,6 +23,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Sample\chrome_roots_pem" />
|
||||
<EmbeddedResource Include="Sample\clash_mixin_yaml" />
|
||||
<EmbeddedResource Include="Sample\clash_tun_yaml" />
|
||||
<EmbeddedResource Include="Sample\custom_routing_black" />
|
||||
@@ -32,6 +33,7 @@
|
||||
<EmbeddedResource Include="Sample\dns_v2ray_normal" />
|
||||
<EmbeddedResource Include="Sample\kill_as_sudo_linux_sh" />
|
||||
<EmbeddedResource Include="Sample\kill_as_sudo_osx_sh" />
|
||||
<EmbeddedResource Include="Sample\mozilla_roots_pem" />
|
||||
<EmbeddedResource Include="Sample\pac" />
|
||||
<EmbeddedResource Include="Sample\proxy_set_linux_sh" />
|
||||
<EmbeddedResource Include="Sample\proxy_set_osx_sh" />
|
||||
@@ -90,7 +92,6 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\NetBridge\src\NetBridgeLib\NetBridgeLib.csproj" />
|
||||
<ProjectReference Include="..\ServiceLib.UdpTest\ServiceLib.UdpTest.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -275,9 +275,10 @@ public partial class CoreConfigSingboxService
|
||||
{
|
||||
var realm4Sbox = new HyRealm4Sbox()
|
||||
{
|
||||
server_url = realm.RendezvousHostPort,
|
||||
server_url = realm.ToServerUrl(),
|
||||
token = realm.Token,
|
||||
realm_id = realm.RealmName,
|
||||
stun_servers = realm.StunList?.Count > 0 ? realm.StunList : null,
|
||||
};
|
||||
outbound.realm = realm4Sbox;
|
||||
outbound.server = null;
|
||||
|
||||
@@ -89,22 +89,25 @@ public partial class CoreConfigV2rayService
|
||||
EMultipleLoad.RoundRobin => "roundRobin",
|
||||
EMultipleLoad.LeastPing => "leastPing",
|
||||
EMultipleLoad.LeastLoad => "leastLoad",
|
||||
EMultipleLoad.Fallback => "leastLoad",
|
||||
_ => "roundRobin",
|
||||
};
|
||||
var balancerTag = $"{selector}{Global.BalancerTagSuffix}";
|
||||
var balancer = new BalancersItem4Ray
|
||||
{
|
||||
selector = [selector],
|
||||
strategy = new()
|
||||
strategy = strategyType == "leastLoad" ? new()
|
||||
{
|
||||
type = strategyType,
|
||||
settings = new()
|
||||
{
|
||||
expected = 1,
|
||||
tolerance = multipleLoad == EMultipleLoad.Fallback ? 0.2 : null,
|
||||
maxRTT = multipleLoad == EMultipleLoad.Fallback ? "5000ms" : null,
|
||||
},
|
||||
},
|
||||
} : null,
|
||||
tag = balancerTag,
|
||||
fallbackTag = multipleLoad == EMultipleLoad.Fallback ? Global.DirectTag : null,
|
||||
fallbackTag = _coreConfig.outbounds?.FirstOrDefault(o => o.tag.StartsWith(selector))?.tag,
|
||||
};
|
||||
_coreConfig.routing.balancers ??= [];
|
||||
_coreConfig.routing.balancers.Add(balancer);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Net.Http.Headers;
|
||||
using System.Reflection.Metadata;
|
||||
|
||||
namespace ServiceLib.Services;
|
||||
|
||||
@@ -80,7 +81,13 @@ public class DownloadService
|
||||
AllowAutoRedirect = false,
|
||||
Proxy = await GetWebProxy(blProxy)
|
||||
};
|
||||
var client = new HttpClient(webRequestHandler);
|
||||
var certificateChainPolicy = CertPemManager.Instance.BuildCertificateChainPolicy();
|
||||
if (certificateChainPolicy != null)
|
||||
{
|
||||
webRequestHandler.SslOptions.CertificateChainPolicy = certificateChainPolicy;
|
||||
webRequestHandler.SslOptions.RemoteCertificateValidationCallback = null;
|
||||
}
|
||||
using var client = new HttpClient(webRequestHandler);
|
||||
|
||||
var response = await client.GetAsync(url);
|
||||
if (response.StatusCode == HttpStatusCode.Redirect && response.Headers.Location is not null)
|
||||
@@ -109,9 +116,10 @@ public class DownloadService
|
||||
/// </summary>
|
||||
public async Task<string?> TryDownloadString(string url, IWebProxy? webProxy, string userAgent)
|
||||
{
|
||||
var timeout = 15;
|
||||
try
|
||||
{
|
||||
var result1 = await DownloadStringAsync(url, webProxy, userAgent, 15);
|
||||
var result1 = await DownloadStringAsync(url, webProxy, userAgent, timeout);
|
||||
if (result1.IsNotEmpty())
|
||||
{
|
||||
return result1;
|
||||
@@ -129,7 +137,7 @@ public class DownloadService
|
||||
|
||||
try
|
||||
{
|
||||
var result2 = await DownloadStringViaDownloader(url, webProxy, userAgent, 15);
|
||||
var result2 = await DownloadStringViaDownloader(url, webProxy, userAgent, timeout);
|
||||
if (result2.IsNotEmpty())
|
||||
{
|
||||
return result2;
|
||||
@@ -155,11 +163,24 @@ public class DownloadService
|
||||
{
|
||||
try
|
||||
{
|
||||
var client = new HttpClient(new SocketsHttpHandler()
|
||||
var connectTimeout = Math.Clamp(timeout / 5, 2, 5);
|
||||
var handler = new SocketsHttpHandler
|
||||
{
|
||||
Proxy = webProxy,
|
||||
UseProxy = webProxy != null
|
||||
});
|
||||
UseProxy = webProxy != null,
|
||||
ConnectTimeout = TimeSpan.FromSeconds(connectTimeout)
|
||||
};
|
||||
var certificateChainPolicy = CertPemManager.Instance.BuildCertificateChainPolicy();
|
||||
if (certificateChainPolicy != null)
|
||||
{
|
||||
handler.SslOptions.CertificateChainPolicy = certificateChainPolicy;
|
||||
handler.SslOptions.RemoteCertificateValidationCallback = null;
|
||||
}
|
||||
|
||||
using var client = new HttpClient(handler)
|
||||
{
|
||||
Timeout = Timeout.InfiniteTimeSpan
|
||||
};
|
||||
|
||||
if (userAgent.IsNullOrEmpty())
|
||||
{
|
||||
@@ -175,8 +196,9 @@ public class DownloadService
|
||||
}
|
||||
|
||||
using var cts = new CancellationTokenSource();
|
||||
var result = await client.GetStringAsync(url, cts.Token).WaitAsync(TimeSpan.FromSeconds(timeout), cts.Token);
|
||||
return result;
|
||||
cts.CancelAfter(TimeSpan.FromSeconds(timeout));
|
||||
|
||||
return await client.GetStringAsync(url, cts.Token);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -187,6 +209,7 @@ public class DownloadService
|
||||
Error?.Invoke(this, new ErrorEventArgs(ex.InnerException));
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -420,7 +420,7 @@ public class SpeedtestService(Config config, Func<SpeedTestResult, Task> updateF
|
||||
private async Task<int> DoRealPing(ServerTestItem it)
|
||||
{
|
||||
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
|
||||
var responseTime = await ConnectionHandler.GetRealPingTime(webProxy, 10);
|
||||
var responseTime = await ConnectionHandler.GetRealPingTime(webProxy);
|
||||
|
||||
ProfileExManager.Instance.SetTestDelay(it.IndexId, responseTime);
|
||||
await UpdateFunc(it.IndexId, responseTime.ToString());
|
||||
|
||||
@@ -272,6 +272,7 @@ public class MainWindowViewModel : MyReactiveObject
|
||||
await ConfigHandler.InitBuiltinFullConfigTemplate(_config);
|
||||
await ProfileExManager.Instance.Init();
|
||||
await CoreManager.Instance.Init(_config, UpdateHandler);
|
||||
await CertPemManager.Instance.Init(_config);
|
||||
TaskManager.Instance.RegUpdateTask(_config, UpdateTaskHandler);
|
||||
|
||||
if (_config.GuiItem.EnableStatistics || _config.GuiItem.DisplayRealTimeSpeed)
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
namespace ServiceLib.ViewModels;
|
||||
|
||||
public class NetBridgeViewModel : MyReactiveObject
|
||||
{
|
||||
[Reactive]
|
||||
public bool EnableNetBridge { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public bool EnabletDnsViaProxy { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public string RuleProcess { get; set; }
|
||||
|
||||
public ReactiveCommand<Unit, Unit> SaveRulesCmd { get; }
|
||||
|
||||
public NetBridgeViewModel(Func<EViewAction, object?, Task<bool>>? updateView)
|
||||
{
|
||||
_config = AppManager.Instance.Config;
|
||||
_updateView = updateView;
|
||||
|
||||
SaveRulesCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
await SaveRulesAsync();
|
||||
});
|
||||
|
||||
this.WhenAnyValue(x => x.EnableNetBridge)
|
||||
.Skip(1)
|
||||
.Subscribe(async enabled =>
|
||||
{
|
||||
await ToggleNetBridgeAsync(enabled);
|
||||
});
|
||||
|
||||
this.WhenAnyValue(x => x.EnabletDnsViaProxy)
|
||||
.Skip(1)
|
||||
.Subscribe(async enabled =>
|
||||
{
|
||||
await ToggleDnsViaProxyAsync(enabled);
|
||||
});
|
||||
|
||||
_ = Init();
|
||||
}
|
||||
|
||||
private async Task Init()
|
||||
{
|
||||
EnabletDnsViaProxy = _config.NetBridgeItem.EnableDnsViaProxy;
|
||||
|
||||
_config.NetBridgeItem ??= new()
|
||||
{
|
||||
RuleProcess = string.Empty
|
||||
};
|
||||
|
||||
EnableNetBridge = false;
|
||||
if (_config.NetBridgeItem.RuleProcess.IsNullOrEmpty())
|
||||
{
|
||||
_config.NetBridgeItem.RuleProcess = "Chrome.exe";
|
||||
}
|
||||
RuleProcess = _config.NetBridgeItem.RuleProcess;
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task ToggleNetBridgeAsync(bool enabled)
|
||||
{
|
||||
await NetBridgeManager.Instance.Init(UpdateViewHandler);
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
var succeed = await NetBridgeManager.Instance.Start();
|
||||
if (succeed)
|
||||
{
|
||||
await NetBridgeManager.Instance.UpdateProxyConfig(Global.Loopback, AppManager.Instance.GetLocalPort(EInboundProtocol.socks));
|
||||
await NetBridgeManager.Instance.UpdateRoutes(RuleProcess);
|
||||
await NetBridgeManager.Instance.SetDnsViaProxy(EnabletDnsViaProxy);
|
||||
}
|
||||
NoticeManager.Instance.Enqueue(succeed ? ResUI.OperationSuccess : ResUI.OperationFailed);
|
||||
}
|
||||
else
|
||||
{
|
||||
var succeed = await NetBridgeManager.Instance.Stop();
|
||||
NoticeManager.Instance.Enqueue(succeed ? ResUI.OperationSuccess : ResUI.OperationFailed);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ToggleDnsViaProxyAsync(bool enabled)
|
||||
{
|
||||
_config.NetBridgeItem.EnableDnsViaProxy = enabled;
|
||||
|
||||
await NetBridgeManager.Instance.SetDnsViaProxy(enabled);
|
||||
}
|
||||
|
||||
/// </summary>
|
||||
private async Task SaveRulesAsync()
|
||||
{
|
||||
_config.NetBridgeItem ??= new();
|
||||
|
||||
var normalizedRuleProcess = RuleProcess;
|
||||
_config.NetBridgeItem.RuleProcess = normalizedRuleProcess;
|
||||
RuleProcess = normalizedRuleProcess;
|
||||
|
||||
if (await ConfigHandler.SaveConfig(_config) != 0)
|
||||
{
|
||||
NoticeManager.Instance.Enqueue(ResUI.OperationFailed);
|
||||
return;
|
||||
}
|
||||
|
||||
await NetBridgeManager.Instance.Init(UpdateViewHandler);
|
||||
if (EnableNetBridge)
|
||||
{
|
||||
var routesUpdated = await NetBridgeManager.Instance.UpdateRoutes(normalizedRuleProcess);
|
||||
NoticeManager.Instance.Enqueue(routesUpdated ? ResUI.OperationSuccess : ResUI.OperationFailed);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<bool> UpdateViewHandler(bool isError, string msg)
|
||||
{
|
||||
NoticeManager.Instance.SendMessageEx(msg);
|
||||
|
||||
return await Task.FromResult(true);
|
||||
}
|
||||
}
|
||||
@@ -72,6 +72,7 @@ public class OptionSettingViewModel : MyReactiveObject
|
||||
[Reactive] public string SrsFileSourceUrl { get; set; }
|
||||
[Reactive] public string RoutingRulesSourceUrl { get; set; }
|
||||
[Reactive] public string IPAPIUrl { get; set; }
|
||||
[Reactive] public string RootCertProvider { get; set; }
|
||||
|
||||
#endregion UI
|
||||
|
||||
@@ -213,6 +214,7 @@ public class OptionSettingViewModel : MyReactiveObject
|
||||
SrsFileSourceUrl = _config.ConstItem.SrsSourceUrl;
|
||||
RoutingRulesSourceUrl = _config.ConstItem.RouteRulesTemplateSourceUrl;
|
||||
IPAPIUrl = _config.SpeedTestItem.IPAPIUrl;
|
||||
RootCertProvider = _config.GuiItem.RootCertProvider;
|
||||
|
||||
#endregion UI
|
||||
|
||||
@@ -402,6 +404,7 @@ public class OptionSettingViewModel : MyReactiveObject
|
||||
_config.ConstItem.SrsSourceUrl = SrsFileSourceUrl;
|
||||
_config.ConstItem.RouteRulesTemplateSourceUrl = RoutingRulesSourceUrl;
|
||||
_config.SpeedTestItem.IPAPIUrl = IPAPIUrl;
|
||||
_config.GuiItem.RootCertProvider = RootCertProvider;
|
||||
|
||||
//systemProxy
|
||||
_config.SystemProxyItem.SystemProxyExceptions = SystemProxyExceptions;
|
||||
|
||||
@@ -8,6 +8,7 @@ public sealed class HotkeyManager
|
||||
private static readonly Lazy<HotkeyManager> _instance = new(() => new());
|
||||
public static HotkeyManager Instance = _instance.Value;
|
||||
private readonly Dictionary<int, EGlobalHotkey> _hotkeyTriggerDic = new();
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
private GlobalHotKeys.HotKeyManager? _hotKeyManager;
|
||||
|
||||
@@ -74,9 +75,7 @@ public sealed class HotkeyManager
|
||||
}
|
||||
}
|
||||
|
||||
_hotKeyManager?.HotKeyPressed
|
||||
.ObserveOn(AvaloniaScheduler.Instance)
|
||||
.Subscribe(OnNext);
|
||||
_hotKeyManager.HotKeyPressed += OnNext;
|
||||
}
|
||||
|
||||
private void OnNext(HotKey key)
|
||||
|
||||
@@ -89,7 +89,6 @@
|
||||
</MenuItem>
|
||||
<MenuItem x:Name="menuBackupAndRestore" Header="{x:Static resx:ResUI.menuBackupAndRestore}" />
|
||||
<MenuItem x:Name="menuOpenTheFileLocation" Header="{x:Static resx:ResUI.menuOpenTheFileLocation}" />
|
||||
<MenuItem x:Name="menuNetBridge" Header="{x:Static resx:ResUI.menuNetBridge}" />
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem x:Name="menuHelp" Header="{x:Static resx:ResUI.menuHelp}">
|
||||
|
||||
@@ -12,7 +12,6 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
|
||||
private readonly WindowNotificationManager? _manager;
|
||||
private CheckUpdateView? _checkUpdateView;
|
||||
private BackupAndRestoreView? _backupAndRestoreView;
|
||||
private NetBridgeView? _netBridgeView;
|
||||
private bool _blCloseByUser = false;
|
||||
|
||||
public MainWindow()
|
||||
@@ -29,7 +28,6 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
|
||||
btnNewUpdate.Click += MenuCheckUpdate_Click;
|
||||
menuBackupAndRestore.Click += MenuBackupAndRestore_Click;
|
||||
menuClose.Click += MenuClose_Click;
|
||||
menuNetBridge.Click += MenuNetBridge_Click;
|
||||
|
||||
ViewModel = new MainWindowViewModel(UpdateViewHandler);
|
||||
|
||||
@@ -167,7 +165,6 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
|
||||
{
|
||||
Title = $"{Utils.GetVersion()}";
|
||||
menuAddServerViaScan.IsVisible = false;
|
||||
menuNetBridge.IsVisible = false;
|
||||
}
|
||||
|
||||
if (_config.UiItem.AutoHideStartup && Utils.IsWindows())
|
||||
@@ -260,7 +257,7 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
|
||||
switch (e)
|
||||
{
|
||||
case EGlobalHotkey.ShowForm:
|
||||
ShowHideWindow(null);
|
||||
Dispatcher.UIThread.Post(() => ShowHideWindow(null));
|
||||
break;
|
||||
|
||||
case EGlobalHotkey.SystemProxyClear:
|
||||
@@ -382,19 +379,6 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
|
||||
DialogHost.Show(_backupAndRestoreView);
|
||||
}
|
||||
|
||||
private void MenuNetBridge_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (Utils.IsAdministrator())
|
||||
{
|
||||
_netBridgeView ??= new NetBridgeView();
|
||||
DialogHost.Show(_netBridgeView);
|
||||
}
|
||||
else
|
||||
{
|
||||
NoticeManager.Instance.SendMessageAndEnqueue(ResUI.RunAsAdmin);
|
||||
}
|
||||
}
|
||||
|
||||
private async void MenuClose_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (await UI.ShowYesNo(this, ResUI.menuExitTips) != ButtonResult.Yes)
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
<UserControl
|
||||
x:Class="v2rayN.Desktop.Views.NetBridgeView"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
||||
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
||||
d:DesignHeight="400"
|
||||
d:DesignWidth="600"
|
||||
x:DataType="vms:NetBridgeViewModel"
|
||||
mc:Ignorable="d">
|
||||
<Border
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Theme="{DynamicResource CardBorder}">
|
||||
|
||||
<DockPanel Margin="{StaticResource Margin8}">
|
||||
<StackPanel
|
||||
Margin="{StaticResource Margin8}"
|
||||
DockPanel.Dock="Top"
|
||||
Orientation="Horizontal">
|
||||
|
||||
<ToggleSwitch
|
||||
x:Name="togEnableNetBridge"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
<TextBlock
|
||||
Width="500"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbEnableNetBridge}"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel
|
||||
Margin="{StaticResource Margin8}"
|
||||
DockPanel.Dock="Top"
|
||||
Orientation="Horizontal">
|
||||
|
||||
<ToggleSwitch
|
||||
x:Name="togEnabletDnsViaProxy"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
<TextBlock
|
||||
Width="500"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbEnabletDnsViaProxy}"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
|
||||
|
||||
<DockPanel>
|
||||
<StackPanel
|
||||
Margin="{StaticResource Margin8}"
|
||||
DockPanel.Dock="Top"
|
||||
Orientation="Horizontal">
|
||||
|
||||
<TextBlock
|
||||
Width="500"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.NetBridgeRuleTips}"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Right"
|
||||
DockPanel.Dock="Bottom"
|
||||
Orientation="Horizontal">
|
||||
|
||||
<Button
|
||||
x:Name="btnSave"
|
||||
Width="100"
|
||||
Content="{x:Static resx:ResUI.TbSaveNetBridgeRule}"
|
||||
IsDefault="True" />
|
||||
</StackPanel>
|
||||
|
||||
<TextBox
|
||||
x:Name="txtRuleProcess"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Stretch"
|
||||
AcceptsReturn="True"
|
||||
BorderThickness="1"
|
||||
Classes="TextArea"
|
||||
TextWrapping="Wrap" />
|
||||
</DockPanel>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
</UserControl>
|
||||
@@ -1,25 +0,0 @@
|
||||
namespace v2rayN.Desktop.Views;
|
||||
|
||||
public partial class NetBridgeView : ReactiveUserControl<NetBridgeViewModel>
|
||||
{
|
||||
public NetBridgeView()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
ViewModel = new NetBridgeViewModel(UpdateViewHandler);
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.BindCommand(ViewModel, vm => vm.SaveRulesCmd, v => v.btnSave).DisposeWith(disposables);
|
||||
|
||||
this.Bind(ViewModel, vm => vm.EnableNetBridge, v => v.togEnableNetBridge.IsChecked).DisposeWith(disposables);
|
||||
|
||||
this.Bind(ViewModel, vm => vm.RuleProcess, v => v.txtRuleProcess.Text).DisposeWith(disposables);
|
||||
});
|
||||
}
|
||||
|
||||
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
||||
{
|
||||
return await Task.FromResult(true);
|
||||
}
|
||||
}
|
||||
@@ -555,20 +555,20 @@
|
||||
HorizontalAlignment="Left" />-->
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="8"
|
||||
Grid.Row="6"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSettingsAutoHideStartup}" />
|
||||
<ToggleSwitch
|
||||
x:Name="togAutoHideStartup"
|
||||
Grid.Row="8"
|
||||
Grid.Row="6"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="9"
|
||||
Grid.Row="7"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
@@ -576,13 +576,13 @@
|
||||
Text="{x:Static resx:ResUI.TbSettingsHide2TrayWhenClose}" />
|
||||
<ToggleSwitch
|
||||
x:Name="togHide2TrayWhenClose"
|
||||
Grid.Row="9"
|
||||
Grid.Row="7"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left"
|
||||
IsVisible="{Binding BlIsLinux}" />
|
||||
<TextBlock
|
||||
Grid.Row="9"
|
||||
Grid.Row="7"
|
||||
Grid.Column="2"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
@@ -590,7 +590,7 @@
|
||||
Text="{x:Static resx:ResUI.TbSettingsHide2TrayWhenCloseTip}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="10"
|
||||
Grid.Row="8"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
@@ -598,25 +598,45 @@
|
||||
Text="{x:Static resx:ResUI.TbSettingsMacOSShowInDock}" />
|
||||
<ToggleSwitch
|
||||
x:Name="togMacOSShowInDock"
|
||||
Grid.Row="10"
|
||||
Grid.Row="8"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left"
|
||||
IsVisible="{Binding BlIsIsMacOS}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="11"
|
||||
Grid.Row="9"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSettingsDoubleClick2Activate}" />
|
||||
<ToggleSwitch
|
||||
x:Name="togDoubleClick2Activate"
|
||||
Grid.Row="11"
|
||||
Grid.Row="9"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="10"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbRootCertificateProvider}" />
|
||||
<ComboBox
|
||||
x:Name="cmbRootCertificateProvider"
|
||||
Grid.Row="10"
|
||||
Grid.Column="1"
|
||||
Width="300"
|
||||
Margin="{StaticResource Margin4}" />
|
||||
<TextBlock
|
||||
Grid.Row="10"
|
||||
Grid.Column="2"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbRootCertificateProviderTip}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="14"
|
||||
Grid.Column="0"
|
||||
@@ -1022,6 +1042,13 @@
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left" />
|
||||
<TextBlock
|
||||
Grid.Row="8"
|
||||
Grid.Column="2"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbLegacyProtectTip}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="9"
|
||||
|
||||
@@ -56,6 +56,7 @@ public partial class OptionSettingWindow : WindowBase<OptionSettingViewModel>
|
||||
cmbSrsFilesSourceUrl.ItemsSource = Global.SingboxRulesetSources;
|
||||
cmbRoutingRulesSourceUrl.ItemsSource = Global.RoutingRulesSources;
|
||||
cmbIPAPIUrl.ItemsSource = Global.IPAPIUrls;
|
||||
cmbRootCertificateProvider.ItemsSource = Global.RootCertProviders;
|
||||
|
||||
cmbMainGirdOrientation.ItemsSource = Utils.GetEnumNames<EGirdOrientation>();
|
||||
|
||||
@@ -111,6 +112,7 @@ public partial class OptionSettingWindow : WindowBase<OptionSettingViewModel>
|
||||
this.Bind(ViewModel, vm => vm.SrsFileSourceUrl, v => v.cmbSrsFilesSourceUrl.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.RoutingRulesSourceUrl, v => v.cmbRoutingRulesSourceUrl.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.IPAPIUrl, v => v.cmbIPAPIUrl.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.RootCertProvider, v => v.cmbRootCertificateProvider.SelectedValue).DisposeWith(disposables);
|
||||
|
||||
this.Bind(ViewModel, vm => vm.NotProxyLocalAddress, v => v.tognotProxyLocalAddress.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SystemProxyAdvancedProtocol, v => v.cmbsystemProxyAdvancedProtocol.SelectedValue).DisposeWith(disposables);
|
||||
|
||||
@@ -35,8 +35,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceLib.Tests", "Service
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceLib.UdpTest", "ServiceLib.UdpTest\ServiceLib.UdpTest.csproj", "{CE9D9298-0289-4718-2522-B236489F2912}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetBridgeLib", "NetBridge\src\NetBridgeLib\NetBridgeLib.csproj", "{4AF81950-DD4E-A636-6BD5-B4A7839D87B0}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -71,10 +69,6 @@ Global
|
||||
{CE9D9298-0289-4718-2522-B236489F2912}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CE9D9298-0289-4718-2522-B236489F2912}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CE9D9298-0289-4718-2522-B236489F2912}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4AF81950-DD4E-A636-6BD5-B4A7839D87B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4AF81950-DD4E-A636-6BD5-B4A7839D87B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4AF81950-DD4E-A636-6BD5-B4A7839D87B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4AF81950-DD4E-A636-6BD5-B4A7839D87B0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
</Folder>
|
||||
<Project Path="AmazTool/AmazTool.csproj" />
|
||||
<Project Path="GlobalHotKeys/src/GlobalHotKeys/GlobalHotKeys.csproj" />
|
||||
<Project Path="NetBridge/src/NetBridgeLib/NetBridgeLib.csproj" />
|
||||
<Project Path="ServiceLib.Tests/ServiceLib.Tests.csproj" />
|
||||
<Project Path="ServiceLib.UdpTest/ServiceLib.UdpTest.csproj" Id="77930428-4dc4-4130-9031-6b9e714f5d20" />
|
||||
<Project Path="ServiceLib/ServiceLib.csproj" />
|
||||
|
||||
@@ -233,10 +233,6 @@
|
||||
x:Name="menuOpenTheFileLocation"
|
||||
Height="{StaticResource MenuItemHeight}"
|
||||
Header="{x:Static resx:ResUI.menuOpenTheFileLocation}" />
|
||||
<MenuItem
|
||||
x:Name="menuNetBridge"
|
||||
Height="{StaticResource MenuItemHeight}"
|
||||
Header="{x:Static resx:ResUI.menuNetBridge}" />
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
<Separator />
|
||||
|
||||
@@ -10,7 +10,6 @@ public partial class MainWindow
|
||||
private static Config _config;
|
||||
private CheckUpdateView? _checkUpdateView;
|
||||
private BackupAndRestoreView? _backupAndRestoreView;
|
||||
private NetBridgeView? _netBridgeView;
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
@@ -28,7 +27,6 @@ public partial class MainWindow
|
||||
menuCheckUpdate.Click += MenuCheckUpdate_Click;
|
||||
btnNewUpdate.Click += MenuCheckUpdate_Click;
|
||||
menuBackupAndRestore.Click += MenuBackupAndRestore_Click;
|
||||
menuNetBridge.Click += MenuNetBridge_Click;
|
||||
|
||||
ViewModel = new MainWindowViewModel(UpdateViewHandler);
|
||||
|
||||
@@ -378,19 +376,6 @@ public partial class MainWindow
|
||||
DialogHost.Show(_backupAndRestoreView, "RootDialog");
|
||||
}
|
||||
|
||||
private void MenuNetBridge_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (Utils.IsAdministrator())
|
||||
{
|
||||
_netBridgeView ??= new NetBridgeView();
|
||||
DialogHost.Show(_netBridgeView, "RootDialog");
|
||||
}
|
||||
else
|
||||
{
|
||||
NoticeManager.Instance.SendMessageAndEnqueue(ResUI.RunAsAdmin);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Event
|
||||
|
||||
#region UI
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
<reactiveui:ReactiveUserControl
|
||||
x:Class="v2rayN.Views.NetBridgeView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:converters="clr-namespace:v2rayN.Converters"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:reactiveui="http://reactiveui.net"
|
||||
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
||||
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
||||
Height="400"
|
||||
d:DesignHeight="400"
|
||||
d:DesignWidth="600"
|
||||
x:TypeArguments="vms:NetBridgeViewModel"
|
||||
Style="{StaticResource ViewGlobal}"
|
||||
mc:Ignorable="d">
|
||||
<DockPanel Margin="{StaticResource Margin8}">
|
||||
<StackPanel
|
||||
Margin="{StaticResource Margin8}"
|
||||
DockPanel.Dock="Top"
|
||||
Orientation="Horizontal">
|
||||
|
||||
<ToggleButton
|
||||
x:Name="togEnableNetBridge"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
<TextBlock
|
||||
Width="500"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbEnableNetBridge}"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel
|
||||
Margin="{StaticResource Margin8}"
|
||||
DockPanel.Dock="Top"
|
||||
Orientation="Horizontal">
|
||||
|
||||
<ToggleButton
|
||||
x:Name="togEnabletDnsViaProxy"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
<TextBlock
|
||||
Width="500"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbEnabletDnsViaProxy}"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
|
||||
<DockPanel>
|
||||
<StackPanel
|
||||
Margin="{StaticResource Margin8}"
|
||||
DockPanel.Dock="Top"
|
||||
Orientation="Horizontal">
|
||||
|
||||
<TextBlock
|
||||
Width="500"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.NetBridgeRuleTips}"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Right"
|
||||
DockPanel.Dock="Bottom"
|
||||
Orientation="Horizontal">
|
||||
|
||||
<Button
|
||||
x:Name="btnSave"
|
||||
Width="100"
|
||||
Content="{x:Static resx:ResUI.TbSaveNetBridgeRule}"
|
||||
IsDefault="True"
|
||||
Style="{StaticResource DefButton}" />
|
||||
</StackPanel>
|
||||
|
||||
<TextBox
|
||||
x:Name="txtRuleProcess"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Stretch"
|
||||
AcceptsReturn="True"
|
||||
BorderThickness="1"
|
||||
Style="{StaticResource DefTextBox}"
|
||||
TextWrapping="Wrap"
|
||||
VerticalScrollBarVisibility="Auto" />
|
||||
|
||||
</DockPanel>
|
||||
</DockPanel>
|
||||
</reactiveui:ReactiveUserControl>
|
||||
@@ -1,26 +0,0 @@
|
||||
namespace v2rayN.Views;
|
||||
|
||||
public partial class NetBridgeView
|
||||
{
|
||||
public NetBridgeView()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
ViewModel = new NetBridgeViewModel(UpdateViewHandler);
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.BindCommand(ViewModel, vm => vm.SaveRulesCmd, v => v.btnSave).DisposeWith(disposables);
|
||||
|
||||
this.Bind(ViewModel, vm => vm.EnableNetBridge, v => v.togEnableNetBridge.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.EnabletDnsViaProxy, v => v.togEnabletDnsViaProxy.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.RuleProcess, v => v.txtRuleProcess.Text).DisposeWith(disposables);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
||||
{
|
||||
return await Task.FromResult(true);
|
||||
}
|
||||
}
|
||||
@@ -777,7 +777,7 @@
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="8"
|
||||
Grid.Row="6"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
@@ -785,13 +785,13 @@
|
||||
Text="{x:Static resx:ResUI.TbSettingsAutoHideStartup}" />
|
||||
<ToggleButton
|
||||
x:Name="togAutoHideStartup"
|
||||
Grid.Row="8"
|
||||
Grid.Row="6"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="10"
|
||||
Grid.Row="7"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
@@ -799,13 +799,13 @@
|
||||
Text="{x:Static resx:ResUI.TbSettingsEnableDragDropSort}" />
|
||||
<ToggleButton
|
||||
x:Name="togEnableDragDropSort"
|
||||
Grid.Row="10"
|
||||
Grid.Row="7"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="11"
|
||||
Grid.Row="8"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
@@ -813,13 +813,13 @@
|
||||
Text="{x:Static resx:ResUI.TbSettingsDoubleClick2Activate}" />
|
||||
<ToggleButton
|
||||
x:Name="togDoubleClick2Activate"
|
||||
Grid.Row="11"
|
||||
Grid.Row="8"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="12"
|
||||
Grid.Row="9"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
@@ -827,11 +827,35 @@
|
||||
Text="{x:Static resx:ResUI.TbSettingsEnableHWA}" />
|
||||
<ToggleButton
|
||||
x:Name="togEnableHWA"
|
||||
Grid.Row="12"
|
||||
Grid.Row="9"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="10"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbRootCertificateProvider}" />
|
||||
<ComboBox
|
||||
x:Name="cmbRootCertificateProvider"
|
||||
Grid.Row="10"
|
||||
Grid.Column="1"
|
||||
Width="300"
|
||||
Margin="{StaticResource Margin8}"
|
||||
MaxDropDownHeight="1000"
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
<TextBlock
|
||||
Grid.Row="10"
|
||||
Grid.Column="2"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbRootCertificateProviderTip}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="13"
|
||||
Grid.Column="0"
|
||||
@@ -1285,6 +1309,14 @@
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
<TextBlock
|
||||
Grid.Row="8"
|
||||
Grid.Column="2"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbLegacyProtectTip}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="9"
|
||||
|
||||
@@ -53,6 +53,7 @@ public partial class OptionSettingWindow
|
||||
cmbSrsFilesSourceUrl.ItemsSource = Global.SingboxRulesetSources;
|
||||
cmbRoutingRulesSourceUrl.ItemsSource = Global.RoutingRulesSources;
|
||||
cmbIPAPIUrl.ItemsSource = Global.IPAPIUrls;
|
||||
cmbRootCertificateProvider.ItemsSource = Global.RootCertProviders;
|
||||
|
||||
cmbMainGirdOrientation.ItemsSource = Utils.GetEnumNames<EGirdOrientation>();
|
||||
|
||||
@@ -117,6 +118,7 @@ public partial class OptionSettingWindow
|
||||
this.Bind(ViewModel, vm => vm.SrsFileSourceUrl, v => v.cmbSrsFilesSourceUrl.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.RoutingRulesSourceUrl, v => v.cmbRoutingRulesSourceUrl.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.IPAPIUrl, v => v.cmbIPAPIUrl.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.RootCertProvider, v => v.cmbRootCertificateProvider.Text).DisposeWith(disposables);
|
||||
|
||||
this.Bind(ViewModel, vm => vm.NotProxyLocalAddress, v => v.tognotProxyLocalAddress.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SystemProxyAdvancedProtocol, v => v.cmbsystemProxyAdvancedProtocol.Text).DisposeWith(disposables);
|
||||
|
||||
Reference in New Issue
Block a user