diff --git a/db/ConfigBuilder.cpp b/db/ConfigBuilder.cpp
index fc173c5..70f90c1 100644
--- a/db/ConfigBuilder.cpp
+++ b/db/ConfigBuilder.cpp
@@ -785,6 +785,7 @@ namespace NekoRay {
.replace("%PROCESS_NAME_RULE%", process_name_rule)
.replace("%CIDR_RULE%", cidr_rule)
.replace("%TUN_NAME%", tun_name)
+ .replace("%STRICT_ROUTE%", dataStore->vpn_strict_route ? "true" : "false")
.replace("%PORT%", Int2String(dataStore->inbound_socks_port));
// write config
QFile file;
diff --git a/examples/sing-box-vpn.json b/examples/sing-box-vpn.json
index 4c8e1fd..a787e6c 100644
--- a/examples/sing-box-vpn.json
+++ b/examples/sing-box-vpn.json
@@ -16,6 +16,7 @@
%IPV6_ADDRESS%
"mtu": %MTU%,
"auto_route": true,
+ "strict_route": %STRICT_ROUTE%,
"stack": "%STACK%",
"endpoint_independent_nat": true,
"sniff": false
diff --git a/fmt/Bean2CoreObj_box.cpp b/fmt/Bean2CoreObj_box.cpp
index 39450cf..0f00a50 100644
--- a/fmt/Bean2CoreObj_box.cpp
+++ b/fmt/Bean2CoreObj_box.cpp
@@ -36,6 +36,12 @@ namespace NekoRay::fmt {
if (!alpn.trimmed().isEmpty()) {
tls["alpn"] = QList2QJsonArray(alpn.split(","));
}
+ if (!utls.isEmpty()) {
+ tls["utls"] = QJsonObject{
+ {"enabled", true},
+ {"fingerprint", utls},
+ };
+ }
outbound->insert("tls", tls);
}
diff --git a/fmt/V2RayStreamSettings.hpp b/fmt/V2RayStreamSettings.hpp
index 23e5e2c..cde72bc 100644
--- a/fmt/V2RayStreamSettings.hpp
+++ b/fmt/V2RayStreamSettings.hpp
@@ -17,6 +17,7 @@ namespace NekoRay::fmt {
QString sni = "";
QString alpn = "";
QString certificate = "";
+ QString utls = "";
bool allow_insecure = false;
// ws early data
QString ws_early_data_name = "";
@@ -35,6 +36,7 @@ namespace NekoRay::fmt {
_add(new configItem("h_type", &header_type, itemType::string));
_add(new configItem("ed_name", &ws_early_data_name, itemType::string));
_add(new configItem("ed_len", &ws_early_data_length, itemType::integer));
+ _add(new configItem("utls", &utls, itemType::string));
}
QJsonObject BuildStreamSettingsV2Ray();
diff --git a/main/NekoRay.cpp b/main/NekoRay.cpp
index ec783f5..aeb06b8 100644
--- a/main/NekoRay.cpp
+++ b/main/NekoRay.cpp
@@ -54,7 +54,8 @@ namespace NekoRay {
_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));
- _add(new configItem("vpn_hide_console", &vpn_hide_consloe, itemType::boolean));
+ _add(new configItem("vpn_hide_console", &vpn_hide_console, itemType::boolean));
+ _add(new configItem("vpn_strict_route", &vpn_strict_route, itemType::boolean));
_add(new configItem("vpn_bypass_process", &vpn_bypass_process, itemType::string));
_add(new configItem("vpn_bypass_cidr", &vpn_bypass_cidr, itemType::string));
_add(new configItem("check_include_pre", &check_include_pre, itemType::boolean));
diff --git a/main/NekoRay_DataStore.hpp b/main/NekoRay_DataStore.hpp
index 8367be7..10c67e0 100644
--- a/main/NekoRay_DataStore.hpp
+++ b/main/NekoRay_DataStore.hpp
@@ -112,7 +112,8 @@ namespace NekoRay {
int vpn_implementation = 0;
int vpn_mtu = 9000;
bool vpn_ipv6 = false;
- bool vpn_hide_consloe = false;
+ bool vpn_hide_console = false;
+ bool vpn_strict_route = false;
QString vpn_bypass_process = "";
QString vpn_bypass_cidr = "";
diff --git a/translations/zh_CN.ts b/translations/zh_CN.ts
index e9860a8..f94873d 100644
--- a/translations/zh_CN.ts
+++ b/translations/zh_CN.ts
@@ -341,14 +341,6 @@
Already set
已设置
-
- Path
- 路径(Path)
-
-
- Host
- 主机(Host)
-
Packet Encoding
包编码
diff --git a/ui/dialog_basic_settings.ui b/ui/dialog_basic_settings.ui
index ce92c62..4df4177 100644
--- a/ui/dialog_basic_settings.ui
+++ b/ui/dialog_basic_settings.ui
@@ -598,33 +598,6 @@
-
- tabWidget
- socks_ip
- custom_inbound_edit
- inbound_socks_port
- inbound_http_port
- http_enable
- test_url
- test_concurrent
- log_level
- mux_cool_enable
- mux_cool
- check_include_pre
- theme
- language
- rfsh_r
- connection_statistics
- start_minimal
- user_agent
- sub_use_proxy
- core_v2ray_asset
- core_v2ray_asset_pick
- extra_core_add
- extra_core_del
- insecure_hint
- skip_cert
-
diff --git a/ui/dialog_vpn_settings.cpp b/ui/dialog_vpn_settings.cpp
index 62697f9..9717578 100644
--- a/ui/dialog_vpn_settings.cpp
+++ b/ui/dialog_vpn_settings.cpp
@@ -14,10 +14,11 @@ DialogVPNSettings::DialogVPNSettings(QWidget *parent) :
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);
- ui->hide_console->setChecked(NekoRay::dataStore->vpn_hide_consloe);
+ ui->hide_console->setChecked(NekoRay::dataStore->vpn_hide_console);
#ifndef Q_OS_WIN
ui->hide_console->setVisible(false);
#endif
+ ui->strict_route->setChecked(NekoRay::dataStore->vpn_strict_route);
//
D_LOAD_STRING(vpn_bypass_cidr)
D_LOAD_STRING(vpn_bypass_process)
@@ -35,7 +36,8 @@ void DialogVPNSettings::accept() {
NekoRay::dataStore->fake_dns = ui->fake_dns->isChecked();
NekoRay::dataStore->vpn_mtu = mtu;
NekoRay::dataStore->vpn_ipv6 = ui->vpn_ipv6->isChecked();
- NekoRay::dataStore->vpn_hide_consloe = ui->hide_console->isChecked();
+ NekoRay::dataStore->vpn_hide_console = ui->hide_console->isChecked();
+ NekoRay::dataStore->vpn_strict_route = ui->strict_route->isChecked();
//
D_SAVE_STRING_QTEXTEDIT(vpn_bypass_cidr)
D_SAVE_STRING_QTEXTEDIT(vpn_bypass_process)
diff --git a/ui/dialog_vpn_settings.ui b/ui/dialog_vpn_settings.ui
index c657517..16a7b86 100644
--- a/ui/dialog_vpn_settings.ui
+++ b/ui/dialog_vpn_settings.ui
@@ -107,6 +107,13 @@
+ -
+
+
+ Strict Route
+
+
+
@@ -147,15 +154,6 @@
-
- vpn_implementation
- vpn_mtu
- hide_console
- vpn_ipv6
- fake_dns
- vpn_bypass_cidr
- vpn_bypass_process
-
diff --git a/ui/edit/dialog_edit_profile.cpp b/ui/edit/dialog_edit_profile.cpp
index f77b807..88087d0 100644
--- a/ui/edit/dialog_edit_profile.cpp
+++ b/ui/edit/dialog_edit_profile.cpp
@@ -190,6 +190,7 @@ void DialogEditProfile::typeSelected(const QString &newType) {
ui->host->setText(stream->host);
ui->sni->setText(stream->sni);
ui->alpn->setText(stream->alpn);
+ ui->utls->setCurrentText(stream->utls);
ui->insecure->setChecked(stream->allow_insecure);
ui->header_type->setCurrentText(stream->header_type);
ui->ws_early_data_name->setText(stream->ws_early_data_name);
@@ -309,6 +310,7 @@ void DialogEditProfile::accept() {
stream->host = ui->host->text();
stream->sni = ui->sni->text();
stream->alpn = ui->alpn->text();
+ stream->utls = ui->utls->currentText();
stream->allow_insecure = ui->insecure->isChecked();
stream->header_type = ui->header_type->currentText();
stream->ws_early_data_name = ui->ws_early_data_name->text();
diff --git a/ui/edit/dialog_edit_profile.ui b/ui/edit/dialog_edit_profile.ui
index a8d681d..d0ed167 100644
--- a/ui/edit/dialog_edit_profile.ui
+++ b/ui/edit/dialog_edit_profile.ui
@@ -319,7 +319,7 @@ serviceName (gRPC)
key (QUIC)
- Path
+ Path
@@ -333,7 +333,7 @@ key (QUIC)
security (QUIC)
- Host
+ Host
@@ -346,10 +346,10 @@ security (QUIC)
- 伪装头部 (tcp/quic)
+ 伪装头部类型 (tcp/quic)
- headerType
+ header
@@ -415,14 +415,104 @@ security (QUIC)
-
-
-
- When enabled, V2Ray will not check the validity of the TLS certificate provided by the remote host (the security is equivalent to plaintext)
-
-
- Allow insecure
-
-
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ When enabled, V2Ray will not check the validity of the TLS certificate provided by the remote host (the security is equivalent to plaintext)
+
+
+ Allow insecure
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Currently only supported in sing-box core.
+
+
+ uTLS
+
+
+
+ -
+
+
+ true
+
+
-
+
+
+
+
+ -
+
+ chrome
+
+
+ -
+
+ firefox
+
+
+ -
+
+ edge
+
+
+ -
+
+ safari
+
+
+ -
+
+ 360
+
+
+ -
+
+ qq
+
+
+ -
+
+ ios
+
+
+ -
+
+ android
+
+
+ -
+
+ random
+
+
+
+
+
-
@@ -501,6 +591,7 @@ security (QUIC)
ws_early_data_length
ws_early_data_name
insecure
+ utls
sni
alpn
certificate_edit
diff --git a/ui/mainwindow.cpp b/ui/mainwindow.cpp
index b97ee60..2a24058 100644
--- a/ui/mainwindow.cpp
+++ b/ui/mainwindow.cpp
@@ -1469,7 +1469,7 @@ bool MainWindow::StartVPNProcess() {
WinCommander::runProcessElevated(QApplication::applicationDirPath() + "/nekobox_core.exe",
{"--disable-color", "run", "-c", configPath},
"",
- NekoRay::dataStore->vpn_hide_consloe
+ NekoRay::dataStore->vpn_hide_console
); // blocking
vpn_pid = 0;
runOnUiThread([=] {