refactor vpn mode

This commit is contained in:
arm64v8a
2023-05-01 20:28:14 +09:00
parent 79ef90f3bf
commit 50387db15e
24 changed files with 391 additions and 382 deletions

View File

@@ -48,7 +48,7 @@ Returns the return value of the executed command
uint WinCommander::runProcessElevated(const QString &path, uint WinCommander::runProcessElevated(const QString &path,
const QStringList &parameters, const QStringList &parameters,
const QString &workingDir, const QString &workingDir,
bool hide, bool aWait) { int nShow, bool aWait) {
uint result = 0; uint result = 0;
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
@@ -79,7 +79,7 @@ uint WinCommander::runProcessElevated(const QString &path,
shex.lpParameters = pszParameters; shex.lpParameters = pszParameters;
shex.lpDirectory = pszDirectory; shex.lpDirectory = pszDirectory;
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow
shex.nShow = hide ? SW_HIDE : SW_SHOWMINIMIZED; shex.nShow = nShow;
ShellExecuteEx(&shex); ShellExecuteEx(&shex);
if (shex.hProcess) if (shex.hProcess)

View File

@@ -28,10 +28,14 @@
class WinCommander { class WinCommander {
public: public:
static const int SW_HIDE = 0;
static const int SW_NORMAL = 1;
static const int SW_SHOWMINIMIZED = 2;
static uint runProcessElevated(const QString &path, static uint runProcessElevated(const QString &path,
const QStringList &parameters = QStringList(), const QStringList &parameters = QStringList(),
const QString &workingDir = QString(), const QString &workingDir = QString(),
bool hide = false, bool aWait = true); int nShow = SW_SHOWMINIMIZED, bool aWait = true);
}; };
#endif // WINCOMMANDER_H #endif // WINCOMMANDER_H

View File

@@ -40,6 +40,11 @@ QJsonObject JsonEditor::OpenEditor() {
auto string = jsonEditor->toPlainText(); auto string = jsonEditor->toPlainText();
while (resultCode == QDialog::Accepted && !VerifyJsonString(string).isEmpty()) { while (resultCode == QDialog::Accepted && !VerifyJsonString(string).isEmpty()) {
if (string.isEmpty()) {
resultCode = QDialog::Accepted;
final = {};
break;
}
QvMessageBoxWarn(this, tr("Json Contains Syntax Errors"), QvMessageBoxWarn(this, tr("Json Contains Syntax Errors"),
tr("You must correct these errors before continuing.")); tr("You must correct these errors before continuing."));
resultCode = this->exec(); resultCode = this->exec();

View File

@@ -13,6 +13,24 @@
namespace NekoRay { namespace NekoRay {
QStringList getAutoBypassExternalProcessPaths(const QSharedPointer<BuildConfigResult> &result) {
QStringList paths;
for (const auto &ext: result->exts) {
auto path = ext.first.program;
if (path.trimmed().isEmpty()) continue;
paths << path.replace("\\", "/");
}
return paths;
}
QString genTunName() {
auto tun_name = "nekoray-tun";
#ifdef Q_OS_MACOS
tun_name = "utun9";
#endif
return tun_name;
}
void MergeJson(const QJsonObject &custom, QJsonObject &outbound) { void MergeJson(const QJsonObject &custom, QJsonObject &outbound) {
// 合并 // 合并
if (custom.isEmpty()) return; if (custom.isEmpty()) return;
@@ -215,8 +233,8 @@ namespace NekoRay {
{"tag", "block"}, {"tag", "block"},
}; };
// DNS Routing // DNS out
if (dataStore->dns_routing && !status->forTest) { if (!status->forTest) {
QJsonObject dnsOut; QJsonObject dnsOut;
dnsOut["protocol"] = "dns"; dnsOut["protocol"] = "dns";
dnsOut["tag"] = "dns-out"; dnsOut["tag"] = "dns-out";
@@ -300,7 +318,7 @@ namespace NekoRay {
// Routing // Routing
QJsonObject routing; QJsonObject routing;
routing["domainStrategy"] = dataStore->domain_strategy; routing["domainStrategy"] = dataStore->domain_strategy;
routing["domainMatcher"] = dataStore->domain_matcher == DomainMatcher::MPH ? "mph" : "linear"; routing["domainMatcher"] = "mph";
if (status->forTest) routing["domainStrategy"] = "AsIs"; if (status->forTest) routing["domainStrategy"] = "AsIs";
// final add user rule (block) // final add user rule (block)
@@ -457,7 +475,12 @@ namespace NekoRay {
// chain rules: this // chain rules: this
auto ext_mapping_port = 0; auto ext_mapping_port = 0;
auto ext_socks_port = 0; auto ext_socks_port = 0;
auto thisExternalStat = ent->bean->NeedExternal(isFirstProfile, dataStore->running_spmode == SystemProxyMode::VPN); auto thisExternalStat = ent->bean->NeedExternal(isFirstProfile);
if (thisExternalStat < 0) {
status->result->error = "This configuration cannot be set automatically, please try another.";
return {};
}
// determine port // determine port
if (thisExternalStat > 0) { if (thisExternalStat > 0) {
if (ent->type == "custom") { if (ent->type == "custom") {
@@ -658,9 +681,28 @@ namespace NekoRay {
}, },
}; };
} }
// apply domain_strategy inboundObj["domain_strategy"] = dataStore->domain_strategy;
inboundObj["domain_strategy"] = dataStore->outbound_domain_strategy; status->inbounds += inboundObj;
// }
// tun-in
if (IS_NEKO_BOX_INTERNAL_TUN && dataStore->spmode_vpn) {
QJsonObject inboundObj;
inboundObj["tag"] = "tun-in";
inboundObj["type"] = "tun";
inboundObj["interface_name"] = genTunName();
inboundObj["auto_route"] = true;
inboundObj["endpoint_independent_nat"] = true;
inboundObj["mtu"] = dataStore->vpn_mtu;
inboundObj["stack"] = Preset::SingBox::VpnImplementation.value(dataStore->vpn_implementation);
inboundObj["strict_route"] = dataStore->vpn_strict_route;
inboundObj["inet4_address"] = "172.19.0.1/28";
if (dataStore->vpn_ipv6) inboundObj["inet4_address"] = "fdfe:dcba:9876::1/126";
if (dataStore->sniffing_mode != SniffingMode::DISABLE) {
inboundObj["sniff"] = true;
inboundObj["sniff_override_destination"] = dataStore->sniffing_mode == SniffingMode::FOR_DESTINATION;
}
inboundObj["domain_strategy"] = dataStore->domain_strategy;
status->inbounds += inboundObj; status->inbounds += inboundObj;
} }
@@ -805,7 +847,12 @@ namespace NekoRay {
// Routing // Routing
// dns hijack // dns hijack
if (!status->forTest) status->routingRules += QJsonObject{{"protocol", "dns"}, {"outbound", "dns-out"}}; if (!status->forTest) {
status->routingRules += QJsonObject{
{"protocol", "dns"},
{"outbound", "dns-out"},
};
}
// sing-box routing rule object // sing-box routing rule object
auto add_rule_route = [&](const QStringList &list, bool isIP, const QString &out) { auto add_rule_route = [&](const QStringList &list, bool isIP, const QString &out) {
@@ -823,6 +870,49 @@ namespace NekoRay {
add_rule_route(status->domainListRemote, false, tagProxy); add_rule_route(status->domainListRemote, false, tagProxy);
add_rule_route(status->domainListDirect, false, "bypass"); add_rule_route(status->domainListDirect, false, "bypass");
// built-in rules
status->routingRules += QJsonObject{
{"network", "udp"},
{"port", QJsonArray{135, 137, 138, 5353}},
{"outbound", "block"},
};
status->routingRules += QJsonObject{
{"ip_cidr", QJsonArray{"224.0.0.0/3", "ff00::/8"}},
{"outbound", "block"},
};
status->routingRules += QJsonObject{
{"source_ip_cidr", QJsonArray{"224.0.0.0/3", "ff00::/8"}},
{"outbound", "block"},
};
// tun user rule
if (IS_NEKO_BOX_INTERNAL_TUN && dataStore->spmode_vpn) {
auto match_out = NekoRay::dataStore->vpn_rule_white ? "proxy" : "bypass";
QString process_name_rule = dataStore->vpn_rule_process.trimmed();
if (!process_name_rule.isEmpty()) {
auto arr = SplitLinesSkipSharp(process_name_rule);
QJsonObject rule{{"outbound", match_out},
{"process_name", QList2QJsonArray(arr)}};
status->routingRules += rule;
}
QString cidr_rule = dataStore->vpn_rule_cidr.trimmed();
if (!cidr_rule.isEmpty()) {
auto arr = SplitLinesSkipSharp(cidr_rule);
QJsonObject rule{{"outbound", match_out},
{"ip_cidr", QList2QJsonArray(arr)}};
status->routingRules += rule;
}
auto autoBypassExternalProcessPaths = getAutoBypassExternalProcessPaths(status->result);
if (!autoBypassExternalProcessPaths.isEmpty()) {
QJsonObject rule{{"outbound", "bypass"},
{"process_name", QList2QJsonArray(autoBypassExternalProcessPaths)}};
status->routingRules += rule;
}
}
// geopath // geopath
auto geoip = FindCoreAsset("geoip.db"); auto geoip = FindCoreAsset("geoip.db");
auto geosite = FindCoreAsset("geosite.db"); auto geosite = FindCoreAsset("geosite.db");
@@ -836,7 +926,7 @@ namespace NekoRay {
QJSONARRAY_ADD(routingRules, status->routingRules) QJSONARRAY_ADD(routingRules, status->routingRules)
auto routeObj = QJsonObject{ auto routeObj = QJsonObject{
{"rules", routingRules}, {"rules", routingRules},
{"auto_detect_interface", NekoRay::dataStore->core_box_auto_detect_interface}, {"auto_detect_interface", dataStore->spmode_vpn},
{ {
"geoip", "geoip",
QJsonObject{ QJsonObject{
@@ -873,9 +963,10 @@ namespace NekoRay {
} }
QString WriteVPNSingBoxConfig() { QString WriteVPNSingBoxConfig() {
// tun user rule
auto match_out = NekoRay::dataStore->vpn_rule_white ? "nekoray-socks" : "direct"; auto match_out = NekoRay::dataStore->vpn_rule_white ? "nekoray-socks" : "direct";
auto no_match_out = NekoRay::dataStore->vpn_rule_white ? "direct" : "nekoray-socks"; auto no_match_out = NekoRay::dataStore->vpn_rule_white ? "direct" : "nekoray-socks";
// user rule
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()) {
auto arr = SplitLinesSkipSharp(process_name_rule); auto arr = SplitLinesSkipSharp(process_name_rule);
@@ -883,6 +974,7 @@ namespace NekoRay {
{"process_name", QList2QJsonArray(arr)}}; {"process_name", QList2QJsonArray(arr)}};
process_name_rule = "," + QJsonObject2QString(rule, false); process_name_rule = "," + QJsonObject2QString(rule, false);
} }
QString cidr_rule = dataStore->vpn_rule_cidr.trimmed(); QString cidr_rule = dataStore->vpn_rule_cidr.trimmed();
if (!cidr_rule.isEmpty()) { if (!cidr_rule.isEmpty()) {
auto arr = SplitLinesSkipSharp(cidr_rule); auto arr = SplitLinesSkipSharp(cidr_rule);
@@ -890,11 +982,9 @@ namespace NekoRay {
{"ip_cidr", QList2QJsonArray(arr)}}; {"ip_cidr", QList2QJsonArray(arr)}};
cidr_rule = "," + QJsonObject2QString(rule, false); cidr_rule = "," + QJsonObject2QString(rule, false);
} }
// tun name
auto tun_name = "nekoray-tun"; // TODO bypass ext core process path?
#ifdef Q_OS_MACOS
tun_name = "utun9";
#endif
// auth // auth
QString socks_user_pass; QString socks_user_pass;
if (dataStore->inbound_auth->NeedAuth()) { if (dataStore->inbound_auth->NeedAuth()) {
@@ -910,7 +1000,7 @@ namespace NekoRay {
.replace("%STACK%", Preset::SingBox::VpnImplementation.value(dataStore->vpn_implementation)) .replace("%STACK%", Preset::SingBox::VpnImplementation.value(dataStore->vpn_implementation))
.replace("%PROCESS_NAME_RULE%", process_name_rule) .replace("%PROCESS_NAME_RULE%", process_name_rule)
.replace("%CIDR_RULE%", cidr_rule) .replace("%CIDR_RULE%", cidr_rule)
.replace("%TUN_NAME%", tun_name) .replace("%TUN_NAME%", genTunName())
.replace("%STRICT_ROUTE%", dataStore->vpn_strict_route ? "true" : "false") .replace("%STRICT_ROUTE%", dataStore->vpn_strict_route ? "true" : "false")
.replace("%SOCKS_USER_PASS%", socks_user_pass) .replace("%SOCKS_USER_PASS%", socks_user_pass)
.replace("%FINAL_OUT%", no_match_out) .replace("%FINAL_OUT%", no_match_out)

View File

@@ -54,7 +54,7 @@ namespace NekoRay::fmt {
// //
virtual int NeedExternal(bool isFirstProfile, bool isVPN) { return 0; }; virtual int NeedExternal(bool isFirstProfile) { return 0; };
virtual CoreObjOutboundBuildResult BuildCoreObjV2Ray() { return {}; }; virtual CoreObjOutboundBuildResult BuildCoreObjV2Ray() { return {}; };

View File

@@ -20,38 +20,50 @@
auto TempFile = QFileInfo(f).absoluteFilePath(); auto TempFile = QFileInfo(f).absoluteFilePath();
namespace NekoRay::fmt { namespace NekoRay::fmt {
// -1: Cannot use this config
// 0: Internal // 0: Internal
// 1: Mapping External // 1: Mapping External
// 2: Direct External // 2: Direct External
int NaiveBean::NeedExternal(bool isFirstProfile, bool isVPN) { int NaiveBean::NeedExternal(bool isFirstProfile) {
if (isFirstProfile && !isVPN) { if (isFirstProfile) {
if (dataStore->spmode_vpn) {
return 1;
}
return 2; return 2;
} }
return 1; return 1;
} }
int HysteriaBean::NeedExternal(bool isFirstProfile, bool isVPN) { int HysteriaBean::NeedExternal(bool isFirstProfile) {
auto hysteriaCore = [=] {
if (isFirstProfile) {
if (dataStore->spmode_vpn && protocol != hysteria_protocol_facktcp && hopPort.trimmed().isEmpty()) {
return 1;
}
return 2;
} else {
if (protocol == hysteria_protocol_facktcp || !hopPort.trimmed().isEmpty()) {
return -1;
}
}
return 1;
};
if (IS_NEKO_BOX) { if (IS_NEKO_BOX) {
if (protocol == hysteria_protocol_udp && hopPort.trimmed().isEmpty()) { if (protocol == hysteria_protocol_udp && hopPort.trimmed().isEmpty()) {
// sing-box support // sing-box support
return 0; return 0;
} else { } else {
// hysteria core support // hysteria core support
if (isFirstProfile && !isVPN) { return hysteriaCore();
return 2;
}
return 1;
} }
} else { } else {
if (isFirstProfile && !isVPN) { return hysteriaCore();
return 2;
}
return 1;
} }
} }
int CustomBean::NeedExternal(bool isFirstProfile, bool isVPN) { int CustomBean::NeedExternal(bool isFirstProfile) {
if (core == "internal" || core == "internal-full") return 0; if (core == "internal" || core == "internal-full") return 0;
return 1; return 1;
} }
@@ -99,8 +111,8 @@ namespace NekoRay::fmt {
// determine server format // determine server format
auto is_direct = external_stat == 2; auto is_direct = external_stat == 2;
auto sni2 = sni; auto sniGen = sni;
if (sni.isEmpty() && is_direct) sni2 = serverAddress; if (sni.isEmpty() && !IsIpAddress(serverAddress)) sniGen = serverAddress;
auto server = serverAddress; auto server = serverAddress;
if (!hopPort.trimmed().isEmpty()) { if (!hopPort.trimmed().isEmpty()) {
@@ -130,7 +142,7 @@ namespace NekoRay::fmt {
if (protocol == hysteria_protocol_facktcp) config["protocol"] = "faketcp"; if (protocol == hysteria_protocol_facktcp) config["protocol"] = "faketcp";
if (protocol == hysteria_protocol_wechat_video) config["protocol"] = "wechat-video"; if (protocol == hysteria_protocol_wechat_video) config["protocol"] = "wechat-video";
if (!sni2.isEmpty()) config["server_name"] = sni2; if (!sniGen.isEmpty()) config["server_name"] = sniGen;
if (!alpn.isEmpty()) config["alpn"] = alpn; if (!alpn.isEmpty()) config["alpn"] = alpn;
if (!caText.trimmed().isEmpty()) { if (!caText.trimmed().isEmpty()) {

View File

@@ -31,7 +31,7 @@ namespace NekoRay::fmt {
return core; return core;
}; };
QString DisplayCoreType() override { return NeedExternal(false, false) ? core : software_core_name; }; QString DisplayCoreType() override { return NeedExternal(false) ? core : software_core_name; };
QString DisplayAddress() override { QString DisplayAddress() override {
if (core == "internal") { if (core == "internal") {
@@ -47,7 +47,7 @@ namespace NekoRay::fmt {
return AbstractBean::DisplayAddress(); return AbstractBean::DisplayAddress();
}; };
int NeedExternal(bool isFirstProfile, bool isVPN) override; int NeedExternal(bool isFirstProfile) override;
ExternalBuildResult BuildExternal(int mapping_port, int socks_port, int external_stat) override; ExternalBuildResult BuildExternal(int mapping_port, int socks_port, int external_stat) override;

View File

@@ -63,11 +63,11 @@ namespace NekoRay::fmt {
return ::DisplayAddress(serverAddress, serverPort); return ::DisplayAddress(serverAddress, serverPort);
} }
QString DisplayCoreType() override { return NeedExternal(false, false) == 0 ? software_core_name : "Hysteria"; }; QString DisplayCoreType() override { return NeedExternal(false) == 0 ? software_core_name : "Hysteria"; };
QString DisplayType() override { return "Hysteria"; }; QString DisplayType() override { return "Hysteria"; };
int NeedExternal(bool isFirstProfile, bool isVPN) override; int NeedExternal(bool isFirstProfile) override;
ExternalBuildResult BuildExternal(int mapping_port, int socks_port, int external_stat) override; ExternalBuildResult BuildExternal(int mapping_port, int socks_port, int external_stat) override;

View File

@@ -27,7 +27,7 @@ namespace NekoRay::fmt {
QString DisplayType() override { return "Naive"; }; QString DisplayType() override { return "Naive"; };
int NeedExternal(bool isFirstProfile, bool isVPN) override; int NeedExternal(bool isFirstProfile) override;
ExternalBuildResult BuildExternal(int mapping_port, int socks_port, int external_stat) override; ExternalBuildResult BuildExternal(int mapping_port, int socks_port, int external_stat) override;

View File

@@ -17,9 +17,6 @@ func main() {
fmt.Println("sing-box-extra:", boxbox.Version(), "NekoBox:", neko_common.Version_neko) fmt.Println("sing-box-extra:", boxbox.Version(), "NekoBox:", neko_common.Version_neko)
fmt.Println() fmt.Println()
// local DNS transport
_ = os.Setenv("GODEBUG", os.Getenv("GODEBUG")+",netdns=go")
// nekobox_core // nekobox_core
if len(os.Args) > 1 && os.Args[1] == "nekobox" { if len(os.Args) > 1 && os.Args[1] == "nekobox" {
neko_common.RunMode = neko_common.RunMode_NekoBox_Core neko_common.RunMode = neko_common.RunMode_NekoBox_Core

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
sudo apt install fuse -y sudo apt-get install fuse -y
cp -r linux64 nekoray.AppDir cp -r linux64 nekoray.AppDir
@@ -25,7 +25,7 @@ chmod +x nekoray.AppDir/AppRun
# build # build
curl -L -O 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 nekoray.AppDir

View File

@@ -16,14 +16,6 @@ namespace NekoRay {
}; };
} }
namespace SystemProxyMode {
enum SystemProxyMode {
DISABLE,
SYSTEM_PROXY,
VPN,
};
}
namespace CoreType { namespace CoreType {
enum CoreType { enum CoreType {
V2RAY, V2RAY,

View File

@@ -30,7 +30,6 @@ namespace NekoRay {
_add(new configItem("remote_dns_strategy", &remote_dns_strategy, itemType::string)); _add(new configItem("remote_dns_strategy", &remote_dns_strategy, itemType::string));
_add(new configItem("direct_dns", &direct_dns, itemType::string)); _add(new configItem("direct_dns", &direct_dns, itemType::string));
_add(new configItem("direct_dns_strategy", &direct_dns_strategy, itemType::string)); _add(new configItem("direct_dns_strategy", &direct_dns_strategy, itemType::string));
_add(new configItem("domain_matcher", &domain_matcher, itemType::integer));
_add(new configItem("domain_strategy", &domain_strategy, itemType::string)); _add(new configItem("domain_strategy", &domain_strategy, itemType::string));
_add(new configItem("outbound_domain_strategy", &outbound_domain_strategy, itemType::string)); _add(new configItem("outbound_domain_strategy", &outbound_domain_strategy, itemType::string));
_add(new configItem("sniffing_mode", &sniffing_mode, itemType::integer)); _add(new configItem("sniffing_mode", &sniffing_mode, itemType::integer));
@@ -46,7 +45,7 @@ namespace NekoRay {
_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));
_add(new configItem("language", &language, itemType::integer)); _add(new configItem("language", &language, itemType::integer));
_add(new configItem("spmode", &remember_spmode, itemType::integer)); _add(new configItem("spmode2", &remember_spmode, itemType::stringList));
_add(new configItem("skip_cert", &skip_cert, itemType::boolean)); _add(new configItem("skip_cert", &skip_cert, itemType::boolean));
_add(new configItem("hk_mw", &hotkey_mainwindow, itemType::string)); _add(new configItem("hk_mw", &hotkey_mainwindow, itemType::string));
_add(new configItem("hk_group", &hotkey_group, itemType::string)); _add(new configItem("hk_group", &hotkey_group, itemType::string));
@@ -74,14 +73,13 @@ namespace NekoRay {
_add(new configItem("max_log_line", &max_log_line, itemType::integer)); _add(new configItem("max_log_line", &max_log_line, itemType::integer));
_add(new configItem("splitter_state", &splitter_state, itemType::string)); _add(new configItem("splitter_state", &splitter_state, itemType::string));
_add(new configItem("utlsFingerprint", &utlsFingerprint, itemType::string)); _add(new configItem("utlsFingerprint", &utlsFingerprint, itemType::string));
_add(new configItem("core_box_auto_detect_interface", &core_box_auto_detect_interface, itemType::boolean));
_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_direct_dns", &core_ray_direct_dns, itemType::boolean));
#ifndef Q_OS_WIN _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)); _add(new configItem("core_ray_windows_disable_auto_interface", &core_ray_windows_disable_auto_interface, itemType::boolean));
_add(new configItem("vpn_already_admin", &vpn_already_admin, itemType::boolean));
#endif #endif
} }

View File

@@ -14,5 +14,6 @@ namespace NekoRay {
} // namespace NekoRay } // namespace NekoRay
#define IS_NEKO_BOX (NekoRay::coreType == NekoRay::CoreType::SING_BOX) #define IS_NEKO_BOX (NekoRay::coreType == NekoRay::CoreType::SING_BOX)
#define IS_NEKO_BOX_INTERNAL_TUN (IS_NEKO_BOX && NekoRay::dataStore->vpn_internal_tun)
#define ROUTES_PREFIX_NAME QString(IS_NEKO_BOX ? "routes_box" : "routes") #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

@@ -54,7 +54,8 @@ namespace NekoRay {
int started_id = -1919; int started_id = -1919;
bool core_running = false; bool core_running = false;
bool core_prepare_exit = false; bool core_prepare_exit = false;
int running_spmode = NekoRay::SystemProxyMode::DISABLE; bool spmode_vpn = false;
bool spmode_system_proxy = false;
bool need_keep_vpn_off = false; bool need_keep_vpn_off = false;
QStringList ignoreConnTag = {}; QStringList ignoreConnTag = {};
@@ -104,7 +105,7 @@ namespace NekoRay {
QString utlsFingerprint = ""; QString utlsFingerprint = "";
// Remember // Remember
int remember_spmode = NekoRay::SystemProxyMode::DISABLE; QStringList remember_spmode = {};
int remember_id = -1919; int remember_id = -1919;
bool remember_enable = false; bool remember_enable = false;
@@ -127,18 +128,17 @@ namespace NekoRay {
QString domain_strategy = "AsIs"; QString domain_strategy = "AsIs";
QString outbound_domain_strategy = "AsIs"; QString outbound_domain_strategy = "AsIs";
int sniffing_mode = SniffingMode::FOR_ROUTING; int sniffing_mode = SniffingMode::FOR_ROUTING;
int domain_matcher = DomainMatcher::MPH;
QString custom_route_global = "{\"rules\": []}"; QString custom_route_global = "{\"rules\": []}";
QString active_routing = "Default"; QString active_routing = "Default";
// VPN // VPN
bool vpn_internal_tun = true;
int vpn_implementation = 0; int vpn_implementation = 0;
int vpn_mtu = 9000; int vpn_mtu = 9000;
bool vpn_ipv6 = false; bool vpn_ipv6 = false;
bool vpn_hide_console = false; bool vpn_hide_console = false;
bool vpn_strict_route = false; bool vpn_strict_route = false;
bool vpn_rule_white = false; bool vpn_rule_white = false;
bool vpn_already_admin = false; // not saved on Windows
QString vpn_rule_process = ""; QString vpn_rule_process = "";
QString vpn_rule_cidr = ""; QString vpn_rule_cidr = "";
@@ -149,7 +149,6 @@ namespace NekoRay {
QString hotkey_system_proxy_menu = ""; QString hotkey_system_proxy_menu = "";
// Core // Core
bool core_box_auto_detect_interface = true;
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 = "";

View File

@@ -91,19 +91,11 @@
<source>Use proxy when updating subscription</source> <source>Use proxy when updating subscription</source>
<translation>استفاده از پروکسی زمانی که اشتراک را بروزرسانی می کنید</translation> <translation>استفاده از پروکسی زمانی که اشتراک را بروزرسانی می کنید</translation>
</message> </message>
<message>
<source>Language</source>
<translation type="vanished">زبان</translation>
</message>
<message> <message>
<source>Security</source> <source>Security</source>
<translatorcomment>امنیت security</translatorcomment> <translatorcomment>امنیت security</translatorcomment>
<translation>امنیت</translation> <translation>امنیت</translation>
</message> </message>
<message>
<source>Insecure hint</source>
<translation type="vanished">اشاره ناامن</translation>
</message>
<message> <message>
<source>Statistics refresh rate</source> <source>Statistics refresh rate</source>
<translation>نرخ تازه سازی آمار ترافیک</translation> <translation>نرخ تازه سازی آمار ترافیک</translation>
@@ -357,10 +349,6 @@ For NekoBox, this rewrites the underlying(localhost) DNS in VPN mode, normal mod
<source>Network Settings (%1)</source> <source>Network Settings (%1)</source>
<translation>تنظیمات شبکه (1%)</translation> <translation>تنظیمات شبکه (1%)</translation>
</message> </message>
<message>
<source>Security Settings</source>
<translation type="vanished">تنظیمات امنیت</translation>
</message>
<message> <message>
<source>When enabled, V2Ray will not check the validity of the TLS certificate provided by the remote host (the security is equivalent to plaintext)</source> <source>When enabled, V2Ray will not check the validity of the TLS certificate provided by the remote host (the security is equivalent to plaintext)</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@@ -503,14 +491,6 @@ These settings can be changed later.</source>
<source>Disable</source> <source>Disable</source>
<translation>غیرفعال کردن</translation> <translation>غیرفعال کردن</translation>
</message> </message>
<message>
<source>The sniffing result is used for routing</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>The sniffing result is used for destination</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Remote DNS</source> <source>Remote DNS</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@@ -523,14 +503,6 @@ These settings can be changed later.</source>
<source>Enable DNS Routing</source> <source>Enable DNS Routing</source>
<translation>فعال کردن مسیریابی DNS</translation> <translation>فعال کردن مسیریابی DNS</translation>
</message> </message>
<message>
<source>V2Ray Domain Strategy</source>
<translation>استراتژی دامنه</translation>
</message>
<message>
<source>Matcher</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Block</source> <source>Block</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@@ -607,16 +579,28 @@ These settings can be changed later.</source>
<source>Default Outbound</source> <source>Default Outbound</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Query Strategy</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Remote</source> <source>Remote</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<source>Inbound &amp; Outbound Domain Strategy</source> <source>DNS Query Strategy</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Domain Strategy</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Server Address Strategy</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sniff result for routing</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Sniff result for destination</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
@@ -682,11 +666,12 @@ https://matsuridayo.github.io/n-configuration/#vpn-tun</source>
<translation type="unfinished">لغو کردن</translation> <translation type="unfinished">لغو کردن</translation>
</message> </message>
<message> <message>
<source>Don&apos;t ask for privilege elevation</source> <source>Internal Tun</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<source>Already Admin</source> <source>Add a tun inbound to the profile startup, instead of using two processes.
This needs to be run NekoBox with administrator privileges.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
@@ -1336,14 +1321,6 @@ Split by line.</source>
<source>Clear</source> <source>Clear</source>
<translation>پاک کردن</translation> <translation>پاک کردن</translation>
</message> </message>
<message>
<source>End</source>
<translation type="vanished">پایان</translation>
</message>
<message>
<source>Active</source>
<translation type="vanished">فعال</translation>
</message>
<message> <message>
<source>Start: %1 <source>Start: %1
End: %2</source> End: %2</source>
@@ -1373,10 +1350,6 @@ End: %2</source>
<source>Starting profile %1</source> <source>Starting profile %1</source>
<translation>اغاز پروفایل %1</translation> <translation>اغاز پروفایل %1</translation>
</message> </message>
<message>
<source>Profile is insecure: %1</source>
<translation type="vanished">پروفایل ناامن می باشد: %1</translation>
</message>
<message> <message>
<source>Stopping profile %1</source> <source>Stopping profile %1</source>
<translation>متوقف کردن پروفایل %1</translation> <translation>متوقف کردن پروفایل %1</translation>
@@ -1405,13 +1378,13 @@ End: %2</source>
<source>Restart nekoray to take effect.</source> <source>Restart nekoray to take effect.</source>
<translation type="unfinished">برای اعمال تغییرات nekoray را مجددا راه اندازی کنید.</translation> <translation type="unfinished">برای اعمال تغییرات nekoray را مجددا راه اندازی کنید.</translation>
</message> </message>
<message>
<source>Please run NekoBox as admin</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>ProxyItem</name> <name>ProxyItem</name>
<message>
<source>Remove</source>
<translation type="vanished">حذف کردن</translation>
</message>
<message> <message>
<source>Confirmation</source> <source>Confirmation</source>
<translation>تائیدیه</translation> <translation>تائیدیه</translation>

View File

@@ -95,10 +95,6 @@
<source>Security</source> <source>Security</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<source>Insecure hint</source>
<translation type="vanished"></translation>
</message>
<message> <message>
<source>Statistics refresh rate</source> <source>Statistics refresh rate</source>
<translation></translation> <translation></translation>
@@ -494,11 +490,11 @@ These settings can be changed later.</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<source>The sniffing result is used for routing</source> <source>Sniff result for routing</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<source>The sniffing result is used for destination</source> <source>Sniff result for destination</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
@@ -513,14 +509,6 @@ These settings can be changed later.</source>
<source>Enable DNS Routing</source> <source>Enable DNS Routing</source>
<translation> DNS </translation> <translation> DNS </translation>
</message> </message>
<message>
<source>V2Ray Domain Strategy</source>
<translation></translation>
</message>
<message>
<source>Matcher</source>
<translation></translation>
</message>
<message> <message>
<source>Block</source> <source>Block</source>
<translation></translation> <translation></translation>
@@ -597,17 +585,21 @@ These settings can be changed later.</source>
<source>Default Outbound</source> <source>Default Outbound</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<source>Query Strategy</source>
<translation>DNS </translation>
</message>
<message> <message>
<source>Remote</source> <source>Remote</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<source>Inbound &amp; Outbound Domain Strategy</source> <source>DNS Query Strategy</source>
<translation></translation> <translation>DNS </translation>
</message>
<message>
<source>Domain Strategy</source>
<translation></translation>
</message>
<message>
<source>Server Address Strategy</source>
<translation></translation>
</message> </message>
</context> </context>
<context> <context>
@@ -675,12 +667,14 @@ https://matsuridayo.github.io/n-configuration/#vpn-tun</translation>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<source>Don&apos;t ask for privilege elevation</source> <source>Internal Tun</source>
<translation></translation> <translation> Tun</translation>
</message> </message>
<message> <message>
<source>Already Admin</source> <source>Add a tun inbound to the profile startup, instead of using two processes.
<translation></translation> This needs to be run NekoBox with administrator privileges.</source>
<translation>tun inbound使
NekoBox</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -1189,10 +1183,6 @@ End: %2</source>
<source>Move %1 item(s)</source> <source>Move %1 item(s)</source>
<translation> %1 </translation> <translation> %1 </translation>
</message> </message>
<message>
<source>Profile is insecure: %1</source>
<translation type="vanished">: %1</translation>
</message>
<message> <message>
<source>Remove Unavailable</source> <source>Remove Unavailable</source>
<translation></translation> <translation></translation>
@@ -1395,6 +1385,10 @@ Split by line.</source>
<source>Restart nekoray to take effect.</source> <source>Restart nekoray to take effect.</source>
<translation> nekoray </translation> <translation> nekoray </translation>
</message> </message>
<message>
<source>Please run NekoBox as admin</source>
<translation> NekoBox</translation>
</message>
</context> </context>
<context> <context>
<name>ProxyItem</name> <name>ProxyItem</name>
@@ -1498,26 +1492,6 @@ Release note:
<source>Chain Proxy</source> <source>Chain Proxy</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<source>The configuration (insecure) can be detected and identified, the transmission is fully visible to the censor and is not resistant to man-in-the-middle tampering with the content of the communication.</source>
<translation type="vanished"> () .</translation>
</message>
<message>
<source>This configuration (Shadowsocks streaming cipher) can be accurately proactively detected and decrypted by censors without requiring a password, and cannot be mitigated by turning on IV replay filters on the server side.
Learn more: https://github.com/net4people/bbs/issues/24</source>
<translation type="vanished"> (Shadowsocks ) , IV .
了解更多: https://github.com/net4people/bbs/issues/24</translation>
</message>
<message>
<source>This configuration (VMess MD5 authentication) has been deprecated by upstream because of its questionable resistance to tampering and concealment.
As of January 1, 2022, compatibility with MD5 authentication information will be disabled on the server side by default. Any client using MD5 authentication information will not be able to connect to a server with VMess MD5 authentication information disabled.</source>
<translation type="vanished"> (VMess MD5 ) , , .
2022 1 1 , MD5 . 使 MD5 VMess MD5 .</translation>
</message>
<message> <message>
<source>Requesting subscription: %1</source> <source>Requesting subscription: %1</source>
<translation>: %1</translation> <translation>: %1</translation>
@@ -1534,10 +1508,6 @@ As of January 1, 2022, compatibility with MD5 authentication information will be
<source>Change of %1:</source> <source>Change of %1:</source>
<translation>%1 :</translation> <translation>%1 :</translation>
</message> </message>
<message>
<source>This profile is cleartext, don&apos;t use it if the server is not in your local network.</source>
<translation type="vanished">使</translation>
</message>
<message> <message>
<source>Select</source> <source>Select</source>
<translation></translation> <translation></translation>

View File

@@ -392,7 +392,6 @@ void DialogBasicSettings::on_core_settings_clicked() {
w->setLayout(layout); w->setLayout(layout);
// //
auto line = -1; auto line = -1;
QCheckBox *core_box_auto_detect_interface;
QCheckBox *core_box_enable_clash_api; QCheckBox *core_box_enable_clash_api;
MyLineEdit *core_box_clash_api; MyLineEdit *core_box_clash_api;
MyLineEdit *core_box_clash_api_secret; MyLineEdit *core_box_clash_api_secret;
@@ -412,12 +411,6 @@ void DialogBasicSettings::on_core_settings_clicked() {
layout->addWidget(core_box_underlying_dns, line, 1); layout->addWidget(core_box_underlying_dns, line, 1);
// //
if (IS_NEKO_BOX) { if (IS_NEKO_BOX) {
auto core_box_auto_detect_interface_l = new QLabel("auto_detect_interface");
core_box_auto_detect_interface = new QCheckBox;
core_box_auto_detect_interface->setChecked(NekoRay::dataStore->core_box_auto_detect_interface);
layout->addWidget(core_box_auto_detect_interface_l, ++line, 0);
layout->addWidget(core_box_auto_detect_interface, line, 1);
//
auto core_box_enable_clash_api_l = new QLabel("Enable Clash API"); auto core_box_enable_clash_api_l = new QLabel("Enable Clash API");
core_box_enable_clash_api = new QCheckBox; core_box_enable_clash_api = new QCheckBox;
core_box_enable_clash_api->setChecked(NekoRay::dataStore->core_box_clash_api > 0); core_box_enable_clash_api->setChecked(NekoRay::dataStore->core_box_clash_api > 0);
@@ -460,7 +453,6 @@ void DialogBasicSettings::on_core_settings_clicked() {
connect(box, &QDialogButtonBox::accepted, w, [=] { connect(box, &QDialogButtonBox::accepted, w, [=] {
NekoRay::dataStore->core_box_underlying_dns = core_box_underlying_dns->text(); NekoRay::dataStore->core_box_underlying_dns = core_box_underlying_dns->text();
if (IS_NEKO_BOX) { if (IS_NEKO_BOX) {
NekoRay::dataStore->core_box_auto_detect_interface = core_box_auto_detect_interface->isChecked();
NekoRay::dataStore->core_box_clash_api = core_box_clash_api->text().toInt() * (core_box_enable_clash_api->isChecked() ? 1 : -1); NekoRay::dataStore->core_box_clash_api = core_box_clash_api->text().toInt() * (core_box_enable_clash_api->isChecked() ? 1 : -1);
NekoRay::dataStore->core_box_clash_api_secret = core_box_clash_api_secret->text(); NekoRay::dataStore->core_box_clash_api_secret = core_box_clash_api_secret->text();
} else { } else {

View File

@@ -31,16 +31,15 @@ DialogManageRoutes::DialogManageRoutes(QWidget *parent) : QDialog(parent), ui(ne
title_base = windowTitle(); title_base = windowTitle();
if (IS_NEKO_BOX) { if (IS_NEKO_BOX) {
ui->domain_v2ray->setVisible(false);
ui->outbound_domain_strategy->addItems(Preset::SingBox::DomainStrategy); ui->outbound_domain_strategy->addItems(Preset::SingBox::DomainStrategy);
ui->domainStrategyCombo->addItems(Preset::SingBox::DomainStrategy);
} else { } else {
ui->domain_v2ray->setVisible(true);
ui->outbound_domain_strategy->addItems({"AsIs", "UseIPv4", "UseIPv6", "PreferIPv4", "PreferIPv6"}); ui->outbound_domain_strategy->addItems({"AsIs", "UseIPv4", "UseIPv6", "PreferIPv4", "PreferIPv6"});
ui->domainStrategyCombo->addItems({"AsIs", "IPIfNonMatch", "IPOnDemand"});
} }
// //
ui->sniffing_mode->setCurrentIndex(NekoRay::dataStore->sniffing_mode); ui->sniffing_mode->setCurrentIndex(NekoRay::dataStore->sniffing_mode);
ui->outbound_domain_strategy->setCurrentText(NekoRay::dataStore->outbound_domain_strategy); ui->outbound_domain_strategy->setCurrentText(NekoRay::dataStore->outbound_domain_strategy);
ui->domainMatcherCombo->setCurrentIndex(NekoRay::dataStore->domain_matcher);
ui->domainStrategyCombo->setCurrentText(NekoRay::dataStore->domain_strategy); ui->domainStrategyCombo->setCurrentText(NekoRay::dataStore->domain_strategy);
ui->dns_routing->setChecked(NekoRay::dataStore->dns_routing); ui->dns_routing->setChecked(NekoRay::dataStore->dns_routing);
ui->dns_remote->setText(NekoRay::dataStore->remote_dns); ui->dns_remote->setText(NekoRay::dataStore->remote_dns);
@@ -88,7 +87,6 @@ DialogManageRoutes::~DialogManageRoutes() {
void DialogManageRoutes::accept() { void DialogManageRoutes::accept() {
NekoRay::dataStore->sniffing_mode = ui->sniffing_mode->currentIndex(); NekoRay::dataStore->sniffing_mode = ui->sniffing_mode->currentIndex();
NekoRay::dataStore->domain_matcher = ui->domainMatcherCombo->currentIndex();
NekoRay::dataStore->domain_strategy = ui->domainStrategyCombo->currentText(); NekoRay::dataStore->domain_strategy = ui->domainStrategyCombo->currentText();
NekoRay::dataStore->outbound_domain_strategy = ui->outbound_domain_strategy->currentText(); NekoRay::dataStore->outbound_domain_strategy = ui->outbound_domain_strategy->currentText();
NekoRay::dataStore->dns_routing = ui->dns_routing->isChecked(); NekoRay::dataStore->dns_routing = ui->dns_routing->isChecked();

View File

@@ -21,12 +21,6 @@
<layout class="QHBoxLayout" name="horizontalLayout_3"> <layout class="QHBoxLayout" name="horizontalLayout_3">
<item> <item>
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text"> <property name="text">
<string>Sniffing Mode</string> <string>Sniffing Mode</string>
</property> </property>
@@ -41,33 +35,38 @@
</item> </item>
<item> <item>
<property name="text"> <property name="text">
<string>The sniffing result is used for routing</string> <string>Sniff result for routing</string>
</property> </property>
</item> </item>
<item> <item>
<property name="text"> <property name="text">
<string>The sniffing result is used for destination</string> <string>Sniff result for destination</string>
</property> </property>
</item> </item>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="Line" name="line_4"> <widget class="QLabel" name="label_6">
<property name="orientation"> <property name="toolTip">
<enum>Qt::Vertical</enum> <string notr="true">For V2Ray, it sets routing.domainStrategy
For sing-box, it sets inbound.domain_strategy</string>
</property>
<property name="text">
<string>Domain Strategy</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="domainStrategyCombo">
<property name="editable">
<bool>false</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="label_3"> <widget class="QLabel" name="label_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text"> <property name="text">
<string>Inbound &amp; Outbound Domain Strategy</string> <string>Server Address Strategy</string>
</property> </property>
</widget> </widget>
</item> </item>
@@ -111,12 +110,6 @@
</item> </item>
<item> <item>
<widget class="QCheckBox" name="dns_routing"> <widget class="QCheckBox" name="dns_routing">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text"> <property name="text">
<string>Enable DNS Routing</string> <string>Enable DNS Routing</string>
</property> </property>
@@ -124,81 +117,19 @@
</item> </item>
<item> <item>
<widget class="QPushButton" name="queryStrategy"> <widget class="QPushButton" name="queryStrategy">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text"> <property name="text">
<string>Query Strategy</string> <string>DNS Query Strategy</string>
</property> </property>
</widget> </widget>
</item> </item>
</layout> </layout>
</item> </item>
<item>
<widget class="QWidget" name="domain_v2ray" native="true">
<layout class="QHBoxLayout" name="_2" stretch="0,1,0,1">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>V2Ray Domain Strategy</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="domainStrategyCombo">
<property name="editable">
<bool>false</bool>
</property>
<item>
<property name="text">
<string notr="true">AsIs</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">IPIfNonMatch</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">IPOnDemand</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>Matcher</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="domainMatcherCombo">
<item>
<property name="text">
<string notr="true">Original</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">Minimal Perfect Hash Matcher</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@@ -461,13 +392,8 @@
</widget> </widget>
<tabstops> <tabstops>
<tabstop>sniffing_mode</tabstop> <tabstop>sniffing_mode</tabstop>
<tabstop>outbound_domain_strategy</tabstop>
<tabstop>dns_remote</tabstop> <tabstop>dns_remote</tabstop>
<tabstop>dns_direct</tabstop> <tabstop>dns_direct</tabstop>
<tabstop>dns_routing</tabstop>
<tabstop>queryStrategy</tabstop>
<tabstop>domainStrategyCombo</tabstop>
<tabstop>domainMatcherCombo</tabstop>
<tabstop>preset</tabstop> <tabstop>preset</tabstop>
<tabstop>custom_route_edit</tabstop> <tabstop>custom_route_edit</tabstop>
<tabstop>def_outbound</tabstop> <tabstop>def_outbound</tabstop>

View File

@@ -18,13 +18,12 @@ DialogVPNSettings::DialogVPNSettings(QWidget *parent) : QDialog(parent), ui(new
ui->vpn_mtu->setCurrentText(Int2String(NekoRay::dataStore->vpn_mtu)); ui->vpn_mtu->setCurrentText(Int2String(NekoRay::dataStore->vpn_mtu));
ui->vpn_ipv6->setChecked(NekoRay::dataStore->vpn_ipv6); ui->vpn_ipv6->setChecked(NekoRay::dataStore->vpn_ipv6);
ui->hide_console->setChecked(NekoRay::dataStore->vpn_hide_console); ui->hide_console->setChecked(NekoRay::dataStore->vpn_hide_console);
ui->vpn_already_admin->setChecked(NekoRay::dataStore->vpn_already_admin); #ifndef Q_OS_WIN
#ifdef Q_OS_WIN
ui->vpn_already_admin->setVisible(false);
#else
ui->hide_console->setVisible(false); ui->hide_console->setVisible(false);
#endif #endif
ui->strict_route->setChecked(NekoRay::dataStore->vpn_strict_route); ui->strict_route->setChecked(NekoRay::dataStore->vpn_strict_route);
ui->single_core->setVisible(IS_NEKO_BOX);
ui->single_core->setChecked(NekoRay::dataStore->vpn_internal_tun);
// //
D_LOAD_STRING(vpn_rule_cidr) D_LOAD_STRING(vpn_rule_cidr)
D_LOAD_STRING(vpn_rule_process) D_LOAD_STRING(vpn_rule_process)
@@ -56,7 +55,7 @@ void DialogVPNSettings::accept() {
NekoRay::dataStore->vpn_hide_console = ui->hide_console->isChecked(); NekoRay::dataStore->vpn_hide_console = ui->hide_console->isChecked();
NekoRay::dataStore->vpn_strict_route = ui->strict_route->isChecked(); NekoRay::dataStore->vpn_strict_route = ui->strict_route->isChecked();
NekoRay::dataStore->vpn_rule_white = ui->whitelist_mode->isChecked(); NekoRay::dataStore->vpn_rule_white = ui->whitelist_mode->isChecked();
NekoRay::dataStore->vpn_already_admin = ui->vpn_already_admin->isChecked(); NekoRay::dataStore->vpn_internal_tun = ui->single_core->isChecked();
// //
D_SAVE_STRING_QTEXTEDIT(vpn_rule_cidr) D_SAVE_STRING_QTEXTEDIT(vpn_rule_cidr)
D_SAVE_STRING_QTEXTEDIT(vpn_rule_process) D_SAVE_STRING_QTEXTEDIT(vpn_rule_process)

View File

@@ -86,13 +86,6 @@
<item> <item>
<widget class="QGroupBox" name="horizontalGroupBox_2"> <widget class="QGroupBox" name="horizontalGroupBox_2">
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QCheckBox" name="hide_console">
<property name="text">
<string>Hide Console</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QCheckBox" name="vpn_ipv6"> <widget class="QCheckBox" name="vpn_ipv6">
<property name="text"> <property name="text">
@@ -100,13 +93,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="fake_dns">
<property name="text">
<string notr="true">FakeDNS</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QCheckBox" name="strict_route"> <widget class="QCheckBox" name="strict_route">
<property name="text"> <property name="text">
@@ -115,12 +101,34 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QCheckBox" name="vpn_already_admin"> <widget class="QCheckBox" name="fake_dns">
<property name="text">
<string notr="true">FakeDNS</string>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="hide_console">
<property name="text">
<string>Hide Console</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="single_core">
<property name="toolTip"> <property name="toolTip">
<string>Don't ask for privilege elevation</string> <string>Add a tun inbound to the profile startup, instead of using two processes.
This needs to be run NekoBox with administrator privileges.</string>
</property> </property>
<property name="text"> <property name="text">
<string>Already Admin</string> <string>Internal Tun</string>
</property> </property>
</widget> </widget>
</item> </item>
@@ -198,6 +206,19 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<tabstops>
<tabstop>vpn_implementation</tabstop>
<tabstop>vpn_mtu</tabstop>
<tabstop>vpn_ipv6</tabstop>
<tabstop>strict_route</tabstop>
<tabstop>fake_dns</tabstop>
<tabstop>hide_console</tabstop>
<tabstop>single_core</tabstop>
<tabstop>vpn_rule_cidr</tabstop>
<tabstop>vpn_rule_process</tabstop>
<tabstop>whitelist_mode</tabstop>
<tabstop>troubleshooting</tabstop>
</tabstops>
<resources/> <resources/>
<connections> <connections>
<connection> <connection>

View File

@@ -94,12 +94,9 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
software_name = "NekoBox"; software_name = "NekoBox";
software_core_name = "sing-box"; software_core_name = "sing-box";
// replace default values // replace default values
if (NekoRay::dataStore->log_level == "warning") { if (NekoRay::dataStore->log_level == "warning") NekoRay::dataStore->log_level = "info";
NekoRay::dataStore->log_level = "info"; if (!Preset::SingBox::DomainStrategy.contains(NekoRay::dataStore->domain_strategy)) NekoRay::dataStore->domain_strategy = "";
} if (!Preset::SingBox::DomainStrategy.contains(NekoRay::dataStore->outbound_domain_strategy)) NekoRay::dataStore->outbound_domain_strategy = "";
if (!Preset::SingBox::DomainStrategy.contains(NekoRay::dataStore->outbound_domain_strategy)) {
NekoRay::dataStore->outbound_domain_strategy = "";
}
// //
if (QDir("dashboard").isEmpty()) { if (QDir("dashboard").isEmpty()) {
QDir().mkdir("dashboard"); QDir().mkdir("dashboard");
@@ -334,20 +331,19 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
MW_dialog_message("", "UpdateDataStore"); MW_dialog_message("", "UpdateDataStore");
}); });
// //
connect(ui->checkBox_VPN, &QCheckBox::clicked, this, [=](bool checked) { connect(ui->checkBox_VPN, &QCheckBox::clicked, this, [=](bool checked) { neko_set_spmode_vpn(checked); });
neko_set_spmode(checked ? NekoRay::SystemProxyMode::VPN : NekoRay::SystemProxyMode::DISABLE); connect(ui->checkBox_SystemProxy, &QCheckBox::clicked, this, [=](bool checked) { neko_set_spmode_system_proxy(checked); });
});
connect(ui->checkBox_SystemProxy, &QCheckBox::clicked, this, [=](bool checked) {
neko_set_spmode(checked ? NekoRay::SystemProxyMode::SYSTEM_PROXY : NekoRay::SystemProxyMode::DISABLE);
});
connect(ui->menu_spmode, &QMenu::aboutToShow, this, [=]() { connect(ui->menu_spmode, &QMenu::aboutToShow, this, [=]() {
ui->menu_spmode_disabled->setChecked(NekoRay::dataStore->running_spmode == NekoRay::SystemProxyMode::DISABLE); ui->menu_spmode_disabled->setChecked(!(NekoRay::dataStore->spmode_system_proxy || NekoRay::dataStore->spmode_vpn));
ui->menu_spmode_system_proxy->setChecked(NekoRay::dataStore->running_spmode == NekoRay::SystemProxyMode::SYSTEM_PROXY); ui->menu_spmode_system_proxy->setChecked(NekoRay::dataStore->spmode_system_proxy);
ui->menu_spmode_vpn->setChecked(NekoRay::dataStore->running_spmode == NekoRay::SystemProxyMode::VPN); ui->menu_spmode_vpn->setChecked(NekoRay::dataStore->spmode_vpn);
});
connect(ui->menu_spmode_system_proxy, &QAction::triggered, this, [=](bool checked) { neko_set_spmode_system_proxy(checked); });
connect(ui->menu_spmode_vpn, &QAction::triggered, this, [=](bool checked) { neko_set_spmode_vpn(checked); });
connect(ui->menu_spmode_disabled, &QAction::triggered, this, [=]() {
neko_set_spmode_system_proxy(false);
neko_set_spmode_vpn(false);
}); });
connect(ui->menu_spmode_system_proxy, &QAction::triggered, this, [=]() { neko_set_spmode(NekoRay::SystemProxyMode::SYSTEM_PROXY); });
connect(ui->menu_spmode_vpn, &QAction::triggered, this, [=]() { neko_set_spmode(NekoRay::SystemProxyMode::VPN); });
connect(ui->menu_spmode_disabled, &QAction::triggered, this, [=]() { neko_set_spmode(NekoRay::SystemProxyMode::DISABLE); });
connect(ui->menu_qr, &QAction::triggered, this, [=]() { display_qr_link(false); }); connect(ui->menu_qr, &QAction::triggered, this, [=]() { display_qr_link(false); });
connect(ui->menu_tcp_ping, &QAction::triggered, this, [=]() { speedtest_current_group(0); }); connect(ui->menu_tcp_ping, &QAction::triggered, this, [=]() { speedtest_current_group(0); });
connect(ui->menu_url_test, &QAction::triggered, this, [=]() { speedtest_current_group(1); }); connect(ui->menu_url_test, &QAction::triggered, this, [=]() { speedtest_current_group(1); });
@@ -417,8 +413,11 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
// Start last // Start last
if (NekoRay::dataStore->remember_enable) { if (NekoRay::dataStore->remember_enable) {
if (NekoRay::dataStore->remember_spmode == NekoRay::SystemProxyMode::SYSTEM_PROXY) { if (NekoRay::dataStore->remember_spmode.contains("system_proxy")) {
neko_set_spmode(NekoRay::dataStore->remember_spmode, false); neko_set_spmode_system_proxy(true, false);
}
if (NekoRay::dataStore->remember_spmode.contains("vpn")) {
neko_set_spmode_vpn(true, false);
} }
if (NekoRay::dataStore->remember_id >= 0) { if (NekoRay::dataStore->remember_id >= 0) {
runOnUiThread([=] { neko_start(NekoRay::dataStore->remember_id); }); runOnUiThread([=] { neko_start(NekoRay::dataStore->remember_id); });
@@ -514,7 +513,7 @@ void MainWindow::dialog_message_impl(const QString &sender, const QString &info)
auto changed = NekoRay::dataStore->Save(); auto changed = NekoRay::dataStore->Save();
if (info.contains("RouteChanged")) changed = true; if (info.contains("RouteChanged")) changed = true;
refresh_proxy_list(); refresh_proxy_list();
if (info.contains("VPNChanged") && NekoRay::dataStore->running_spmode == NekoRay::SystemProxyMode::VPN) { if (info.contains("VPNChanged") && NekoRay::dataStore->spmode_vpn) {
MessageBoxWarning(tr("VPN settings changed"), tr("Restart VPN to take effect.")); MessageBoxWarning(tr("VPN settings changed"), tr("Restart VPN to take effect."));
} else if (changed && NekoRay::dataStore->started_id >= 0 && } else if (changed && NekoRay::dataStore->started_id >= 0 &&
QMessageBox::question(GetMessageBoxParent(), tr("Confirmation"), tr("Settings changed, restart proxy?")) == QMessageBox::StandardButton::Yes) { QMessageBox::question(GetMessageBoxParent(), tr("Confirmation"), tr("Settings changed, restart proxy?")) == QMessageBox::StandardButton::Yes) {
@@ -624,8 +623,9 @@ void MainWindow::on_commitDataRequest() {
} }
void MainWindow::on_menu_exit_triggered() { void MainWindow::on_menu_exit_triggered() {
neko_set_spmode(NekoRay::SystemProxyMode::DISABLE, false); neko_set_spmode_system_proxy(false, false);
if (NekoRay::dataStore->running_spmode == NekoRay::SystemProxyMode::VPN) return; neko_set_spmode_vpn(false, false);
if (NekoRay::dataStore->spmode_vpn) return;
RegisterHotkey(true); RegisterHotkey(true);
// //
on_commitDataRequest(); on_commitDataRequest();
@@ -638,13 +638,21 @@ void MainWindow::on_menu_exit_triggered() {
if (exit_reason == 1) { if (exit_reason == 1) {
QDir::setCurrent(QApplication::applicationDirPath()); QDir::setCurrent(QApplication::applicationDirPath());
QProcess::startDetached("./updater", QStringList{}); QProcess::startDetached("./updater", QStringList{});
} else if (exit_reason == 2) { } else if (exit_reason == 2 || exit_reason == 3) {
QDir::setCurrent(QApplication::applicationDirPath()); QDir::setCurrent(QApplication::applicationDirPath());
auto arguments = NekoRay::dataStore->argv; auto arguments = NekoRay::dataStore->argv;
if (arguments.length() > 0) arguments.removeFirst(); if (arguments.length() > 0) arguments.removeFirst();
auto isLauncher = qEnvironmentVariable("NKR_FROM_LAUNCHER") == "1"; auto isLauncher = qEnvironmentVariable("NKR_FROM_LAUNCHER") == "1";
if (isLauncher) arguments.prepend("--"); if (isLauncher) arguments.prepend("--");
QProcess::startDetached(isLauncher ? "./launcher" : QApplication::applicationFilePath(), arguments); auto program = isLauncher ? "./launcher" : QApplication::applicationFilePath();
if (exit_reason == 3) { // restart as admin
#ifdef Q_OS_WIN
WinCommander::runProcessElevated(program, arguments, "", WinCommander::SW_NORMAL, false);
#endif
} else {
QProcess::startDetached(program, arguments);
}
} }
tray->hide(); tray->hide();
QCoreApplication::quit(); QCoreApplication::quit();
@@ -654,23 +662,11 @@ void MainWindow::on_menu_exit_triggered() {
refresh_status(); \ refresh_status(); \
return; return;
void MainWindow::neko_set_spmode(int mode, bool save) { void MainWindow::neko_set_spmode_system_proxy(bool enable, bool save) {
if (mode != NekoRay::dataStore->running_spmode) { if (enable != NekoRay::dataStore->spmode_system_proxy) {
// DISABLE if (enable) {
if (NekoRay::dataStore->running_spmode == NekoRay::SystemProxyMode::SYSTEM_PROXY) {
ClearSystemProxy();
} else if (NekoRay::dataStore->running_spmode == NekoRay::SystemProxyMode::VPN) {
if (!StopVPNProcess()) {
neko_set_spmode_FAILED
}
}
// ENABLE
if (mode == NekoRay::SystemProxyMode::SYSTEM_PROXY) {
#if defined(Q_OS_WIN) || defined(Q_OS_MACOS) #if defined(Q_OS_WIN) || defined(Q_OS_MACOS)
if (mode == NekoRay::SystemProxyMode::SYSTEM_PROXY && !IS_NEKO_BOX && !IsValidPort(NekoRay::dataStore->inbound_http_port)) { if (!IS_NEKO_BOX && !IsValidPort(NekoRay::dataStore->inbound_http_port)) {
auto btn = QMessageBox::warning(this, software_name, auto btn = QMessageBox::warning(this, software_name,
tr("Http inbound is not enabled, can't set system proxy."), tr("Http inbound is not enabled, can't set system proxy."),
"OK", tr("Settings"), "", 0, 0); "OK", tr("Settings"), "", 0, 0);
@@ -682,29 +678,72 @@ void MainWindow::neko_set_spmode(int mode, bool save) {
#endif #endif
auto socks_port = NekoRay::dataStore->inbound_socks_port; auto socks_port = NekoRay::dataStore->inbound_socks_port;
auto http_port = NekoRay::dataStore->inbound_http_port; auto http_port = NekoRay::dataStore->inbound_http_port;
if (IS_NEKO_BOX) { if (IS_NEKO_BOX) http_port = socks_port;
http_port = socks_port;
}
SetSystemProxy(http_port, socks_port); SetSystemProxy(http_port, socks_port);
} else if (mode == NekoRay::SystemProxyMode::VPN) { } else {
ClearSystemProxy();
}
}
if (save) {
NekoRay::dataStore->remember_spmode.removeAll("system_proxy");
if (enable) {
NekoRay::dataStore->remember_spmode.append("system_proxy");
}
NekoRay::dataStore->Save();
}
NekoRay::dataStore->spmode_system_proxy = enable;
refresh_status();
}
void MainWindow::neko_set_spmode_vpn(bool enable, bool save) {
if (enable != NekoRay::dataStore->spmode_vpn) {
if (enable) {
if (IS_NEKO_BOX_INTERNAL_TUN) {
#ifdef Q_OS_WIN
if (!Windows_IsInAdmin()) {
auto n = QMessageBox::warning(GetMessageBoxParent(), software_name, tr("Please run NekoBox as admin"), QMessageBox::Yes | QMessageBox::No);
if (n == QMessageBox::Yes) {
this->exit_reason = 3;
on_menu_exit_triggered();
}
neko_set_spmode_FAILED
}
#endif
// TODO check permission for Linux
} else {
if (NekoRay::dataStore->need_keep_vpn_off) { if (NekoRay::dataStore->need_keep_vpn_off) {
MessageBoxWarning(software_name, MessageBoxWarning(software_name, tr("Current server is incompatible with VPN. Please stop the server first, enable VPN mode, and then restart."));
tr("Current server is incompatible with VPN. Please stop the server first, enable VPN mode, and then restart."));
neko_set_spmode_FAILED neko_set_spmode_FAILED
} }
if (!StartVPNProcess()) { if (!StartVPNProcess()) {
neko_set_spmode_FAILED neko_set_spmode_FAILED
} }
} }
} else {
if (IS_NEKO_BOX_INTERNAL_TUN) {
// current core is sing-box
} else {
if (!StopVPNProcess()) {
neko_set_spmode_FAILED
}
}
}
} }
if (save) { if (save) {
NekoRay::dataStore->remember_spmode = mode; NekoRay::dataStore->remember_spmode.removeAll("vpn");
if (enable) {
NekoRay::dataStore->remember_spmode.append("vpn");
}
NekoRay::dataStore->Save(); NekoRay::dataStore->Save();
} }
NekoRay::dataStore->running_spmode = mode; NekoRay::dataStore->spmode_vpn = enable;
refresh_status(); refresh_status();
if (NekoRay::dataStore->started_id >= 0) neko_start(NekoRay::dataStore->started_id);
} }
void MainWindow::refresh_status(const QString &traffic_update) { void MainWindow::refresh_status(const QString &traffic_update) {
@@ -736,8 +775,8 @@ void MainWindow::refresh_status(const QString &traffic_update) {
if (IS_NEKO_BOX) inbound_txt = QString("Mixed: %1").arg(display_socks); if (IS_NEKO_BOX) inbound_txt = QString("Mixed: %1").arg(display_socks);
ui->label_inbound->setText(inbound_txt); ui->label_inbound->setText(inbound_txt);
// //
ui->checkBox_VPN->setChecked(NekoRay::dataStore->running_spmode == NekoRay::SystemProxyMode::VPN); ui->checkBox_VPN->setChecked(NekoRay::dataStore->spmode_vpn);
ui->checkBox_SystemProxy->setChecked(NekoRay::dataStore->running_spmode == NekoRay::SystemProxyMode::SYSTEM_PROXY); ui->checkBox_SystemProxy->setChecked(NekoRay::dataStore->spmode_system_proxy);
if (select_mode) ui->label_running->setText("[" + tr("Select") + "]"); if (select_mode) ui->label_running->setText("[" + tr("Select") + "]");
auto make_title = [=](bool isTray) { auto make_title = [=](bool isTray) {
@@ -747,11 +786,8 @@ void MainWindow::refresh_status(const QString &traffic_update) {
#endif #endif
if (select_mode) tt << "[" + tr("Select") + "]"; if (select_mode) tt << "[" + tr("Select") + "]";
if (!title_error.isEmpty()) tt << "[" + title_error + "]"; if (!title_error.isEmpty()) tt << "[" + title_error + "]";
if (NekoRay::dataStore->running_spmode == NekoRay::SystemProxyMode::SYSTEM_PROXY) { if (NekoRay::dataStore->spmode_vpn) tt << "[VPN]";
tt << "[" + tr("System Proxy") + "]"; if (NekoRay::dataStore->spmode_system_proxy) tt << "[" + tr("System Proxy") + "]";
} else if (NekoRay::dataStore->running_spmode == NekoRay::SystemProxyMode::VPN) {
tt << "[" + tr("VPN Mode") + "]";
}
tt << software_name; tt << software_name;
if (!isTray) tt << "(" + QString(NKR_VERSION) + ")"; if (!isTray) tt << "(" + QString(NKR_VERSION) + ")";
if (!NekoRay::dataStore->active_routing.isEmpty() && NekoRay::dataStore->active_routing != "Default") { if (!NekoRay::dataStore->active_routing.isEmpty() && NekoRay::dataStore->active_routing != "Default") {
@@ -762,13 +798,16 @@ void MainWindow::refresh_status(const QString &traffic_update) {
}; };
auto icon_status_new = Icon::NONE; auto icon_status_new = Icon::NONE;
if (NekoRay::dataStore->running_spmode == NekoRay::SystemProxyMode::SYSTEM_PROXY) {
icon_status_new = Icon::SYSTEM_PROXY; if (!running.isNull()) {
} else if (NekoRay::dataStore->running_spmode == NekoRay::SystemProxyMode::VPN) { if (NekoRay::dataStore->spmode_vpn) {
icon_status_new = Icon::VPN; icon_status_new = Icon::VPN;
} else if (!running.isNull()) { } else if (NekoRay::dataStore->spmode_system_proxy) {
icon_status_new = Icon::SYSTEM_PROXY;
} else {
icon_status_new = Icon::RUNNING; icon_status_new = Icon::RUNNING;
} }
}
// refresh title & window icon // refresh title & window icon
setWindowTitle(make_title(false)); setWindowTitle(make_title(false));
@@ -1677,11 +1716,10 @@ bool MainWindow::StartVPNProcess() {
runOnNewThread([=] { runOnNewThread([=] {
vpn_pid = 1; // TODO get pid? vpn_pid = 1; // TODO get pid?
WinCommander::runProcessElevated(QApplication::applicationDirPath() + "/nekobox_core.exe", WinCommander::runProcessElevated(QApplication::applicationDirPath() + "/nekobox_core.exe",
{"--disable-color", "run", "-c", configPath}, {"--disable-color", "run", "-c", configPath}, "",
"", NekoRay::dataStore->vpn_hide_console ? WinCommander::SW_HIDE : WinCommander::SW_SHOWMINIMIZED); // blocking
NekoRay::dataStore->vpn_hide_console); // blocking
vpn_pid = 0; vpn_pid = 0;
runOnUiThread([=] { neko_set_spmode(NekoRay::SystemProxyMode::DISABLE); }); runOnUiThread([=] { neko_set_spmode_vpn(false); });
}); });
#else #else
QFile::remove(protectPath); QFile::remove(protectPath);
@@ -1695,7 +1733,7 @@ bool MainWindow::StartVPNProcess() {
if (state == QProcess::NotRunning) { if (state == QProcess::NotRunning) {
vpn_pid = 0; vpn_pid = 0;
vpn_process->deleteLater(); vpn_process->deleteLater();
GetMainWindow()->neko_set_spmode(NekoRay::SystemProxyMode::DISABLE); GetMainWindow()->neko_set_spmode_vpn(false);
} }
}); });
// //
@@ -1704,11 +1742,7 @@ bool MainWindow::StartVPNProcess() {
vpn_process->start("osascript", {"-e", QString("do shell script \"%1\" with administrator privileges") vpn_process->start("osascript", {"-e", QString("do shell script \"%1\" with administrator privileges")
.arg("bash " + scriptPath)}); .arg("bash " + scriptPath)});
#else #else
if (NekoRay::dataStore->vpn_already_admin) {
vpn_process->start("bash", {scriptPath});
} else {
vpn_process->start("pkexec", {"bash", scriptPath}); vpn_process->start("pkexec", {"bash", scriptPath});
}
#endif #endif
vpn_process->waitForStarted(); vpn_process->waitForStarted();
vpn_pid = vpn_process->processId(); // actually it's pkexec or bash PID vpn_pid = vpn_process->processId(); // actually it's pkexec or bash PID
@@ -1731,15 +1765,11 @@ bool MainWindow::StopVPNProcess(bool unconditional) {
p.start("osascript", {"-e", QString("do shell script \"%1\" with administrator privileges") p.start("osascript", {"-e", QString("do shell script \"%1\" with administrator privileges")
.arg("pkill -2 -U 0 nekobox_core")}); .arg("pkill -2 -U 0 nekobox_core")});
#else #else
if (NekoRay::dataStore->vpn_already_admin) {
p.start("bash", {"kill", "-2", Int2String(vpn_pid)});
} else {
if (unconditional) { if (unconditional) {
p.start("pkexec", {"killall", "-2", "nekobox_core"}); p.start("pkexec", {"killall", "-2", "nekobox_core"});
} else { } else {
p.start("pkexec", {"pkill", "-2", "-P", Int2String(vpn_pid)}); p.start("pkexec", {"pkill", "-2", "-P", Int2String(vpn_pid)});
} }
}
#endif #endif
p.waitForFinished(); p.waitForFinished();
ok = p.exitCode() == 0; ok = p.exitCode() == 0;

View File

@@ -51,7 +51,9 @@ public:
void neko_stop(bool crash = false); void neko_stop(bool crash = false);
void neko_set_spmode(int mode, bool save = true); void neko_set_spmode_system_proxy(bool enable, bool save = true);
void neko_set_spmode_vpn(bool enable, bool save = true);
void show_log_impl(const QString &log); void show_log_impl(const QString &log);