Compare commits

...

70 Commits
3.23 ... main

Author SHA1 Message Date
armv9
adef6cd4af 4.0.1 2024-12-12 17:03:36 +09:00
armv9
399b171adf misc change 2024-12-12 17:03:32 +09:00
armv9
6e4c180428 fix: dns outbound 2024-12-12 17:02:37 +09:00
armv9
75c6496151 change: domain rule use domain_suffix 2024-12-12 17:02:14 +09:00
Integral
62c59f6fd3
refactor: replace non-empty QString constructors with QStringLiteral() 2024-11-03 12:50:41 +08:00
armv9
12d6fc24e7 4.0-beta4 2024-10-09 13:32:41 +09:00
armv9
6de7c588b6 update core 2024-10-09 13:32:41 +09:00
armv9
99c8d50943 add url test button on main window 2024-10-09 13:32:41 +09:00
极速蜗牛
2a177256ce
Add /usr/share/sing-box to core asset search path (#1350) 2024-07-20 13:23:24 +08:00
Chi_Tang
b1d1674912
fixed pkgbuild for 4.0 (#1348) 2024-07-13 17:36:39 +08:00
armv9
2dd9cf45eb update readme 2024-07-13 15:57:07 +09:00
armv9
96a6586c5e 4.0-beta3 2024-07-13 15:39:11 +09:00
armv9
375ffec58d remove v2ray_asset_dir 2024-07-13 15:37:07 +09:00
armv9
7aa863b881 remove log high light 2024-07-13 15:26:01 +09:00
armv9
79838d8679 urltest: use dns 2024-07-07 15:25:15 +09:00
armv9
61e27f4014 fix appimage 2024-07-05 11:48:51 +09:00
armv9
e868de0209 4.0-beta2 2024-07-05 11:34:06 +09:00
armv9
6f81ba7773 change exe name 2024-07-05 11:34:06 +09:00
armv9
be0eae662b update qt 2024-07-05 11:16:26 +09:00
armv9
f6cf1414bf hysteria -> hysteria2 2024-07-05 10:29:22 +09:00
armv9
7c783308a7 fix: linux external tun 2024-07-03 16:55:16 +09:00
armv9
cd9bb8f72d v2ray format migration 2024-07-03 16:55:14 +09:00
armv9
df141f9079 fix: win32 gui 2024-07-02 13:26:54 +09:00
armv9
4376ce7d33 Merge branch 'master' of https://github.com/Si1entW4ve/nekoray 2024-07-02 12:31:53 +09:00
armv9
584d50e317 4.0-beta1 2024-07-02 12:11:18 +09:00
armv9
961112ea5b update core 1.9.3 2024-07-02 12:02:34 +09:00
armv9
8a2eab506f remove enable_js_hook 2024-06-28 11:56:47 +09:00
armv9
9bc3be6ea0 remove switch core 2024-06-28 11:54:59 +09:00
armv9
48e04d2173 remove DialogFirstSetup 2024-06-28 11:52:02 +09:00
armv9
3f738cee4e up 2024-06-27 12:04:49 +09:00
Si1ent W4ve
121311c938
fix & rename 2024-03-21 01:45:49 +08:00
purofle
4f45617666
Update README.md 2024-02-24 22:10:13 +08:00
AA
7655f0e16a
Farsi Docs updated (#1154)
* Create Build_Linux_fa.md

The Persian translation of the file Build_Linux.md has been added.

* Update README_fa.md

* change path of file

* Update README_fa.md

* Farsi Docs updated

* HookJS doc fixed
2024-01-09 23:48:52 +08:00
AA
9d8b12ff66
docs: Add Persian Build_Linux file (#1152)
* Create Build_Linux_fa.md

The Persian translation of the file Build_Linux.md has been added.

* Update README_fa.md

* change path of file

* Update README_fa.md
2024-01-08 23:48:58 +08:00
JustMarkov
364ea93cc1
docs: add Russian README (#1078)
* Update README.md

* Create README_ru.md
2024-01-03 22:27:40 +08:00
arm64v8a
894410da39 3.26 2023-12-09 14:59:48 +09:00
arm64v8a
06508634a7 fix: #1024 2023-12-09 14:59:45 +09:00
BlacAmDK
1b078a8aab
fix: RunGuard not works on Qt6 (#1095)
* Revert "fix: RunGuard not works on Qt6"

This reverts commit 32ef100cf3.

* fix: RunGuard not works on Qt6
2023-12-05 22:17:54 +08:00
purofle
beb87352ae
bump version
3.25
2023-11-25 18:48:10 +08:00
Fw[a]rd
5bf393597e
fix: unknown transport type: h2 in vmess protocol (#1062) 2023-11-25 18:44:21 +08:00
BlacAmDK
205caef7a5
Fix Linux autostart config line endings (#1049)
Fix Linux autostart config line endings.
2023-11-21 22:41:37 +08:00
arm64v8a
6087ec741d update core 2023-11-18 10:44:05 +09:00
purofle
7bd8a2f651
refactor: update box
Closes: #1039
2023-11-15 01:13:05 +08:00
purofle
d882424329
refactor: disable httpupgrade
httpupgrade is not implemented in sing-box 1.6.4
2023-11-15 01:12:42 +08:00
purofle
cd8da82c92
fix: Speed may be +InfMiB/s
Closes: #1032
2023-11-14 00:36:29 +08:00
purofle
06e5de0998
fix: go mod tidy 2023-11-14 00:22:47 +08:00
purofle
376ac1c515
update box
Closes: #1038
2023-11-13 23:11:40 +08:00
purofle
937523c6b3
fix: unknown transport type: h2
closes: #1012
2023-11-11 22:52:04 +08:00
purofle
c6caf42ce9
fix: go mod tidy 2023-11-10 01:11:36 +08:00
purofle
1aa59f1314
refactor: update box 2023-11-10 01:02:46 +08:00
エルフです
c9442ebb57
Skip AUR CI for non-project file changes & Unified README format (#1014)
* fix: Skip AUR CI for non-project file changes

* style: Unified README format

* Update README_ja.md

* Update README.md
2023-11-08 12:05:42 +08:00
purofle
a858af3ae4
docs: fix AUR CI Badge url 2023-11-05 11:33:46 +08:00
purofle
5ef732fbb1
Merge pull request #1013 from chitang233/main 2023-11-05 11:19:10 +08:00
Chi_Tang
514fb4c811
feat: update PKGBUILD on pushing 2023-11-05 10:38:08 +08:00
purofle
974bb9167d
refactor: only show httpupgrade on nekobox 2023-11-03 12:47:09 +08:00
Misaka-blog
369cc7c1aa fix: go mod tidy 2023-11-02 15:46:57 +08:00
Misaka-blog
7538075112 Feat: Add support for httpupgrade transport 2023-11-02 15:42:48 +08:00
purofle
32ef100cf3
fix: RunGuard not works on Qt6
Closes: #955
2023-10-31 15:24:26 +08:00
purofle
a6e7dfe717
Merge pull request #991 from mohitd404/main
Closes #989
2023-10-31 09:44:31 +08:00
Mohit Dhote
dad696ef18
Updated CODE_OF_CONDUCT.md file
Fixed #989
2023-10-30 14:49:31 +05:30
Ikko Eltociear Ashimine
7621c0a1df
docs: add Japanese README (#988) 2023-10-30 09:44:49 +08:00
Misaka-blog
4df116508e update box 2023-10-28 23:59:04 +08:00
arm64v8a
11e1eaf232 3.24 2023-10-28 12:18:27 +09:00
cancanneednews
b623e4ca96
Deleted domains already exist in upstream (#978) 2023-10-27 20:34:12 +08:00
Misaka-blog
0597580857 Pack Debian package for artifact-pack 2023-10-27 08:16:16 +08:00
Misaka-blog
1bebdc546c Supports Clash Meta's ports field 2023-10-27 08:12:57 +08:00
Misaka-blog
20805c4ed0 Update box and issue template 2023-10-26 21:48:06 +08:00
Misaka-blog
bc83fc5700 feat: port hopping delivery 2023-10-26 14:53:07 +08:00
Misaka-blog
e2e066551c feat(nekobox): add hop port for hysteria2 2023-10-25 19:05:53 +08:00
xtex
0175f5d456
fix: linux cap test with libcap-progs at /usr/sbin (gh#764)
Signed-off-by: xtex <xtexchooser@duck.com>
2023-10-14 21:58:25 +08:00
126 changed files with 918 additions and 4805 deletions

22
.github/ISSUE_TEMPLATE/bug-report-en.md vendored Normal file
View File

@ -0,0 +1,22 @@
---
name: 'Bug Report'
about: 'Please troubleshoot server-side issues and upgrade to the latest client before raising a question.'
title: 'BUG: '
labels: ''
assignees: ''
---
## Describe the problem
Expected behavior:
Actual behavior:
## How to reproduce
Provide helpful screenshots, videos, text descriptions, subscription links, etc.
## log
If you have logs, please upload them. Please see the detailed steps for exporting logs in the documentation.

View File

@ -1,6 +1,6 @@
--- ---
name: 'Bug Report zh_CN' name: '问题反馈'
about: '问题反馈,在提出问题前请先自行排除服务器端问题和升级到最新客户端。' about: '在提出问题前请先自行排除服务器端问题和升级到最新客户端。'
title: 'BUG: ' title: 'BUG: '
labels: '' labels: ''
assignees: '' assignees: ''

View File

@ -0,0 +1,12 @@
---
name: 'Feature Request'
about: 'Make suggestions for new features of the software'
title: ''
labels: ''
assignees: ''
---
## Description suggestions
## Necessity of recommendations

View File

@ -1,6 +1,6 @@
--- ---
name: 'Feature Request zh_CN' name: '功能请求'
about: '功能请求,提出建议。' about: '对软件的新功能提出建议。'
title: '' title: ''
labels: '' labels: ''
assignees: '' assignees: ''

View File

@ -4,20 +4,20 @@ on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:
tag: tag:
description: 'Release Tag' description: "Release Tag"
required: true required: true
publish: publish:
description: 'Publish: If want ignore' description: "Publish: If want ignore"
required: false required: false
artifact-pack: artifact-pack:
description: 'artifact-pack: If want ignore' description: "artifact-pack: If want ignore"
required: false required: false
jobs: jobs:
build-go: build-go:
strategy: strategy:
matrix: matrix:
cross_os: [ windows, linux ] cross_os: [windows, linux]
cross_arch: [ amd64 ] cross_arch: [amd64]
include: include:
- cross_os: public_res - cross_os: public_res
cross_arch: public_res cross_arch: public_res
@ -38,7 +38,7 @@ jobs:
if: steps.cache-common.outputs.cache-hit != 'true' if: steps.cache-common.outputs.cache-hit != 'true'
uses: actions/setup-go@v3 uses: actions/setup-go@v3
with: with:
go-version: ^1.21 go-version: ^1.22
- name: Build golang parts - name: Build golang parts
if: steps.cache-common.outputs.cache-hit != 'true' if: steps.cache-common.outputs.cache-hit != 'true'
shell: bash shell: bash
@ -51,7 +51,7 @@ jobs:
if: steps.cache-common.outputs.cache-hit != 'true' if: steps.cache-common.outputs.cache-hit != 'true'
run: tar czvf artifacts.tgz ./deployment run: tar czvf artifacts.tgz ./deployment
- name: Uploading Artifact - name: Uploading Artifact
uses: actions/upload-artifact@master uses: actions/upload-artifact@v3
with: with:
name: NekoRay-${{ github.sha }}-Common-${{ matrix.cross_os }}-${{ matrix.cross_arch }} name: NekoRay-${{ github.sha }}-Common-${{ matrix.cross_os }}-${{ matrix.cross_arch }}
path: artifacts.tgz path: artifacts.tgz
@ -61,7 +61,7 @@ jobs:
include: include:
- platform: windows-2022 - platform: windows-2022
arch: x64 arch: x64
qt_version: "6.5" qt_version: "6.7"
- platform: ubuntu-20.04 - platform: ubuntu-20.04
arch: x64 arch: x64
qt_version: "5.12" qt_version: "5.12"
@ -141,7 +141,7 @@ jobs:
shell: bash shell: bash
run: tar czvf artifacts.tgz ./deployment run: tar czvf artifacts.tgz ./deployment
- name: Uploading Artifact - name: Uploading Artifact
uses: actions/upload-artifact@master uses: actions/upload-artifact@v3
with: with:
name: NekoRay-${{ github.sha }}-${{ matrix.platform }}-${{ matrix.arch }}-Qt${{ matrix.qt_version }} name: NekoRay-${{ github.sha }}-${{ matrix.platform }}-${{ matrix.arch }}-Qt${{ matrix.qt_version }}
path: artifacts.tgz path: artifacts.tgz
@ -179,7 +179,6 @@ jobs:
zip -r $version_standalone-windows64.zip nekoray zip -r $version_standalone-windows64.zip nekoray
rm -rf nekoray rm -rf nekoray
- name: Pack Debian - name: Pack Debian
if: github.event.inputs.publish != 'y'
run: | run: |
source libs/env_deploy.sh source libs/env_deploy.sh
find . -name artifacts.tgz | xargs -n1 tar xvzf find . -name artifacts.tgz | xargs -n1 tar xvzf
@ -197,7 +196,7 @@ jobs:
cp -r public_res/* linux64 cp -r public_res/* linux64
#### ####
bash ../libs/package_appimage.sh bash ../libs/package_appimage.sh
mv nekoray-x86_64.AppImage $version_standalone-linux-x64.AppImage mv nekobox-x86_64.AppImage $version_standalone-linux-x64.AppImage
- name: Clean Up - name: Clean Up
run: | run: |
cd deployment cd deployment
@ -206,7 +205,7 @@ jobs:
rm -rf public_res rm -rf public_res
rm -rf *.pdb rm -rf *.pdb
- name: Uploading Artifact - name: Uploading Artifact
uses: actions/upload-artifact@master uses: actions/upload-artifact@v3
with: with:
name: Deployment-${{ github.sha }} name: Deployment-${{ github.sha }}
path: deployment path: deployment

18
.github/workflows/update-pkgbuild.yml vendored Normal file
View File

@ -0,0 +1,18 @@
name: AUR CI
on:
push:
branches:
- main
paths-ignore:
- '**.md'
- 'LICENSE'
- '!.github/workflows/**'
jobs:
update:
runs-on: ubuntu-latest
steps:
- uses: chitang233/aur-pkgbuild-builder@main
with:
deploy_key: ${{ secrets.DEPLOY_KEY }}
package_name: 'nekoray-git'

3
.gitignore vendored
View File

@ -82,3 +82,6 @@ CMakeLists.txt.user*
/deployment /deployment
/neko*.sh /neko*.sh
/qtsdk /qtsdk
.vs
out

3
.gitmodules vendored
View File

@ -1,6 +1,3 @@
[submodule "3rdparty/QHotkey"] [submodule "3rdparty/QHotkey"]
path = 3rdparty/QHotkey path = 3rdparty/QHotkey
url = https://github.com/Skycoder42/QHotkey.git url = https://github.com/Skycoder42/QHotkey.git
[submodule "3rdparty/qjs"]
path = 3rdparty/qjs
url = https://github.com/MatsuriDayo/qjs

View File

@ -75,9 +75,6 @@ bool RunGuard::isAnotherRunning(quint64 *data_out) {
} }
bool RunGuard::tryToRun(quint64 *data_in) { bool RunGuard::tryToRun(quint64 *data_in) {
if (isAnotherRunning(nullptr)) // Extra check
return false;
memLock.acquire(); memLock.acquire();
const bool result = sharedMem.create(sizeof(quint64)); const bool result = sharedMem.create(sizeof(quint64));
if (result) memcpy(sharedMem.data(), data_in, sizeof(quint64)); if (result) memcpy(sharedMem.data(), data_in, sizeof(quint64));

1
3rdparty/qjs vendored

@ -1 +0,0 @@
Subproject commit 3fb0770c9ee5ab031a56072520641d4577b694e3

View File

@ -353,7 +353,7 @@ namespace Qv2ray::components::proxy {
// execute and get the code // execute and get the code
const auto returnCode = QProcess::execute(action.first, action.second); const auto returnCode = QProcess::execute(action.first, action.second);
// print out the commands and result codes // print out the commands and result codes
DEBUG(QString("[%1] Program: %2, Args: %3").arg(returnCode).arg(action.first).arg(action.second.join(";"))); DEBUG(QStringLiteral("[%1] Program: %2, Args: %3").arg(returnCode).arg(action.first).arg(action.second.join(";")));
// give the code back // give the code back
results << (returnCode == QProcess::NormalExit); results << (returnCode == QProcess::NormalExit);
} }
@ -423,7 +423,7 @@ namespace Qv2ray::components::proxy {
// execute and get the code // execute and get the code
const auto returnCode = QProcess::execute(action.first, action.second); const auto returnCode = QProcess::execute(action.first, action.second);
// print out the commands and result codes // print out the commands and result codes
DEBUG(QString("[%1] Program: %2, Args: %3").arg(returnCode).arg(action.first).arg(action.second.join(";"))); DEBUG(QStringLiteral("[%1] Program: %2, Args: %3").arg(returnCode).arg(action.first).arg(action.second.join(";")));
} }
#else #else

View File

@ -1,132 +0,0 @@
#include "LogHighlighter.hpp"
#define TO_EOL "(([\\s\\S]*)|([\\d\\D]*)|([\\w\\W]*))$"
#define REGEX_IPV6_ADDR \
R"(\[\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*\])"
#define REGEX_IPV4_ADDR \
R"((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5]))"
#define REGEX_PORT_NUMBER R"(([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])*)"
namespace Qv2ray::ui {
SyntaxHighlighter::SyntaxHighlighter(bool darkMode, QTextDocument *parent) : QSyntaxHighlighter(parent) {
HighlightingRule rule;
if (darkMode) {
tcpudpFormat.setForeground(QColor(0, 200, 230));
ipHostFormat.setForeground(Qt::yellow);
warningFormat.setForeground(QColor(255, 160, 15));
warningFormat2.setForeground(Qt::cyan);
} else {
ipHostFormat.setForeground(QColor(0, 52, 130));
tcpudpFormat.setForeground(QColor(0, 52, 130));
warningFormat.setBackground(QColor(255, 160, 15));
warningFormat.setForeground(Qt::white);
warningFormat2.setForeground(Qt::darkCyan);
}
const static QColor darkGreenColor(10, 180, 0);
acceptedFormat.setForeground(darkGreenColor);
acceptedFormat.setFontItalic(true);
acceptedFormat.setFontWeight(QFont::Bold);
rule.pattern = QRegularExpression("\\saccepted\\s");
rule.format = acceptedFormat;
highlightingRules.append(rule);
//
rejectedFormat.setFontWeight(QFont::Bold);
rejectedFormat.setBackground(Qt::red);
rejectedFormat.setForeground(Qt::white);
rejectedFormat.setFontWeight(QFont::Bold);
rule.pattern = QRegularExpression("\\srejected\\s" TO_EOL);
rule.format = rejectedFormat;
highlightingRules.append(rule);
//
dateFormat.setForeground(darkMode ? Qt::cyan : Qt::darkCyan);
rule.pattern = QRegularExpression("\\d\\d\\d\\d/\\d\\d/\\d\\d");
rule.format = dateFormat;
highlightingRules.append(rule);
//
timeFormat.setForeground(darkMode ? Qt::cyan : Qt::darkCyan);
rule.pattern = QRegularExpression("\\d\\d:\\d\\d:\\d\\d");
rule.format = timeFormat;
highlightingRules.append(rule);
//
debugFormat.setForeground(Qt::darkGray);
rule.pattern = QRegularExpression("\\[D[Ee][Bb][Uu].*?\\]");
rule.format = debugFormat;
highlightingRules.append(rule);
//
infoFormat.setForeground(darkMode ? Qt::lightGray : Qt::darkCyan);
rule.pattern = QRegularExpression("\\[I[Nn][Ff][Oo].*?\\]");
rule.format = infoFormat;
highlightingRules.append(rule);
//
warningFormat.setFontWeight(QFont::Bold);
warningFormat2.setFontWeight(QFont::Bold);
rule.pattern = QRegularExpression("\\[W[Aa][Rr][Nn].*?\\]");
rule.format = warningFormat2;
highlightingRules.append(rule);
//
rule.pattern = QRegularExpression("\\[E[Rr][Rr][Oo].*?\\]");
rule.format = rejectedFormat;
highlightingRules.append(rule);
//
v2rayComponentFormat.setForeground(darkMode ? darkGreenColor : Qt::darkYellow);
rule.pattern = QRegularExpression(R"( (\w+\/)+\w+: )");
rule.format = v2rayComponentFormat;
highlightingRules.append(rule);
//
failedFormat.setFontWeight(QFont::Bold);
failedFormat.setBackground(Qt::red);
failedFormat.setForeground(Qt::white);
rule.pattern = QRegularExpression("failed");
rule.format = failedFormat;
highlightingRules.append(rule);
//
rule.pattern = QRegularExpression(">>>>+");
rule.format = warningFormat;
highlightingRules.append(rule);
//
rule.pattern = QRegularExpression("<<<<+");
rule.format = warningFormat;
highlightingRules.append(rule);
{
// IP IPv6 Host;
rule.pattern = QRegularExpression(REGEX_IPV4_ADDR ":" REGEX_PORT_NUMBER);
rule.pattern.setPatternOptions(QRegularExpression::ExtendedPatternSyntaxOption);
rule.format = ipHostFormat;
highlightingRules.append(rule);
//
rule.pattern = QRegularExpression(REGEX_IPV6_ADDR ":" REGEX_PORT_NUMBER);
rule.pattern.setPatternOptions(QRegularExpression::ExtendedPatternSyntaxOption);
rule.format = ipHostFormat;
highlightingRules.append(rule);
//
rule.pattern = QRegularExpression("([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}(/|):" REGEX_PORT_NUMBER);
rule.pattern.setPatternOptions(QRegularExpression::PatternOption::ExtendedPatternSyntaxOption);
rule.format = ipHostFormat;
highlightingRules.append(rule);
}
for (const auto &pattern: {"tcp:", "udp:"}) {
tcpudpFormat.setFontWeight(QFont::Bold);
rule.pattern = QRegularExpression(pattern);
rule.format = tcpudpFormat;
highlightingRules.append(rule);
}
}
void SyntaxHighlighter::highlightBlock(const QString &text) {
for (const HighlightingRule &rule: highlightingRules) {
QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
while (matchIterator.hasNext()) {
QRegularExpressionMatch match = matchIterator.next();
setFormat(match.capturedStart(), match.capturedLength(), rule.format);
}
}
setCurrentBlockState(0);
}
} // namespace Qv2ray::ui

View File

@ -1,92 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#pragma once
#include <QRegularExpression>
#include <QSyntaxHighlighter>
#include <QTextCharFormat>
#include <QTextDocument>
namespace Qv2ray {
namespace ui {
class SyntaxHighlighter : public QSyntaxHighlighter {
Q_OBJECT
public:
explicit SyntaxHighlighter(bool darkMode, QTextDocument *parent = nullptr);
protected:
void highlightBlock(const QString &text) override;
private:
struct HighlightingRule {
QRegularExpression pattern;
QTextCharFormat format;
};
QVector<HighlightingRule> highlightingRules;
QTextCharFormat tcpudpFormat;
QTextCharFormat dateFormat;
QTextCharFormat acceptedFormat;
QTextCharFormat rejectedFormat;
QTextCharFormat failedFormat;
QTextCharFormat warningFormat;
QTextCharFormat warningFormat2;
QTextCharFormat infoFormat;
QTextCharFormat debugFormat;
QTextCharFormat timeFormat;
QTextCharFormat ipHostFormat;
QTextCharFormat v2rayComponentFormat;
};
} // namespace ui
} // namespace Qv2ray
using namespace Qv2ray::ui;

View File

@ -191,13 +191,13 @@ QVariant QJsonModel::data(const QModelIndex &index, int role) const {
if (role == Qt::DisplayRole) { if (role == Qt::DisplayRole) {
if (index.column() == 0) if (index.column() == 0)
return QString("%1").arg(item->key()); return QStringLiteral("%1").arg(item->key());
if (index.column() == 1) if (index.column() == 1)
return QString("%1").arg(item->value()); return QStringLiteral("%1").arg(item->value());
} else if (Qt::EditRole == role) { } else if (Qt::EditRole == role) {
if (index.column() == 1) { if (index.column() == 1) {
return QString("%1").arg(item->value()); return QStringLiteral("%1").arg(item->value());
} }
} }

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 3.5)
project(nekoray VERSION 0.1 LANGUAGES CXX) project(nekobox VERSION 0.1 LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_INCLUDE_CURRENT_DIR ON)
@ -30,9 +30,7 @@ if (NKR_CROSS)
endif () endif ()
#### Platform Variables #### #### Platform Variables ####
if (APPLE) if (WIN32)
include("cmake/macos/macos.cmake")
elseif (WIN32)
include("cmake/windows/windows.cmake") include("cmake/windows/windows.cmake")
else () else ()
include("cmake/linux/linux.cmake") include("cmake/linux/linux.cmake")
@ -65,10 +63,6 @@ include("cmake/nkr.cmake")
find_package(Threads) find_package(Threads)
if (NKR_PACKAGE OR NKR_PACKAGE_MACOS)
nkr_add_compile_definitions(NKR_CPP_USE_APPDATA)
endif ()
#### NKR EXTERNAL #### #### NKR EXTERNAL ####
if (NKR_NO_EXTERNAL) if (NKR_NO_EXTERNAL)
@ -76,15 +70,6 @@ if (NKR_NO_EXTERNAL)
set(NKR_NO_YAML 1) set(NKR_NO_YAML 1)
set(NKR_NO_ZXING 1) set(NKR_NO_ZXING 1)
set(NKR_NO_QHOTKEY 1) set(NKR_NO_QHOTKEY 1)
set(NKR_NO_QUICKJS 1)
endif ()
# quickjs (static submodule)
if (NKR_NO_QUICKJS)
nkr_add_compile_definitions(NKR_NO_QUICKJS)
else ()
add_subdirectory(3rdparty/qjs)
list(APPEND NKR_EXTERNAL_TARGETS quickjs)
endif () endif ()
# grpc # grpc
@ -140,14 +125,12 @@ set(PROJECT_SOURCES
main/main.cpp main/main.cpp
main/NekoGui.cpp main/NekoGui.cpp
main/NekoGui_Utils.cpp main/NekoGui_Utils.cpp
main/QJS.cpp
main/HTTPRequestHelper.cpp main/HTTPRequestHelper.cpp
3rdparty/base64.cpp 3rdparty/base64.cpp
3rdparty/qrcodegen.cpp 3rdparty/qrcodegen.cpp
3rdparty/QtExtKeySequenceEdit.cpp 3rdparty/QtExtKeySequenceEdit.cpp
3rdparty/qv2ray/v2/ui/LogHighlighter.cpp
3rdparty/qv2ray/v2/ui/QvAutoCompleteTextEdit.cpp 3rdparty/qv2ray/v2/ui/QvAutoCompleteTextEdit.cpp
3rdparty/qv2ray/v2/components/proxy/QvProxyConfigurator.cpp 3rdparty/qv2ray/v2/components/proxy/QvProxyConfigurator.cpp
3rdparty/qv2ray/v2/ui/widgets/common/QJsonModel.cpp 3rdparty/qv2ray/v2/ui/widgets/common/QJsonModel.cpp
@ -166,7 +149,6 @@ set(PROJECT_SOURCES
db/ConfigBuilder.cpp db/ConfigBuilder.cpp
fmt/AbstractBean.cpp fmt/AbstractBean.cpp
fmt/Bean2CoreObj_ray.cpp
fmt/Bean2CoreObj_box.cpp fmt/Bean2CoreObj_box.cpp
fmt/Bean2External.cpp fmt/Bean2External.cpp
fmt/Bean2Link.cpp fmt/Bean2Link.cpp
@ -241,10 +223,6 @@ set(PROJECT_SOURCES
ui/dialog_hotkey.h ui/dialog_hotkey.h
ui/dialog_hotkey.ui ui/dialog_hotkey.ui
ui/dialog_first_setup.cpp
ui/dialog_first_setup.h
ui/dialog_first_setup.ui
ui/widget/ProxyItem.cpp ui/widget/ProxyItem.cpp
ui/widget/ProxyItem.h ui/widget/ProxyItem.h
ui/widget/ProxyItem.ui ui/widget/ProxyItem.ui
@ -259,23 +237,23 @@ set(PROJECT_SOURCES
# Qt exe # Qt exe
if (${QT_VERSION_MAJOR} GREATER_EQUAL 6) if (${QT_VERSION_MAJOR} GREATER_EQUAL 6)
qt_add_executable(nekoray qt_add_executable(nekobox
MANUAL_FINALIZATION MANUAL_FINALIZATION
${PROJECT_SOURCES} ${PROJECT_SOURCES}
) )
# Define target properties for Android with Qt 6 as: # Define target properties for Android with Qt 6 as:
# set_property(TARGET nekoray APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR # set_property(TARGET nekobox APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
# ${CMAKE_CURRENT_SOURCE_DIR}/android) # ${CMAKE_CURRENT_SOURCE_DIR}/android)
# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation # For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
else () else ()
if (ANDROID) if (ANDROID)
add_library(nekoray SHARED add_library(nekobox SHARED
${PROJECT_SOURCES} ${PROJECT_SOURCES}
) )
# Define properties for Android with Qt 5 after find_package() calls as: # Define properties for Android with Qt 5 after find_package() calls as:
# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android") # set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
else () else ()
add_executable(nekoray add_executable(nekobox
${PROJECT_SOURCES} ${PROJECT_SOURCES}
) )
endif () endif ()
@ -283,22 +261,11 @@ endif ()
# Target # Target
set_property(TARGET nekoray PROPERTY AUTOUIC ON) set_property(TARGET nekobox PROPERTY AUTOUIC ON)
set_property(TARGET nekoray PROPERTY AUTOMOC ON) set_property(TARGET nekobox PROPERTY AUTOMOC ON)
set_property(TARGET nekoray PROPERTY AUTORCC ON) set_property(TARGET nekobox PROPERTY AUTORCC ON)
# Target Source macOS set_target_properties(nekobox PROPERTIES
set(MACOSX_ICON ${CMAKE_SOURCE_DIR}/res/nekoray.icns)
if (APPLE)
target_sources(nekoray PRIVATE ${MACOSX_ICON})
endif ()
set_target_properties(nekoray PROPERTIES
MACOSX_BUNDLE_ICON_FILE "nekoray.icns"
RESOURCE ${MACOSX_ICON}
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/res/MacOSXBundleInfo.plist
MACOSX_BUNDLE_GUI_IDENTIFIER moe.nekoray.macosx
MACOSX_BUNDLE TRUE
WIN32_EXECUTABLE TRUE WIN32_EXECUTABLE TRUE
) )
@ -313,17 +280,17 @@ set(LUPDATE_OPTIONS
-locations none -no-obsolete -locations none -no-obsolete
) )
if (${QT_VERSION_MAJOR} GREATER_EQUAL 6) if (${QT_VERSION_MAJOR} GREATER_EQUAL 6)
qt_add_lupdate(nekoray TS_FILES ${TS_FILES} OPTIONS ${LUPDATE_OPTIONS}) qt_add_lupdate(nekobox TS_FILES ${TS_FILES} OPTIONS ${LUPDATE_OPTIONS})
qt_add_lrelease(nekoray TS_FILES ${TS_FILES} QM_FILES_OUTPUT_VARIABLE QM_FILES) qt_add_lrelease(nekobox TS_FILES ${TS_FILES} QM_FILES_OUTPUT_VARIABLE QM_FILES)
else () else ()
qt5_create_translation(QM_FILES ${PROJECT_SOURCES} ${TS_FILES} OPTIONS ${LUPDATE_OPTIONS}) qt5_create_translation(QM_FILES ${PROJECT_SOURCES} ${TS_FILES} OPTIONS ${LUPDATE_OPTIONS})
endif () endif ()
configure_file(translations/translations.qrc ${CMAKE_BINARY_DIR} COPYONLY) configure_file(translations/translations.qrc ${CMAKE_BINARY_DIR} COPYONLY)
target_sources(nekoray PRIVATE ${CMAKE_BINARY_DIR}/translations.qrc) target_sources(nekobox PRIVATE ${CMAKE_BINARY_DIR}/translations.qrc)
# Target Link # Target Link
target_link_libraries(nekoray PRIVATE target_link_libraries(nekobox PRIVATE
Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::Svg Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::Svg
Threads::Threads Threads::Threads
${NKR_EXTERNAL_TARGETS} ${NKR_EXTERNAL_TARGETS}
@ -331,5 +298,5 @@ target_link_libraries(nekoray PRIVATE
) )
if (QT_VERSION_MAJOR EQUAL 6) if (QT_VERSION_MAJOR EQUAL 6)
qt_finalize_executable(nekoray) qt_finalize_executable(nekobox)
endif () endif ()

View File

@ -1,17 +1,13 @@
# NekoRay / NekoBox For PC # NekoBox For PC
Qt based cross-platform GUI proxy configuration manager (backend: v2ray / sing-box) Qt based cross-platform GUI proxy configuration manager (backend: sing-box)
Support Windows / Linux out of the box now. Support Windows / Linux out of the box now.
基于 Qt 的跨平台代理配置管理器 (后端 v2ray / sing-box) 基于 Qt 的跨平台代理配置管理器 (后端 sing-box)
目前支持 Windows / Linux 开箱即用 目前支持 Windows / Linux 开箱即用
## Readme Translations
中文 / English / [fa_IR](README_fa.md)
## 下载 / Download ## 下载 / Download
### GitHub Releases (Portable ZIP) ### GitHub Releases (Portable ZIP)
@ -27,17 +23,20 @@ Support Windows / Linux out of the box now.
### Package ### Package
#### AUR #### AUR
- [nekoray](https://aur.archlinux.org/packages/nekoray) - [nekoray](https://aur.archlinux.org/packages/nekoray)
- [nekoray-git](https://aur.archlinux.org/packages/nekoray-git) - [nekoray-git](https://aur.archlinux.org/packages/nekoray-git)
#### archlinuxcn #### archlinuxcn
- [nekoray](https://github.com/archlinuxcn/repo/tree/master/archlinuxcn/nekoray) - [nekoray](https://github.com/archlinuxcn/repo/tree/master/archlinuxcn/nekoray)
- [nekoray-git](https://github.com/archlinuxcn/repo/tree/master/archlinuxcn/nekoray-git) - [nekoray-git](https://github.com/archlinuxcn/repo/tree/master/archlinuxcn/nekoray-git)
#### Scoop extras #### Scoop Extras
`scoop install nekoray` `scoop install nekoray`
## 更改记录 & 发布频道 / Changelog & Telegram channel ## 更改记录 & 发布频道 / Changelog & Telegram Channel
https://t.me/Matsuridayo https://t.me/Matsuridayo
@ -47,24 +46,23 @@ https://matsuridayo.github.io
## 代理 / Proxy ## 代理 / Proxy
* SOCKS (4/4a/5) - SOCKS (4/4a/5)
* HTTP(S) - HTTP(S)
* Shadowsocks - Shadowsocks
* VMess - VMess
* VLESS - VLESS
* Trojan - Trojan
* TUIC ( sing-box ) - TUIC ( sing-box )
* NaïveProxy ( Custom Core ) - NaïveProxy ( Custom Core )
* Hysteria ( Custom Core or sing-box ) - Hysteria2 ( Custom Core or sing-box )
* Hysteria2 ( Custom Core or sing-box ) - Custom Outbound
* Custom Outbound - Custom Config
* Custom Config - Custom Core
* Custom Core
## 订阅 / Subscription ## 订阅 / Subscription
* Raw: some widely used formats (like shadowsocks, clash and v2rayN) - Raw: some widely used formats (like Shadowsocks, Clash and v2rayN)
* 原始格式:一些广泛使用的格式(如 shadowsocks、clash 和 v2rayN - 原始格式: 一些广泛使用的格式 (如 Shadowsocks、Clash 和 v2rayN)
## 运行参数 ## 运行参数
@ -78,14 +76,6 @@ https://matsuridayo.github.io
[Linux 运行教程](docs/Run_Linux.md) [Linux 运行教程](docs/Run_Linux.md)
## macOS
由于缺乏维护,不再提供 macOS 版本下载。
您还可以在下面的存储库中非正式地获取更新版本。[非官方发布 / Unofficial releases](https://github.com/aaaamirabbas/nekoray-macos/releases)
仍可以参照下方教程自行编译,常见问题请参考历史 Issue欢迎 Pull Request 修复。
## 编译教程 / Compile Tutorial ## 编译教程 / Compile Tutorial
请看 [技术文档 / Technical documentation](https://github.com/MatsuriDayo/nekoray/tree/main/docs) 请看 [技术文档 / Technical documentation](https://github.com/MatsuriDayo/nekoray/tree/main/docs)
@ -106,9 +96,6 @@ XMR
`49bwESYQjoRL3xmvTcjZKHEKaiGywjLYVQJMUv79bXonGiyDCs8AzE3KiGW2ytTybBCpWJUvov8SjZZEGg66a4e59GXa6k5` `49bwESYQjoRL3xmvTcjZKHEKaiGywjLYVQJMUv79bXonGiyDCs8AzE3KiGW2ytTybBCpWJUvov8SjZZEGg66a4e59GXa6k5`
* 您也可以通过 [Google Play](https://play.google.com/store/apps/details?id=moe.nb4a) 购买捐赠,另有支付宝微信购买方式,见 TG 频道置顶。
* Donating via [Google Play](https://play.google.com/store/apps/details?id=moe.nb4a), using credit cards.
## Credits ## Credits
Core: Core:
@ -116,8 +103,8 @@ Core:
- [v2fly/v2ray-core](https://github.com/v2fly/v2ray-core) ( < 3.10 ) - [v2fly/v2ray-core](https://github.com/v2fly/v2ray-core) ( < 3.10 )
- [MatsuriDayo/Matsuri](https://github.com/MatsuriDayo/Matsuri) ( < 3.10 ) - [MatsuriDayo/Matsuri](https://github.com/MatsuriDayo/Matsuri) ( < 3.10 )
- [MatsuriDayo/v2ray-core](https://github.com/MatsuriDayo/v2ray-core) ( < 3.10 ) - [MatsuriDayo/v2ray-core](https://github.com/MatsuriDayo/v2ray-core) ( < 3.10 )
- [XTLS/Xray-core](https://github.com/XTLS/Xray-core) ( >= 3.10 ) - [XTLS/Xray-core](https://github.com/XTLS/Xray-core) ( 3.10 <= Version <= 3.26 )
- [MatsuriDayo/Xray-core](https://github.com/MatsuriDayo/Xray-core) ( >= 3.10 ) - [MatsuriDayo/Xray-core](https://github.com/MatsuriDayo/Xray-core) ( 3.10 <= Version <= 3.26 )
- [SagerNet/sing-box](https://github.com/SagerNet/sing-box) - [SagerNet/sing-box](https://github.com/SagerNet/sing-box)
- [Matsuridayo/sing-box-extra](https://github.com/MatsuriDayo/sing-box-extra) - [Matsuridayo/sing-box-extra](https://github.com/MatsuriDayo/sing-box-extra)

View File

@ -1,94 +0,0 @@
# NekoRay
مدیریت پیکربندی پروکسی با رابط کاربری مبتنی بر QT , کراس پلتفرم . (بک اند : v2ray / sing-box )
اکنون از Windows / Linux / macOS amd64 پشتیبانی می کند.
## دانلود / Download
### GitHub Releases (Portable ZIP)
فرمت قابل حمل، بدون نصب. برای دانلود باینری های از پیش کامپایل شده به Releases بروید، آنها را باز کرده و از آنها استفاده کنید.
[![GitHub All Releases](https://img.shields.io/github/downloads/Matsuridayo/nekoray/total?label=downloads-total&logo=github&style=flat-square)](https://github.com/Matsuridayo/nekoray/releases)
[Download](https://github.com/Matsuridayo/nekoray/releases)
### بسته
1. AUR [nekoray-git](https://aur.archlinux.org/packages/nekoray-git)
2. Scoop extras: `scoop install nekoray`
3. Homebrew (unoffical): [homebrew-nekoray](https://github.com/tdjnodj/homebrew-nekoray)
4. APT (unoffical): [tdjnodj/apt](https://github.com/tdjnodj/apt)
## تغییرات برنامه و کانال تلگرام / Changelog & Telegram channel
https://t.me/Matsuridayo
## صفحه مستندات / Homepage & Documents
https://matsuridayo.github.io
## پروکسی / Proxy
* SOCKS (4/4a/5)
* HTTP(S)
* Shadowsocks
* VMess
* VLESS
* Trojan
* NaïveProxy ( Custom Core )
* Hysteria ( Custom Core or sing-box )
* Hysteria2 ( Custom Core or sing-box )
* Custom Outbound
* Custom Core
## اشتراک / Subscription
* فرمت های خام: برخی از فرمت های پرکاربرد (مانند shadowsocks، clash و v2rayN)
## پارامترهای عملیاتی
- `-many` نمونه در حال اجرا همان دایرکتوری را نادیده بگیرید و به اجبار یک نمونه جدید راه اندازی کنید(0.11+)
- `-appdata` پس از باز کردن، فایل پیکربندی در دایرکتوری مشترک قرار می گیرد و نمی توان آن را بیشتر باز کرد و به طور خودکار ارتقا داد. (0.11+)
## Windows
اگر به شما می گوید که DLL وجود ندارد و نمی تواند اجرا شود، لطفاً [Microsoft C++ Runtime Library] (https://aka.ms/vs/17/release/vc_redist.x64.exe) را دانلود و نصب کنید.
## Linux
[آموزش اجرای لینوکس](docs/Run_Linux.md)
## آموزش کامپایل
[Linux](docs/Build_Linux.md)
[Windows](docs/Build_Windows.md)
[macOs](docs/Build_MacOS_fa.md)
## کمک مالی / Donate
از کمک های مالی برای حمایت از توسعه پروژه استقبال می شود。
USDT TRC20
`TRhnA7SXE5Sap5gSG3ijxRmdYFiD4KRhPs`
XMR
`49bwESYQjoRL3xmvTcjZKHEKaiGywjLYVQJMUv79bXonGiyDCs8AzE3KiGW2ytTybBCpWJUvov8SjZZEGg66a4e59GXa6k5`
## Credits
- [v2fly/v2ray-core](https://github.com/v2fly/v2ray-core)
- [MatsuriDayo/Matsuri](https://github.com/MatsuriDayo/Matsuri)
- [MatsuriDayo/v2ray-core](https://github.com/MatsuriDayo/v2ray-core)
- [SagerNet/sing-box](https://github.com/SagerNet/sing-box)
- [Qv2ray](https://github.com/Qv2ray/Qv2ray)
- [Qt](https://www.qt.io/)
- [protobuf](https://github.com/protocolbuffers/protobuf)
- [yaml-cpp](https://github.com/jbeder/yaml-cpp)
- [zxing-cpp](https://github.com/nu-book/zxing-cpp)
- [QHotkey](https://github.com/Skycoder42/QHotkey)
- [AppImageKit](https://github.com/AppImage/AppImageKit)

View File

@ -1,18 +0,0 @@
{
"title": "nekoray",
"icon": "res/nekoray.icns",
"contents": [
{
"x": 448,
"y": 344,
"type": "link",
"path": "/Applications"
},
{
"x": 192,
"y": 344,
"type": "file",
"path": "build/nekoray.app"
}
]
}

View File

@ -4,12 +4,12 @@ set(PLATFORM_LIBRARIES wininet wsock32 ws2_32 user32 rasapi32 iphlpapi)
include(cmake/windows/generate_product_version.cmake) include(cmake/windows/generate_product_version.cmake)
generate_product_version( generate_product_version(
QV2RAY_RC QV2RAY_RC
ICON "${CMAKE_SOURCE_DIR}/res/nekoray.ico" ICON "${CMAKE_SOURCE_DIR}/res/nekobox.ico"
NAME "nekoray" NAME "nekobox"
BUNDLE "nekoray" BUNDLE "nekobox"
COMPANY_NAME "nekoray" COMPANY_NAME "nekobox"
COMPANY_COPYRIGHT "nekoray" COMPANY_COPYRIGHT "nekobox"
FILE_DESCRIPTION "nekoray" FILE_DESCRIPTION "nekobox"
) )
add_definitions(-DUNICODE -D_UNICODE -DNOMINMAX) add_definitions(-DUNICODE -D_UNICODE -DNOMINMAX)
set(GUI_TYPE WIN32) set(GUI_TYPE WIN32)

View File

@ -2,14 +2,12 @@
#include "db/Database.hpp" #include "db/Database.hpp"
#include "fmt/includes.h" #include "fmt/includes.h"
#include "fmt/Preset.hpp" #include "fmt/Preset.hpp"
#include "main/QJS.hpp"
#include <QApplication> #include <QApplication>
#include <QFile> #include <QFile>
#include <QFileInfo> #include <QFileInfo>
#define BOX_UNDERLYING_DNS dataStore->core_box_underlying_dns.isEmpty() ? "underlying://0.0.0.0" : dataStore->core_box_underlying_dns #define BOX_UNDERLYING_DNS dataStore->core_box_underlying_dns.isEmpty() ? "local" : dataStore->core_box_underlying_dns
#define BOX_UNDERLYING_DNS_EXPORT dataStore->core_box_underlying_dns.isEmpty() ? (status->forExport ? "local" : "underlying://0.0.0.0") : dataStore->core_box_underlying_dns
namespace NekoGui { namespace NekoGui {
@ -24,30 +22,48 @@ namespace NekoGui {
} }
QString genTunName() { QString genTunName() {
auto tun_name = "nekoray-tun"; auto tun_name = "neko-tun";
#ifdef Q_OS_MACOS #ifdef Q_OS_MACOS
tun_name = "utun9"; tun_name = "utun9";
#endif #endif
return tun_name; return tun_name;
} }
void MergeJson(const QJsonObject &custom, QJsonObject &outbound) { void MergeJson(QJsonObject &dst, const QJsonObject &src) {
// 合并 // 合并
if (custom.isEmpty()) return; if (src.isEmpty()) return;
for (const auto &key: custom.keys()) { for (const auto &key: src.keys()) {
if (outbound.contains(key)) { auto v_src = src[key];
auto v = custom[key]; if (dst.contains(key)) {
auto v_orig = outbound[key]; auto v_dst = dst[key];
if (v.isObject() && v_orig.isObject()) { // isObject 则合并? if (v_src.isObject() && v_dst.isObject()) { // isObject 则合并?
auto vo = v.toObject(); auto v_src_obj = v_src.toObject();
QJsonObject vo_orig = v_orig.toObject(); auto v_dst_obj = v_dst.toObject();
MergeJson(vo, vo_orig); MergeJson(v_dst_obj, v_src_obj);
outbound[key] = vo_orig; dst[key] = v_dst_obj;
} else { } else {
outbound[key] = v; dst[key] = v_src;
}
} else if (v_src.isArray()) {
if (key.startsWith("+")) {
auto key2 = SubStrAfter(key, "+");
auto v_dst = dst[key2];
auto v_src_arr = v_src.toArray();
auto v_dst_arr = v_dst.toArray();
QJSONARRAY_ADD(v_src_arr, v_dst_arr)
dst[key2] = v_src_arr;
} else if (key.endsWith("+")) {
auto key2 = SubStrBefore(key, "+");
auto v_dst = dst[key2];
auto v_src_arr = v_src.toArray();
auto v_dst_arr = v_dst.toArray();
QJSONARRAY_ADD(v_dst_arr, v_src_arr)
dst[key2] = v_dst_arr;
} else {
dst[key] = v_src;
} }
} else { } else {
outbound[key] = custom[key]; dst[key] = v_src;
} }
} }
} }
@ -66,36 +82,19 @@ namespace NekoGui {
if (customBean != nullptr && customBean->core == "internal-full") { if (customBean != nullptr && customBean->core == "internal-full") {
result->coreConfig = QString2QJsonObject(customBean->config_simple); result->coreConfig = QString2QJsonObject(customBean->config_simple);
} else { } else {
if (IS_NEKO_BOX) { BuildConfigSingBox(status);
BuildConfigSingBox(status);
} else {
BuildConfigV2Ray(status);
}
} }
// apply custom config // apply custom config
MergeJson(QString2QJsonObject(ent->bean->custom_config), result->coreConfig); MergeJson(result->coreConfig, QString2QJsonObject(ent->bean->custom_config));
// hook.js
if (result->error.isEmpty() && !forTest) {
auto source = qjs::ReadHookJS();
if (!source.isEmpty()) {
qjs::QJS js(source);
auto js_result = js.EvalFunction("hook.hook_core_config", QJsonObject2QString(result->coreConfig, true));
auto js_result_json = QString2QJsonObject(js_result);
if (!js_result_json.isEmpty() && result->coreConfig != js_result_json) {
MW_show_log("hook.js modified your " + software_core_name + " json config.");
result->coreConfig = js_result_json;
}
}
}
return result; return result;
} }
QString BuildChain(int chainId, const std::shared_ptr<BuildConfigStatus> &status) { QString BuildChain(int chainId, const std::shared_ptr<BuildConfigStatus> &status) {
auto group = profileManager->GetGroup(status->ent->gid); auto group = profileManager->GetGroup(status->ent->gid);
if (group == nullptr) { if (group == nullptr) {
status->result->error = QString("This profile is not in any group, your data may be corrupted."); status->result->error = QStringLiteral("This profile is not in any group, your data may be corrupted.");
return {}; return {};
} }
@ -107,11 +106,11 @@ namespace NekoGui {
for (auto id: list) { for (auto id: list) {
resolved += profileManager->GetProfile(id); resolved += profileManager->GetProfile(id);
if (resolved.last() == nullptr) { if (resolved.last() == nullptr) {
status->result->error = QString("chain missing ent: %1").arg(id); status->result->error = QStringLiteral("chain missing ent: %1").arg(id);
break; break;
} }
if (resolved.last()->type == "chain") { if (resolved.last()->type == "chain") {
status->result->error = QString("chain in chain is not allowed: %1").arg(id); status->result->error = QStringLiteral("chain in chain is not allowed: %1").arg(id);
break; break;
} }
} }
@ -128,7 +127,7 @@ namespace NekoGui {
if (group->front_proxy_id >= 0) { if (group->front_proxy_id >= 0) {
auto fEnt = profileManager->GetProfile(group->front_proxy_id); auto fEnt = profileManager->GetProfile(group->front_proxy_id);
if (fEnt == nullptr) { if (fEnt == nullptr) {
status->result->error = QString("front proxy ent not found."); status->result->error = QStringLiteral("front proxy ent not found.");
return {}; return {};
} }
ents += resolveChain(fEnt); ents += resolveChain(fEnt);
@ -172,254 +171,6 @@ namespace NekoGui {
status->ipListDirect += line; \ status->ipListDirect += line; \
} }
// V2Ray
void BuildConfigV2Ray(const std::shared_ptr<BuildConfigStatus> &status) {
// Log
auto logObj = QJsonObject{{"loglevel", dataStore->log_level}};
status->result->coreConfig.insert("log", logObj);
// Inbounds
QJsonObject sniffing{
{"destOverride", QJsonArray{"http", "tls", "quic"}},
{"enabled", true},
{"metadataOnly", false},
{"routeOnly", dataStore->routing->sniffing_mode == SniffingMode::FOR_ROUTING},
};
// socks-in
if (IsValidPort(dataStore->inbound_socks_port) && !status->forTest) {
QJsonObject inboundObj;
inboundObj["tag"] = "socks-in";
inboundObj["protocol"] = "socks";
inboundObj["listen"] = dataStore->inbound_address;
inboundObj["port"] = dataStore->inbound_socks_port;
QJsonObject socksSettings = {{"udp", true}};
if (dataStore->routing->sniffing_mode != SniffingMode::DISABLE) {
inboundObj["sniffing"] = sniffing;
}
if (dataStore->inbound_auth->NeedAuth()) {
socksSettings["auth"] = "password";
socksSettings["accounts"] = QJsonArray{
QJsonObject{
{"user", dataStore->inbound_auth->username},
{"pass", dataStore->inbound_auth->password},
},
};
}
inboundObj["settings"] = socksSettings;
status->inbounds += inboundObj;
}
// http-in
if (IsValidPort(dataStore->inbound_http_port) && !status->forTest) {
QJsonObject inboundObj;
inboundObj["tag"] = "http-in";
inboundObj["protocol"] = "http";
inboundObj["listen"] = dataStore->inbound_address;
inboundObj["port"] = dataStore->inbound_http_port;
if (dataStore->routing->sniffing_mode != SniffingMode::DISABLE) {
inboundObj["sniffing"] = sniffing;
}
if (dataStore->inbound_auth->NeedAuth()) {
inboundObj["settings"] = QJsonObject{
{"accounts", QJsonArray{
QJsonObject{
{"user", dataStore->inbound_auth->username},
{"pass", dataStore->inbound_auth->password},
},
}},
};
}
status->inbounds += inboundObj;
}
// Outbounds
auto tagProxy = BuildChain(0, status);
if (!status->result->error.isEmpty()) return;
// direct & bypass & block
status->outbounds += QJsonObject{
{"protocol", "freedom"},
{"domainStrategy", dataStore->core_ray_freedom_domainStrategy},
{"tag", "direct"},
};
status->outbounds += QJsonObject{
{"protocol", "freedom"},
{"domainStrategy", dataStore->core_ray_freedom_domainStrategy},
{"tag", "bypass"},
};
status->outbounds += QJsonObject{
{"protocol", "blackhole"},
{"tag", "block"},
};
// DNS out
if (!status->forTest) {
QJsonObject dnsOut;
dnsOut["protocol"] = "dns";
dnsOut["tag"] = "dns-out";
QJsonObject dnsOut_settings;
dnsOut_settings["network"] = "tcp";
dnsOut_settings["port"] = 53;
dnsOut_settings["address"] = "8.8.8.8";
dnsOut_settings["userLevel"] = 1;
dnsOut["settings"] = dnsOut_settings;
dnsOut["proxySettings"] = QJsonObject{{"tag", tagProxy},
{"transportLayer", true}};
status->outbounds += dnsOut;
status->routingRules += QJsonObject{
{"type", "field"},
{"port", "53"},
{"inboundTag", QJsonArray{"socks-in", "http-in"}},
{"outboundTag", "dns-out"},
};
}
// custom inbound
if (!status->forTest) QJSONARRAY_ADD(status->inbounds, QString2QJsonObject(dataStore->custom_inbound)["inbounds"].toArray())
status->result->coreConfig.insert("inbounds", status->inbounds);
status->result->coreConfig.insert("outbounds", status->outbounds);
// user rule
if (!status->forTest) {
DOMAIN_USER_RULE
IP_USER_RULE
}
// final add DNS
QJsonObject dns;
QJsonArray dnsServers;
// Remote or FakeDNS
QJsonObject dnsServerRemote;
dnsServerRemote["address"] = dataStore->routing->remote_dns;
dnsServerRemote["domains"] = QList2QJsonArray<QString>(status->domainListDNSRemote);
dnsServerRemote["queryStrategy"] = dataStore->routing->remote_dns_strategy;
if (!status->forTest) dnsServers += dnsServerRemote;
// Direct
auto directDnsAddress = dataStore->routing->direct_dns;
if (directDnsAddress.contains("://")) {
auto directDnsIp = SubStrBefore(SubStrAfter(directDnsAddress, "://"), "/");
if (IsIpAddress(directDnsIp)) {
status->routingRules.push_front(QJsonObject{
{"type", "field"},
{"ip", QJsonArray{directDnsIp}},
{"outboundTag", "direct"},
});
} else {
status->routingRules.push_front(QJsonObject{
{"type", "field"},
{"domain", QJsonArray{directDnsIp}},
{"outboundTag", "direct"},
});
}
} else if (directDnsAddress != "localhost") {
status->routingRules.push_front(QJsonObject{
{"type", "field"},
{"ip", QJsonArray{directDnsAddress}},
{"outboundTag", "direct"},
});
}
QJsonObject directObj{
{"address", directDnsAddress.replace("https://", "https+local://")},
{"queryStrategy", dataStore->routing->direct_dns_strategy},
{"domains", QList2QJsonArray<QString>(status->domainListDNSDirect)},
};
if (dataStore->routing->dns_final_out == "bypass") {
dnsServers.prepend(directObj);
} else {
dnsServers.append(directObj);
}
dns["disableFallback"] = true;
dns["servers"] = dnsServers;
dns["tag"] = "dns";
if (dataStore->routing->use_dns_object) {
dns = QString2QJsonObject(dataStore->routing->dns_object);
}
status->result->coreConfig.insert("dns", dns);
// Routing
QJsonObject routing;
routing["domainStrategy"] = dataStore->routing->domain_strategy;
if (status->forTest) routing["domainStrategy"] = "AsIs";
// final add user rule (block)
QJsonObject routingRule_tmp;
routingRule_tmp["type"] = "field";
routingRule_tmp["outboundTag"] = "block";
if (!status->ipListBlock.isEmpty()) {
auto tmp = routingRule_tmp;
tmp["ip"] = QList2QJsonArray<QString>(status->ipListBlock);
status->routingRules += tmp;
}
if (!status->domainListBlock.isEmpty()) {
auto tmp = routingRule_tmp;
tmp["domain"] = QList2QJsonArray<QString>(status->domainListBlock);
status->routingRules += tmp;
}
// final add user rule (proxy)
routingRule_tmp["outboundTag"] = "proxy";
if (!status->ipListRemote.isEmpty()) {
auto tmp = routingRule_tmp;
tmp["ip"] = QList2QJsonArray<QString>(status->ipListRemote);
status->routingRules += tmp;
}
if (!status->domainListRemote.isEmpty()) {
auto tmp = routingRule_tmp;
tmp["domain"] = QList2QJsonArray<QString>(status->domainListRemote);
status->routingRules += tmp;
}
// final add user rule (bypass)
routingRule_tmp["outboundTag"] = "bypass";
if (!status->ipListDirect.isEmpty()) {
auto tmp = routingRule_tmp;
tmp["ip"] = QList2QJsonArray<QString>(status->ipListDirect);
status->routingRules += tmp;
}
if (!status->domainListDirect.isEmpty()) {
auto tmp = routingRule_tmp;
tmp["domain"] = QList2QJsonArray<QString>(status->domainListDirect);
status->routingRules += tmp;
}
// def_outbound
if (!status->forTest) status->routingRules += QJsonObject{
{"type", "field"},
{"port", "0-65535"},
{"outboundTag", dataStore->routing->def_outbound},
};
// final add routing rule
auto routingRules = QString2QJsonObject(dataStore->routing->custom)["rules"].toArray();
if (status->forTest) routingRules = {};
if (!status->forTest) QJSONARRAY_ADD(routingRules, QString2QJsonObject(dataStore->custom_route_global)["rules"].toArray())
QJSONARRAY_ADD(routingRules, status->routingRules)
routing["rules"] = routingRules;
status->result->coreConfig.insert("routing", routing);
// Policy & stats
QJsonObject policy;
QJsonObject levels;
QJsonObject level1;
level1["connIdle"] = 30;
levels["1"] = level1;
policy["levels"] = levels;
QJsonObject policySystem;
policySystem["statsOutboundDownlink"] = true;
policySystem["statsOutboundUplink"] = true;
policy["system"] = policySystem;
status->result->coreConfig.insert("policy", policy);
status->result->coreConfig.insert("stats", QJsonObject());
}
QString BuildChainInternal(int chainId, const QList<std::shared_ptr<ProxyEntity>> &ents, QString BuildChainInternal(int chainId, const QList<std::shared_ptr<ProxyEntity>> &ents,
const std::shared_ptr<BuildConfigStatus> &status) { const std::shared_ptr<BuildConfigStatus> &status) {
QString chainTag = "c-" + Int2String(chainId); QString chainTag = "c-" + Int2String(chainId);
@ -469,29 +220,14 @@ namespace NekoGui {
// chain rules: past // chain rules: past
if (pastExternalStat == 0) { if (pastExternalStat == 0) {
auto replaced = status->outbounds.last().toObject(); auto replaced = status->outbounds.last().toObject();
if (IS_NEKO_BOX) { replaced["detour"] = tagOut;
replaced["detour"] = tagOut;
} else {
replaced["proxySettings"] = QJsonObject{
{"tag", tagOut},
{"transportLayer", true},
};
}
status->outbounds.removeLast(); status->outbounds.removeLast();
status->outbounds += replaced; status->outbounds += replaced;
} else { } else {
if (IS_NEKO_BOX) { status->routingRules += QJsonObject{
status->routingRules += QJsonObject{ {"inbound", QJsonArray{pastTag + "-mapping"}},
{"inbound", QJsonArray{pastTag + "-mapping"}}, {"outbound", tagOut},
{"outbound", tagOut}, };
};
} else {
status->routingRules += QJsonObject{
{"type", "field"},
{"inboundTag", QJsonArray{pastTag + "-mapping"}},
{"outboundTag", tagOut},
};
}
} }
} else { } else {
// index == 0 means last profile in chain / not chain // index == 0 means last profile in chain / not chain
@ -530,43 +266,20 @@ namespace NekoGui {
if (thisExternalStat == 2) dataStore->need_keep_vpn_off = true; if (thisExternalStat == 2) dataStore->need_keep_vpn_off = true;
if (thisExternalStat == 1) { if (thisExternalStat == 1) {
// mapping // mapping
if (IS_NEKO_BOX) { status->inbounds += QJsonObject{
status->inbounds += QJsonObject{ {"type", "direct"},
{"type", "direct"}, {"tag", tagOut + "-mapping"},
{"tag", tagOut + "-mapping"}, {"listen", "127.0.0.1"},
{"listen", "127.0.0.1"}, {"listen_port", ext_mapping_port},
{"listen_port", ext_mapping_port}, {"override_address", ent->bean->serverAddress},
{"override_address", ent->bean->serverAddress}, {"override_port", ent->bean->serverPort},
{"override_port", ent->bean->serverPort}, };
};
} else {
status->inbounds += QJsonObject{
{"protocol", "dokodemo-door"},
{"tag", tagOut + "-mapping"},
{"listen", "127.0.0.1"},
{"port", ext_mapping_port},
{"settings", QJsonObject{
// to
{"address", ent->bean->serverAddress},
{"port", ent->bean->serverPort},
{"network", "tcp,udp"},
}},
};
}
// no chain rule and not outbound, so need to set to direct // no chain rule and not outbound, so need to set to direct
if (isFirstProfile) { if (isFirstProfile) {
if (IS_NEKO_BOX) { status->routingRules += QJsonObject{
status->routingRules += QJsonObject{ {"inbound", QJsonArray{tagOut + "-mapping"}},
{"inbound", QJsonArray{tagOut + "-mapping"}}, {"outbound", "direct"},
{"outbound", "direct"}, };
};
} else {
status->routingRules += QJsonObject{
{"type", "field"},
{"inboundTag", QJsonArray{tagOut + "-mapping"}},
{"outboundTag", "direct"},
};
}
} }
} }
@ -589,23 +302,11 @@ namespace NekoGui {
status->result->extRs.emplace_back(std::make_shared<NekoGui_fmt::ExternalBuildResult>(extR)); status->result->extRs.emplace_back(std::make_shared<NekoGui_fmt::ExternalBuildResult>(extR));
// SOCKS OUTBOUND // SOCKS OUTBOUND
if (IS_NEKO_BOX) { outbound["type"] = "socks";
outbound["type"] = "socks"; outbound["server"] = "127.0.0.1";
outbound["server"] = "127.0.0.1"; outbound["server_port"] = ext_socks_port;
outbound["server_port"] = ext_socks_port;
} else {
outbound["protocol"] = "socks";
QJsonObject settings;
QJsonArray servers;
QJsonObject server;
server["address"] = "127.0.0.1";
server["port"] = ext_socks_port;
servers.push_back(server);
settings["servers"] = servers;
outbound["settings"] = settings;
}
} else { } else {
const auto coreR = IS_NEKO_BOX ? ent->bean->BuildCoreObjSingBox() : ent->bean->BuildCoreObjV2Ray(); const auto coreR = ent->bean->BuildCoreObjSingBox();
if (coreR.outbound.isEmpty()) { if (coreR.outbound.isEmpty()) {
status->result->error = "unsupported outbound"; status->result->error = "unsupported outbound";
return {}; return {};
@ -628,14 +329,8 @@ namespace NekoGui {
needMux &= dataStore->mux_concurrency > 0; needMux &= dataStore->mux_concurrency > 0;
if (stream != nullptr) { if (stream != nullptr) {
if (IS_NEKO_BOX) { if (stream->network == "grpc" || stream->network == "quic" || (stream->network == "http" && stream->security == "tls")) {
if (stream->network == "grpc" || stream->network == "quic" || (stream->network == "http" && stream->security == "tls")) { needMux = false;
needMux = false;
}
} else {
if (stream->network == "grpc" || stream->network == "quic") {
needMux = false;
}
} }
if (stream->multiplex_status == 0) { if (stream->multiplex_status == 0) {
if (!dataStore->mux_default_on) needMux = false; if (!dataStore->mux_default_on) needMux = false;
@ -650,36 +345,22 @@ namespace NekoGui {
} }
// common // common
if (IS_NEKO_BOX) { // apply domain_strategy
// apply domain_strategy outbound["domain_strategy"] = dataStore->routing->outbound_domain_strategy;
outbound["domain_strategy"] = dataStore->routing->outbound_domain_strategy; // apply mux
// apply mux if (!muxApplied && needMux) {
if (!muxApplied && needMux) { auto muxObj = QJsonObject{
auto muxObj = QJsonObject{ {"enabled", true},
{"enabled", true}, {"protocol", dataStore->mux_protocol},
{"protocol", dataStore->mux_protocol}, {"padding", dataStore->mux_padding},
{"padding", dataStore->mux_padding}, {"max_streams", dataStore->mux_concurrency},
{"max_streams", dataStore->mux_concurrency}, };
}; outbound["multiplex"] = muxObj;
outbound["multiplex"] = muxObj; muxApplied = true;
muxApplied = true;
}
} else {
// apply domain_strategy
if (!status->forTest) outbound["domainStrategy"] = dataStore->routing->outbound_domain_strategy;
// apply mux
if (!muxApplied && needMux) {
auto muxObj = QJsonObject{
{"enabled", true},
{"concurrency", dataStore->mux_concurrency},
};
outbound["mux"] = muxObj;
muxApplied = true;
}
} }
// apply custom outbound settings // apply custom outbound settings
MergeJson(QString2QJsonObject(ent->bean->custom_outbound), outbound); MergeJson(outbound, QString2QJsonObject(ent->bean->custom_outbound));
// Bypass Lookup for the first profile // Bypass Lookup for the first profile
auto serverAddress = ent->bean->serverAddress; auto serverAddress = ent->bean->serverAddress;
@ -735,7 +416,7 @@ namespace NekoGui {
} }
// tun-in // tun-in
if (IS_NEKO_BOX_INTERNAL_TUN && dataStore->spmode_vpn && !status->forTest) { if (dataStore->vpn_internal_tun && dataStore->spmode_vpn && !status->forTest) {
QJsonObject inboundObj; QJsonObject inboundObj;
inboundObj["tag"] = "tun-in"; inboundObj["tag"] = "tun-in";
inboundObj["type"] = "tun"; inboundObj["type"] = "tun";
@ -823,7 +504,7 @@ namespace NekoGui {
} else if (item.startsWith("keyword:")) { } else if (item.startsWith("keyword:")) {
domain_keyword += item.replace("keyword:", "").toLower(); domain_keyword += item.replace("keyword:", "").toLower();
} else { } else {
domain_full += item.toLower(); domain_subdomain += item.toLower();
} }
} }
} }
@ -860,22 +541,22 @@ namespace NekoGui {
}; };
// Direct // Direct
auto directDNSAddress = dataStore->routing->direct_dns; QJsonObject directObj{
if (directDNSAddress == "localhost") directDNSAddress = BOX_UNDERLYING_DNS_EXPORT; {"tag", "dns-direct"},
if (!status->forTest) { {"address_resolver", "dns-local"},
QJsonObject directObj{ {"strategy", dataStore->routing->direct_dns_strategy},
{"tag", "dns-direct"}, {"address", dataStore->routing->direct_dns},
{"address_resolver", "dns-local"}, {"detour", "direct"},
{"strategy", dataStore->routing->direct_dns_strategy}, };
{"address", directDNSAddress.replace("+local://", "://")}, if (dataStore->routing->dns_final_out == "bypass") {
{"detour", "direct"}, dnsServers.prepend(directObj);
}; } else {
if (dataStore->routing->dns_final_out == "bypass") { dnsServers.append(directObj);
dnsServers.prepend(directObj);
} else {
dnsServers.append(directObj);
}
} }
dnsRules.append(QJsonObject{
{"outbound", "any"},
{"server", "dns-direct"},
});
// block // block
if (!status->forTest) if (!status->forTest)
@ -885,7 +566,7 @@ namespace NekoGui {
}; };
// Fakedns // Fakedns
if (dataStore->fake_dns && IS_NEKO_BOX_INTERNAL_TUN && dataStore->spmode_vpn && !status->forTest) { if (dataStore->fake_dns && dataStore->vpn_internal_tun && dataStore->spmode_vpn && !status->forTest) {
dnsServers += QJsonObject{ dnsServers += QJsonObject{
{"tag", "dns-fake"}, {"tag", "dns-fake"},
{"address", "fakeip"}, {"address", "fakeip"},
@ -897,10 +578,10 @@ namespace NekoGui {
}; };
} }
// Underlying 100% Working DNS // Underlying 100% Working DNS ?
dnsServers += QJsonObject{ dnsServers += QJsonObject{
{"tag", "dns-local"}, {"tag", "dns-local"},
{"address", BOX_UNDERLYING_DNS_EXPORT}, {"address", BOX_UNDERLYING_DNS},
{"detour", "direct"}, {"detour", "direct"},
}; };
@ -927,7 +608,7 @@ namespace NekoGui {
} }
// fakedns rule // fakedns rule
if (dataStore->fake_dns && IS_NEKO_BOX_INTERNAL_TUN && dataStore->spmode_vpn && !status->forTest) { if (dataStore->fake_dns && dataStore->vpn_internal_tun && dataStore->spmode_vpn && !status->forTest) {
dnsRules += QJsonObject{ dnsRules += QJsonObject{
{"inbound", "tun-in"}, {"inbound", "tun-in"},
{"server", "dns-fake"}, {"server", "dns-fake"},
@ -985,7 +666,7 @@ namespace NekoGui {
}; };
// tun user rule // tun user rule
if (IS_NEKO_BOX_INTERNAL_TUN && dataStore->spmode_vpn && !status->forTest) { if (dataStore->vpn_internal_tun && dataStore->spmode_vpn && !status->forTest) {
auto match_out = dataStore->vpn_rule_white ? "proxy" : "bypass"; auto match_out = dataStore->vpn_rule_white ? "proxy" : "bypass";
QString process_name_rule = dataStore->vpn_rule_process.trimmed(); QString process_name_rule = dataStore->vpn_rule_process.trimmed();
@ -1025,7 +706,7 @@ namespace NekoGui {
QJSONARRAY_ADD(routingRules, status->routingRules) QJSONARRAY_ADD(routingRules, status->routingRules)
auto routeObj = QJsonObject{ auto routeObj = QJsonObject{
{"rules", routingRules}, {"rules", routingRules},
{"auto_detect_interface", dataStore->spmode_vpn}, {"auto_detect_interface", dataStore->spmode_vpn}, // TODO force enable?
{ {
"geoip", "geoip",
QJsonObject{ QJsonObject{
@ -1063,8 +744,8 @@ namespace NekoGui {
QString WriteVPNSingBoxConfig() { QString WriteVPNSingBoxConfig() {
// tun user rule // tun user rule
auto match_out = dataStore->vpn_rule_white ? "nekoray-socks" : "direct"; auto match_out = dataStore->vpn_rule_white ? "neko-socks" : "direct";
auto no_match_out = dataStore->vpn_rule_white ? "direct" : "nekoray-socks"; auto no_match_out = dataStore->vpn_rule_white ? "direct" : "neko-socks";
QString process_name_rule = dataStore->vpn_rule_process.trimmed(); QString process_name_rule = dataStore->vpn_rule_process.trimmed();
if (!process_name_rule.isEmpty()) { if (!process_name_rule.isEmpty()) {
@ -1106,16 +787,6 @@ namespace NekoGui {
.replace("%DNS_ADDRESS%", BOX_UNDERLYING_DNS) .replace("%DNS_ADDRESS%", BOX_UNDERLYING_DNS)
.replace("%FAKE_DNS_INBOUND%", dataStore->fake_dns ? "tun-in" : "empty") .replace("%FAKE_DNS_INBOUND%", dataStore->fake_dns ? "tun-in" : "empty")
.replace("%PORT%", Int2String(dataStore->inbound_socks_port)); .replace("%PORT%", Int2String(dataStore->inbound_socks_port));
// hook.js
auto source = qjs::ReadHookJS();
if (!source.isEmpty()) {
qjs::QJS js(source);
auto js_result = js.EvalFunction("hook.hook_tun_config", config);
if (config != js_result) {
MW_show_log("hook.js modified your Tun config.");
config = js_result;
}
}
// write config // write config
QFile file; QFile file;
file.setFileName(QFileInfo(configFn).fileName()); file.setFileName(QFileInfo(configFn).fileName());
@ -1125,7 +796,7 @@ namespace NekoGui {
return QFileInfo(file).absoluteFilePath(); return QFileInfo(file).absoluteFilePath();
} }
QString WriteVPNLinuxScript(const QString &protectPath, const QString &configPath) { QString WriteVPNLinuxScript(const QString &configPath) {
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
return {}; return {};
#endif #endif
@ -1134,19 +805,7 @@ namespace NekoGui {
if (QFile::exists("vpn/vpn-run-root.sh")) scriptFn = "vpn/vpn-run-root.sh"; if (QFile::exists("vpn/vpn-run-root.sh")) scriptFn = "vpn/vpn-run-root.sh";
auto script = ReadFileText(scriptFn) auto script = ReadFileText(scriptFn)
.replace("./nekobox_core", QApplication::applicationDirPath() + "/nekobox_core") .replace("./nekobox_core", QApplication::applicationDirPath() + "/nekobox_core")
.replace("$PROTECT_LISTEN_PATH", protectPath) .replace("$CONFIG_PATH", configPath);
.replace("$CONFIG_PATH", configPath)
.replace("$TABLE_FWMARK", "514");
// hook.js
auto source = qjs::ReadHookJS();
if (!source.isEmpty()) {
qjs::QJS js(source);
auto js_result = js.EvalFunction("hook.hook_tun_script", script);
if (script != js_result) {
MW_show_log("hook.js modified your Tun script.");
script = js_result;
}
}
// write script // write script
QFile file2; QFile file2;
file2.setFileName(QFileInfo(scriptFn).fileName()); file2.setFileName(QFileInfo(scriptFn).fileName());

View File

@ -46,8 +46,6 @@ namespace NekoGui {
std::shared_ptr<BuildConfigResult> BuildConfig(const std::shared_ptr<ProxyEntity> &ent, bool forTest, bool forExport); std::shared_ptr<BuildConfigResult> BuildConfig(const std::shared_ptr<ProxyEntity> &ent, bool forTest, bool forExport);
void BuildConfigV2Ray(const std::shared_ptr<BuildConfigStatus> &status);
void BuildConfigSingBox(const std::shared_ptr<BuildConfigStatus> &status); void BuildConfigSingBox(const std::shared_ptr<BuildConfigStatus> &status);
QString BuildChain(int chainId, const std::shared_ptr<BuildConfigStatus> &status); QString BuildChain(int chainId, const std::shared_ptr<BuildConfigStatus> &status);
@ -57,5 +55,5 @@ namespace NekoGui {
QString WriteVPNSingBoxConfig(); QString WriteVPNSingBoxConfig();
QString WriteVPNLinuxScript(const QString &protectPath, const QString &configPath); QString WriteVPNLinuxScript(const QString &configPath);
} // namespace NekoGui } // namespace NekoGui

View File

@ -42,7 +42,7 @@ namespace NekoGui {
// Load Proxys // Load Proxys
QList<int> delProfile; QList<int> delProfile;
for (auto id: profilesIdOrder) { for (auto id: profilesIdOrder) {
auto ent = LoadProxyEntity(QString("profiles/%1.json").arg(id)); auto ent = LoadProxyEntity(QStringLiteral("profiles/%1.json").arg(id));
// Corrupted profile? // Corrupted profile?
if (ent == nullptr || ent->bean == nullptr || ent->bean->version == -114514) { if (ent == nullptr || ent->bean == nullptr || ent->bean->version == -114514) {
delProfile << id; delProfile << id;
@ -58,7 +58,7 @@ namespace NekoGui {
auto loadedOrder = groupsTabOrder; auto loadedOrder = groupsTabOrder;
groupsTabOrder = {}; groupsTabOrder = {};
for (auto id: groupsIdOrder) { for (auto id: groupsIdOrder) {
auto ent = LoadGroup(QString("groups/%1.json").arg(id)); auto ent = LoadGroup(QStringLiteral("groups/%1.json").arg(id));
// Corrupted group? // Corrupted group?
if (ent->id != id) { if (ent->id != id) {
continue; continue;
@ -103,7 +103,7 @@ namespace NekoGui {
auto newId = i++; auto newId = i++;
profile->id = newId; profile->id = newId;
profile->gid = gidOld2New[gid]; profile->gid = gidOld2New[gid];
profile->fn = QString("profiles/%1.json").arg(newId); profile->fn = QStringLiteral("profiles/%1.json").arg(newId);
profile->Save(); profile->Save();
newProfiles[newId] = profile; newProfiles[newId] = profile;
newProfilesIdOrder << newId; newProfilesIdOrder << newId;
@ -122,7 +122,7 @@ namespace NekoGui {
auto group = groups[oldGid]; auto group = groups[oldGid];
QFile::remove(group->fn); QFile::remove(group->fn);
group->id = newId; group->id = newId;
group->fn = QString("groups/%1.json").arg(newId); group->fn = QStringLiteral("groups/%1.json").arg(newId);
group->Save(); group->Save();
newGroups[newId] = group; newGroups[newId] = group;
newGroupsIdOrder << newId; newGroupsIdOrder << newId;
@ -184,8 +184,6 @@ namespace NekoGui {
bean = new NekoGui_fmt::TrojanVLESSBean(NekoGui_fmt::TrojanVLESSBean::proxy_VLESS); bean = new NekoGui_fmt::TrojanVLESSBean(NekoGui_fmt::TrojanVLESSBean::proxy_VLESS);
} else if (type == "naive") { } else if (type == "naive") {
bean = new NekoGui_fmt::NaiveBean(); bean = new NekoGui_fmt::NaiveBean();
} else if (type == "hysteria") {
bean = new NekoGui_fmt::QUICBean(NekoGui_fmt::QUICBean::proxy_Hysteria);
} else if (type == "hysteria2") { } else if (type == "hysteria2") {
bean = new NekoGui_fmt::QUICBean(NekoGui_fmt::QUICBean::proxy_Hysteria2); bean = new NekoGui_fmt::QUICBean(NekoGui_fmt::QUICBean::proxy_Hysteria2);
} else if (type == "tuic") { } else if (type == "tuic") {
@ -229,7 +227,7 @@ namespace NekoGui {
if (latency < 0) { if (latency < 0) {
return QObject::tr("Unavailable"); return QObject::tr("Unavailable");
} else if (latency > 0) { } else if (latency > 0) {
return UNICODE_LRO + QString("%1 ms").arg(latency); return UNICODE_LRO + QStringLiteral("%1 ms").arg(latency);
} else { } else {
return ""; return "";
} }
@ -270,7 +268,7 @@ namespace NekoGui {
profiles[ent->id] = ent; profiles[ent->id] = ent;
profilesIdOrder.push_back(ent->id); profilesIdOrder.push_back(ent->id);
ent->fn = QString("profiles/%1.json").arg(ent->id); ent->fn = QStringLiteral("profiles/%1.json").arg(ent->id);
ent->Save(); ent->Save();
return true; return true;
} }
@ -280,7 +278,7 @@ namespace NekoGui {
if (dataStore->started_id == id) return; if (dataStore->started_id == id) return;
profiles.erase(id); profiles.erase(id);
profilesIdOrder.removeAll(id); profilesIdOrder.removeAll(id);
QFile(QString("profiles/%1.json").arg(id)).remove(); QFile(QStringLiteral("profiles/%1.json").arg(id)).remove();
} }
void ProfileManager::MoveProfile(const std::shared_ptr<ProxyEntity> &ent, int gid) { void ProfileManager::MoveProfile(const std::shared_ptr<ProxyEntity> &ent, int gid) {
@ -344,7 +342,7 @@ namespace NekoGui {
groupsIdOrder.push_back(ent->id); groupsIdOrder.push_back(ent->id);
groupsTabOrder.push_back(ent->id); groupsTabOrder.push_back(ent->id);
ent->fn = QString("groups/%1.json").arg(ent->id); ent->fn = QStringLiteral("groups/%1.json").arg(ent->id);
ent->Save(); ent->Save();
return true; return true;
} }
@ -361,7 +359,7 @@ namespace NekoGui {
groups.erase(gid); groups.erase(gid);
groupsIdOrder.removeAll(gid); groupsIdOrder.removeAll(gid);
groupsTabOrder.removeAll(gid); groupsTabOrder.removeAll(gid);
QFile(QString("groups/%1.json").arg(gid)).remove(); QFile(QStringLiteral("groups/%1.json").arg(gid)).remove();
} }
std::shared_ptr<Group> ProfileManager::GetGroup(int id) { std::shared_ptr<Group> ProfileManager::GetGroup(int id) {

View File

@ -29,12 +29,12 @@ namespace NekoGui_traffic {
} }
[[nodiscard]] QString DisplaySpeed() const { [[nodiscard]] QString DisplaySpeed() const {
return UNICODE_LRO + QString("%1↑ %2↓").arg(ReadableSize(uplink_rate), ReadableSize(downlink_rate)); return UNICODE_LRO + QStringLiteral("%1↑ %2↓").arg(ReadableSize(uplink_rate), ReadableSize(downlink_rate));
} }
[[nodiscard]] QString DisplayTraffic() const { [[nodiscard]] QString DisplayTraffic() const {
if (downlink + uplink == 0) return ""; if (downlink + uplink == 0) return "";
return UNICODE_LRO + QString("%1↑ %2↓").arg(ReadableSize(uplink), ReadableSize(downlink)); return UNICODE_LRO + QStringLiteral("%1↑ %2↓").arg(ReadableSize(uplink), ReadableSize(downlink));
} }
}; };
} // namespace NekoGui_traffic } // namespace NekoGui_traffic

View File

@ -1,11 +1,10 @@
## 构建 nekoray_core & nekobox_core ## 构建 nekobox_core
### 目录结构 ### 目录结构
``` ```
| nekoray | nekoray
| go/cmd/* | go/cmd/*
| Xray-core
| sing-box-extra | sing-box-extra
| sing-box | sing-box
| ...... | ......

View File

@ -22,9 +22,9 @@ cmake -GNinja ..
ninja ninja
``` ```
编译完成后得到 `nekoray` 编译完成后得到 `nekobox`
解压 Release 的压缩包,替换其中的 `nekoray`,删除 `launcher` 即可使用。 解压 Release 的压缩包,替换其中的 `nekobox`,删除 `launcher` 即可使用。
## 复杂编译法 ## 复杂编译法
@ -38,15 +38,13 @@ ninja
| NKR_NO_QHOTKEY | | 不包含 qhotkey | | NKR_NO_QHOTKEY | | 不包含 qhotkey |
| NKR_NO_ZXING | | 不包含 zxing | | NKR_NO_ZXING | | 不包含 zxing |
| NKR_NO_GRPC | | 不包含 gRPC | | NKR_NO_GRPC | | 不包含 gRPC |
| NKR_NO_QUICKJS | | 不包含 quickjs |
| NKR_PACKAGE | | 编译 package 版本 (aur) | | NKR_PACKAGE | | 编译 package 版本 (aur) |
| NKR_PACKAGE_MACOS | | 编译 macos 版本 |
| NKR_LIBS | ./libs/deps/built | 依赖搜索目录 | | NKR_LIBS | ./libs/deps/built | 依赖搜索目录 |
| NKR_DISABLE_LIBS | | 禁用 NKR_LIBS | | NKR_DISABLE_LIBS | | 禁用 NKR_LIBS |
1. `NKR_LIBS` 的值会被追加到 `CMAKE_PREFIX_PATH` 1. `NKR_LIBS` 的值会被追加到 `CMAKE_PREFIX_PATH`
2. `NKR_PACKAGE` 打开后,`NKR_LIBS` 的默认值为 `./libs/deps/package` ,具体依赖请看 `build_deps_all.sh` 2. `NKR_PACKAGE` 打开后,`NKR_LIBS` 的默认值为 `./libs/deps/package` ,具体依赖请看 `build_deps_all.sh`
3. `NKR_PACKAGE_MACOS` 或 `NKR_PACKAGE` 打开后,应用将使用 appdata 目录存放配置,自动更新等功能将被禁用。 3. `NKR_PACKAGE` 打开后,应用将使用 appdata 目录存放配置,自动更新等功能将被禁用。
### C++ 部分 ### C++ 部分
@ -71,7 +69,7 @@ cmake -GNinja ..
ninja ninja
``` ```
编译完成后得到 `nekoray` 编译完成后得到 `nekobox`
### Go 部分编译 ### Go 部分编译

View File

@ -1,67 +0,0 @@
提示编译通过不代表所有功能可用Tun 系统代理 这种功能大概率是不可用的。如果您懂得修复,我们欢迎您的 Pull Request。
Tip: Passing the compilation does not mean that all functions are available, and the function of Tun system proxy is probably not available. If you know how to fix it, we welcome your Pull Request.
## git clone 源码
```
git clone https://github.com/MatsuriDayo/nekoray.git --recursive
```
## 先决条件
1. 安装 `CMake` `Ninja` `npm`
2. 安装 Qt `5.15.x` 编译环境,并设置好有关环境变量,以免 CMake 找不到 Qt。 (`qtbase` `qtsvg` `qttools`)
3. 安装 `appdmg` (`sudo npm install -g appdmg`)
## CMake 参数
同 Build_Linux
## C++ 部分
### 编译安装 C/C++ 依赖
(这一步可能要挂梯)
```shell
./libs/build_deps_all.sh
```
### 编译本体
```shell
mkdir build
cd build
cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DNKR_PACKAGE_MACOS=1 ..
ninja
```
### Go 部分编译
请看 [Build_Core.md](./Build_Core.md)
## 打包
如有疑问,请参考[这个脚本](https://github.com/MatsuriDayo/nekoray/blob/main/libs/deploy_macos.sh)
### 准备core
将 编译得到的 `nekoray_core` `nekobox_core` 放入 `build/nekoray.app/Contents/MacOS`
### 准备geo文件可选
```shell
curl -Lso build/nekoray.app/Contents/MacOS/geoip.dat "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat"
curl -Lso build/nekoray.app/Contents/MacOS/geosite.dat "https://github.com/v2fly/domain-list-community/releases/latest/download/dlc.dat"
curl -Lso build/nekoray.app/Contents/MacOS/geoip.db "https://github.com/SagerNet/sing-geoip/releases/latest/download/geoip.db"
curl -Lso build/nekoray.app/Contents/MacOS/geosite.db "https://github.com/SagerNet/sing-geosite/releases/latest/download/geosite.db"
```
如果打包时没有包含geo文件可在应用内设置 `v2ray资源路径` 代替。
### 在nekoray目录下打包
```shell
appdmg appdmg.json /path/to/nekoray.dmg
```

View File

@ -1,163 +0,0 @@
Tip: Passing the compilation does not mean that all functions are available, and the function of Tun system proxy is probably not available. If you know how to fix it, we welcome your Pull Request.
## پروژه Nekoray را از منبع آن دریافت کنید
در `Terminal` در مسیر دلخواه خود، دستور زیر را وارد کنید و دکمه `return` را بفشارید.
```shell
git clone https://github.com/MatsuriDayo/nekoray.git --recursive
```
اگر `git` روی دستگاه از پیش نصب نباشد، دستگاه، خودکار نصب آن را پیشنهاد می‌کند. مرحله‌های نصب را به انجام برسانید و سپس دوباره دستور پیش گفته را در `Terminal` اجرا کنید.
سپس وارد پوشه `nekoray` شوید.
برای کامپایل کردن پروژه، پیش‌نیازهای زیر را نصب کنید. برای این، دستور زیر را در `Terminal` وارد کنید و دکمه `Return` را بفشارید.
```shell
cd nekoray
```
<br>
## پیش‌نیازها
###۱. `CMake`
برای نصب `CMake` دستور زیر را در `terminal` وارد کنید و دکمه `return` را بفشارید.
```shell
brew install cmake
```
اگر با خطای `zsh: command not found: brew` روبه‌رو شدید به این معنی است که `homebrew` در دستگاه شما نصب نیست. برای نصب آن نخست باید `XCode's command line tools` را نصب کنید. اگر به این مشکل برخورده‌ اید، گام های `۱.۱`، `۱.۲` و `۱.۳` را دنبال کنید.
<br>
####۱.۱. نصب `XCode's command line tools`
دستور زیر را در `terminal` وادر کنید و دکمه `return` را بفشارید.
```shell
xcode-select --install
```
<br>
####۱.۲. نصب `homebrew`
دستور زیر را در `terminal` وارد کنید و دکمه `return` را بفشارید.
```shell
curl -fsSL -o install.sh https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh
```
<br>
####۱.۳. حال می‌توانید با دستوری که پیشتر گفتیم، `CMake` را نصب کنید.
<br>
###۲. `Ninja`
برای نصب `Ninja` دستور زیر را در `terminal` وارد کنید و دکمه `return` را بفشارید.
```shell
sudo port install ninja
```
اگر با خطای `sudo: port: command not found` روبه‌رو شدید، به این معنی است که `MacPorts` روی دستگاه شما نصب نیست. نسخه `MacPorts` متناسب با نسخه `macOs` خود را بارگری و نصب کنید. سپس بار دیگر، دستور نصب `Ninja` را در `terminal` وارد کرده و دکمه `return` را بفشارید.
<br>
###۳. `npm`
برای نصب `npm` دستور زیر را در `terminal` وارد کنید و دکمه `return` را بفشارید.
```shell
brew install npm
```
<br>
###۴. `qtbase`
برای نصب `qtbase` دستور زیر را در `terminal` وارد کنید و دکمه `return` را بفشارید.
```shell
sudo port install qt5-qtbase
```
<br>
###۵. `qtsvg`
برای نصب `qtsvg` دستور زیر را در `terminal` وارد کنید و دکمه `return` را بفشارید.
```shell
sudo port install qt5-qtsvg
```
<br>
###۶. `qttools`
برای نصب `qttools` دستور زیر را در `terminal` وارد کنید و دکمه `return` را بفشارید.
```shell
sudo port install qt5-qttools
```
<br>
###۷. `appdmg`
برای نصب `appdmg` دستور زیر را در `terminal` وارد کنید و دکمه `return` را بفشارید.
```shell
sudo npm install -g appdmg
```
<br>
## C++
### وابستگی‌های C و ++C را کامپایل و نصب کنید.
دستور زیر را در `terminal` وارد کرده و دکمه `return` را بفشارید.
```shell
./libs/build_deps_all.sh
```
<br>
### آنتولوژی را کامپایل کنید.
دستور زیر را در `terminal` وارد کرده و دکمه `return` را بفشارید.
```shell
mkdir build
cd build
cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DNKR_PACKAGE_MACOS=1 ..
ninja
```
<br>
## هسته نرم افزار
### هسته نرم افزار را کامپایل کنید.
چگونگی کامپایل کردن هسته نرم افزار را [اینجا ](./Build_Core_fa.md)بخوانید.
<br>
### جایگذاری هسته
فایل کامپایل شده `nekoray_core` و `nekobox_core` را در مسیر زیر کپی کنید.
`build/nekoray.app/Contents/MacOS`
<br>
## فایل‌های جغرافی را تهیه کنید. (اختیاری)
اگر مایلید، با اجرای دستورهای زیر در `Terminal` فایل های جغرافی را تهیه کنید.
```shell
curl -Lso build/nekoray.app/Contents/MacOS/geoip.dat "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat"
curl -Lso build/nekoray.app/Contents/MacOS/geosite.dat "https://github.com/v2fly/domain-list-community/releases/latest/download/dlc.dat"
curl -Lso build/nekoray.app/Contents/MacOS/geoip.db "https://github.com/SagerNet/sing-geoip/releases/latest/download/geoip.db"
curl -Lso build/nekoray.app/Contents/MacOS/geosite.db "https://github.com/SagerNet/sing-geosite/releases/latest/download/geosite.db"
```
<br>
## پایان کار
فایل اجرایی `Nekoray` در مسیر زیر قرار دارد. می‌توانید آن را در مسیر دلخواه کپی کنید.
`مسیر پروژه Nekoray/build`

View File

@ -55,9 +55,9 @@ cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=D:/path/to/qt/5.15.
ninja ninja
``` ```
编译完成后得到 `nekoray.exe` 编译完成后得到 `nekobox.exe`
最后运行 `windeployqt nekoray.exe` 自动复制所需 DLL 等文件到当前目录 最后运行 `windeployqt nekobox.exe` 自动复制所需 DLL 等文件到当前目录
### Go 部分编译 ### Go 部分编译

View File

@ -1,106 +0,0 @@
# hook.js 使用
## 如何启用
1. 打开 `基本设置 - 安全 - 启用 hook.js 功能`
2. js 代码请放置于 `config/hook.nekoray.js``config/hook.nekobox.js`
## 技术信息
* JS Engine: QuickJS ES2020
* 提供的接口:如下面代码所示
## 示例代码 (typescript)
```ts
const globalAny: any = globalThis
// 目前提供的方法
interface nekoray_in {
log(...a: any): void
}
// 目前提供的 hook 点
interface nekoray_hook {
hook_core_config(config: string): string
hook_tun_config(config: string): string
hook_tun_script(script: string): string
hook_import(content: string): string
}
class my_hook implements nekoray_hook {
private nekoray = globalAny.nekoray as nekoray_in
hook_core_config(config: string): string {
var json = JSON.parse(config)
var my_rule = {
"geosite": "cn",
"server": "dns-direct",
"disable_cache": true
}
json["dns"]["rules"].push(my_rule)
return JSON.stringify(json)
}
hook_tun_config(config: string): string {
return config // 返回输入,表示不修改
}
hook_tun_script(script: string): string {
console.log("Script") // 输出到 stdout
this.nekoray.log("Script:", script) // 输出到日志
return script
}
hook_import(content: string): string {
var newContent: Array<any> = []
content.split("\n").forEach((line: any) => {
if (line.startsWith("vmess://")) {
newContent.push(line)
}
})
return newContent.join("\n")
}
}
globalAny.hook = new my_hook
```
## 示例代码 (javascript)
```js
var globalAny = globalThis;
var my_hook = /** @class */ (function () {
function my_hook() {
this.nekoray = globalAny.nekoray;
}
my_hook.prototype.hook_core_config = function (config) {
var json = JSON.parse(config);
var my_rule = {
"geosite": "cn",
"server": "dns-direct",
"disable_cache": true
};
json["dns"]["rules"].push(my_rule);
return JSON.stringify(json);
};
my_hook.prototype.hook_tun_config = function (config) {
return config; // 返回输入,表示不修改
};
my_hook.prototype.hook_tun_script = function (script) {
console.log("Script"); // 输出到 stdout
this.nekoray.log("Script:", script); // 输出到日志
return script;
};
my_hook.prototype.hook_import = function (content) {
var newContent = [];
content.split("\n").forEach(function (line) {
if (line.startsWith("vmess://")) {
newContent.push(line);
}
});
return newContent.join("\n");
};
return my_hook;
}());
globalAny.hook = new my_hook;
```

View File

@ -4,4 +4,3 @@
1. Build GUI: `Build_*.md` 1. Build GUI: `Build_*.md`
2. Build Core: `Build_Core.md` 2. Build Core: `Build_Core.md`
3. Hook.js usage: `HookJS.md`

View File

@ -38,7 +38,7 @@ namespace NekoGui_fmt {
} }
QString AbstractBean::DisplayTypeAndName() { QString AbstractBean::DisplayTypeAndName() {
return QString("[%1] %2").arg(DisplayType(), DisplayName()); return QStringLiteral("[%1] %2").arg(DisplayType(), DisplayName());
} }
void AbstractBean::ResolveDomainToIP(const std::function<void()> &onFinished) { void AbstractBean::ResolveDomainToIP(const std::function<void()> &onFinished) {

View File

@ -59,8 +59,6 @@ namespace NekoGui_fmt {
virtual int NeedExternal(bool isFirstProfile) { return 0; }; virtual int NeedExternal(bool isFirstProfile) { return 0; };
virtual CoreObjOutboundBuildResult BuildCoreObjV2Ray() { return {}; };
virtual CoreObjOutboundBuildResult BuildCoreObjSingBox() { return {}; }; virtual CoreObjOutboundBuildResult BuildCoreObjSingBox() { return {}; };
virtual ExternalBuildResult BuildExternal(int mapping_port, int socks_port, int external_stat) { return {}; }; virtual ExternalBuildResult BuildExternal(int mapping_port, int socks_port, int external_stat) { return {}; };

View File

@ -28,6 +28,9 @@ namespace NekoGui_fmt {
if (!host.isEmpty()) transport["host"] = QList2QJsonArray(host.split(",")); if (!host.isEmpty()) transport["host"] = QList2QJsonArray(host.split(","));
} else if (network == "grpc") { } else if (network == "grpc") {
if (!path.isEmpty()) transport["service_name"] = path; if (!path.isEmpty()) transport["service_name"] = path;
} else if (network == "httpupgrade") {
if (!path.isEmpty()) transport["path"] = path;
if (!host.isEmpty()) transport["host"] = host;
} }
outbound->insert("transport", transport); outbound->insert("transport", transport);
} else if (header_type == "http") { } else if (header_type == "http") {
@ -188,23 +191,16 @@ namespace NekoGui_fmt {
{"tls", coreTlsObj}, {"tls", coreTlsObj},
}; };
if (proxy_type == proxy_Hysteria) { if (proxy_type == proxy_Hysteria2) {
outbound["type"] = "hysteria";
outbound["obfs"] = obfsPassword;
outbound["disable_mtu_discovery"] = disableMtuDiscovery;
outbound["recv_window"] = streamReceiveWindow;
outbound["recv_window_conn"] = connectionReceiveWindow;
outbound["up_mbps"] = uploadMbps;
outbound["down_mbps"] = downloadMbps;
if (!hopPort.trimmed().isEmpty()) outbound["hop_ports"] = hopPort;
if (authPayloadType == hysteria_auth_base64) outbound["auth"] = authPayload;
if (authPayloadType == hysteria_auth_string) outbound["auth_str"] = authPayload;
} else if (proxy_type == proxy_Hysteria2) {
outbound["type"] = "hysteria2"; outbound["type"] = "hysteria2";
outbound["password"] = password; outbound["password"] = password;
outbound["up_mbps"] = uploadMbps; outbound["up_mbps"] = uploadMbps;
outbound["down_mbps"] = downloadMbps; outbound["down_mbps"] = downloadMbps;
if (!hopPort.trimmed().isEmpty()) {
outbound["hop_ports"] = hopPort;
outbound["hop_interval"] = hopInterval;
}
if (!obfsPassword.isEmpty()) { if (!obfsPassword.isEmpty()) {
outbound["obfs"] = QJsonObject{ outbound["obfs"] = QJsonObject{
{"type", "salamander"}, {"type", "salamander"},

View File

@ -1,211 +0,0 @@
#include "db/ProxyEntity.hpp"
#include "fmt/includes.h"
#define MAKE_SETTINGS_STREAM_SETTINGS \
outbound["settings"] = settings; \
auto streamSettings = stream->BuildStreamSettingsV2Ray(); \
outbound["streamSettings"] = streamSettings;
namespace NekoGui_fmt {
QJsonObject V2rayStreamSettings::BuildStreamSettingsV2Ray() {
QJsonObject streamSettings{{"network", network}};
if (network == "ws") {
QJsonObject ws;
if (!host.isEmpty()) ws["headers"] = QJsonObject{{"Host", host}};
// ws path & ed
if (!path.isEmpty()) ws["path"] = path;
streamSettings["wsSettings"] = ws;
} else if (network == "http") {
QJsonObject http;
if (!path.isEmpty()) http["path"] = path;
if (!host.isEmpty()) http["host"] = QList2QJsonArray(host.split(","));
streamSettings["httpSettings"] = http;
} else if (network == "grpc") {
QJsonObject grpc;
if (!path.isEmpty()) grpc["serviceName"] = path;
streamSettings["grpcSettings"] = grpc;
} else if (network == "quic") {
QJsonObject quic;
if (!header_type.isEmpty()) quic["header"] = QJsonObject{{"type", header_type}};
if (!path.isEmpty()) quic["key"] = path;
if (!host.isEmpty()) quic["security"] = host;
streamSettings["quicSettings"] = quic;
} else if (network == "tcp" && !header_type.isEmpty()) {
QJsonObject header{{"type", header_type}};
if (header_type == "http") {
header["request"] = QJsonObject{
{"path", QList2QJsonArray(path.split(","))},
{"headers", QJsonObject{{"Host", QList2QJsonArray(host.split(","))}}},
};
}
streamSettings["tcpSettings"] = QJsonObject{{"header", header}};
}
if (security == "tls") {
QJsonObject tls;
if (!utlsFingerprint.isEmpty()) tls["fingerprint"] = utlsFingerprint;
if (!sni.trimmed().isEmpty()) tls["serverName"] = sni;
if (reality_pbk.trimmed().isEmpty()) {
if (allow_insecure || NekoGui::dataStore->skip_cert) tls["allowInsecure"] = true;
if (!alpn.trimmed().isEmpty()) tls["alpn"] = QList2QJsonArray(alpn.split(","));
if (!certificate.trimmed().isEmpty()) {
tls["disableSystemRoot"] = true;
tls["certificates"] = QJsonArray{
QJsonObject{
{"usage", "verify"},
{"certificate", QList2QJsonArray(SplitLines(certificate.trimmed()))},
},
};
}
streamSettings["tlsSettings"] = tls;
streamSettings["security"] = "tls";
} else {
tls["publicKey"] = reality_pbk;
tls["shortId"] = reality_sid;
tls["spiderX"] = reality_spx;
if (utlsFingerprint.isEmpty()) tls["fingerprint"] = "chrome";
streamSettings["realitySettings"] = tls;
streamSettings["security"] = "reality";
}
}
return streamSettings;
}
CoreObjOutboundBuildResult SocksHttpBean::BuildCoreObjV2Ray() {
CoreObjOutboundBuildResult result;
QJsonObject outbound;
outbound["protocol"] = socks_http_type == type_HTTP ? "http" : "socks";
QJsonObject settings;
QJsonArray servers;
QJsonObject server;
server["address"] = serverAddress;
server["port"] = serverPort;
QJsonArray users;
QJsonObject user;
user["user"] = username;
user["pass"] = password;
users.push_back(user);
if (!username.isEmpty() && !password.isEmpty()) server["users"] = users;
servers.push_back(server);
settings["servers"] = servers;
MAKE_SETTINGS_STREAM_SETTINGS
result.outbound = outbound;
return result;
}
CoreObjOutboundBuildResult ShadowSocksBean::BuildCoreObjV2Ray() {
CoreObjOutboundBuildResult result;
QJsonObject outbound{{"protocol", "shadowsocks"}};
QJsonObject settings;
QJsonArray servers;
QJsonObject server;
server["address"] = serverAddress;
server["port"] = serverPort;
server["method"] = method;
server["password"] = password;
if (uot != 0) {
server["uot"] = true;
server["UoTVersion"] = uot;
} else {
server["uot"] = false;
}
servers.push_back(server);
settings["servers"] = servers;
if (!plugin.trimmed().isEmpty()) {
settings["plugin"] = SubStrBefore(plugin, ";");
settings["pluginOpts"] = SubStrAfter(plugin, ";");
}
MAKE_SETTINGS_STREAM_SETTINGS
result.outbound = outbound;
return result;
}
CoreObjOutboundBuildResult VMessBean::BuildCoreObjV2Ray() {
CoreObjOutboundBuildResult result;
QJsonObject outbound{{"protocol", "vmess"}};
QJsonObject settings{
{"vnext", QJsonArray{
QJsonObject{
{"address", serverAddress},
{"port", serverPort},
{"users", QJsonArray{
QJsonObject{
{"id", uuid.trimmed()},
{"alterId", aid},
{"security", security},
}}},
}}}};
MAKE_SETTINGS_STREAM_SETTINGS
result.outbound = outbound;
return result;
}
CoreObjOutboundBuildResult TrojanVLESSBean::BuildCoreObjV2Ray() {
CoreObjOutboundBuildResult result;
QJsonObject outbound{
{"protocol", proxy_type == proxy_VLESS ? "vless" : "trojan"},
};
QJsonObject settings;
if (proxy_type == proxy_VLESS) {
if (flow == "none") {
flow = "";
}
settings = QJsonObject{
{"vnext", QJsonArray{
QJsonObject{
{"address", serverAddress},
{"port", serverPort},
{"users", QJsonArray{
QJsonObject{
{"id", password.trimmed()},
{"encryption", "none"},
{"flow", flow},
}}},
}}}};
} else {
settings = QJsonObject{
{"servers", QJsonArray{
QJsonObject{
{"address", serverAddress},
{"port", serverPort},
{"password", password},
}}}};
}
MAKE_SETTINGS_STREAM_SETTINGS
result.outbound = outbound;
return result;
}
CoreObjOutboundBuildResult CustomBean::BuildCoreObjV2Ray() {
CoreObjOutboundBuildResult result;
if (core == "internal") {
result.outbound = QString2QJsonObject(config_simple);
}
return result;
}
} // namespace NekoGui_fmt

View File

@ -9,7 +9,7 @@
#define WriteTempFile(fn, data) \ #define WriteTempFile(fn, data) \
QDir dir; \ QDir dir; \
if (!dir.exists("temp")) dir.mkdir("temp"); \ if (!dir.exists("temp")) dir.mkdir("temp"); \
QFile f(QString("temp/") + fn); \ QFile f(QStringLiteral("temp/") + fn); \
bool ok = f.open(QIODevice::WriteOnly | QIODevice::Truncate); \ bool ok = f.open(QIODevice::WriteOnly | QIODevice::Truncate); \
if (ok) { \ if (ok) { \
f.write(data); \ f.write(data); \
@ -36,54 +36,26 @@ namespace NekoGui_fmt {
} }
int QUICBean::NeedExternal(bool isFirstProfile) { int QUICBean::NeedExternal(bool isFirstProfile) {
auto hysteriaCore = [=] { auto extCore = [=] {
if (isFirstProfile) { if (isFirstProfile) {
if (NekoGui::dataStore->spmode_vpn && hyProtocol != hysteria_protocol_facktcp && hopPort.trimmed().isEmpty()) { if (NekoGui::dataStore->spmode_vpn && hopPort.trimmed().isEmpty()) {
return 1; return 1;
} }
return 2; return 2;
} else { } else {
if (hyProtocol == hysteria_protocol_facktcp || !hopPort.trimmed().isEmpty()) { if (!hopPort.trimmed().isEmpty()) {
return -1; return -1;
} }
} }
return 1; return 1;
}; };
auto hysteria2Core = [=] { if (!forceExternal) {
if (isFirstProfile) { // sing-box support
if (NekoGui::dataStore->spmode_vpn || !hopPort.trimmed().isEmpty()) { return 0;
return 1;
}
return 2;
}
return 1;
};
auto tuicCore = [=] {
if (isFirstProfile) {
if (NekoGui::dataStore->spmode_vpn) {
return 1;
}
return 2;
}
return 1;
};
if (IS_NEKO_BOX) {
if (!forceExternal && (proxy_type == proxy_TUIC || hyProtocol == hysteria_protocol_udp)) {
// sing-box support
return 0;
} else {
// hysteria core support
return hysteriaCore();
}
} else if (proxy_type == proxy_TUIC) {
return tuicCore();
} else if (proxy_type == proxy_Hysteria2) {
return hysteria2Core();
} else { } else {
return hysteriaCore(); // external core support
return extCore();
} }
} }
@ -189,7 +161,7 @@ namespace NekoGui_fmt {
QJsonObject transport; QJsonObject transport;
transport["type"] = "udp"; transport["type"] = "udp";
transport["udp"] = QJsonObject{ transport["udp"] = QJsonObject{
{"hopInterval", hopInterval}, {"hopInterval", QString::number(hopInterval) + "s"},
}; };
config["transport"] = transport; config["transport"] = transport;
@ -241,68 +213,11 @@ namespace NekoGui_fmt {
WriteTempFile("hysteria2_" + GetRandomString(10) + ".json", result.config_export.toUtf8()); WriteTempFile("hysteria2_" + GetRandomString(10) + ".json", result.config_export.toUtf8());
result.arguments = QStringList{"-c", TempFile}; result.arguments = QStringList{"-c", TempFile};
return result;
} else { // Hysteria
ExternalBuildResult result{NekoGui::dataStore->extraCore->Get("hysteria")};
QJsonObject config;
// determine server format
auto is_direct = external_stat == 2;
auto sniGen = sni;
if (sni.isEmpty() && !IsIpAddress(serverAddress)) sniGen = serverAddress;
auto server = serverAddress;
if (!hopPort.trimmed().isEmpty()) {
server = WrapIPV6Host(server) + ":" + hopPort;
} else {
server = WrapIPV6Host(server) + ":" + Int2String(serverPort);
}
config["server"] = is_direct ? server : "127.0.0.1:" + Int2String(mapping_port);
// listen
config["socks5"] = QJsonObject{
{"listen", "127.0.0.1:" + Int2String(socks_port)},
};
// misc
config["retry"] = 5;
config["fast_open"] = true;
config["lazy_start"] = true;
config["obfs"] = obfsPassword;
config["up_mbps"] = uploadMbps;
config["down_mbps"] = downloadMbps;
if (authPayloadType == hysteria_auth_base64) config["auth"] = authPayload;
if (authPayloadType == hysteria_auth_string) config["auth_str"] = authPayload;
if (hyProtocol == hysteria_protocol_facktcp) config["protocol"] = "faketcp";
if (hyProtocol == hysteria_protocol_wechat_video) config["protocol"] = "wechat-video";
if (!sniGen.isEmpty()) config["server_name"] = sniGen;
if (!alpn.isEmpty()) config["alpn"] = alpn;
if (!caText.trimmed().isEmpty()) {
WriteTempFile("hysteria_" + GetRandomString(10) + ".crt", caText.toUtf8());
config["ca"] = TempFile;
}
if (allowInsecure) config["insecure"] = true;
if (streamReceiveWindow > 0) config["recv_window_conn"] = streamReceiveWindow;
if (connectionReceiveWindow > 0) config["recv_window"] = connectionReceiveWindow;
if (disableMtuDiscovery) config["disable_mtu_discovery"] = true;
config["hop_interval"] = hopInterval;
//
result.config_export = QJsonObject2QString(config, false);
WriteTempFile("hysteria_" + GetRandomString(10) + ".json", result.config_export.toUtf8());
result.arguments = QStringList{"--no-check", "-c", TempFile};
return result; return result;
} }
ExternalBuildResult e;
e.error = "unknown type";
return e;
} }
ExternalBuildResult CustomBean::BuildExternal(int mapping_port, int socks_port, int external_stat) { ExternalBuildResult CustomBean::BuildExternal(int mapping_port, int socks_port, int external_stat) {

View File

@ -13,7 +13,7 @@ namespace NekoGui_fmt {
url.setScheme("http"); url.setScheme("http");
} }
} else { } else {
url.setScheme(QString("socks%1").arg(socks_http_type)); url.setScheme(QStringLiteral("socks%1").arg(socks_http_type));
} }
if (!name.isEmpty()) url.setFragment(name); if (!name.isEmpty()) url.setFragment(name);
if (!username.isEmpty()) url.setUserName(username); if (!username.isEmpty()) url.setUserName(username);
@ -51,7 +51,7 @@ namespace NekoGui_fmt {
// type // type
query.addQueryItem("type", stream->network); query.addQueryItem("type", stream->network);
if (stream->network == "ws" || stream->network == "http") { if (stream->network == "ws" || stream->network == "http" || stream->network == "httpupgrade") {
if (!stream->path.isEmpty()) query.addQueryItem("path", stream->path); if (!stream->path.isEmpty()) query.addQueryItem("path", stream->path);
if (!stream->host.isEmpty()) query.addQueryItem("host", stream->host); if (!stream->host.isEmpty()) query.addQueryItem("host", stream->host);
} else if (stream->network == "grpc") { } else if (stream->network == "grpc") {
@ -152,7 +152,7 @@ namespace NekoGui_fmt {
// type // type
query.addQueryItem("type", stream->network); query.addQueryItem("type", stream->network);
if (stream->network == "ws" || stream->network == "http") { if (stream->network == "ws" || stream->network == "http" || stream->network == "httpupgrade") {
if (!stream->path.isEmpty()) query.addQueryItem("path", stream->path); if (!stream->path.isEmpty()) query.addQueryItem("path", stream->path);
if (!stream->host.isEmpty()) query.addQueryItem("host", stream->host); if (!stream->host.isEmpty()) query.addQueryItem("host", stream->host);
} else if (stream->network == "grpc") { } else if (stream->network == "grpc") {
@ -182,29 +182,7 @@ namespace NekoGui_fmt {
QString QUICBean::ToShareLink() { QString QUICBean::ToShareLink() {
QUrl url; QUrl url;
if (proxy_type == proxy_Hysteria) { if (proxy_type == proxy_TUIC) {
url.setScheme("hysteria");
url.setHost(serverAddress);
url.setPort(serverPort);
QUrlQuery q;
q.addQueryItem("upmbps", Int2String(uploadMbps));
q.addQueryItem("downmbps", Int2String(downloadMbps));
if (!obfsPassword.isEmpty()) {
q.addQueryItem("obfs", "xplus");
q.addQueryItem("obfsParam", obfsPassword);
}
if (authPayloadType == hysteria_auth_string) q.addQueryItem("auth", authPayload);
if (hyProtocol == hysteria_protocol_facktcp) q.addQueryItem("protocol", "faketcp");
if (hyProtocol == hysteria_protocol_wechat_video) q.addQueryItem("protocol", "wechat-video");
if (!hopPort.trimmed().isEmpty()) q.addQueryItem("mport", hopPort);
if (allowInsecure) q.addQueryItem("insecure", "1");
if (!sni.isEmpty()) q.addQueryItem("peer", sni);
if (!alpn.isEmpty()) q.addQueryItem("alpn", alpn);
if (connectionReceiveWindow > 0) q.addQueryItem("recv_window", Int2String(connectionReceiveWindow));
if (streamReceiveWindow > 0) q.addQueryItem("recv_window_conn", Int2String(streamReceiveWindow));
if (!q.isEmpty()) url.setQuery(q);
if (!name.isEmpty()) url.setFragment(name);
} else if (proxy_type == proxy_TUIC) {
url.setScheme("tuic"); url.setScheme("tuic");
url.setUserName(uuid); url.setUserName(uuid);
url.setPassword(password); url.setPassword(password);
@ -235,7 +213,7 @@ namespace NekoGui_fmt {
q.addQueryItem("obfs", "salamander"); q.addQueryItem("obfs", "salamander");
q.addQueryItem("obfs-password", obfsPassword); q.addQueryItem("obfs-password", obfsPassword);
} }
// if (!hopPort.trimmed().isEmpty()) q.addQueryItem("mport", hopPort); if (!hopPort.trimmed().isEmpty()) q.addQueryItem("mport", hopPort);
if (allowInsecure) q.addQueryItem("insecure", "1"); if (allowInsecure) q.addQueryItem("insecure", "1");
if (!sni.isEmpty()) q.addQueryItem("sni", sni); if (!sni.isEmpty()) q.addQueryItem("sni", sni);
if (!q.isEmpty()) url.setQuery(q); if (!q.isEmpty()) url.setQuery(q);

View File

@ -24,7 +24,7 @@ namespace NekoGui_fmt {
QString DisplayType() override { QString DisplayType() override {
if (core == "internal") { if (core == "internal") {
auto obj = QString2QJsonObject(config_simple); auto obj = QString2QJsonObject(config_simple);
return obj[IS_NEKO_BOX ? "type" : "protocol"].toString(); return obj["type"].toString();
} else if (core == "internal-full") { } else if (core == "internal-full") {
return software_core_name + " config"; return software_core_name + " config";
} }
@ -36,11 +36,7 @@ namespace NekoGui_fmt {
QString DisplayAddress() override { QString DisplayAddress() override {
if (core == "internal") { if (core == "internal") {
auto obj = QString2QJsonObject(config_simple); auto obj = QString2QJsonObject(config_simple);
if (IS_NEKO_BOX) { return ::DisplayAddress(obj["server"].toString(), obj["server_port"].toInt());
return ::DisplayAddress(obj["server"].toString(), obj["server_port"].toInt());
} else {
return {};
}
} else if (core == "internal-full") { } else if (core == "internal-full") {
return {}; return {};
} }
@ -52,7 +48,5 @@ namespace NekoGui_fmt {
ExternalBuildResult BuildExternal(int mapping_port, int socks_port, int external_stat) override; ExternalBuildResult BuildExternal(int mapping_port, int socks_port, int external_stat) override;
CoreObjOutboundBuildResult BuildCoreObjSingBox() override; CoreObjOutboundBuildResult BuildCoreObjSingBox() override;
CoreObjOutboundBuildResult BuildCoreObjV2Ray() override;
}; };
} // namespace NekoGui_fmt } // namespace NekoGui_fmt

View File

@ -54,7 +54,13 @@ namespace NekoGui_fmt {
if (serverPort == -1) serverPort = 443; if (serverPort == -1) serverPort = 443;
// security // security
stream->network = GetQueryValue(query, "type", "tcp");
auto type = GetQueryValue(query, "type", "tcp");
if (type == "h2") {
type = "http";
}
stream->network = type;
if (proxy_type == proxy_Trojan) { if (proxy_type == proxy_Trojan) {
stream->security = GetQueryValue(query, "security", "tls").replace("reality", "tls").replace("none", ""); stream->security = GetQueryValue(query, "security", "tls").replace("reality", "tls").replace("none", "");
} else { } else {
@ -81,6 +87,9 @@ namespace NekoGui_fmt {
} else if (stream->network == "http") { } else if (stream->network == "http") {
stream->path = GetQueryValue(query, "path", ""); stream->path = GetQueryValue(query, "path", "");
stream->host = GetQueryValue(query, "host", "").replace("|", ","); stream->host = GetQueryValue(query, "host", "").replace("|", ",");
} else if (stream->network == "httpupgrade") {
stream->path = GetQueryValue(query, "path", "");
stream->host = GetQueryValue(query, "host", "");
} else if (stream->network == "grpc") { } else if (stream->network == "grpc") {
stream->path = GetQueryValue(query, "serviceName", ""); stream->path = GetQueryValue(query, "serviceName", "");
} else if (stream->network == "tcp") { } else if (stream->network == "tcp") {
@ -154,7 +163,12 @@ namespace NekoGui_fmt {
stream->sni = objN["sni"].toString(); stream->sni = objN["sni"].toString();
stream->header_type = objN["type"].toString(); stream->header_type = objN["type"].toString();
auto net = objN["net"].toString(); auto net = objN["net"].toString();
if (!net.isEmpty()) stream->network = net; if (!net.isEmpty()) {
if (net == "h2") {
net = "http";
}
stream->network = net;
}
auto scy = objN["scy"].toString(); auto scy = objN["scy"].toString();
if (!scy.isEmpty()) security = scy; if (!scy.isEmpty()) security = scy;
// TLS (XTLS?) // TLS (XTLS?)
@ -177,7 +191,11 @@ namespace NekoGui_fmt {
security = GetQueryValue(query, "encryption", "auto"); security = GetQueryValue(query, "encryption", "auto");
// security // security
stream->network = GetQueryValue(query, "type", "tcp"); auto type = GetQueryValue(query, "type", "tcp");
if (type == "h2") {
type = "http";
}
stream->network = type;
stream->security = GetQueryValue(query, "security", "tls").replace("reality", "tls"); stream->security = GetQueryValue(query, "security", "tls").replace("reality", "tls");
auto sni1 = GetQueryValue(query, "sni"); auto sni1 = GetQueryValue(query, "sni");
auto sni2 = GetQueryValue(query, "peer"); auto sni2 = GetQueryValue(query, "peer");
@ -199,6 +217,9 @@ namespace NekoGui_fmt {
} else if (stream->network == "http") { } else if (stream->network == "http") {
stream->path = GetQueryValue(query, "path", ""); stream->path = GetQueryValue(query, "path", "");
stream->host = GetQueryValue(query, "host", "").replace("|", ","); stream->host = GetQueryValue(query, "host", "").replace("|", ",");
} else if (stream->network == "httpupgrade") {
stream->path = GetQueryValue(query, "path", "");
stream->host = GetQueryValue(query, "host", "");
} else if (stream->network == "grpc") { } else if (stream->network == "grpc") {
stream->path = GetQueryValue(query, "serviceName", ""); stream->path = GetQueryValue(query, "serviceName", "");
} else if (stream->network == "tcp") { } else if (stream->network == "tcp") {
@ -235,37 +256,7 @@ namespace NekoGui_fmt {
auto query = QUrlQuery(url.query()); auto query = QUrlQuery(url.query());
if (url.host().isEmpty() || url.port() == -1) return false; if (url.host().isEmpty() || url.port() == -1) return false;
if (url.scheme() == "hysteria") { if (url.scheme() == "tuic") {
// https://hysteria.network/docs/uri-scheme/
if (!query.hasQueryItem("upmbps") || !query.hasQueryItem("downmbps")) return false;
name = url.fragment(QUrl::FullyDecoded);
serverAddress = url.host();
serverPort = url.port();
hopPort = query.queryItemValue("mport");
obfsPassword = query.queryItemValue("obfsParam");
allowInsecure = QStringList{"1", "true"}.contains(query.queryItemValue("insecure"));
uploadMbps = query.queryItemValue("upmbps").toInt();
downloadMbps = query.queryItemValue("downmbps").toInt();
auto protocolStr = (query.hasQueryItem("protocol") ? query.queryItemValue("protocol") : "udp").toLower();
if (protocolStr == "faketcp") {
hyProtocol = NekoGui_fmt::QUICBean::hysteria_protocol_facktcp;
} else if (protocolStr.startsWith("wechat")) {
hyProtocol = NekoGui_fmt::QUICBean::hysteria_protocol_wechat_video;
}
if (query.hasQueryItem("auth")) {
authPayload = query.queryItemValue("auth");
authPayloadType = NekoGui_fmt::QUICBean::hysteria_auth_string;
}
alpn = query.queryItemValue("alpn");
sni = FIRST_OR_SECOND(query.queryItemValue("peer"), query.queryItemValue("sni"));
connectionReceiveWindow = query.queryItemValue("recv_window").toInt();
streamReceiveWindow = query.queryItemValue("recv_window_conn").toInt();
} else if (url.scheme() == "tuic") {
// by daeuniverse // by daeuniverse
// https://github.com/daeuniverse/dae/discussions/182 // https://github.com/daeuniverse/dae/discussions/182
@ -287,7 +278,7 @@ namespace NekoGui_fmt {
name = url.fragment(QUrl::FullyDecoded); name = url.fragment(QUrl::FullyDecoded);
serverAddress = url.host(); serverAddress = url.host();
serverPort = url.port(); serverPort = url.port();
// hopPort = query.queryItemValue("mport"); hopPort = query.queryItemValue("mport");
obfsPassword = query.queryItemValue("obfs-password"); obfsPassword = query.queryItemValue("obfs-password");
allowInsecure = QStringList{"1", "true"}.contains(query.queryItemValue("insecure")); allowInsecure = QStringList{"1", "true"}.contains(query.queryItemValue("insecure"));

View File

@ -1,15 +1,6 @@
#pragma once #pragma once
namespace Preset { namespace Preset {
namespace Xray {
inline QStringList UtlsFingerPrint = {"", "chrome", "firefox", "edge", "safari", "360", "qq", "ios", "android", "random", "randomized"};
inline QStringList ShadowsocksMethods = {"aes-128-gcm", "aes-256-gcm", "aes-192-gcm", "chacha20-ietf-poly1305", "xchacha20-ietf-poly1305",
"2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305",
"aes-128-ctr", "aes-192-ctr", "aes-256-ctr", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb",
"rc4", "rc4-md5", "bf-cfb", "chacha20", "chacha20-ietf", "xchacha20", "none"};
inline QStringList Flows = {"xtls-rprx-vision", "xtls-rprx-vision-udp443"};
} // namespace Xray
namespace SingBox { namespace SingBox {
inline QStringList VpnImplementation = {"gvisor", "system", "mixed"}; inline QStringList VpnImplementation = {"gvisor", "system", "mixed"};
inline QStringList DomainStrategy = {"", "ipv4_only", "ipv6_only", "prefer_ipv4", "prefer_ipv6"}; inline QStringList DomainStrategy = {"", "ipv4_only", "ipv6_only", "prefer_ipv4", "prefer_ipv6"};

View File

@ -5,32 +5,19 @@
namespace NekoGui_fmt { namespace NekoGui_fmt {
class QUICBean : public AbstractBean { class QUICBean : public AbstractBean {
public: public:
static constexpr int proxy_Hysteria = 0; // static constexpr int proxy_Hysteria = 0;
static constexpr int proxy_TUIC = 1; static constexpr int proxy_TUIC = 1;
static constexpr int proxy_Hysteria2 = 3; static constexpr int proxy_Hysteria2 = 3;
int proxy_type = proxy_Hysteria; int proxy_type = proxy_Hysteria2;
bool forceExternal = false; bool forceExternal = false;
// Hysteria 1 // Hysteria 2
static constexpr int hysteria_protocol_udp = 0;
static constexpr int hysteria_protocol_facktcp = 1;
static constexpr int hysteria_protocol_wechat_video = 2;
int hyProtocol = 0;
static constexpr int hysteria_auth_none = 0;
static constexpr int hysteria_auth_string = 1;
static constexpr int hysteria_auth_base64 = 2;
int authPayloadType = 0;
QString authPayload = "";
// Hysteria 1&2
QString obfsPassword = ""; QString obfsPassword = "";
int uploadMbps = 100; int uploadMbps = 0;
int downloadMbps = 100; int downloadMbps = 0;
qint64 streamReceiveWindow = 0; qint64 streamReceiveWindow = 0;
qint64 connectionReceiveWindow = 0; qint64 connectionReceiveWindow = 0;
@ -62,8 +49,7 @@ namespace NekoGui_fmt {
explicit QUICBean(int _proxy_type) : AbstractBean(0) { explicit QUICBean(int _proxy_type) : AbstractBean(0) {
proxy_type = _proxy_type; proxy_type = _proxy_type;
if (proxy_type == proxy_Hysteria || proxy_type == proxy_Hysteria2) { if (proxy_type == proxy_Hysteria2) {
_add(new configItem("authPayload", &authPayload, itemType::string));
_add(new configItem("obfsPassword", &obfsPassword, itemType::string)); _add(new configItem("obfsPassword", &obfsPassword, itemType::string));
_add(new configItem("uploadMbps", &uploadMbps, itemType::integer)); _add(new configItem("uploadMbps", &uploadMbps, itemType::integer));
_add(new configItem("downloadMbps", &downloadMbps, itemType::integer)); _add(new configItem("downloadMbps", &downloadMbps, itemType::integer));
@ -72,14 +58,7 @@ namespace NekoGui_fmt {
_add(new configItem("disableMtuDiscovery", &disableMtuDiscovery, itemType::boolean)); _add(new configItem("disableMtuDiscovery", &disableMtuDiscovery, itemType::boolean));
_add(new configItem("hopInterval", &hopInterval, itemType::integer)); _add(new configItem("hopInterval", &hopInterval, itemType::integer));
_add(new configItem("hopPort", &hopPort, itemType::string)); _add(new configItem("hopPort", &hopPort, itemType::string));
if (proxy_type == proxy_Hysteria) { // hy1 _add(new configItem("password", &password, itemType::string));
_add(new configItem("authPayloadType", &authPayloadType, itemType::integer));
_add(new configItem("protocol", &hyProtocol, itemType::integer));
} else { // hy2
uploadMbps = 0;
downloadMbps = 0;
_add(new configItem("password", &password, itemType::string));
}
} else if (proxy_type == proxy_TUIC) { } else if (proxy_type == proxy_TUIC) {
_add(new configItem("uuid", &uuid, itemType::string)); _add(new configItem("uuid", &uuid, itemType::string));
_add(new configItem("password", &password, itemType::string)); _add(new configItem("password", &password, itemType::string));
@ -108,8 +87,6 @@ namespace NekoGui_fmt {
return software_core_name; return software_core_name;
} else if (proxy_type == proxy_TUIC) { } else if (proxy_type == proxy_TUIC) {
return "tuic"; return "tuic";
} else if (proxy_type == proxy_Hysteria) {
return "hysteria";
} else { } else {
return "hysteria2"; return "hysteria2";
} }
@ -118,8 +95,6 @@ namespace NekoGui_fmt {
QString DisplayType() override { QString DisplayType() override {
if (proxy_type == proxy_TUIC) { if (proxy_type == proxy_TUIC) {
return "TUIC"; return "TUIC";
} else if (proxy_type == proxy_Hysteria) {
return "Hysteria1";
} else { } else {
return "Hysteria2"; return "Hysteria2";
} }

View File

@ -23,8 +23,6 @@ namespace NekoGui_fmt {
QString DisplayType() override { return "Shadowsocks"; }; QString DisplayType() override { return "Shadowsocks"; };
CoreObjOutboundBuildResult BuildCoreObjV2Ray() override;
CoreObjOutboundBuildResult BuildCoreObjSingBox() override; CoreObjOutboundBuildResult BuildCoreObjSingBox() override;
bool TryParseLink(const QString &link); bool TryParseLink(const QString &link);

View File

@ -26,8 +26,6 @@ namespace NekoGui_fmt {
QString DisplayType() override { return socks_http_type == type_HTTP ? "HTTP" : "Socks"; }; QString DisplayType() override { return socks_http_type == type_HTTP ? "HTTP" : "Socks"; };
CoreObjOutboundBuildResult BuildCoreObjV2Ray() override;
CoreObjOutboundBuildResult BuildCoreObjSingBox() override; CoreObjOutboundBuildResult BuildCoreObjSingBox() override;
bool TryParseLink(const QString &link); bool TryParseLink(const QString &link);

View File

@ -24,8 +24,6 @@ namespace NekoGui_fmt {
QString DisplayType() override { return proxy_type == proxy_VLESS ? "VLESS" : "Trojan"; }; QString DisplayType() override { return proxy_type == proxy_VLESS ? "VLESS" : "Trojan"; };
CoreObjOutboundBuildResult BuildCoreObjV2Ray() override;
CoreObjOutboundBuildResult BuildCoreObjSingBox() override; CoreObjOutboundBuildResult BuildCoreObjSingBox() override;
bool TryParseLink(const QString &link); bool TryParseLink(const QString &link);

View File

@ -8,7 +8,7 @@ namespace NekoGui_fmt {
QString network = "tcp"; QString network = "tcp";
QString security = ""; QString security = "";
QString packet_encoding = ""; QString packet_encoding = "";
// ws/http/grpc/tcp-http // ws/http/grpc/tcp-http/httpupgrade
QString path = ""; QString path = "";
QString host = ""; QString host = "";
// kcp/quic/tcp-http // kcp/quic/tcp-http
@ -49,8 +49,6 @@ namespace NekoGui_fmt {
_add(new configItem("mux_s", &multiplex_status, itemType::integer)); _add(new configItem("mux_s", &multiplex_status, itemType::integer));
} }
QJsonObject BuildStreamSettingsV2Ray();
void BuildStreamSettingsSingBox(QJsonObject *outbound); void BuildStreamSettingsSingBox(QJsonObject *outbound);
}; };

View File

@ -21,8 +21,6 @@ namespace NekoGui_fmt {
QString DisplayType() override { return "VMess"; }; QString DisplayType() override { return "VMess"; };
CoreObjOutboundBuildResult BuildCoreObjV2Ray() override;
CoreObjOutboundBuildResult BuildCoreObjSingBox() override; CoreObjOutboundBuildResult BuildCoreObjSingBox() override;
bool TryParseLink(const QString &link); bool TryParseLink(const QString &link);

View File

@ -7,16 +7,16 @@ import (
"github.com/matsuridayo/libneko/neko_common" "github.com/matsuridayo/libneko/neko_common"
"github.com/matsuridayo/libneko/neko_log" "github.com/matsuridayo/libneko/neko_log"
"github.com/matsuridayo/sing-box-extra/boxapi" box "github.com/sagernet/sing-box"
"github.com/matsuridayo/sing-box-extra/boxbox" "github.com/sagernet/sing-box/boxapi"
"github.com/matsuridayo/sing-box-extra/boxmain" boxmain "github.com/sagernet/sing-box/cmd/sing-box"
) )
var instance *boxbox.Box var instance *box.Box
var instance_cancel context.CancelFunc var instance_cancel context.CancelFunc
func setupCore() { func setupCore() {
boxmain.DisableColor() boxmain.SetDisableColor(true)
// //
neko_log.SetupLog(50*1024, "./neko.log") neko_log.SetupLog(50*1024, "./neko.log")
// //
@ -24,7 +24,7 @@ func setupCore() {
return instance return instance
} }
neko_common.DialContext = func(ctx context.Context, specifiedInstance interface{}, network, addr string) (net.Conn, error) { neko_common.DialContext = func(ctx context.Context, specifiedInstance interface{}, network, addr string) (net.Conn, error) {
if i, ok := specifiedInstance.(*boxbox.Box); ok { if i, ok := specifiedInstance.(*box.Box); ok {
return boxapi.DialContext(ctx, i, network, addr) return boxapi.DialContext(ctx, i, network, addr)
} }
if instance != nil { if instance != nil {
@ -33,7 +33,7 @@ func setupCore() {
return neko_common.DialContextSystem(ctx, network, addr) return neko_common.DialContextSystem(ctx, network, addr)
} }
neko_common.DialUDP = func(ctx context.Context, specifiedInstance interface{}) (net.PacketConn, error) { neko_common.DialUDP = func(ctx context.Context, specifiedInstance interface{}) (net.PacketConn, error) {
if i, ok := specifiedInstance.(*boxbox.Box); ok { if i, ok := specifiedInstance.(*box.Box); ok {
return boxapi.DialUDP(ctx, i) return boxapi.DialUDP(ctx, i)
} }
if instance != nil { if instance != nil {
@ -42,7 +42,7 @@ func setupCore() {
return neko_common.DialUDPSystem(ctx) return neko_common.DialUDPSystem(ctx)
} }
neko_common.CreateProxyHttpClient = func(specifiedInstance interface{}) *http.Client { neko_common.CreateProxyHttpClient = func(specifiedInstance interface{}) *http.Client {
if i, ok := specifiedInstance.(*boxbox.Box); ok { if i, ok := specifiedInstance.(*box.Box); ok {
return boxapi.CreateProxyHttpClient(i) return boxapi.CreateProxyHttpClient(i)
} }
return boxapi.CreateProxyHttpClient(instance) return boxapi.CreateProxyHttpClient(instance)

View File

@ -4,7 +4,6 @@ go 1.19
require ( require (
github.com/matsuridayo/libneko v1.0.0 // replaced github.com/matsuridayo/libneko v1.0.0 // replaced
github.com/matsuridayo/sing-box-extra v1.0.0 // replaced
github.com/sagernet/sing-box v1.0.0 // replaced github.com/sagernet/sing-box v1.0.0 // replaced
// github.com/sagernet/sing-dns v1.0.0 // indirect; replaced // github.com/sagernet/sing-dns v1.0.0 // indirect; replaced
grpc_server v1.0.0 grpc_server v1.0.0
@ -14,93 +13,93 @@ require (
berty.tech/go-libtor v1.0.385 // indirect berty.tech/go-libtor v1.0.385 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect
github.com/ajg/form v1.5.1 // indirect github.com/ajg/form v1.5.1 // indirect
github.com/andybalholm/brotli v1.0.5 // indirect github.com/andybalholm/brotli v1.0.6 // indirect
github.com/caddyserver/certmagic v0.19.2 // indirect github.com/caddyserver/certmagic v0.20.0 // indirect
github.com/cloudflare/circl v1.3.3 // indirect github.com/cloudflare/circl v1.3.7 // indirect
github.com/cretz/bine v0.2.0 // indirect github.com/cretz/bine v0.2.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/gaukas/godicttls v0.0.4 // indirect
github.com/go-chi/chi/v5 v5.0.10 // indirect github.com/go-chi/chi/v5 v5.0.12 // indirect
github.com/go-chi/cors v1.2.1 // indirect github.com/go-chi/cors v1.2.1 // indirect
github.com/go-chi/render v1.0.3 // indirect github.com/go-chi/render v1.0.3 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/gofrs/uuid/v5 v5.0.0 // indirect github.com/gobwas/httphead v0.1.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect github.com/gobwas/pool v0.2.1 // indirect
github.com/gofrs/uuid/v5 v5.2.0 // indirect
github.com/google/btree v1.1.2 // indirect github.com/google/btree v1.1.2 // indirect
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
github.com/hashicorp/yamux v0.1.1 // indirect github.com/hashicorp/yamux v0.1.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/insomniacslk/dhcp v0.0.0-20230908212754-65c27093e38a // indirect github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2 // indirect
github.com/josharian/native v1.1.0 // indirect github.com/josharian/native v1.1.0 // indirect
github.com/klauspost/compress v1.15.15 // indirect github.com/klauspost/compress v1.17.4 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/libdns/alidns v1.0.3 // indirect github.com/libdns/alidns v1.0.3 // indirect
github.com/libdns/cloudflare v0.1.0 // indirect github.com/libdns/cloudflare v0.1.1 // indirect
github.com/libdns/libdns v0.2.1 // indirect github.com/libdns/libdns v0.2.2 // indirect
github.com/logrusorgru/aurora v2.0.3+incompatible // indirect github.com/logrusorgru/aurora v2.0.3+incompatible // indirect
github.com/metacubex/tfo-go v0.0.0-20240821025650-e9be0afd5e7d // indirect
github.com/mholt/acmez v1.2.0 // indirect github.com/mholt/acmez v1.2.0 // indirect
github.com/miekg/dns v1.1.56 // indirect github.com/miekg/dns v1.1.59 // indirect
github.com/onsi/ginkgo/v2 v2.9.5 // indirect github.com/onsi/ginkgo/v2 v2.9.7 // indirect
github.com/ooni/go-libtor v1.1.8 // indirect github.com/ooni/go-libtor v1.1.8 // indirect
github.com/oschwald/maxminddb-golang v1.12.0 // indirect github.com/oschwald/maxminddb-golang v1.12.0 // indirect
github.com/pierrec/lz4/v4 v4.1.14 // indirect github.com/pierrec/lz4/v4 v4.1.14 // indirect
github.com/quic-go/qpack v0.4.0 // indirect github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qtls-go1-20 v0.3.4 // indirect github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
github.com/sagernet/bbolt v0.0.0-20231008142710-b2d6e2f20458 // indirect github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a // indirect
github.com/sagernet/cloudflare-tls v0.0.0-20230829051644-4a68352d0c4a // indirect github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 // indirect
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 // indirect github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f // indirect
github.com/sagernet/gvisor v0.0.0-20230930141345-5fef6f2e17ab // indirect github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba // indirect
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect github.com/sagernet/quic-go v0.47.0-beta.2 // indirect
github.com/sagernet/quic-go v0.0.0-20231008035953-32727fef9460 // indirect
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect
github.com/sagernet/sing v0.2.14-0.20231011041941-e4d9384bcd84 // indirect github.com/sagernet/sing v0.4.3 // indirect
github.com/sagernet/sing-dns v0.1.10 // indirect github.com/sagernet/sing-dns v0.2.3 // indirect
github.com/sagernet/sing-mux v0.1.3 // indirect github.com/sagernet/sing-mux v0.2.0 // indirect
github.com/sagernet/sing-quic v0.1.3-0.20231011042217-13b8d0b8f74b // indirect github.com/sagernet/sing-quic v0.2.2 // indirect
github.com/sagernet/sing-shadowsocks v0.2.5 // indirect github.com/sagernet/sing-shadowsocks v0.2.7 // indirect
github.com/sagernet/sing-shadowsocks2 v0.1.4 // indirect github.com/sagernet/sing-shadowsocks2 v0.2.0 // indirect
github.com/sagernet/sing-shadowtls v0.1.4 // indirect github.com/sagernet/sing-shadowtls v0.1.4 // indirect
github.com/sagernet/sing-tun v0.1.16-0.20231006112722-19cc8b9e81aa // indirect github.com/sagernet/sing-tun v0.3.3 // indirect
github.com/sagernet/sing-vmess v0.1.8 // indirect github.com/sagernet/sing-vmess v0.1.12 // indirect
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 // indirect github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect
github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6 // indirect github.com/sagernet/utls v1.5.4 // indirect
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 // indirect github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8 // indirect
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e // indirect github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 // indirect
github.com/sagernet/wireguard-go v0.0.0-20230807125731-5d4a7ef2dc5f // indirect github.com/spf13/cobra v1.8.0 // indirect
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 // indirect
github.com/spf13/cobra v1.7.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/pflag v1.0.5 // indirect
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
github.com/zeebo/blake3 v0.2.3 // indirect github.com/zeebo/blake3 v0.2.3 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.26.0 // indirect go.uber.org/zap v1.27.0 // indirect
go4.org/netipx v0.0.0-20230824141953-6213f710f925 // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
golang.org/x/crypto v0.14.0 // indirect golang.org/x/crypto v0.23.0 // indirect
golang.org/x/exp v0.0.0-20231005195138-3e424a577f31 // indirect golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect
golang.org/x/mod v0.12.0 // indirect golang.org/x/mod v0.18.0 // indirect
golang.org/x/net v0.16.0 // indirect golang.org/x/net v0.25.0 // indirect
golang.org/x/sys v0.13.0 // indirect golang.org/x/sync v0.8.0 // indirect
golang.org/x/text v0.13.0 // indirect golang.org/x/sys v0.25.0 // indirect
golang.org/x/time v0.3.0 // indirect golang.org/x/text v0.18.0 // indirect
golang.org/x/tools v0.13.0 // indirect golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 // indirect golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect
google.golang.org/grpc v1.58.2 // indirect google.golang.org/grpc v1.63.2 // indirect
google.golang.org/protobuf v1.31.0 // indirect google.golang.org/protobuf v1.33.0 // indirect
lukechampine.com/blake3 v1.2.1 // indirect lukechampine.com/blake3 v1.3.0 // indirect
) )
replace grpc_server => ../../grpc_server replace grpc_server => ../../grpc_server
replace github.com/matsuridayo/libneko => ../../../../libneko replace github.com/matsuridayo/libneko => ../../../../libneko
replace github.com/matsuridayo/sing-box-extra => ../../../../sing-box-extra
replace github.com/sagernet/sing-box => ../../../../sing-box replace github.com/sagernet/sing-box => ../../../../sing-box
replace github.com/sagernet/sing-quic => ../../../../sing-quic
// replace github.com/sagernet/sing => ../../../../sing // replace github.com/sagernet/sing => ../../../../sing
// replace github.com/sagernet/sing-dns => ../../../../sing-dns // replace github.com/sagernet/sing-dns => ../../../../sing-dns

View File

@ -2,41 +2,38 @@ berty.tech/go-libtor v1.0.385 h1:RWK94C3hZj6Z2GdvePpHJLnWYobFr3bY/OdUJ5aoEXw=
berty.tech/go-libtor v1.0.385/go.mod h1:9swOOQVb+kmvuAlsgWUK/4c52pm69AdbJsxLzk+fJEw= berty.tech/go-libtor v1.0.385/go.mod h1:9swOOQVb+kmvuAlsgWUK/4c52pm69AdbJsxLzk+fJEw=
cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ= cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go/compute v1.21.0 h1:JNBsyXVoOoNJtTQcnEY5uYpZIbeCTYIeDe0Xh1bySMk= cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg=
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/caddyserver/certmagic v0.19.2 h1:HZd1AKLx4592MalEGQS39DKs2ZOAJCEM/xYPMQ2/ui0= github.com/caddyserver/certmagic v0.20.0 h1:bTw7LcEZAh9ucYCRXyCpIrSAGplplI0vGYJ4BpCQ/Fc=
github.com/caddyserver/certmagic v0.19.2/go.mod h1:fsL01NomQ6N+kE2j37ZCnig2MFosG+MIO4ztnmG/zz8= github.com/caddyserver/certmagic v0.20.0/go.mod h1:N4sXgpICQUskEWpj7zVzvWD41p3NYacrNoZYiRM2jTg=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cretz/bine v0.1.0/go.mod h1:6PF6fWAvYtwjRGkAuDEJeWNOv3a2hUouSP/yRYXmvHw= github.com/cretz/bine v0.1.0/go.mod h1:6PF6fWAvYtwjRGkAuDEJeWNOv3a2hUouSP/yRYXmvHw=
github.com/cretz/bine v0.2.0 h1:8GiDRGlTgz+o8H9DSnsl+5MeBK4HsExxgl6WgzOCuZo= github.com/cretz/bine v0.2.0 h1:8GiDRGlTgz+o8H9DSnsl+5MeBK4HsExxgl6WgzOCuZo=
github.com/cretz/bine v0.2.0/go.mod h1:WU4o9QR9wWp8AVKtTM1XD5vUHkEqnf2vVSo6dBqbetI= github.com/cretz/bine v0.2.0/go.mod h1:WU4o9QR9wWp8AVKtTM1XD5vUHkEqnf2vVSo6dBqbetI=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk= github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk=
github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI=
github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s=
github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4= github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4= github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4=
@ -49,40 +46,40 @@ github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/gofrs/uuid/v5 v5.0.0 h1:p544++a97kEL+svbcFbCQVM9KFu0Yo25UoISXGNNH9M= github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gofrs/uuid/v5 v5.2.0 h1:qw1GMx6/y8vhVsx626ImfKMuS5CvJmhIKKtuyvfajMM=
github.com/gofrs/uuid/v5 v5.2.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/insomniacslk/dhcp v0.0.0-20230908212754-65c27093e38a h1:S33o3djA1nPRd+d/bf7jbbXytXuK/EoXow7+aa76grQ= github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2 h1:9K06NfxkBh25x56yVhWWlKFE8YpicaSfHwoV8SFbueA=
github.com/insomniacslk/dhcp v0.0.0-20230908212754-65c27093e38a/go.mod h1:zmdm3sTSDP3vOOX3CEWRkkRHtKr1DxBx+J1OQFoDQQs= github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2/go.mod h1:3A9PQ1cunSDF/1rbTq99Ts4pVnycWg+vlPkfeD2NLFI=
github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA= github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
@ -90,20 +87,22 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/libdns/alidns v1.0.3 h1:LFHuGnbseq5+HCeGa1aW8awyX/4M2psB9962fdD2+yQ= github.com/libdns/alidns v1.0.3 h1:LFHuGnbseq5+HCeGa1aW8awyX/4M2psB9962fdD2+yQ=
github.com/libdns/alidns v1.0.3/go.mod h1:e18uAG6GanfRhcJj6/tps2rCMzQJaYVcGKT+ELjdjGE= github.com/libdns/alidns v1.0.3/go.mod h1:e18uAG6GanfRhcJj6/tps2rCMzQJaYVcGKT+ELjdjGE=
github.com/libdns/cloudflare v0.1.0 h1:93WkJaGaiXCe353LHEP36kAWCUw0YjFqwhkBkU2/iic= github.com/libdns/cloudflare v0.1.1 h1:FVPfWwP8zZCqj268LZjmkDleXlHPlFU9KC4OJ3yn054=
github.com/libdns/cloudflare v0.1.0/go.mod h1:a44IP6J1YH6nvcNl1PverfJviADgXUnsozR3a7vBKN8= github.com/libdns/cloudflare v0.1.1/go.mod h1:9VK91idpOjg6v7/WbjkEW49bSCxj00ALesIFDhJ8PBU=
github.com/libdns/libdns v0.2.0/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40= github.com/libdns/libdns v0.2.0/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis= github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s=
github.com/libdns/libdns v0.2.1/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40= github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
github.com/metacubex/tfo-go v0.0.0-20240821025650-e9be0afd5e7d h1:j9LtzkYstLFoNvXW824QQeN7Y26uPL5249kzWKbzO9U=
github.com/metacubex/tfo-go v0.0.0-20240821025650-e9be0afd5e7d/go.mod h1:c7bVFM9f5+VzeZ/6Kg77T/jrg1Xp8QpqlSHvG/aXVts=
github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30= github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30=
github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE= github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE=
github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE= github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs=
github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY= github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk=
github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q= github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss=
github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k= github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0=
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU=
github.com/ooni/go-libtor v1.1.8 h1:Wo3V3DVTxl5vZdxtQakqYP+DAHx7pPtAFSl1bnAa08w= github.com/ooni/go-libtor v1.1.8 h1:Wo3V3DVTxl5vZdxtQakqYP+DAHx7pPtAFSl1bnAa08w=
github.com/ooni/go-libtor v1.1.8/go.mod h1:q1YyLwRD9GeMyeerVvwc0vJ2YgwDLTp2bdVcrh/JXyI= github.com/ooni/go-libtor v1.1.8/go.mod h1:q1YyLwRD9GeMyeerVvwc0vJ2YgwDLTp2bdVcrh/JXyI=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
@ -117,58 +116,49 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
github.com/quic-go/qtls-go1-20 v0.3.4 h1:MfFAPULvst4yoMgY9QmtpYmfij/em7O8UUi+bNVm7Cg= github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs=
github.com/quic-go/qtls-go1-20 v0.3.4/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagernet/bbolt v0.0.0-20231008142710-b2d6e2f20458 h1:7NXD6FUQucBklrw/TLCqeAARyFuoK9fD5iJ+Y/EHHBQ= github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkkD2QgdTuzQG263YZ+2emfpeyGqW0=
github.com/sagernet/bbolt v0.0.0-20231008142710-b2d6e2f20458/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM= github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM=
github.com/sagernet/cloudflare-tls v0.0.0-20230829051644-4a68352d0c4a h1:wZHruBxZCsQLXHAozWpnJBL3wJ/XufDpz0qKtgpSnA4= github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 h1:YbmpqPQEMdlk9oFSKYWRqVuu9qzNiOayIonKmv1gCXY=
github.com/sagernet/cloudflare-tls v0.0.0-20230829051644-4a68352d0c4a/go.mod h1:dNV1ZP9y3qx5ltULeKaQZTZWTLHflgW5DES+Ses7cMI= github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1/go.mod h1:J2yAxTFPDjrDPhuAi9aWFz2L3ox9it4qAluBBbN0H5k=
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 h1:5+m7c6AkmAylhauulqN/c5dnh8/KssrE9c93TQrXldA= github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f h1:NkhuupzH5ch7b/Y/6ZHJWrnNLoiNnSJaow6DPb8VW2I=
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61/go.mod h1:QUQ4RRHD6hGGHdFMEtR8T2P6GS6R3D/CXKdaYHKKXms= github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f/go.mod h1:KXmw+ouSJNOsuRpg4wgwwCQuunrGz4yoAqQjsLjc6N0=
github.com/sagernet/gvisor v0.0.0-20230930141345-5fef6f2e17ab h1:u+xQoi/Yc6bNUvTfrDD6HhGRybn2lzrhf5vmS+wb4Ho= github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba h1:EY5AS7CCtfmARNv2zXUOrsEMPFDGYxaw65JzA2p51Vk=
github.com/sagernet/gvisor v0.0.0-20230930141345-5fef6f2e17ab/go.mod h1:3akUhSHSVtLuJaYcW5JPepUraBOW06Ibz2HKwaK5rOk= github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE= github.com/sagernet/quic-go v0.47.0-beta.2 h1:1tCGWFOSaXIeuQaHrwOMJIYvlupjTcaVInGQw5ArULU=
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM= github.com/sagernet/quic-go v0.47.0-beta.2/go.mod h1:bLVKvElSEMNv7pu7SZHscW02TYigzQ5lQu3Nh4wNh8Q=
github.com/sagernet/quic-go v0.0.0-20231008035953-32727fef9460 h1:dAe4OIJAtE0nHOzTHhAReQteh3+sa63rvXbuIpbeOTY=
github.com/sagernet/quic-go v0.0.0-20231008035953-32727fef9460/go.mod h1:uJGpmJCOcMQqMlHKc3P1Vz6uygmpz4bPeVIoOhdVQnM=
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc= github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc=
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU= github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY= github.com/sagernet/sing v0.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo=
github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk= github.com/sagernet/sing v0.4.3 h1:Ty/NAiNnVd6844k7ujlL5lkzydhcTH5Psc432jXA4Y8=
github.com/sagernet/sing v0.2.14-0.20231011041941-e4d9384bcd84 h1:bPpV5QTOm6s9oJUCdfInImOgsWueoZWaJ7IpRkZuEsk= github.com/sagernet/sing v0.4.3/go.mod h1:ieZHA/+Y9YZfXs2I3WtuwgyCZ6GPsIR7HdKb1SdEnls=
github.com/sagernet/sing v0.2.14-0.20231011041941-e4d9384bcd84/go.mod h1:AhNEHu0GXrpqkuzvTwvC8+j2cQUU/dh+zLEmq4C99pg= github.com/sagernet/sing-dns v0.2.3 h1:YzeBUn2tR38F7HtvGEQ0kLRLmZWMEgi/+7wqa4Twb1k=
github.com/sagernet/sing-dns v0.1.10 h1:iIU7nRBlUYj+fF2TaktGIvRiTFFrHwSMedLQsvlTZCI= github.com/sagernet/sing-dns v0.2.3/go.mod h1:BJpJv6XLnrUbSyIntOT6DG9FW0f4fETmPAHvNjOprLg=
github.com/sagernet/sing-dns v0.1.10/go.mod h1:vtUimtf7Nq9EdvD5WTpfCr69KL1M7bcgOVKiYBiAY/c= github.com/sagernet/sing-mux v0.2.0 h1:4C+vd8HztJCWNYfufvgL49xaOoOHXty2+EAjnzN3IYo=
github.com/sagernet/sing-mux v0.1.3 h1:fAf7PZa2A55mCeh0KKM02f1k2Y4vEmxuZZ/51ahkkLA= github.com/sagernet/sing-mux v0.2.0/go.mod h1:khzr9AOPocLa+g53dBplwNDz4gdsyx/YM3swtAhlkHQ=
github.com/sagernet/sing-mux v0.1.3/go.mod h1:wGeIeiiFLx4HUM5LAg65wrNZ/X1muOimqK0PEhNbPi0= github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8=
github.com/sagernet/sing-quic v0.1.3-0.20231011042217-13b8d0b8f74b h1:u95u1icfN2Ya7FTkuWfyNrC4llMn8AYwD+ZsGkVWkac= github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE=
github.com/sagernet/sing-quic v0.1.3-0.20231011042217-13b8d0b8f74b/go.mod h1:1M7xP4802K9Kz6BQ7LlA7UeCapWvWlH1Htmk2bAqkWc= github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg=
github.com/sagernet/sing-shadowsocks v0.2.5 h1:qxIttos4xu6ii7MTVJYA8EFQR7Q3KG6xMqmLJIFtBaY= github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
github.com/sagernet/sing-shadowsocks v0.2.5/go.mod h1:MGWGkcU2xW2G2mfArT9/QqpVLOGU+dBaahZCtPHdt7A=
github.com/sagernet/sing-shadowsocks2 v0.1.4 h1:vht2M8t3m5DTgXR2j24KbYOygG5aOp+MUhpQnAux728=
github.com/sagernet/sing-shadowsocks2 v0.1.4/go.mod h1:Mgdee99NxxNd5Zld3ixIs18yVs4x2dI2VTDDE1N14Wc=
github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k= github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k=
github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4= github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4=
github.com/sagernet/sing-tun v0.1.16-0.20231006112722-19cc8b9e81aa h1:lQVFeYJ916CXunKB3JrsOQqCtT16OAitMXw8Z0lRNvY= github.com/sagernet/sing-tun v0.3.3 h1:LZnQNmfGcNG2KPTPkLgc+Lo7k606QJVkPp2DnjriwUk=
github.com/sagernet/sing-tun v0.1.16-0.20231006112722-19cc8b9e81aa/go.mod h1:d5kKDDW3I8Tr1OSWNaHXzrnsg1LbOx9sYVx83cHPhm8= github.com/sagernet/sing-tun v0.3.3/go.mod h1:DxLIyhjWU/HwGYoX0vNGg2c5QgTQIakphU1MuERR5tQ=
github.com/sagernet/sing-vmess v0.1.8 h1:XVWad1RpTy9b5tPxdm5MCU8cGfrTGdR8qCq6HV2aCNc= github.com/sagernet/sing-vmess v0.1.12 h1:2gFD8JJb+eTFMoa8FIVMnknEi+vCSfaiTXTfEYAYAPg=
github.com/sagernet/sing-vmess v0.1.8/go.mod h1:vhx32UNzTDUkNwOyIjcZQohre1CaytquC5mPplId8uA= github.com/sagernet/sing-vmess v0.1.12/go.mod h1:luTSsfyBGAc9VhtCqwjR+dt1QgqBhuYBCONB/POhF8I=
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as= github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37/go.mod h1:3skNSftZDJWTGVtVaM2jfbce8qHnmH/AGDRe62iNOg0= github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo=
github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6 h1:Px+hN4Vzgx+iCGVnWH5A8eR7JhNnIV3rGQmBxA7cw6Q= github.com/sagernet/utls v1.5.4 h1:KmsEGbB2dKUtCNC+44NwAdNAqnqQ6GA4pTO0Yik56co=
github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6/go.mod h1:zovq6vTvEM6ECiqE3Eeb9rpIylPpamPcmrJ9tv0Bt0M= github.com/sagernet/utls v1.5.4/go.mod h1:CTGxPWExIloRipK3XFpYv0OVyhO8kk3XCGW/ieyTh1s=
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 h1:kDUqhc9Vsk5HJuhfIATJ8oQwBmpOZJuozQG7Vk88lL4= github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8 h1:R0OMYAScomNAVpTfbHFpxqJpvwuhxSRi+g6z7gZhABs=
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2/go.mod h1:JKQMZq/O2qnZjdrt+B57olmfgEmLtY9iiSIEYtWvoSM= github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8/go.mod h1:K4J7/npM+VAMUeUmTa2JaA02JmyheP0GpRBOUvn3ecc=
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e h1:7uw2njHFGE+VpWamge6o56j2RWk4omF6uLKKxMmcWvs= github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 h1:6uUiZcDRnZSAegryaUGwPC/Fj13JSHwiTftrXhMmYOc=
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e/go.mod h1:45TUl8+gH4SIKr4ykREbxKWTxkDlSzFENzctB1dVRRY= github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854/go.mod h1:LtfoSK3+NG57tvnVEHgcuBW9ujgE8enPSgzgwStwCAA=
github.com/sagernet/wireguard-go v0.0.0-20230807125731-5d4a7ef2dc5f h1:Kvo8w8Y9lzFGB/7z09MJ3TR99TFtfI/IuY87Ygcycho=
github.com/sagernet/wireguard-go v0.0.0-20230807125731-5d4a7ef2dc5f/go.mod h1:mySs0abhpc/gLlvhoq7HP1RzOaRmIXVeZGCh++zoApk=
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 h1:rc/CcqLH3lh8n+csdOuDfP+NuykE0U6AeYSJJHKDgSg=
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9/go.mod h1:a/83NAfUXvEuLpmxDssAXxgUgrEy12MId3Wd7OTs76s=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@ -178,7 +168,7 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 h1:tHNk7XK9GkmKUR6Gh8gVBKXc2MVSZ4G/NnWLtzw4gNA= github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 h1:tHNk7XK9GkmKUR6Gh8gVBKXc2MVSZ4G/NnWLtzw4gNA=
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264= github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264=
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg= github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
@ -192,32 +182,32 @@ github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvv
github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go4.org/netipx v0.0.0-20230824141953-6213f710f925 h1:eeQDDVKFkx0g4Hyy8pHgmZaK0EqB4SD6rvKbUdN3ziQ= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
go4.org/netipx v0.0.0-20230824141953-6213f710f925/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20231005195138-3e424a577f31 h1:9k5exFQKQglLo+RoP+4zMjOFE14P6+vyR0baDAi0Rcs= golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY=
golang.org/x/exp v0.0.0-20231005195138-3e424a577f31/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -228,42 +218,42 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.16.0 h1:7eBu7KsSvFDtSXUIDbh3aqlK4DPsZ1rByC8PFfBThos= golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8= golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@ -272,8 +262,8 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -282,23 +272,21 @@ golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 h1:CawjfCvY
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6/go.mod h1:3rxYc4HtVcSG9gVaTs2GEBdehh+sYPOwKtyUWEOTb80= golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6/go.mod h1:3rxYc4HtVcSG9gVaTs2GEBdehh+sYPOwKtyUWEOTb80=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.58.2 h1:SXUpjxeVF3FKrTYQI4f4KvbGD5u2xccdYdurwowix5I= google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
@ -306,5 +294,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE=
lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=

View File

@ -4,7 +4,6 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"time"
"grpc_server" "grpc_server"
"grpc_server/gen" "grpc_server/gen"
@ -12,9 +11,9 @@ import (
"github.com/matsuridayo/libneko/neko_common" "github.com/matsuridayo/libneko/neko_common"
"github.com/matsuridayo/libneko/neko_log" "github.com/matsuridayo/libneko/neko_log"
"github.com/matsuridayo/libneko/speedtest" "github.com/matsuridayo/libneko/speedtest"
"github.com/matsuridayo/sing-box-extra/boxapi" box "github.com/sagernet/sing-box"
"github.com/matsuridayo/sing-box-extra/boxbox" "github.com/sagernet/sing-box/boxapi"
"github.com/matsuridayo/sing-box-extra/boxmain" boxmain "github.com/sagernet/sing-box/cmd/sing-box"
"log" "log"
@ -76,7 +75,8 @@ func (s *server) Stop(ctx context.Context, in *gen.EmptyReq) (out *gen.ErrorResp
return return
} }
instance.CloseWithTimeout(instance_cancel, time.Second*2, log.Println) instance_cancel()
instance.Close()
instance = nil instance = nil
@ -94,7 +94,7 @@ func (s *server) Test(ctx context.Context, in *gen.TestReq) (out *gen.TestResp,
}() }()
if in.Mode == gen.TestMode_UrlTest { if in.Mode == gen.TestMode_UrlTest {
var i *boxbox.Box var i *box.Box
var cancel context.CancelFunc var cancel context.CancelFunc
if in.Config != nil { if in.Config != nil {
// Test instance // Test instance
@ -114,7 +114,7 @@ func (s *server) Test(ctx context.Context, in *gen.TestReq) (out *gen.TestResp,
} }
} }
// Latency // Latency
out.Ms, err = speedtest.UrlTest(boxapi.CreateProxyHttpClient(i), in.Url, in.Timeout) out.Ms, err = speedtest.UrlTest(boxapi.CreateProxyHttpClient(i), in.Url, in.Timeout, speedtest.UrlTestStandard_RTT)
} else if in.Mode == gen.TestMode_TcpPing { } else if in.Mode == gen.TestMode_TcpPing {
out.Ms, err = speedtest.TcpPing(in.Address, in.Timeout) out.Ms, err = speedtest.TcpPing(in.Address, in.Timeout)
} else if in.Mode == gen.TestMode_FullTest { } else if in.Mode == gen.TestMode_FullTest {

View File

@ -8,13 +8,12 @@ import (
"grpc_server" "grpc_server"
"github.com/matsuridayo/libneko/neko_common" "github.com/matsuridayo/libneko/neko_common"
"github.com/matsuridayo/sing-box-extra/boxbox" boxmain "github.com/sagernet/sing-box/cmd/sing-box"
"github.com/matsuridayo/sing-box-extra/boxmain" "github.com/sagernet/sing-box/constant"
_ "github.com/matsuridayo/sing-box-extra/distro/all"
) )
func main() { func main() {
fmt.Println("sing-box-extra:", boxbox.Version, "NekoBox:", neko_common.Version_neko) fmt.Println("sing-box:", constant.Version, "NekoBox:", neko_common.Version_neko)
fmt.Println() fmt.Println()
// nekobox_core // nekobox_core

View File

@ -1,122 +0,0 @@
package main
import (
"context"
"fmt"
"log"
"net"
"net/http"
"os"
"time"
"github.com/matsuridayo/libneko/neko_common"
"github.com/matsuridayo/libneko/neko_log"
appLog "github.com/xtls/xray-core/app/log"
commonLog "github.com/xtls/xray-core/common/log"
v2rayNet "github.com/xtls/xray-core/common/net"
core "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/dns"
)
var instance *NekoV2RayInstance
var getNekorayTunIndex = func() int { return 0 } // Windows only
var underlyingNetDialer *net.Dialer
type v2rayLogWriter struct {
}
func (w *v2rayLogWriter) Write(s string) error {
log.Print(s)
return nil
}
func (w *v2rayLogWriter) Close() error {
return nil
}
func setupCore() {
// core setup
os.Setenv("v2ray.conf.geoloader", "memconservative")
neko_log.SetupLog(50*1024, "./neko.log")
_ = appLog.RegisterHandlerCreator(appLog.LogType_Console, func(lt appLog.LogType, options appLog.HandlerCreatorOptions) (commonLog.Handler, error) {
return commonLog.NewLogger(func() commonLog.Writer {
return &v2rayLogWriter{}
}), nil
})
// localdns setup
resolver_def := &net.Resolver{PreferGo: false}
resolver_go := &net.Resolver{PreferGo: true}
if underlyingNetDialer != nil && os.Getenv("NKR_CORE_RAY_DIRECT_DNS") == "1" {
resolver_def.Dial = underlyingNetDialer.DialContext
resolver_go.Dial = underlyingNetDialer.DialContext
log.Println("using NKR_CORE_RAY_DIRECT_DNS")
}
v2rayNet.LookupIP = func(host string) (ips []net.IP, err error) {
// fix old sekai
defer func() {
if len(ips) == 0 {
log.Println("LookupIP error:", host, err)
err = dns.ErrEmptyResponse
}
}()
// Normal mode use system resolver (go bug)
if getNekorayTunIndex() == 0 {
return resolver_def.LookupIP(context.Background(), "ip", host)
}
// Windows Tun Mode use Go resolver
return resolver_go.LookupIP(context.Background(), "ip", host)
}
neko_common.GetCurrentInstance = func() interface{} {
return instance
}
neko_common.DialContext = func(ctx context.Context, specifiedInstance interface{}, network, addr string) (net.Conn, error) {
dest, err := v2rayNet.ParseDestination(fmt.Sprintf("%s:%s", network, addr))
if err != nil {
return nil, err
}
if i, ok := specifiedInstance.(*NekoV2RayInstance); ok {
return core.Dial(ctx, i.Instance, dest)
}
if instance != nil {
return core.Dial(ctx, instance.Instance, dest)
}
return neko_common.DialContextSystem(ctx, network, addr)
}
neko_common.DialUDP = func(ctx context.Context, specifiedInstance interface{}) (net.PacketConn, error) {
if i, ok := specifiedInstance.(*NekoV2RayInstance); ok {
return core.DialUDP(ctx, i.Instance)
}
if instance != nil {
return core.DialUDP(ctx, instance.Instance)
}
return neko_common.DialUDPSystem(ctx)
}
neko_common.CreateProxyHttpClient = func(specifiedInstance interface{}) *http.Client {
if i, ok := specifiedInstance.(*NekoV2RayInstance); ok {
return createProxyHttpClient(i)
}
return createProxyHttpClient(instance)
}
}
// PROXY
func createProxyHttpClient(i *NekoV2RayInstance) *http.Client {
transport := &http.Transport{
TLSHandshakeTimeout: time.Second * 3,
ResponseHeaderTimeout: time.Second * 3,
}
if i != nil {
transport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
return neko_common.DialContext(ctx, i, network, addr)
}
}
client := &http.Client{
Transport: transport,
}
return client
}

View File

@ -1,74 +0,0 @@
module nekoray_core
go 1.21
toolchain go1.21.0
require (
github.com/jsimonetti/rtnetlink v1.2.2
github.com/matsuridayo/libneko v1.0.0 // replaced
github.com/xtls/xray-core v1.0.0 // replaced
grpc_server v1.0.0
kernel.org/pub/linux/libs/security/libcap/cap v1.2.65
)
require (
cloud.google.com/go/compute/metadata v0.2.3 // indirect
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
github.com/gaukas/godicttls v0.0.4 // indirect
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/pprof v0.0.0-20230821062121-407c9e7a662f // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
github.com/josharian/native v1.0.0 // indirect
github.com/klauspost/compress v1.16.7 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/mdlayher/netlink v1.6.0 // indirect
github.com/mdlayher/socket v0.1.1 // indirect
github.com/onsi/ginkgo/v2 v2.12.0 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pires/go-proxyproto v0.7.0 // indirect
github.com/quic-go/qtls-go1-20 v0.3.3 // indirect
github.com/quic-go/quic-go v0.38.1 // indirect
github.com/refraction-networking/utls v1.4.3 // indirect
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
github.com/sagernet/sing v0.2.9 // indirect
github.com/sagernet/sing-shadowsocks v0.2.4 // indirect
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c // indirect
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb // indirect
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e // indirect
github.com/xtls/reality v0.0.0-20230828171259-e426190d57f6 // indirect
go.uber.org/atomic v1.11.0 // indirect
go4.org/netipx v0.0.0-20230824141953-6213f710f925 // indirect
golang.org/x/crypto v0.12.0 // indirect
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.12.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/grpc v1.57.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gvisor.dev/gvisor v0.0.0-20230822212503-5bf4e5f98744 // indirect
kernel.org/pub/linux/libs/security/libcap/psx v1.2.65 // indirect
lukechampine.com/blake3 v1.2.1 // indirect
)
replace github.com/matsuridayo/libneko v1.0.0 => ../../../../libneko
replace grpc_server v1.0.0 => ../../grpc_server
replace github.com/xtls/xray-core => ../../../../Xray-core

View File

@ -1,394 +0,0 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.37.0 h1:69FNAINiZfsEuwH3fKq8QrAAnHz+2m4XL4kVYi5BX0Q=
cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo=
cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY=
cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE=
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU=
dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU=
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY=
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA=
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cilium/ebpf v0.9.1/go.mod h1:+OhNOIXx/Fnu1IE8bJz2dzOA+VSfyTfdNUVdlQnxUFY=
github.com/cilium/ebpf v0.9.3 h1:5KtxXZU+scyERvkJMEm16TbScVvuuMrlhPly78ZMbSc=
github.com/cilium/ebpf v0.9.3/go.mod h1:w27N4UjpaQ9X/DGrSugxUG+H+NhgntDuPb5lCzxCn8A=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 h1:y7y0Oa6UawqTFPCDw9JG6pdKt4F9pAhHv0B7FMGaGD0=
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk=
github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 h1:Arcl6UOIS/kgO2nW3A65HN+7CMjSDP/gofXL4CZt1V4=
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20230821062121-407c9e7a662f h1:pDhu5sgp8yJlEF/g6osliIIpF9K4F5jvkULXa4daRDQ=
github.com/google/pprof v0.0.0-20230821062121-407c9e7a662f/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
github.com/josharian/native v1.0.0 h1:Ts/E8zCSEsG17dUqv7joXJFybuMLjQfWE04tsBODTxk=
github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
github.com/jsimonetti/rtnetlink v1.2.2 h1:Ok9vYMcpxfHyF/iRqNTYJPDLxVaVItvPamAhtzttDBY=
github.com/jsimonetti/rtnetlink v1.2.2/go.mod h1:T3BJ2qI9ZJFkUYWLrzECdcXhCvaGRfnMFmoYF0X8w2A=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mdlayher/netlink v1.6.0 h1:rOHX5yl7qnlpiVkFWoqccueppMtXzeziFjWAjLg6sz0=
github.com/mdlayher/netlink v1.6.0/go.mod h1:0o3PlBmGst1xve7wQ7j/hwpNaFaH4qCRyWCdcZk8/vA=
github.com/mdlayher/socket v0.1.1 h1:q3uOGirUPfAV2MUoaC7BavjQ154J7+JOkTWyiV+intI=
github.com/mdlayher/socket v0.1.1/go.mod h1:mYV5YIZAfHh4dzDVzI8x8tWLWCliuX8Mon5Awbj+qDs=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo=
github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
github.com/onsi/ginkgo/v2 v2.12.0 h1:UIVDowFPwpg6yMUpPjGkYvf06K3RAiJXUhCxEwQVHRI=
github.com/onsi/ginkgo/v2 v2.12.0/go.mod h1:ZNEzXISYlqpb8S36iN71ifqLi3vVD1rVJGvWRCJOUpQ=
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pires/go-proxyproto v0.7.0 h1:IukmRewDQFWC7kfnb66CSomk2q/seBuilHBYFwyq0Hs=
github.com/pires/go-proxyproto v0.7.0/go.mod h1:Vz/1JPY/OACxWGQNIRY2BeyDmpoaWmEP40O9LbuiFR4=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/quic-go/qtls-go1-20 v0.3.3 h1:17/glZSLI9P9fDAeyCHBFSWSqJcwx1byhLwP5eUIDCM=
github.com/quic-go/qtls-go1-20 v0.3.3/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
github.com/quic-go/quic-go v0.38.1 h1:M36YWA5dEhEeT+slOu/SwMEucbYd0YFidxG3KlGPZaE=
github.com/quic-go/quic-go v0.38.1/go.mod h1:ijnZM7JsFIkp4cRyjxJNIzdSfCLmUMg9wdyhGmg+SN4=
github.com/refraction-networking/utls v1.4.3 h1:BdWS3BSzCwWCFfMIXP3mjLAyQkdmog7diaD/OqFbAzM=
github.com/refraction-networking/utls v1.4.3/go.mod h1:4u9V/awOSBrRw6+federGmVJQfPtemEqLBXkML1b0bo=
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/sagernet/sing v0.2.9 h1:3wsTz+JG5Wzy65eZnh6AuCrD2QqcRF6Iq6f7ttmJsAo=
github.com/sagernet/sing v0.2.9/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
github.com/sagernet/sing-shadowsocks v0.2.4 h1:s/CqXlvFAZhlIoHWUwPw5CoNnQ9Ibki9pckjuugtVfY=
github.com/sagernet/sing-shadowsocks v0.2.4/go.mod h1:80fNKP0wnqlu85GZXV1H1vDPC/2t+dQbFggOw4XuFUM=
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c h1:vK2wyt9aWYHHvNLWniwijBu/n4pySypiKRhN32u/JGo=
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c/go.mod h1:euOmN6O5kk9dQmgSS8Df4psAl3TCjxOz0NW60EWkSaI=
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U=
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw=
github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI=
github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU=
github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag=
github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg=
github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw=
github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y=
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q=
github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ=
github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I=
github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0=
github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ=
github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk=
github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF8gHIiADmOVOV5LS43gt3ONnlEl3xkwI=
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU=
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
github.com/xtls/reality v0.0.0-20230828171259-e426190d57f6 h1:T+YCYGfFdzyaKTDCdZn/hEiKvsw6yUfd+e4hze0rCUw=
github.com/xtls/reality v0.0.0-20230828171259-e426190d57f6/go.mod h1:rkuAY1S9F8eI8gDiPDYvACE8e2uwkyg8qoOTuwWov7Y=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
go4.org/netipx v0.0.0-20230824141953-6213f710f925 h1:eeQDDVKFkx0g4Hyy8pHgmZaK0EqB4SD6rvKbUdN3ziQ=
go4.org/netipx v0.0.0-20230824141953-6213f710f925/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090 h1:Di6/M8l0O2lCLc6VVRWhgCiApHV8MnQurBnFSHsQtNY=
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g=
golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4=
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss=
golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw=
google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
gvisor.dev/gvisor v0.0.0-20230822212503-5bf4e5f98744 h1:tE44CyJgxEGzoPtHs9GI7ddKdgEGCREQBP54AmaVM+I=
gvisor.dev/gvisor v0.0.0-20230822212503-5bf4e5f98744/go.mod h1:lYEMhXbxgudVhALYsMQrBaUAjM3NMinh8mKL1CJv7rc=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
kernel.org/pub/linux/libs/security/libcap/cap v1.2.65 h1:gIDtZoGnKeoIZ7XaKRmljMib4JV/TsjUhSzAeShNl6U=
kernel.org/pub/linux/libs/security/libcap/cap v1.2.65/go.mod h1:Fp9fDSuNh1vVDA7sozXklfQ+LxXMpB5/H4hDR8eu+0s=
kernel.org/pub/linux/libs/security/libcap/psx v1.2.65 h1:v2G3aCgEMr8qh4GpOGMukkv92EE7jtY+Uh9mB7cAACk=
kernel.org/pub/linux/libs/security/libcap/psx v1.2.65/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24=
lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI=
lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=

View File

@ -1,162 +0,0 @@
package main
import (
"context"
"errors"
"fmt"
"grpc_server"
"grpc_server/gen"
"log"
"github.com/matsuridayo/libneko/neko_common"
"github.com/matsuridayo/libneko/speedtest"
"github.com/xtls/xray-core/nekoutils"
)
type server struct {
grpc_server.BaseServer
}
func (s *server) Start(ctx context.Context, in *gen.LoadConfigReq) (out *gen.ErrorResp, _ error) {
var err error
defer func() {
out = &gen.ErrorResp{}
if err != nil {
out.Error = err.Error()
instance = nil
}
}()
if neko_common.Debug {
log.Println("Start:", in.CoreConfig)
log.Println("EnableNekorayConnections:", in.EnableNekorayConnections)
}
if instance != nil {
err = errors.New("instance already started")
return
}
instance, err = NewNekoV2rayInstance(in.CoreConfig)
if err != nil {
return
}
nekoutils.SetConnectionPoolV2RayEnabled(instance.CorePtr(), in.EnableNekorayConnections)
err = instance.Start()
if err != nil {
return
}
return
}
func (s *server) Stop(ctx context.Context, in *gen.EmptyReq) (out *gen.ErrorResp, _ error) {
var err error
defer func() {
out = &gen.ErrorResp{}
if err != nil {
out.Error = err.Error()
}
}()
if instance == nil {
return
}
err = instance.Close()
instance = nil
return
}
func (s *server) Test(ctx context.Context, in *gen.TestReq) (out *gen.TestResp, _ error) {
var err error
out = &gen.TestResp{Ms: 0}
defer func() {
if err != nil {
out.Error = err.Error()
}
}()
if neko_common.Debug {
log.Println("Test:", in)
}
if in.Mode == gen.TestMode_UrlTest {
var i *NekoV2RayInstance
if in.Config != nil {
// Test instance
i, err = NewNekoV2rayInstance(in.Config.CoreConfig)
if err != nil {
return
}
defer i.Close()
err = i.Start()
if err != nil {
return
}
} else {
// Test running instance
i = instance
if i == nil {
return
}
}
// Latency
var t int32
t, err = speedtest.UrlTest(createProxyHttpClient(i), in.Url, in.Timeout)
out.Ms = t // sn: ms==0 是错误
} else if in.Mode == gen.TestMode_TcpPing {
out.Ms, err = speedtest.TcpPing(in.Address, in.Timeout)
} else if in.Mode == gen.TestMode_FullTest {
if in.Config == nil {
return
}
// Test instance
i, err := NewNekoV2rayInstance(in.Config.CoreConfig)
if err != nil {
return
}
defer i.Close()
err = i.Start()
if err != nil {
return
}
return grpc_server.DoFullTest(ctx, in, i)
}
return
}
func (s *server) QueryStats(ctx context.Context, in *gen.QueryStatsReq) (out *gen.QueryStatsResp, _ error) {
out = &gen.QueryStatsResp{}
if instance != nil && instance.StatsManager != nil {
counter := instance.StatsManager.GetCounter(fmt.Sprintf("outbound>>>%s>>>traffic>>>%s", in.Tag, in.Direct))
if counter != nil {
out.Traffic = counter.Set(0)
}
}
return
}
func (s *server) ListConnections(ctx context.Context, in *gen.EmptyReq) (out *gen.ListConnectionsResp, _ error) {
// nekoray_connections_json
out = &gen.ListConnectionsResp{}
if instance != nil {
out.NekorayConnectionsJson = nekoutils.ListConnections(instance.CorePtr())
}
return
}

View File

@ -1,86 +0,0 @@
package main
import (
// The following are necessary as they register handlers in their init functions.
// Mandatory features. Can't remove unless there are replacements.
_ "github.com/xtls/xray-core/app/dispatcher"
_ "github.com/xtls/xray-core/app/proxyman/inbound"
_ "github.com/xtls/xray-core/app/proxyman/outbound"
// Default commander and all its services. This is an optional feature.
_ "github.com/xtls/xray-core/app/commander"
_ "github.com/xtls/xray-core/app/log/command"
_ "github.com/xtls/xray-core/app/proxyman/command"
_ "github.com/xtls/xray-core/app/stats/command"
// Developer preview services
_ "github.com/xtls/xray-core/app/observatory/command"
// Other optional features.
_ "github.com/xtls/xray-core/app/dns"
_ "github.com/xtls/xray-core/app/dns/fakedns"
_ "github.com/xtls/xray-core/app/log"
_ "github.com/xtls/xray-core/app/metrics"
_ "github.com/xtls/xray-core/app/policy"
_ "github.com/xtls/xray-core/app/reverse"
_ "github.com/xtls/xray-core/app/router"
_ "github.com/xtls/xray-core/app/stats"
// Fix dependency cycle caused by core import in internet package
_ "github.com/xtls/xray-core/transport/internet/tagged/taggedimpl"
// Developer preview features
_ "github.com/xtls/xray-core/app/observatory"
// Inbound and outbound proxies.
_ "github.com/xtls/xray-core/proxy/blackhole"
_ "github.com/xtls/xray-core/proxy/dns"
_ "github.com/xtls/xray-core/proxy/dokodemo"
_ "github.com/xtls/xray-core/proxy/freedom"
_ "github.com/xtls/xray-core/proxy/http"
_ "github.com/xtls/xray-core/proxy/loopback"
_ "github.com/xtls/xray-core/proxy/shadowsocks"
_ "github.com/xtls/xray-core/proxy/socks"
_ "github.com/xtls/xray-core/proxy/trojan"
_ "github.com/xtls/xray-core/proxy/vless/inbound"
_ "github.com/xtls/xray-core/proxy/vless/outbound"
_ "github.com/xtls/xray-core/proxy/vmess/inbound"
_ "github.com/xtls/xray-core/proxy/vmess/outbound"
_ "github.com/xtls/xray-core/proxy/wireguard"
// Transports
_ "github.com/xtls/xray-core/transport/internet/domainsocket"
_ "github.com/xtls/xray-core/transport/internet/grpc"
_ "github.com/xtls/xray-core/transport/internet/http"
_ "github.com/xtls/xray-core/transport/internet/kcp"
_ "github.com/xtls/xray-core/transport/internet/quic"
_ "github.com/xtls/xray-core/transport/internet/reality"
_ "github.com/xtls/xray-core/transport/internet/tcp"
_ "github.com/xtls/xray-core/transport/internet/tls"
_ "github.com/xtls/xray-core/transport/internet/udp"
_ "github.com/xtls/xray-core/transport/internet/websocket"
// Transport headers
_ "github.com/xtls/xray-core/transport/internet/headers/http"
_ "github.com/xtls/xray-core/transport/internet/headers/noop"
_ "github.com/xtls/xray-core/transport/internet/headers/srtp"
_ "github.com/xtls/xray-core/transport/internet/headers/tls"
_ "github.com/xtls/xray-core/transport/internet/headers/utp"
_ "github.com/xtls/xray-core/transport/internet/headers/wechat"
_ "github.com/xtls/xray-core/transport/internet/headers/wireguard"
// JSON & TOML & YAML
_ "github.com/xtls/xray-core/main/json"
// _ "github.com/xtls/xray-core/main/toml"
// _ "github.com/xtls/xray-core/main/yaml"
// Load config from file or http(s)
// _ "github.com/xtls/xray-core/main/confloader/external"
// Commands
// _ "github.com/xtls/xray-core/main/commands/all"
// Custom
_ "github.com/xtls/xray-core/proxy/shadowsocks/plugin/v2ray_plugin"
)

View File

@ -1,50 +0,0 @@
package main
import (
"log"
"strings"
core "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/stats"
"github.com/xtls/xray-core/nekoutils"
)
type NekoV2RayInstance struct {
*core.Instance
StatsManager stats.Manager
}
func NewNekoV2rayInstance(configStr string) (*NekoV2RayInstance, error) {
// load v4 or v5 config
var config *core.Config
var err error
config, err = core.LoadConfig("json", strings.NewReader(configStr))
if err != nil {
log.Println(configStr, err.Error())
return nil, err
}
c, err := core.New(config)
if err != nil {
return nil, err
}
instance := &NekoV2RayInstance{
Instance: c,
}
instance.StatsManager = c.GetFeature(stats.ManagerType()).(stats.Manager)
return instance, nil
}
func (i *NekoV2RayInstance) CorePtr() uintptr {
return 0
}
func (i *NekoV2RayInstance) Close() error {
nekoutils.ResetConnections(i.CorePtr())
nekoutils.SetConnectionPoolV2RayEnabled(i.CorePtr(), false)
return i.Instance.Close()
}

View File

@ -1,32 +0,0 @@
package main
import (
"fmt"
"grpc_server"
"os"
_ "unsafe"
"github.com/matsuridayo/libneko/neko_common"
)
//go:linkname build github.com/xtls/xray-core/core.build
var build string
func main() {
build = "Matsuridayo/nekoray"
fmt.Println("Xray:", neko_common.Version_v2ray, "NekoRay:", neko_common.Version_neko)
fmt.Println()
// nekoray_core
if len(os.Args) > 1 && os.Args[1] == "nekoray" {
neko_common.RunMode = neko_common.RunMode_NekoRay_Core
grpc_server.RunCore(setupCore, &server{})
return
}
// tool
if len(os.Args) > 1 && os.Args[1] == "tool" {
ToolBox()
return
}
}

View File

@ -1,194 +0,0 @@
package main
import (
"encoding/binary"
"log"
"net"
"os"
"strings"
"sync"
"syscall"
"unsafe"
"github.com/matsuridayo/libneko/iphlpapi"
"github.com/xtls/xray-core/transport/internet"
)
// https://docs.microsoft.com/en-us/windows/win32/api/ipmib/ns-ipmib-mib_ipforwardrow
var routes []iphlpapi.RouteRow
var interfaces []net.Interface
var lock sync.Mutex
func init() {
if os.Getenv("NKR_CORE_RAY_WINDOWS_DISABLE_AUTO_INTERFACE") == "1" {
log.Println("using NKR_CORE_RAY_WINDOWS_DISABLE_AUTO_INTERFACE")
} else {
initRoute()
}
//
getNekorayTunIndex = func() (index int) {
lock.Lock()
defer lock.Unlock()
for _, intf := range interfaces {
if intf.Name == "nekoray-tun" {
index = intf.Index
return
}
}
return
}
}
func initRoute() {
internet.RegisterListenerController(func(network, address string, conn syscall.RawConn) error {
var err error
conn.Control(func(fd uintptr) {
bindInterfaceIndex := getBindInterfaceIndex(address)
if bindInterfaceIndex != 0 {
if err = bindInterface(fd, bindInterfaceIndex, true, true); err != nil {
log.Println("bind inbound interface", network, address, err)
}
}
})
return err
})
internet.RegisterDialerController(func(network, address string, conn syscall.RawConn) error {
var err error
conn.Control(func(fd uintptr) {
bindInterfaceIndex := getBindInterfaceIndex(address)
if bindInterfaceIndex != 0 {
var v4, v6 bool
if strings.HasSuffix(network, "6") {
v4 = false
v6 = true
} else {
v4 = true
v6 = false
}
if err = bindInterface(fd, bindInterfaceIndex, v4, v6); err != nil {
log.Println("bind outbound interface", network, address, err)
}
}
})
return err
})
underlyingNetDialer = &net.Dialer{
Control: func(network, address string, c syscall.RawConn) error {
c.Control(func(fd uintptr) {
bindInterfaceIndex := getBindInterfaceIndex(address)
if bindInterfaceIndex != 0 {
var v4, v6 bool
if strings.HasSuffix(network, "6") {
v4 = false
v6 = true
} else {
v4 = true
v6 = false
}
if err := bindInterface(fd, bindInterfaceIndex, v4, v6); err != nil {
log.Println("underlyingNetDialer: bind interface", network, address, err)
}
}
})
return nil
},
}
//
updateRoutes()
iphlpapi.RegisterNotifyRouteChange2(func(callerContext uintptr, row uintptr, notificationType uint32) uintptr {
updateRoutes()
return 0
}, false)
}
func updateRoutes() {
lock.Lock()
defer lock.Unlock()
var err error
routes, err = iphlpapi.GetRoutes()
if err != nil {
log.Println("warning: GetRoutes failed", err)
}
interfaces, err = net.Interfaces()
if err != nil {
log.Println("warning: Interfaces failed", err)
}
}
func getBindInterfaceIndex(address string) uint32 {
host, _, _ := net.SplitHostPort(address)
if net.ParseIP(host).IsLoopback() {
return 0
}
lock.Lock()
defer lock.Unlock()
if interfaces == nil {
log.Println("warning: no interfaces info")
return 0
}
var nextInterface int
for i, intf := range interfaces {
if intf.Name == "nekoray-tun" {
if len(interfaces) > i+1 {
nextInterface = interfaces[i+1].Index
}
break
}
}
// Not in Tun Mode
if nextInterface == 0 {
return 0
}
if routes == nil {
log.Println("warning: no routes info")
return 0
}
for _, route := range routes {
// MIB_IPROUTE_TYPE_INDIRECT
if route.ForwardType == 4 {
// MIB_IPPROTO_NETMGMT
if route.ForwardProto == 3 {
if route.GetForwardMask().IsUnspecified() {
return route.ForwardIfIndex
}
}
}
}
// Default route not found
return uint32(nextInterface)
}
const (
IP_UNICAST_IF = 31 // nolint: golint,stylecheck
IPV6_UNICAST_IF = 31 // nolint: golint,stylecheck
)
func bindInterface(fd uintptr, interfaceIndex uint32, v4, v6 bool) error {
if v4 {
/* MSDN says for IPv4 this needs to be in net byte order, so that it's like an IP address with leading zeros. */
bytes := make([]byte, 4)
binary.BigEndian.PutUint32(bytes, interfaceIndex)
interfaceIndex_v4 := *(*uint32)(unsafe.Pointer(&bytes[0]))
if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_IP, IP_UNICAST_IF, int(interfaceIndex_v4)); err != nil {
return err
}
}
if v6 {
if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_IPV6, IPV6_UNICAST_IF, int(interfaceIndex)); err != nil {
return err
}
}
return nil
}

View File

@ -1,125 +0,0 @@
package main
import (
"fmt"
"log"
"net"
"strings"
"syscall"
"github.com/jsimonetti/rtnetlink"
"github.com/xtls/xray-core/transport/internet"
linuxcap "kernel.org/pub/linux/libs/security/libcap/cap"
)
var rtnetlink_conn *rtnetlink.Conn
var cap_net_admin = 0
func nekorayLinuxProtect(fd int) bool {
if cap_net_admin == 0 {
str := strings.ToLower(linuxcap.GetProc().String())
if strings.Contains(str, "cap_net_admin") || str == "=ep" {
cap_net_admin = 1
} else {
cap_net_admin = -1
}
}
// check is in Tun Mode
if is_fwmark_exist(514) {
if cap_net_admin == 1 {
// have permission
if err := syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_MARK, 514); err != nil {
log.Println("syscall.SetsockoptInt:", err)
return false
}
} else {
// don't have permission
if err := cmsgProtect(fd, "./protect"); err != nil {
log.Println("cmsgProtect:", err)
return false
}
}
}
return true
}
func cmsgProtect(fd int, unixPath string) error {
socket, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
if err != nil {
return err
}
defer syscall.Close(socket)
syscall.SetsockoptTimeval(socket, syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &syscall.Timeval{Sec: 3})
syscall.SetsockoptTimeval(socket, syscall.SOL_SOCKET, syscall.SO_SNDTIMEO, &syscall.Timeval{Sec: 3})
err = syscall.Connect(socket, &syscall.SockaddrUnix{Name: unixPath})
if err != nil {
return err
}
err = syscall.Sendmsg(socket, nil, syscall.UnixRights(fd), nil, 0)
if err != nil {
return err
}
dummy := []byte{1}
n, err := syscall.Read(socket, dummy)
if err != nil {
return err
}
if n != 1 {
return fmt.Errorf("cmsgProtect protect failed")
}
return nil
}
func is_fwmark_exist(number int) bool {
var err error
if rtnetlink_conn == nil {
rtnetlink_conn, err = rtnetlink.Dial(nil)
if err != nil {
log.Println(err)
}
return false
}
rules, err := rtnetlink_conn.Rule.List()
if err != nil {
rtnetlink_conn = nil
return false
}
for _, rule := range rules {
if rule.Attributes != nil && rule.Attributes.FwMark != nil && uint32(number) == *rule.Attributes.FwMark {
return true
}
}
return false
}
func init() {
internet.RegisterListenerController(func(network, address string, conn syscall.RawConn) error {
conn.Control(func(fd uintptr) {
nekorayLinuxProtect(int(fd))
})
return nil
})
internet.RegisterDialerController(func(network, address string, conn syscall.RawConn) error {
conn.Control(func(fd uintptr) {
nekorayLinuxProtect(int(fd))
})
return nil
})
underlyingNetDialer = &net.Dialer{
Control: func(network, address string, c syscall.RawConn) error {
c.Control(func(fd uintptr) {
nekorayLinuxProtect(int(fd))
})
return nil
},
}
}

View File

@ -1,91 +0,0 @@
package main
import (
"flag"
"io"
"log"
"net"
"net/http"
"os"
"syscall"
"github.com/jsimonetti/rtnetlink"
linuxcap "kernel.org/pub/linux/libs/security/libcap/cap"
)
func ToolBox() {
//
var protectListenPath string
var protectFwMark int
//
flag.StringVar(&protectListenPath, "protect-listen-path", "", "Set unix protect server listen path (Linux ROOT only)")
flag.IntVar(&protectFwMark, "protect-fwmark", 0, "Set unix protect fwmark (Linux ROOT only)")
flag.CommandLine.Parse(os.Args[3:])
//
switch os.Args[2] {
case "rule":
{
// Dial a connection to the rtnetlink socket
conn, err := rtnetlink.Dial(nil)
if err != nil {
log.Fatal(err)
}
defer conn.Close()
// Request a list of rules
rules, err := conn.Rule.List()
if err != nil {
log.Fatal(err)
}
for _, rule := range rules {
log.Printf("%+v", rule)
log.Printf("%+v", rule.Attributes)
}
for _, rule := range rules {
if rule.Attributes.FwMark != nil {
log.Printf("%+v", rule.Attributes)
log.Println(*rule.Attributes.FwMark, *rule.Attributes.Table)
}
}
}
case "cap":
{
set := linuxcap.GetProc()
if set != nil {
log.Println(set)
}
}
// case "protect":
// {
// if protectListenPath == "" {
// log.Println("missing protect-listen-path")
// return
// }
// protect_server.ServeProtect(protectListenPath, protectFwMark)
// }
case "btd": // Test the permission
{
d := &net.Dialer{
Control: func(network, address string, c syscall.RawConn) (err error) {
c.Control(func(fd uintptr) {
err = syscall.BindToDevice(int(fd), os.Args[3])
})
return
},
}
c := http.Client{
Transport: &http.Transport{
DialContext: d.DialContext,
},
}
resp, err := c.Get(os.Args[4])
if err != nil {
log.Fatalln(err)
}
io.Copy(os.Stdout, resp.Body)
resp.Body.Close()
}
}
}

View File

@ -1,6 +0,0 @@
//go:build !windows && !linux
package main
func ToolBox() {
}

View File

@ -1,27 +0,0 @@
package main
import (
"log"
"net"
"os"
)
func ToolBox() {
switch os.Args[2] {
case "if":
{
intfs, err := net.Interfaces()
if err != nil {
log.Fatalln(err)
}
for _, intf := range intfs {
log.Println(intf)
}
for _, route := range routes {
log.Println(route)
}
log.Println("TUN:", getNekorayTunIndex())
log.Println("Upstream:", getBindInterfaceIndex("8.8.8.8:8888"))
}
}
}

View File

@ -17,7 +17,7 @@ func Launcher() {
_debug := flag.Bool("debug", false, "Debug mode") _debug := flag.Bool("debug", false, "Debug mode")
flag.Parse() flag.Parse()
cmd := exec.Command("./nekoray", flag.Args()...) cmd := exec.Command("./nekobox", flag.Args()...)
ld_env := "LD_LIBRARY_PATH=" + filepath.Join(wd, "./usr/lib") ld_env := "LD_LIBRARY_PATH=" + filepath.Join(wd, "./usr/lib")
qt_plugin_env := "QT_PLUGIN_PATH=" + filepath.Join(wd, "./usr/plugins") qt_plugin_env := "QT_PLUGIN_PATH=" + filepath.Join(wd, "./usr/plugins")

View File

@ -30,9 +30,9 @@ func main() {
time.Sleep(time.Second) time.Sleep(time.Second)
Updater() Updater()
// 3. start // 3. start
exec.Command("./nekoray.exe").Start() exec.Command("./nekobox.exe").Start()
} else { } else {
// 1. nekoray stop it self and run "updater.exe" // 1. main prog quit and run "updater.exe"
Copy("./updater.exe", "./updater.old") Copy("./updater.exe", "./updater.old")
exec.Command("./updater.old", os.Args[1:]...).Start() exec.Command("./updater.old", os.Args[1:]...).Start()
} }
@ -43,7 +43,7 @@ func main() {
if os.Getenv("NKR_FROM_LAUNCHER") == "1" { if os.Getenv("NKR_FROM_LAUNCHER") == "1" {
Launcher() Launcher()
} else { } else {
exec.Command("./nekoray").Start() exec.Command("./nekobox").Start()
} }
} }
return return

View File

@ -71,6 +71,11 @@ func Updater() {
os.RemoveAll("./nekoray_update") os.RemoveAll("./nekoray_update")
os.RemoveAll("./nekoray.zip") os.RemoveAll("./nekoray.zip")
os.RemoveAll("./nekoray.tar.gz") os.RemoveAll("./nekoray.tar.gz")
// nekoray -> nekobox
os.Remove("./nekoray.exe")
os.Remove("./nekoray.png")
os.Remove("./nekoray_core.exe")
} }
func Exist(path string) bool { func Exist(path string) bool {

View File

@ -7,6 +7,7 @@ import (
"grpc_server/gen" "grpc_server/gen"
"io" "io"
"log" "log"
"math"
"net" "net"
"net/http" "net/http"
"strings" "strings"
@ -16,6 +17,11 @@ import (
"github.com/matsuridayo/libneko/speedtest" "github.com/matsuridayo/libneko/speedtest"
) )
const (
KiB = 1024
MiB = 1024 * KiB
)
func getBetweenStr(str, start, end string) string { func getBetweenStr(str, start, end string) string {
n := strings.Index(str, start) n := strings.Index(str, start)
if n == -1 { if n == -1 {
@ -37,7 +43,7 @@ func DoFullTest(ctx context.Context, in *gen.TestReq, instance interface{}) (out
// Latency // Latency
var latency string var latency string
if in.FullLatency { if in.FullLatency {
t, _ := speedtest.UrlTest(httpClient, in.Url, in.Timeout) t, _ := speedtest.UrlTest(httpClient, in.Url, in.Timeout, speedtest.UrlTestStandard_RTT)
out.Ms = t out.Ms = t
if t > 0 { if t > 0 {
latency = fmt.Sprint(t, "ms") latency = fmt.Sprint(t, "ms")
@ -124,11 +130,14 @@ func DoFullTest(ctx context.Context, in *gen.TestReq, instance interface{}) (out
if err == nil && resp != nil && resp.Body != nil { if err == nil && resp != nil && resp.Body != nil {
bodyClose = resp.Body bodyClose = resp.Body
defer resp.Body.Close() defer resp.Body.Close()
//
time_start := time.Now() timeStart := time.Now()
n, _ := io.Copy(io.Discard, resp.Body) n, _ := io.Copy(io.Discard, resp.Body)
time_end := time.Now() timeEnd := time.Now()
result <- fmt.Sprintf("%.2fMiB/s", (float64(n)/time_end.Sub(time_start).Seconds())/1048576)
duration := math.Max(timeEnd.Sub(timeStart).Seconds(), 0.000001)
resultSpeed := (float64(n) / duration) / MiB
result <- fmt.Sprintf("%.2fMiB/s", resultSpeed)
} else { } else {
result <- "Error" result <- "Error"
} }

View File

@ -94,10 +94,7 @@ func RunCore(setupCore func(), server gen.LibcoreServiceServer) {
) )
gen.RegisterLibcoreServiceServer(s, server) gen.RegisterLibcoreServiceServer(s, server)
name := "nekoray_core" name := "nekobox_core"
if neko_common.RunMode == neko_common.RunMode_NekoBox_Core {
name = "nekobox_core"
}
log.Printf("%s grpc server listening at %v\n", name, lis.Addr()) log.Printf("%s grpc server listening at %v\n", name, lis.Addr())
if err := s.Serve(lis); err != nil { if err := s.Serve(lis); err != nil {

View File

@ -53,10 +53,6 @@ func (s *BaseServer) Update(ctx context.Context, in *gen.UpdateReq) (*gen.Update
var search string var search string
if runtime.GOOS == "windows" && runtime.GOARCH == "amd64" { if runtime.GOOS == "windows" && runtime.GOARCH == "amd64" {
search = "windows64" search = "windows64"
// check Qt5 update after nekoray v3.3
if _, err := os.Stat("../Qt5Core.dll"); err == nil {
search = "windows7-x64"
}
} else if runtime.GOOS == "linux" && runtime.GOARCH == "amd64" { } else if runtime.GOOS == "linux" && runtime.GOARCH == "amd64" {
search = "linux64" search = "linux64"
} else if runtime.GOOS == "darwin" { } else if runtime.GOOS == "darwin" {

View File

@ -6,8 +6,6 @@ source libs/env_deploy.sh
[ "$GOOS" == "windows" ] && [ "$GOARCH" == "arm64" ] && DEST=$DEPLOYMENT/windows-arm64 || true [ "$GOOS" == "windows" ] && [ "$GOARCH" == "arm64" ] && DEST=$DEPLOYMENT/windows-arm64 || true
[ "$GOOS" == "linux" ] && [ "$GOARCH" == "amd64" ] && DEST=$DEPLOYMENT/linux64 || true [ "$GOOS" == "linux" ] && [ "$GOARCH" == "amd64" ] && DEST=$DEPLOYMENT/linux64 || true
[ "$GOOS" == "linux" ] && [ "$GOARCH" == "arm64" ] && DEST=$DEPLOYMENT/linux-arm64 || true [ "$GOOS" == "linux" ] && [ "$GOARCH" == "arm64" ] && DEST=$DEPLOYMENT/linux-arm64 || true
[ "$GOOS" == "darwin" ] && [ "$GOARCH" == "amd64" ] && DEST=$DEPLOYMENT/macos-amd64 || true
[ "$GOOS" == "darwin" ] && [ "$GOARCH" == "arm64" ] && DEST=$DEPLOYMENT/macos-arm64 || true
if [ -z $DEST ]; then if [ -z $DEST ]; then
echo "Please set GOOS GOARCH" echo "Please set GOOS GOARCH"
exit 1 exit 1
@ -23,16 +21,7 @@ pushd go/cmd/updater
[ "$GOOS" == "linux" ] && mv $DEST/updater $DEST/launcher || true [ "$GOOS" == "linux" ] && mv $DEST/updater $DEST/launcher || true
popd popd
#### Go: nekoray_core ####
neko_common="github.com/matsuridayo/libneko/neko_common"
pushd ../Xray-core
Version_Xray=$(git log --pretty=format:'%h' -n 1)
popd
pushd go/cmd/nekoray_core
go build -v -o $DEST -trimpath -ldflags "-w -s -X $neko_common.Version_v2ray=$Version_Xray -X $neko_common.Version_neko=$version_standalone"
popd
#### Go: nekobox_core #### #### Go: nekobox_core ####
pushd go/cmd/nekobox_core pushd go/cmd/nekobox_core
go build -v -o $DEST -trimpath -ldflags "-w -s -X $neko_common.Version_neko=$version_standalone" -tags "with_clash_api,with_gvisor,with_quic,with_wireguard,with_utls,with_ech" go build -v -o $DEST -trimpath -ldflags "-w -s -X github.com/matsuridayo/libneko/neko_common.Version_neko=$version_standalone" -tags "with_clash_api,with_gvisor,with_quic,with_wireguard,with_utls,with_ech"
popd popd

View File

@ -7,7 +7,7 @@ rm -rf $DEST
mkdir -p $DEST mkdir -p $DEST
#### copy binary #### #### copy binary ####
cp $BUILD/nekoray $DEST cp $BUILD/nekobox $DEST
#### Download: prebuilt runtime #### #### Download: prebuilt runtime ####
curl -Lso usr.zip https://github.com/MatsuriDayo/nekoray_qt_runtime/releases/download/20220503/20230202-5.12.8-ubuntu20.04-linux64.zip curl -Lso usr.zip https://github.com/MatsuriDayo/nekoray_qt_runtime/releases/download/20220503/20230202-5.12.8-ubuntu20.04-linux64.zip

View File

@ -1,29 +0,0 @@
#!/bin/bash
set -e
if [[ $(uname -m) == 'arm64' ]]; then
ARCH="arm64"
else
ARCH="amd64"
fi
source libs/env_deploy.sh
DEST=$DEPLOYMENT/macos-$ARCH
rm -rf $DEST
mkdir -p $DEST
#### copy golang & public_res => .app ####
pushd download-artifact
find . -name artifacts.tgz | xargs -n1 tar xvzf
mv deployment/public_res/* deployment/macos-$ARCH
mv deployment/macos-$ARCH/* $BUILD/nekoray.app/Contents/MacOS
popd
#### deploy qt & DLL runtime => .app ####
pushd $BUILD
macdeployqt nekoray.app -verbose=3
popd
#### pack dmg ###
sudo npm install -g appdmg
appdmg appdmg.json $DEST/nekoray.dmg

View File

@ -2,20 +2,16 @@
set -e set -e
source libs/env_deploy.sh source libs/env_deploy.sh
if [ "$DL_QT_VER" == "5.15" ]; then DEST=$DEPLOYMENT/windows64
DEST=$DEPLOYMENT/windows7-x64
else
DEST=$DEPLOYMENT/windows64
fi
rm -rf $DEST rm -rf $DEST
mkdir -p $DEST mkdir -p $DEST
#### copy exe #### #### copy exe ####
cp $BUILD/nekoray.exe $DEST cp $BUILD/nekobox.exe $DEST
#### deploy qt & DLL runtime #### #### deploy qt & DLL runtime ####
pushd $DEST pushd $DEST
windeployqt nekoray.exe --no-compiler-runtime --no-system-d3d-compiler --no-opengl-sw --verbose 2 windeployqt nekobox.exe --no-compiler-runtime --no-system-d3d-compiler --no-opengl-sw --verbose 2
rm -rf translations rm -rf translations
rm -rf libEGL.dll libGLESv2.dll Qt6Pdf.dll rm -rf libEGL.dll libGLESv2.dll Qt6Pdf.dll

View File

@ -3,7 +3,7 @@ cd qtsdk
if [ "$DL_QT_VER" == "5.15" ]; then if [ "$DL_QT_VER" == "5.15" ]; then
curl -LSO https://github.com/MatsuriDayo/nekoray_qt_runtime/releases/download/20220503/Qt5.15.7-Windows-x86_64-VS2019-16.11.20-20221103.7z curl -LSO https://github.com/MatsuriDayo/nekoray_qt_runtime/releases/download/20220503/Qt5.15.7-Windows-x86_64-VS2019-16.11.20-20221103.7z
else else
curl -LSO https://github.com/MatsuriDayo/nekoray_qt_runtime/releases/download/20220503/Qt6.5.2-Windows-x86_64-VS2022-17.6.5-20230803.7z curl -LSO https://github.com/MatsuriDayo/nekoray_qt_runtime/releases/download/20220503/Qt6.7.2-Windows-x86_64-VS2022-17.10.3-20240621.7z
fi fi
7z x *.7z 7z x *.7z
rm *.7z rm *.7z

View File

@ -1,4 +1,4 @@
SRC_ROOT="$PWD" SRC_ROOT="$PWD"
DEPLOYMENT="$SRC_ROOT/deployment" DEPLOYMENT="$SRC_ROOT/deployment"
BUILD="$SRC_ROOT/build" BUILD="$SRC_ROOT/build"
version_standalone="nekoray-"$(cat nekoray_version.txt) version_standalone="nekoray-"$(cat nekoray_version.txt) # 下次改

View File

@ -7,24 +7,35 @@ source libs/get_source_env.sh
pushd .. pushd ..
#### ####
if [ ! -d "sing-box-extra" ]; then
git clone --no-checkout https://github.com/MatsuriDayo/sing-box-extra.git
fi
pushd sing-box-extra
git checkout "$COMMIT_SING_BOX_EXTRA"
ENV_SING_BOX_EXTRA=1 if [ ! -d "sing-box" ]; then
source $SRC_ROOT/libs/get_source_env.sh git clone --no-checkout https://github.com/MatsuriDayo/sing-box.git
NO_ENV=1 ./libs/get_source.sh fi
pushd sing-box
git checkout "$COMMIT_SING_BOX"
popd popd
#### ####
if [ ! -d "Xray-core" ]; then
git clone --no-checkout https://github.com/MatsuriDayo/Xray-core.git if [ ! -d "sing-quic" ]; then
git clone --no-checkout https://github.com/MatsuriDayo/sing-quic.git
fi fi
pushd Xray-core pushd sing-quic
git checkout "$COMMIT_MATSURI_XRAY" git checkout "$COMMIT_SING_QUIC"
popd
popd
####
if [ ! -d "libneko" ]; then
git clone --no-checkout https://github.com/MatsuriDayo/libneko.git
fi
pushd libneko
git checkout "$COMMIT_LIBNEKO"
popd
####
popd popd

View File

@ -1,9 +1,3 @@
if [ ! -z $ENV_NEKORAY ]; then export COMMIT_SING_BOX="06557f6cef23160668122a17a818b378b5a216b5"
export COMMIT_SING_BOX_EXTRA="f95483a6bfe3894efdf917f4ccceac8c0aec1693" export COMMIT_SING_QUIC="b49ce60d9b3622d5238fee96bfd3c5f6e3915b42"
export COMMIT_MATSURI_XRAY="01208225ee7e508044cca8eb6776a117bcecd997" export COMMIT_LIBNEKO="1c47a3af71990a7b2192e03292b4d246c308ef0b"
fi
if [ ! -z $ENV_SING_BOX_EXTRA ]; then
source libs/get_source_env.sh
# export COMMIT_LIBNEKO="a26f0dbb1467bd181f76e2560e956633d9637e9d"
fi

View File

@ -2,37 +2,37 @@
sudo apt-get install fuse -y sudo apt-get install fuse -y
cp -r linux64 nekoray.AppDir cp -r linux64 nekobox.AppDir
# The file for Appimage # The file for Appimage
rm nekoray.AppDir/launcher rm nekobox.AppDir/launcher
cat >nekoray.AppDir/nekoray.desktop <<-EOF cat >nekobox.AppDir/nekobox.desktop <<-EOF
[Desktop Entry] [Desktop Entry]
Name=nekoray Name=nekobox
Exec=echo "NekoRay started" Exec=echo "nekobox started"
Icon=nekoray Icon=nekobox
Type=Application Type=Application
Categories=Network Categories=Network
EOF EOF
cat >nekoray.AppDir/AppRun <<-EOF cat >nekobox.AppDir/AppRun <<-EOF
#!/bin/bash #!/bin/bash
echo "PATH: \${PATH}" echo "PATH: \${PATH}"
echo "NekoRay runing on: \$APPDIR" echo "nekobox runing on: \$APPDIR"
LD_LIBRARY_PATH=\${APPDIR}/usr/lib QT_PLUGIN_PATH=\${APPDIR}/usr/plugins \${APPDIR}/nekoray -appdata "\$@" LD_LIBRARY_PATH=\${APPDIR}/usr/lib QT_PLUGIN_PATH=\${APPDIR}/usr/plugins \${APPDIR}/nekobox -appdata "\$@"
EOF EOF
chmod +x nekoray.AppDir/AppRun chmod +x nekobox.AppDir/AppRun
# build # build
curl -fLSO https://github.com/AppImage/AppImageKit/releases/latest/download/appimagetool-x86_64.AppImage curl -fLSO https://github.com/AppImage/AppImageKit/releases/latest/download/appimagetool-x86_64.AppImage
chmod +x appimagetool-x86_64.AppImage chmod +x appimagetool-x86_64.AppImage
./appimagetool-x86_64.AppImage nekoray.AppDir ./appimagetool-x86_64.AppImage nekobox.AppDir
# clean # clean
rm appimagetool-x86_64.AppImage rm appimagetool-x86_64.AppImage
rm -rf nekoray.AppDir rm -rf nekobox.AppDir

View File

@ -24,9 +24,9 @@ if [ ! -s /usr/share/applications/nekoray.desktop ]; then
cat >/usr/share/applications/nekoray.desktop<<-END cat >/usr/share/applications/nekoray.desktop<<-END
[Desktop Entry] [Desktop Entry]
Name=nekoray Name=nekoray
Comment=Qt based cross-platform GUI proxy configuration manager (backend: Xray / sing-box) Comment=Qt based cross-platform GUI proxy configuration manager (backend: sing-box)
Exec=sh -c "PATH=/opt/nekoray:\$PATH /opt/nekoray/nekoray -appdata" Exec=sh -c "PATH=/opt/nekoray:\$PATH /opt/nekoray/nekobox -appdata"
Icon=/opt/nekoray/nekoray.png Icon=/opt/nekoray/nekobox.png
Terminal=false Terminal=false
Type=Application Type=Application
Categories=Network;Application; Categories=Network;Application;

View File

@ -18,7 +18,7 @@ namespace NekoGui {
namespace CoreType { namespace CoreType {
enum CoreType { enum CoreType {
V2RAY, V2RAY, // DO NOT USE
SING_BOX, SING_BOX,
}; };
} }

View File

@ -18,7 +18,7 @@ namespace NekoGui_network {
if (NekoGui::dataStore->sub_use_proxy) { if (NekoGui::dataStore->sub_use_proxy) {
QNetworkProxy p; QNetworkProxy p;
// Note: sing-box mixed socks5 protocol error // Note: sing-box mixed socks5 protocol error
p.setType(IS_NEKO_BOX ? QNetworkProxy::HttpProxy : QNetworkProxy::Socks5Proxy); p.setType(QNetworkProxy::HttpProxy);
p.setHostName("127.0.0.1"); p.setHostName("127.0.0.1");
p.setPort(NekoGui::dataStore->inbound_socks_port); p.setPort(NekoGui::dataStore->inbound_socks_port);
if (NekoGui::dataStore->inbound_auth->NeedAuth()) { if (NekoGui::dataStore->inbound_auth->NeedAuth()) {
@ -51,7 +51,7 @@ namespace NekoGui_network {
for (const auto &err: errors) { for (const auto &err: errors) {
error_str << err.errorString(); error_str << err.errorString();
} }
MW_show_log(QString("SSL Errors: %1 %2").arg(error_str.join(","), NekoGui::dataStore->sub_insecure ? "(Ignored)" : "")); MW_show_log(QStringLiteral("SSL Errors: %1 %2").arg(error_str.join(","), NekoGui::dataStore->sub_insecure ? "(Ignored)" : ""));
}); });
// Wait for response // Wait for response
auto abortTimer = new QTimer; auto abortTimer = new QTimer;

View File

@ -237,7 +237,6 @@ namespace NekoGui {
_add(new configItem("current_group", &current_group, itemType::integer)); _add(new configItem("current_group", &current_group, itemType::integer));
_add(new configItem("inbound_address", &inbound_address, itemType::string)); _add(new configItem("inbound_address", &inbound_address, itemType::string));
_add(new configItem("inbound_socks_port", &inbound_socks_port, itemType::integer)); _add(new configItem("inbound_socks_port", &inbound_socks_port, itemType::integer));
_add(new configItem("inbound_http_port", &inbound_http_port, itemType::integer));
_add(new configItem("log_level", &log_level, itemType::string)); _add(new configItem("log_level", &log_level, itemType::string));
_add(new configItem("mux_protocol", &mux_protocol, itemType::string)); _add(new configItem("mux_protocol", &mux_protocol, itemType::string));
_add(new configItem("mux_concurrency", &mux_concurrency, itemType::integer)); _add(new configItem("mux_concurrency", &mux_concurrency, itemType::integer));
@ -248,7 +247,6 @@ namespace NekoGui {
_add(new configItem("theme", &theme, itemType::string)); _add(new configItem("theme", &theme, itemType::string));
_add(new configItem("custom_inbound", &custom_inbound, itemType::string)); _add(new configItem("custom_inbound", &custom_inbound, itemType::string));
_add(new configItem("custom_route", &custom_route_global, itemType::string)); _add(new configItem("custom_route", &custom_route_global, itemType::string));
_add(new configItem("v2ray_asset_dir", &v2ray_asset_dir, itemType::string));
_add(new configItem("sub_use_proxy", &sub_use_proxy, itemType::boolean)); _add(new configItem("sub_use_proxy", &sub_use_proxy, itemType::boolean));
_add(new configItem("remember_id", &remember_id, itemType::integer)); _add(new configItem("remember_id", &remember_id, itemType::integer));
_add(new configItem("remember_enable", &remember_enable, itemType::boolean)); _add(new configItem("remember_enable", &remember_enable, itemType::boolean));
@ -276,7 +274,6 @@ namespace NekoGui {
_add(new configItem("sub_clear", &sub_clear, itemType::boolean)); _add(new configItem("sub_clear", &sub_clear, itemType::boolean));
_add(new configItem("sub_insecure", &sub_insecure, itemType::boolean)); _add(new configItem("sub_insecure", &sub_insecure, itemType::boolean));
_add(new configItem("sub_auto_update", &sub_auto_update, itemType::integer)); _add(new configItem("sub_auto_update", &sub_auto_update, itemType::integer));
_add(new configItem("enable_js_hook", &enable_js_hook, itemType::integer));
_add(new configItem("log_ignore", &log_ignore, itemType::stringList)); _add(new configItem("log_ignore", &log_ignore, itemType::stringList));
_add(new configItem("start_minimal", &start_minimal, itemType::boolean)); _add(new configItem("start_minimal", &start_minimal, itemType::boolean));
_add(new configItem("max_log_line", &max_log_line, itemType::integer)); _add(new configItem("max_log_line", &max_log_line, itemType::integer));
@ -285,12 +282,7 @@ namespace NekoGui {
_add(new configItem("core_box_clash_api", &core_box_clash_api, itemType::integer)); _add(new configItem("core_box_clash_api", &core_box_clash_api, itemType::integer));
_add(new configItem("core_box_clash_api_secret", &core_box_clash_api_secret, itemType::string)); _add(new configItem("core_box_clash_api_secret", &core_box_clash_api_secret, itemType::string));
_add(new configItem("core_box_underlying_dns", &core_box_underlying_dns, itemType::string)); _add(new configItem("core_box_underlying_dns", &core_box_underlying_dns, itemType::string));
_add(new configItem("core_ray_direct_dns", &core_ray_direct_dns, itemType::boolean));
_add(new configItem("core_ray_freedom_domainStrategy", &core_ray_freedom_domainStrategy, itemType::string));
_add(new configItem("vpn_internal_tun", &vpn_internal_tun, itemType::boolean)); _add(new configItem("vpn_internal_tun", &vpn_internal_tun, itemType::boolean));
#ifdef Q_OS_WIN
_add(new configItem("core_ray_windows_disable_auto_interface", &core_ray_windows_disable_auto_interface, itemType::boolean));
#endif
} }
void DataStore::UpdateStartedId(int id) { void DataStore::UpdateStartedId(int id) {
@ -311,11 +303,7 @@ namespace NekoGui {
if (isDefault) { if (isDefault) {
QString version = SubStrBefore(NKR_VERSION, "-"); QString version = SubStrBefore(NKR_VERSION, "-");
if (!version.contains(".")) version = "2.0"; if (!version.contains(".")) version = "2.0";
if (IS_NEKO_BOX) { return "NekoBox/PC/" + version + " (Prefer ClashMeta Format)";
return "NekoBox/PC/" + version + " (Prefer ClashMeta Format)";
} else {
return "NekoRay/PC/" + version + " (Prefer ClashMeta Format)";
}
} }
return user_agent; return user_agent;
} }
@ -333,15 +321,11 @@ namespace NekoGui {
block_domain = block_domain =
"geosite:category-ads-all\n" "geosite:category-ads-all\n"
"domain:appcenter.ms\n" "domain:appcenter.ms\n"
"domain:app-measurement.com\n"
"domain:firebase.io\n" "domain:firebase.io\n"
"domain:crashlytics.com\n" "domain:crashlytics.com\n";
"domain:google-analytics.com";
}
if (IS_NEKO_BOX) {
if (!Preset::SingBox::DomainStrategy.contains(domain_strategy)) domain_strategy = "";
if (!Preset::SingBox::DomainStrategy.contains(outbound_domain_strategy)) outbound_domain_strategy = "";
} }
if (!Preset::SingBox::DomainStrategy.contains(domain_strategy)) domain_strategy = "";
if (!Preset::SingBox::DomainStrategy.contains(outbound_domain_strategy)) outbound_domain_strategy = "";
_add(new configItem("direct_ip", &this->direct_ip, itemType::string)); _add(new configItem("direct_ip", &this->direct_ip, itemType::string));
_add(new configItem("direct_domain", &this->direct_domain, itemType::string)); _add(new configItem("direct_domain", &this->direct_domain, itemType::string));
_add(new configItem("proxy_ip", &this->proxy_ip, itemType::string)); _add(new configItem("proxy_ip", &this->proxy_ip, itemType::string));
@ -365,7 +349,7 @@ namespace NekoGui {
} }
QString Routing::DisplayRouting() const { QString Routing::DisplayRouting() const {
return QString("[Proxy] %1\n[Proxy] %2\n[Direct] %3\n[Direct] %4\n[Block] %5\n[Block] %6\n[Default Outbound] %7\n[DNS] %8") return QStringLiteral("[Proxy] %1\n[Proxy] %2\n[Direct] %3\n[Direct] %4\n[Block] %5\n[Block] %6\n[Default Outbound] %7\n[DNS] %8")
.arg(SplitLinesSkipSharp(proxy_domain).join(","), 10) .arg(SplitLinesSkipSharp(proxy_domain).join(","), 10)
.arg(SplitLinesSkipSharp(proxy_ip).join(","), 10) .arg(SplitLinesSkipSharp(proxy_ip).join(","), 10)
.arg(SplitLinesSkipSharp(direct_domain).join(","), 10) .arg(SplitLinesSkipSharp(direct_domain).join(","), 10)
@ -431,16 +415,13 @@ namespace NekoGui {
// System Utils // System Utils
QString FindCoreAsset(const QString &name) { QString FindCoreAsset(const QString &name) {
QStringList search{NekoGui::dataStore->v2ray_asset_dir}; QStringList search{};
search << QApplication::applicationDirPath(); search << QApplication::applicationDirPath();
search << "/usr/share/sing-geoip"; search << "/usr/share/sing-geoip";
search << "/usr/share/sing-geosite"; search << "/usr/share/sing-geosite";
search << "/usr/share/xray"; search << "/usr/share/sing-box";
search << "/usr/local/share/xray"; search << "/usr/lib/nekobox";
search << "/opt/xray"; search << "/usr/share/nekobox";
search << "/usr/share/v2ray";
search << "/usr/local/share/v2ray";
search << "/opt/v2ray";
for (const auto &dir: search) { for (const auto &dir: search) {
if (dir.isEmpty()) continue; if (dir.isEmpty()) continue;
QFileInfo asset(dir + "/" + name); QFileInfo asset(dir + "/" + name);

View File

@ -8,7 +8,7 @@
// Switch core support // Switch core support
namespace NekoGui { namespace NekoGui {
inline int coreType = CoreType::V2RAY; inline int coreType = CoreType::SING_BOX;
QString FindCoreAsset(const QString &name); QString FindCoreAsset(const QString &name);
@ -17,7 +17,5 @@ namespace NekoGui {
bool IsAdmin(); bool IsAdmin();
} // namespace NekoGui } // namespace NekoGui
#define IS_NEKO_BOX (NekoGui::coreType == NekoGui::CoreType::SING_BOX) #define ROUTES_PREFIX_NAME QStringLiteral("routes_box")
#define IS_NEKO_BOX_INTERNAL_TUN (IS_NEKO_BOX && NekoGui::dataStore->vpn_internal_tun)
#define ROUTES_PREFIX_NAME QString(IS_NEKO_BOX ? "routes_box" : "routes")
#define ROUTES_PREFIX QString(ROUTES_PREFIX_NAME + "/") #define ROUTES_PREFIX QString(ROUTES_PREFIX_NAME + "/")

View File

@ -14,9 +14,9 @@ namespace NekoGui {
QString custom = "{\"rules\": []}"; QString custom = "{\"rules\": []}";
// DNS // DNS
QString remote_dns = "https://8.8.8.8/dns-query"; QString remote_dns = "https://dns.google/dns-query";
QString remote_dns_strategy = ""; QString remote_dns_strategy = "";
QString direct_dns = "localhost"; QString direct_dns = "https://doh.pub/dns-query";
QString direct_dns_strategy = ""; QString direct_dns_strategy = "";
bool dns_routing = true; bool dns_routing = true;
bool use_dns_object = false; bool use_dns_object = false;
@ -93,7 +93,7 @@ namespace NekoGui {
// Saved // Saved
// Misc // Misc
QString log_level = "warning"; QString log_level = "info";
QString test_latency_url = "http://cp.cloudflare.com/"; QString test_latency_url = "http://cp.cloudflare.com/";
QString test_download_url = "http://cachefly.cachefly.net/10mb.test"; QString test_download_url = "http://cachefly.cachefly.net/10mb.test";
int test_download_timeout = 30; int test_download_timeout = 30;
@ -102,12 +102,11 @@ namespace NekoGui {
int traffic_loop_interval = 1000; int traffic_loop_interval = 1000;
bool connection_statistics = false; bool connection_statistics = false;
int current_group = 0; // group id int current_group = 0; // group id
QString mux_protocol = ""; QString mux_protocol = "h2mux";
bool mux_padding = false; bool mux_padding = false;
int mux_concurrency = 8; int mux_concurrency = 8;
bool mux_default_on = false; bool mux_default_on = false;
QString theme = "0"; QString theme = "0";
QString v2ray_asset_dir = "";
int language = 0; int language = 0;
QString mw_size = ""; QString mw_size = "";
bool check_include_pre = false; bool check_include_pre = false;
@ -126,7 +125,6 @@ namespace NekoGui {
// Security // Security
bool skip_cert = false; bool skip_cert = false;
int enable_js_hook = 0;
QString utlsFingerprint = ""; QString utlsFingerprint = "";
// Remember // Remember
@ -137,7 +135,6 @@ namespace NekoGui {
// Socks & HTTP Inbound // Socks & HTTP Inbound
QString inbound_address = "127.0.0.1"; QString inbound_address = "127.0.0.1";
int inbound_socks_port = 2080; // or Mixed int inbound_socks_port = 2080; // or Mixed
int inbound_http_port = 2081;
InboundAuthorization *inbound_auth = new InboundAuthorization; InboundAuthorization *inbound_auth = new InboundAuthorization;
QString custom_inbound = "{\"inbounds\": []}"; QString custom_inbound = "{\"inbounds\": []}";
@ -167,9 +164,6 @@ namespace NekoGui {
int core_box_clash_api = -9090; int core_box_clash_api = -9090;
QString core_box_clash_api_secret = ""; QString core_box_clash_api_secret = "";
QString core_box_underlying_dns = ""; QString core_box_underlying_dns = "";
bool core_ray_direct_dns = false;
bool core_ray_windows_disable_auto_interface = false;
QString core_ray_freedom_domainStrategy = "";
// Other Core // Other Core
ExtraCore *extraCore = new ExtraCore; ExtraCore *extraCore = new ExtraCore;

View File

@ -8,8 +8,8 @@
// //
inline QString software_name = "NekoRay"; inline QString software_name = "NekoBox";
inline QString software_core_name = "Xray"; inline QString software_core_name = "sing-box";
// Main Functions // Main Functions

View File

@ -1,148 +0,0 @@
#include "QJS.hpp"
#ifdef _MSC_VER
#define JS_STRICT_NAN_BOXING
#endif
#include "3rdparty/qjs/nekoray_qjs.h"
#include "main/NekoGui.hpp"
namespace qjs {
#ifndef NKR_NO_QUICKJS
namespace exception {
static void js_dump_obj(JSContext *ctx, QString &out, JSValueConst val) {
const char *str;
str = JS_ToCString(ctx, val);
if (str) {
out.append(str);
out.append('\n');
JS_FreeCString(ctx, str);
} else {
out += "[exception]\n";
}
}
static void js_std_dump_error1(JSContext *ctx, QString &out, JSValueConst exception_val) {
JSValue val;
auto is_error = JS_IsError(ctx, exception_val);
js_dump_obj(ctx, out, exception_val);
if (is_error) {
val = JS_GetPropertyStr(ctx, exception_val, "stack");
if (!JS_IsUndefined(val)) {
js_dump_obj(ctx, out, val);
}
JS_FreeValue(ctx, val);
}
}
QString js_std_dump_error(JSContext *ctx) {
QString result;
JSValue exception_val;
exception_val = JS_GetException(ctx);
js_std_dump_error1(ctx, result, exception_val);
JS_FreeValue(ctx, exception_val);
return result;
}
} // namespace exception
JSValue func_log(JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
QString qString;
int i;
const char *str;
size_t len;
for (i = 0; i < argc; i++) {
if (i != 0) qString.append(' ');
str = JS_ToCStringLen(ctx, &len, argv[i]);
if (!str)
return JS_EXCEPTION;
qString.append(str);
JS_FreeCString(ctx, str);
}
MW_show_log(qString);
qDebug() << "func_log:" << qString;
return JS_UNDEFINED;
}
#endif
#define NEKO_CTX ((nekoray_qjs_context *) this->neko_ctx)
QJS::QJS() {
#ifndef NKR_NO_QUICKJS
MW_show_log("loading quickjs......");
//
this->neko_ctx = malloc(sizeof(nekoray_qjs_context));
nekoray_qjs_new_arg arg;
arg.neko_ctx = NEKO_CTX;
arg.enable_std = NekoGui::dataStore->enable_js_hook == 2 ? 1 : 0;
arg.func_log = func_log;
nekoray_qjs_new(arg);
#endif
}
QJS::QJS(const QByteArray &jsSource) : QJS() {
this->Eval(jsSource);
}
QJS::~QJS() {
#ifndef NKR_NO_QUICKJS
nekoray_qjs_free(NEKO_CTX);
free(this->neko_ctx);
#endif
}
QString QJS::Eval(const QByteArray &jsSource) const {
#ifndef NKR_NO_QUICKJS
auto result = nekoray_qjs_eval(NEKO_CTX, jsSource.data(), jsSource.length());
if (JS_IsException(result)) {
MW_show_log(exception::js_std_dump_error(NEKO_CTX->ctx));
return {};
}
auto cString = JS_ToCString(NEKO_CTX->ctx, result);
QString qString(cString);
JS_FreeCString(NEKO_CTX->ctx, cString);
JS_FreeValue(NEKO_CTX->ctx, result);
return qString;
#else
return {};
#endif
}
QString QJS::Eval(const QString &jsSource) const {
return this->Eval(jsSource.toUtf8());
}
QString QJS::EvalFile(const QString &jsPath) const {
return this->Eval(ReadFile(jsPath));
}
QString QJS::EvalFunction(const QString &funcName, const QString &arg) const {
#ifndef NKR_NO_QUICKJS
auto ba1 = arg.toUtf8();
JSValue globalObj = JS_GetGlobalObject(NEKO_CTX->ctx);
JSValue tempObj = JS_NewStringLen(NEKO_CTX->ctx, ba1.data(), ba1.length());
JS_SetPropertyStr(NEKO_CTX->ctx, globalObj, "tempObj", tempObj);
auto result = this->Eval(QString("%1(tempObj)").arg(funcName));
JS_DeleteProperty(NEKO_CTX->ctx, globalObj, JS_NewAtom(NEKO_CTX->ctx, "tempObj"), 1); // Free tempObj
JS_FreeValue(NEKO_CTX->ctx, globalObj);
return result;
#else
return {};
#endif
}
QByteArray ReadHookJS() {
#ifndef NKR_NO_QUICKJS
if (NekoGui::dataStore->enable_js_hook > 0) {
return ReadFile(QString("./hook.%1.js").arg(software_name.toLower()));
}
#endif
return {};
}
} // namespace qjs

View File

@ -1,23 +0,0 @@
#pragma once
class QByteArray;
class QString;
namespace qjs {
class QJS {
public:
QJS();
explicit QJS(const QByteArray &jsSource);
~QJS();
QString Eval(const QByteArray &jsSource) const;
QString Eval(const QString &jsSource) const;
QString EvalFile(const QString &jsPath) const;
QString EvalFunction(const QString &funcName, const QString &arg) const;
private:
void *neko_ctx;
};
QByteArray ReadHookJS();
} // namespace qjs

View File

@ -13,7 +13,6 @@
#include "main/NekoGui.hpp" #include "main/NekoGui.hpp"
#include "ui/mainwindow_interface.h" #include "ui/mainwindow_interface.h"
#include "ui/dialog_first_setup.h"
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
#include "sys/windows/MiniDump.h" #include "sys/windows/MiniDump.h"
@ -141,7 +140,7 @@ int main(int argc, char* argv[]) {
return 0; return 0;
} }
// Some Bad System // Some Bad System
QMessageBox::warning(nullptr, "NekoRay", "RunGuard disallow to run, use -many to force start."); QMessageBox::warning(nullptr, "NekoGui", "RunGuard disallow to run, use -many to force start.");
return 0; return 0;
} }
MF_release_runguard = [&] { guard.release(); }; MF_release_runguard = [&] { guard.release(); };
@ -149,7 +148,7 @@ int main(int argc, char* argv[]) {
// icons // icons
#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) #if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
QIcon::setFallbackSearchPaths(QStringList{ QIcon::setFallbackSearchPaths(QStringList{
":/nekoray", ":/neko",
":/icon", ":/icon",
}); });
#endif #endif
@ -159,28 +158,6 @@ int main(int argc, char* argv[]) {
QIcon::setThemeName("breeze"); QIcon::setThemeName("breeze");
} }
// Load coreType
auto coreLoaded = ReadFileText("groups/coreType");
if (coreLoaded.isEmpty()) {
NekoGui::coreType = -1;
loadTranslate(QLocale().name());
auto dialogFirstSetup = new DialogFirstSetup;
dialogFirstSetup->exec();
dialogFirstSetup->deleteLater();
if (NekoGui::coreType < 0) {
return 0;
} else {
QDir().mkdir("groups");
QFile file;
file.setFileName("groups/coreType");
file.open(QIODevice::ReadWrite | QIODevice::Truncate);
file.write(Int2String(NekoGui::coreType).toUtf8());
file.close();
}
} else {
NekoGui::coreType = coreLoaded.toInt();
}
// Dir // Dir
QDir dir; QDir dir;
bool dir_success = true; bool dir_success = true;
@ -200,9 +177,6 @@ int main(int argc, char* argv[]) {
// Load dataStore // Load dataStore
switch (NekoGui::coreType) { switch (NekoGui::coreType) {
case NekoGui::CoreType::V2RAY:
NekoGui::dataStore->fn = "groups/nekoray.json";
break;
case NekoGui::CoreType::SING_BOX: case NekoGui::CoreType::SING_BOX:
NekoGui::dataStore->fn = "groups/nekobox.json"; NekoGui::dataStore->fn = "groups/nekobox.json";
break; break;

View File

@ -1 +1 @@
3.23-2023-10-14 4.0.1-2024-12-12

View File

@ -1,38 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
<key>CFBundleGetInfoString</key>
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
<key>CFBundleIconFile</key>
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
<key>CFBundleIdentifier</key>
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLongVersionString</key>
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
<key>CFBundleName</key>
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSHighResolutionCapable</key>
<string>True</string>
</dict>
</plist>

View File

@ -4,7 +4,7 @@
<body> <body>
<h3> <h3>
<p>Please put your clash dashboard files to "nekoray/config/dashboard" dir.</p> <p>Please put your clash dashboard files to "./config/dashboard" dir.</p>
<p>For example, you can download from the following URL.</p> <p>For example, you can download from the following URL.</p>
<p> <p>
<a href="https://github.com/MetaCubeX/Yacd-meta/archive/refs/heads/gh-pages.zip">Download Yacd-meta</a> <a href="https://github.com/MetaCubeX/Yacd-meta/archive/refs/heads/gh-pages.zip">Download Yacd-meta</a>

View File

@ -16,7 +16,6 @@
</qresource> </qresource>
<qresource prefix="/neko"> <qresource prefix="/neko">
<file alias="nekobox.png">public/nekobox.png</file> <file alias="nekobox.png">public/nekobox.png</file>
<file alias="nekoray.png">public/nekoray.png</file>
<file>neko.css</file> <file>neko.css</file>
<file>vpn/vpn-run-root.sh</file> <file>vpn/vpn-run-root.sh</file>
<file>vpn/sing-box-vpn.json</file> <file>vpn/sing-box-vpn.json</file>

View File

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

View File

@ -12,7 +12,7 @@
{ {
"tag": "dns-remote", "tag": "dns-remote",
"address": "8.8.8.8", "address": "8.8.8.8",
"detour": "nekoray-socks" "detour": "neko-socks"
}, },
{ {
"tag": "dns-direct", "tag": "dns-direct",
@ -75,7 +75,7 @@
"outbounds": [ "outbounds": [
{ {
"type": "socks", "type": "socks",
"tag": "nekoray-socks", "tag": "neko-socks",
"udp_fragment": true, "udp_fragment": true,
//%SOCKS_USER_PASS% //%SOCKS_USER_PASS%
"server": "127.0.0.1", "server": "127.0.0.1",

View File

@ -6,40 +6,25 @@ if [ "$EUID" -ne 0 ]; then
echo "[Warning] Tun script not running as root" echo "[Warning] Tun script not running as root"
fi fi
if [ "$(uname)" == "Darwin" ]; then
IS_MACOS=1
fi
[ -z $TABLE_FWMARK ] && echo "Please set env TABLE_FWMARK" && exit
command -v pkill >/dev/null 2>&1 || echo "[Warning] pkill not found" command -v pkill >/dev/null 2>&1 || echo "[Warning] pkill not found"
BASEDIR=$(dirname "$0") BASEDIR=$(dirname "$0")
cd $BASEDIR cd $BASEDIR
pre_start_linux() { pre_start_linux() {
# set bypass: fwmark
ip rule add pref 8999 fwmark $TABLE_FWMARK table main || return
ip -6 rule add pref 8999 fwmark $TABLE_FWMARK table main || return
# for Tun2Socket # for Tun2Socket
iptables -I INPUT -s 172.19.0.2 -d 172.19.0.1 -p tcp -j ACCEPT iptables -I INPUT -s 172.19.0.2 -d 172.19.0.1 -p tcp -j ACCEPT
ip6tables -I INPUT -s fdfe:dcba:9876::2 -d fdfe:dcba:9876::1 -p tcp -j ACCEPT ip6tables -I INPUT -s fdfe:dcba:9876::2 -d fdfe:dcba:9876::1 -p tcp -j ACCEPT
} }
start() { start() {
[ -z $IS_MACOS ] && pre_start_linux pre_start_linux
"./nekobox_core" run -c "$CONFIG_PATH" --protect-listen-path "$PROTECT_LISTEN_PATH" --protect-fwmark $TABLE_FWMARK "./nekobox_core" run -c "$CONFIG_PATH"
} }
stop() { stop() {
[ -z $IS_MACOS ] || return
for local in $BYPASS_IPS; do
ip rule del to $local table main
done
iptables -D INPUT -s 172.19.0.2 -d 172.19.0.1 -p tcp -j ACCEPT iptables -D INPUT -s 172.19.0.2 -d 172.19.0.1 -p tcp -j ACCEPT
ip6tables -D INPUT -s fdfe:dcba:9876::2 -d fdfe:dcba:9876::1 -p tcp -j ACCEPT ip6tables -D INPUT -s fdfe:dcba:9876::2 -d fdfe:dcba:9876::1 -p tcp -j ACCEPT
ip rule del fwmark $TABLE_FWMARK
ip -6 rule del fwmark $TABLE_FWMARK
} }
if [ "$1" != "stop" ]; then if [ "$1" != "stop" ]; then

View File

@ -205,7 +205,7 @@ namespace NekoGui_rpc {
#define NOT_OK \ #define NOT_OK \
*rpcOK = false; \ *rpcOK = false; \
onError(QString("QNetworkReply::NetworkError code: %1\n").arg(status)); onError(QStringLiteral("QNetworkReply::NetworkError code: %1\n").arg(status));
void Client::Exit() { void Client::Exit() {
libcore::EmptyReq request; libcore::EmptyReq request;

View File

@ -1,7 +1,6 @@
#include "db/ProfileFilter.hpp" #include "db/ProfileFilter.hpp"
#include "fmt/includes.h" #include "fmt/includes.h"
#include "fmt/Preset.hpp" #include "fmt/Preset.hpp"
#include "main/QJS.hpp"
#include "main/HTTPRequestHelper.hpp" #include "main/HTTPRequestHelper.hpp"
#include "GroupUpdater.hpp" #include "GroupUpdater.hpp"
@ -123,14 +122,6 @@ namespace NekoGui_sub {
if (!ok) return; if (!ok) return;
} }
// Hysteria1
if (str.startsWith("hysteria://")) {
needFix = false;
ent = NekoGui::ProfileManager::NewProxyEntity("hysteria");
auto ok = ent->QUICBean()->TryParseLink(str);
if (!ok) return;
}
// Hysteria2 // Hysteria2
if (str.startsWith("hysteria2://") || str.startsWith("hy2://")) { if (str.startsWith("hysteria2://") || str.startsWith("hy2://")) {
needFix = false; needFix = false;
@ -201,7 +192,7 @@ namespace NekoGui_sub {
try { try {
return n.as<int>(); return n.as<int>();
} catch (const YAML::Exception &ex2) { } catch (const YAML::Exception &ex2) {
ex2.what(); qDebug() << ex2.what();
} }
qDebug() << ex.what(); qDebug() << ex.what();
return def; return def;
@ -414,41 +405,10 @@ namespace NekoGui_sub {
break; break;
} }
} }
} else if (type == "hysteria") {
auto bean = ent->QUICBean();
bean->hopPort = Node2QString(proxy["ports"]);
bean->allowInsecure = Node2Bool(proxy["skip-cert-verify"]);
auto alpn = Node2QStringList(proxy["alpn"]);
bean->caText = Node2QString(proxy["ca-str"]);
if (!alpn.isEmpty()) bean->alpn = alpn[0];
bean->sni = Node2QString(proxy["sni"]);
auto auth_str = FIRST_OR_SECOND(Node2QString(proxy["auth_str"]), Node2QString(proxy["auth-str"]));
auto auth = Node2QString(proxy["auth"]);
if (!auth_str.isEmpty()) {
bean->authPayloadType = NekoGui_fmt::QUICBean::hysteria_auth_string;
bean->authPayload = auth_str;
}
if (!auth.isEmpty()) {
bean->authPayloadType = NekoGui_fmt::QUICBean::hysteria_auth_base64;
bean->authPayload = auth;
}
bean->obfsPassword = Node2QString(proxy["obfs"]);
if (Node2Bool(proxy["disable_mtu_discovery"]) || Node2Bool(proxy["disable-mtu-discovery"])) bean->disableMtuDiscovery = true;
bean->streamReceiveWindow = Node2Int(proxy["recv-window"]);
bean->connectionReceiveWindow = Node2Int(proxy["recv-window-conn"]);
auto upMbps = Node2QString(proxy["up"]).split(" ")[0].toInt();
auto downMbps = Node2QString(proxy["down"]).split(" ")[0].toInt();
if (upMbps > 0) bean->uploadMbps = upMbps;
if (downMbps > 0) bean->downloadMbps = downMbps;
} else if (type == "hysteria2") { } else if (type == "hysteria2") {
auto bean = ent->QUICBean(); auto bean = ent->QUICBean();
// bean->hopPort = Node2QString(proxy["ports"]); bean->hopPort = Node2QString(proxy["ports"]);
bean->allowInsecure = Node2Bool(proxy["skip-cert-verify"]); bean->allowInsecure = Node2Bool(proxy["skip-cert-verify"]);
bean->caText = Node2QString(proxy["ca-str"]); bean->caText = Node2QString(proxy["ca-str"]);
@ -593,17 +553,6 @@ namespace NekoGui_sub {
} }
} }
// hook.js
auto source = qjs::ReadHookJS();
if (!source.isEmpty()) {
qjs::QJS js(source);
auto js_result = js.EvalFunction("hook.hook_import", content);
if (content != js_result) {
MW_show_log("hook.js modified your import content.");
content = js_result;
}
}
// 解析并添加 profile // 解析并添加 profile
rawUpdater->update(content); rawUpdater->update(content);

View File

@ -149,7 +149,7 @@ bool AutoRun_IsEnabled() {
#include <QProcessEnvironment> #include <QProcessEnvironment>
#include <QTextStream> #include <QTextStream>
#define NEWLINE "\r\n" #define NEWLINE "\n"
// launchatlogin.cpp // launchatlogin.cpp
// ShadowClash // ShadowClash

Some files were not shown because too many files have changed in this diff Show More