From efdac7fa6f0b85f703545f795ab757fed870f64a Mon Sep 17 00:00:00 2001
From: arm64v8a <48624112+arm64v8a@users.noreply.github.com>
Date: Fri, 5 Aug 2022 17:07:32 +0800
Subject: [PATCH] vpn settings
---
examples/sing-box-vpn.json | 7 +-
examples/vpn-run-root.sh | 19 ++-
go/tun_linux.go | 2 +
main/NekoRay.cpp | 3 +
main/NekoRay_DataStore.hpp | 26 +--
translations/zh_CN.ts | 16 ++
ui/dialog_manage_routes.cpp | 42 ++++-
ui/dialog_manage_routes.ui | 318 ++++++++++++++++++++++++-----------
ui/edit/dialog_edit_group.ui | 6 -
ui/mainwindow.cpp | 16 +-
ui/mainwindow_grpc.cpp | 4 +-
11 files changed, 320 insertions(+), 139 deletions(-)
diff --git a/examples/sing-box-vpn.json b/examples/sing-box-vpn.json
index 20ee12f..ce3892f 100644
--- a/examples/sing-box-vpn.json
+++ b/examples/sing-box-vpn.json
@@ -1,14 +1,11 @@
{
- "dns": {
- "servers": [],
- "rules": [],
- "strategy": "ipv4_only"
- },
"inbounds": [
{
"type": "tun",
"interface_name": "nekoray-tun",
"inet4_address": "172.19.0.1/30",
+ %IPV6_ADDRESS%
+ "mtu": %MTU%,
"auto_route": true,
"sniff": false
}
diff --git a/examples/vpn-run-root.sh b/examples/vpn-run-root.sh
index dcb9033..2fcf8b2 100755
--- a/examples/vpn-run-root.sh
+++ b/examples/vpn-run-root.sh
@@ -11,6 +11,7 @@ fi
[ -z $TABLE_FWMARK ] && echo "Please set env TABLE_FWMARK" && exit
[ -z $TUN_NAME ] && echo "Please set env TUN_NAME" && exit
[ -z $USER_ID ] && echo "Please set env USER_ID" && exit
+[ -z $MTU ] && MTU=1500
command -v pkill >/dev/null 2>&1 || exit
BASEDIR=$(dirname "$0")
@@ -19,16 +20,22 @@ cd $BASEDIR
start() {
# add tun (TODO the ip must be the same as matsuri)
ip tuntap add $TUN_NAME mode tun user $USER_ID || return
- ip addr add 172.19.0.1/30 dev $TUN_NAME || return
+ ip link set dev nekoray-tun mtu $MTU || return
ip link set dev $TUN_NAME up || return
# set ipv4 rule
+ ip addr add 172.19.0.1/30 dev $TUN_NAME || return
ip rule add table $TABLE_FWMARK || return
ip route add table $TABLE_FWMARK default dev $TUN_NAME || return
- # set ipv6 unreachable
+ # set ipv6 rule
ip -6 rule add table $TABLE_FWMARK || return
- ip -6 route add table $TABLE_FWMARK unreachable default || return
+ if [ -z $ENABLE_IPV6 ]; then
+ ip -6 route add table $TABLE_FWMARK unreachable default || return
+ else
+ ip -6 addr add fdfe:dcba:9876::1/126 dev $TUN_NAME || return
+ ip -6 route add table $TABLE_FWMARK default dev $TUN_NAME || return
+ fi
# set bypass: fwmark
ip rule add fwmark $TABLE_FWMARK table main || return
@@ -39,6 +46,10 @@ start() {
ip rule add to $local table main
done
+ # for Tun2Socket
+ 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
+
if [ ! -z $USE_NEKORAY ]; then
"./nekoray_core" tool protect --protect-listen-path "$PROTECT_LISTEN_PATH" --protect-fwmark $TABLE_FWMARK
else
@@ -55,6 +66,8 @@ stop() {
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
+ ip6tables -D INPUT -s fdfe:dcba:9876::2 -d fdfe:dcba:9876::1 -p tcp -j ACCEPT
ip rule del table $TABLE_FWMARK
ip rule del fwmark $TABLE_FWMARK
ip route del table $TABLE_FWMARK default
diff --git a/go/tun_linux.go b/go/tun_linux.go
index c380957..d16f59d 100644
--- a/go/tun_linux.go
+++ b/go/tun_linux.go
@@ -3,6 +3,7 @@ package main
import (
"errors"
"libcore"
+ "libcore/comm"
"nekoray_core/gen"
"sync"
"syscall"
@@ -33,6 +34,7 @@ func TunStart(config *gen.SetTunReq) (err error) {
V2Ray: instance, // use current if started
Implementation: config.Implementation,
Sniffing: true,
+ IPv6Mode: comm.IPv6Prefer,
FakeDNS: config.Fakedns,
})
return
diff --git a/main/NekoRay.cpp b/main/NekoRay.cpp
index d5ac8d0..0f3e97e 100644
--- a/main/NekoRay.cpp
+++ b/main/NekoRay.cpp
@@ -50,6 +50,9 @@ namespace NekoRay {
_add(new configItem("active_routing", &active_routing, itemType::string));
_add(new configItem("mw_size", &mw_size, itemType::string));
_add(new configItem("conn_stat", &connection_statistics, itemType::boolean));
+ _add(new configItem("vpn_impl", &vpn_implementation, itemType::integer));
+ _add(new configItem("vpn_mtu", &vpn_mtu, itemType::integer));
+ _add(new configItem("vpn_ipv6", &vpn_ipv6, itemType::boolean));
}
void DataStore::UpdateStartedId(int id) {
diff --git a/main/NekoRay_DataStore.hpp b/main/NekoRay_DataStore.hpp
index d81addf..54e7949 100644
--- a/main/NekoRay_DataStore.hpp
+++ b/main/NekoRay_DataStore.hpp
@@ -42,6 +42,14 @@ namespace NekoRay {
int core_port = 19810;
int started_id = -1919;
+ Routing *routing = new Routing;
+ int imported_count = 0;
+ bool refreshing_group_list = false;
+
+ // Flags
+ bool flag_use_appdata = false;
+ bool flag_many = false;
+
// Saved
// Misc
@@ -91,6 +99,11 @@ namespace NekoRay {
QString custom_route_global = "{\"rules\": []}";
QString active_routing = "Default";
+ // VPN
+ int vpn_implementation = 0;
+ int vpn_mtu = 9000;
+ bool vpn_ipv6 = false;
+
// Hotkey
QString hotkey_mainwindow = "";
QString hotkey_group = "";
@@ -99,19 +112,6 @@ namespace NekoRay {
// Other Core
ExtraCore *extraCore = new ExtraCore;
- // Running Cache
-
- Routing *routing = new Routing;
- int imported_count = 0;
- bool refreshing_group_list = false;
-
- // Running Flags
-
- bool flag_use_appdata = false;
- bool flag_many = false;
-
- //
-
DataStore();
void UpdateStartedId(int id);
diff --git a/translations/zh_CN.ts b/translations/zh_CN.ts
index 6fb99ef..8f94e61 100644
--- a/translations/zh_CN.ts
+++ b/translations/zh_CN.ts
@@ -450,6 +450,14 @@
Custom (global)
自定义 (全局)
+
+ VPN Implementation
+ VPN 实现
+
+
+ VPN Enable IPv6
+ 启用 VPN IPv6
+
EditChain
@@ -1026,6 +1034,14 @@ End: %2
Enable VPN
启用 VPN
+
+ VPN settings changed
+ VPN 设置改变
+
+
+ Restart VPN to take effect.
+ 重启 VPN 生效。
+
ProxyItem
diff --git a/ui/dialog_manage_routes.cpp b/ui/dialog_manage_routes.cpp
index f53534f..5e1e24c 100644
--- a/ui/dialog_manage_routes.cpp
+++ b/ui/dialog_manage_routes.cpp
@@ -38,14 +38,22 @@ DialogManageRoutes::DialogManageRoutes(QWidget *parent) :
ui->dns_direct->setText(NekoRay::dataStore->direct_dns);
ui->enhance_resolve_server_domain->setChecked(NekoRay::dataStore->enhance_resolve_server_domain);
D_C_LOAD_STRING(custom_route_global)
-
+ //
+ ui->vpn_implementation->setCurrentIndex(NekoRay::dataStore->vpn_implementation);
+ ui->vpn_mtu->setCurrentText(Int2String(NekoRay::dataStore->vpn_mtu));
+ ui->vpn_ipv6->setChecked(NekoRay::dataStore->vpn_ipv6);
+#ifdef Q_OS_WIN
+ ui->vpn_implementation->setEditable(true);
+ ui->vpn_implementation->setCurrentText("Windows: sing-box gVisor");
+ ui->vpn_implementation->setDisabled(true);
+#endif
+ //
connect(ui->custom_route_edit, &QPushButton::clicked, this, [=] {
C_EDIT_JSON_ALLOW_EMPTY(custom_route)
});
connect(ui->custom_route_global_edit, &QPushButton::clicked, this, [=] {
C_EDIT_JSON_ALLOW_EMPTY(custom_route_global)
});
-
//
builtInSchemesMenu = new QMenu(this);
builtInSchemesMenu->addActions(this->getBuiltInSchemes());
@@ -81,19 +89,39 @@ void DialogManageRoutes::accept() {
NekoRay::dataStore->domain_strategy = ui->domainStrategyCombo->currentText();
NekoRay::dataStore->outbound_domain_strategy = ui->outbound_domain_strategy->currentText();
NekoRay::dataStore->dns_routing = ui->dns_routing->isChecked();
- NekoRay::dataStore->fake_dns = ui->fake_dns->isChecked();
NekoRay::dataStore->remote_dns = ui->dns_remote->text();
NekoRay::dataStore->direct_dns = ui->dns_direct->text();
NekoRay::dataStore->enhance_resolve_server_domain = ui->enhance_resolve_server_domain->isChecked();
D_C_SAVE_STRING(custom_route_global)
-
//
+ bool vpnChanged = false;
+ auto fakedns = ui->fake_dns->isChecked();
+ auto mtu = ui->vpn_mtu->currentText().toInt();
+ if (mtu > 10000 || mtu < 1000) mtu = 9000;
+ auto ipv6 = ui->vpn_ipv6->isChecked();
+#ifndef Q_OS_WIN
+ auto impl = ui->vpn_implementation->currentIndex();
+ vpnChanged |= NekoRay::dataStore->vpn_implementation != impl;
+ NekoRay::dataStore->vpn_implementation = impl;
+#endif
+ vpnChanged |= NekoRay::dataStore->fake_dns != fakedns;
+ vpnChanged |= NekoRay::dataStore->vpn_mtu != mtu;
+ vpnChanged |= NekoRay::dataStore->vpn_ipv6 != ipv6;
+ NekoRay::dataStore->fake_dns = fakedns;
+ NekoRay::dataStore->vpn_mtu = mtu;
+ NekoRay::dataStore->vpn_ipv6 = ipv6;
+ //
+ bool routeChanged = false;
+ if (NekoRay::dataStore->active_routing != active_routing) routeChanged = true;
SAVE_TO_ROUTING(NekoRay::dataStore->routing)
NekoRay::dataStore->active_routing = active_routing;
NekoRay::dataStore->routing->fn = "routes/" + NekoRay::dataStore->active_routing;
- NekoRay::dataStore->routing->Save();
-
- dialog_message(Dialog_DialogManageRoutes, "UpdateDataStore");
+ if (NekoRay::dataStore->routing->Save()) routeChanged = true;
+ //
+ QString info = "UpdateDataStore";
+ if (routeChanged) info += "RouteChanged";
+ if (vpnChanged) info += "VPNChanged";
+ dialog_message(Dialog_DialogManageRoutes, info);
QDialog::accept();
}
diff --git a/ui/dialog_manage_routes.ui b/ui/dialog_manage_routes.ui
index acc1acf..f3a3c1e 100644
--- a/ui/dialog_manage_routes.ui
+++ b/ui/dialog_manage_routes.ui
@@ -17,117 +17,227 @@
-
-
-
-
-
-
-
- Outbound Domain Strategy
-
-
-
- -
-
+
+
-
+
-
-
- Disable
-
-
- -
-
- The sniffing result is used for routing
-
-
- -
-
- The sniffing result is used for destination
-
-
-
-
- -
-
-
- Direct DNS
-
-
-
- -
-
-
- Sniffing Mode
-
-
-
- -
-
-
- Remote DNS
-
-
-
- -
-
-
- false
-
-
-
-
- AsIs
-
-
- -
-
- UseIP
-
-
- -
-
- UseIPv4
-
-
- -
-
- UseIPv6
-
-
- -
-
- PreferIPv4
-
-
- -
-
- PreferIPv6
-
-
-
-
- -
-
-
-
-
-
- -
-
-
- 使用多个境外 DNS 查询服务器地址,一定程度上可缓解对服务器域名的 DNS 污染,可能有副作用。
+
+
+
+ 0
+ 0
+
- 增强域名解析
+ Sniffing Mode
+
+
+
+ -
+
+
-
+
+ Disable
+
+
+ -
+
+ The sniffing result is used for routing
+
+
+ -
+
+ The sniffing result is used for destination
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Outbound Domain Strategy
+
+
+
+ -
+
+
+ false
+
+
-
+
+ AsIs
+
+
+ -
+
+ UseIP
+
+
+ -
+
+ UseIPv4
+
+
+ -
+
+ UseIPv6
+
+
+ -
+
+ PreferIPv4
+
+
+ -
+
+ PreferIPv6
+
+
+
+
+
+
+ -
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ VPN Implementation
+
+
+
+ -
+
+
-
+
+ gVisor
+
+
+ -
+
+ System NAT
+
+
+ -
+
+ Tun2Socket
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ MTU
+
+
+
+ -
+
+
+ true
+
+
-
+
+ 9000
+
+
+ -
+
+ 1500
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ VPN Enable IPv6
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ FakeDNS
- -
-
+
-
+
+
-
+
+
+ Remote DNS
+
+
+
-
-
-
+
- FakeDNS
+ Direct DNS
+
+
+
+ -
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ 使用多个境外 DNS 查询服务器地址,一定程度上可缓解对服务器域名的 DNS 污染,可能有副作用。
+
+
+ 增强域名解析
@@ -141,6 +251,12 @@
-
+
+
+ 0
+ 0
+
+
Enable DNS Routing
@@ -344,8 +460,10 @@
sniffing_mode
outbound_domain_strategy
- dns_remote
+ vpn_implementation
+ vpn_mtu
fake_dns
+ dns_remote
dns_direct
enhance_resolve_server_domain
dns_routing
@@ -353,6 +471,8 @@
domainMatcherCombo
preset
custom_route_edit
+ custom_route_global_edit
+ load_save
diff --git a/ui/edit/dialog_edit_group.ui b/ui/edit/dialog_edit_group.ui
index 8bd020a..d74d021 100644
--- a/ui/edit/dialog_edit_group.ui
+++ b/ui/edit/dialog_edit_group.ui
@@ -35,9 +35,6 @@
0
-
- 0
-
-
@@ -92,9 +89,6 @@
-
- 6
-
0
diff --git a/ui/mainwindow.cpp b/ui/mainwindow.cpp
index a74be5e..6be63eb 100644
--- a/ui/mainwindow.cpp
+++ b/ui/mainwindow.cpp
@@ -472,10 +472,13 @@ void MainWindow::show_group(int gid) {
void MainWindow::dialog_message_impl(const QString &sender, const QString &info) {
if (info.contains("UpdateDataStore")) {
auto changed = NekoRay::dataStore->Save();
+ if (info.contains("RouteChanged")) changed = true;
refresh_proxy_list();
- if (changed && NekoRay::dataStore->started_id >= 0 &&
- QMessageBox::question(this, tr("Confirmation"), tr("Settings changed, restart proxy?")
- ) == QMessageBox::StandardButton::Yes) {
+ if (info.contains("VPNChanged") && title_spmode == NekoRay::SystemProxyMode::VPN) {
+ MessageBoxWarning(tr("VPN settings changed"), tr("Restart VPN to take effect."));
+ } else if (changed && NekoRay::dataStore->started_id >= 0 &&
+ QMessageBox::question(this, tr("Confirmation"), tr("Settings changed, restart proxy?")
+ ) == QMessageBox::StandardButton::Yes) {
neko_start(NekoRay::dataStore->started_id);
}
refresh_status();
@@ -1336,7 +1339,10 @@ bool MainWindow::StartVPNProcess() {
#ifdef Q_OS_WIN
auto configFn = ":/nekoray/vpn/sing-box-vpn.json";
if (QFile::exists("vpn/sing-box-vpn.json")) configFn = "vpn/sing-box-vpn.json";
- auto config = ReadFileText(configFn).replace("%PORT%", Int2String(NekoRay::dataStore->inbound_socks_port));
+ auto config = ReadFileText(configFn)
+ .replace("%IPV6_ADDRESS%", NekoRay::dataStore->vpn_ipv6 ? "\"inet6_address\": \"fdfe:dcba:9876::1/128\"," : "")
+ .replace("%MTU%", Int2String(NekoRay::dataStore->vpn_mtu))
+ .replace("%PORT%", Int2String(NekoRay::dataStore->inbound_socks_port));
#else
auto protectPath = QDir::currentPath() + "/protect";
auto configFn = ":/nekoray/vpn/vpn-run-root.sh";
@@ -1344,11 +1350,13 @@ bool MainWindow::StartVPNProcess() {
auto config = ReadFileText(configFn)
.replace("$PORT", Int2String(NekoRay::dataStore->inbound_socks_port))
.replace("$USE_NEKORAY", "1")
+ .replace("$ENABLE_IPV6", NekoRay::dataStore->vpn_ipv6 ? "1" : "")
.replace("./nekoray_core", QApplication::applicationDirPath() + "/nekoray_core")
.replace("./tun2socks", QApplication::applicationDirPath() + "/tun2socks")
.replace("$PROTECT_LISTEN_PATH", protectPath)
.replace("$TUN_NAME", "nekoray-tun")
.replace("$USER_ID", Int2String((int) getuid()))
+ .replace("$MTU", Int2String(NekoRay::dataStore->vpn_mtu))
.replace("$TABLE_FWMARK", "514");
#endif
//
diff --git a/ui/mainwindow_grpc.cpp b/ui/mainwindow_grpc.cpp
index f57d3f1..19573ce 100644
--- a/ui/mainwindow_grpc.cpp
+++ b/ui/mainwindow_grpc.cpp
@@ -364,8 +364,8 @@ bool MainWindow::Tun2rayStartStop(bool start) {
if (start) {
libcore::SetTunReq req;
req.set_name("nekoray-tun");
- req.set_mtu(1500);
- req.set_implementation(0);
+ req.set_mtu(NekoRay::dataStore->vpn_mtu);
+ req.set_implementation(NekoRay::dataStore->vpn_implementation);
req.set_fakedns(NekoRay::dataStore->fake_dns);
auto error = defaultClient->SetTun(&ok, req);
if (!ok) return false;