mirror of
https://github.com/Mahdi-zarei/nekoray.git
synced 2025-12-31 15:09:02 +08:00
feat: prepare for route rules
This commit is contained in:
parent
43f4de3fe0
commit
2bc9fd210c
@ -763,100 +763,4 @@ namespace NekoGui {
|
||||
|
||||
if (!experimentalObj.isEmpty()) status->result->coreConfig.insert("experimental", experimentalObj);
|
||||
}
|
||||
|
||||
QString WriteVPNSingBoxConfig() {
|
||||
// tun user rule
|
||||
auto match_out = dataStore->vpn_rule_white ? "nekoray-socks" : "direct";
|
||||
auto no_match_out = dataStore->vpn_rule_white ? "direct" : "nekoray-socks";
|
||||
|
||||
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)}};
|
||||
process_name_rule = "," + QJsonObject2QString(rule, false);
|
||||
}
|
||||
|
||||
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)}};
|
||||
cidr_rule = "," + QJsonObject2QString(rule, false);
|
||||
}
|
||||
|
||||
// TODO bypass ext core process path?
|
||||
|
||||
// auth
|
||||
QString socks_user_pass;
|
||||
if (dataStore->inbound_auth->NeedAuth()) {
|
||||
socks_user_pass = R"( "username": "%1", "password": "%2", )";
|
||||
socks_user_pass = socks_user_pass.arg(dataStore->inbound_auth->username, dataStore->inbound_auth->password);
|
||||
}
|
||||
// gen config
|
||||
auto configFn = ":/neko/vpn/sing-box-vpn.json";
|
||||
if (QFile::exists("vpn/sing-box-vpn.json")) configFn = "vpn/sing-box-vpn.json";
|
||||
auto config = ReadFileText(configFn)
|
||||
.replace("//%IPV6_ADDRESS%", dataStore->vpn_ipv6 ? R"("inet6_address": "fdfe:dcba:9876::1/126",)" : "")
|
||||
.replace("//%SOCKS_USER_PASS%", socks_user_pass)
|
||||
.replace("//%PROCESS_NAME_RULE%", process_name_rule)
|
||||
.replace("//%CIDR_RULE%", cidr_rule)
|
||||
.replace("%MTU%", Int2String(dataStore->vpn_mtu))
|
||||
.replace("%STACK%", Preset::SingBox::VpnImplementation.value(dataStore->vpn_implementation))
|
||||
.replace("%TUN_NAME%", genTunName())
|
||||
.replace("%STRICT_ROUTE%", dataStore->vpn_strict_route ? "true" : "false")
|
||||
.replace("%FINAL_OUT%", no_match_out)
|
||||
.replace("%DNS_ADDRESS%", BOX_UNDERLYING_DNS)
|
||||
.replace("%FAKE_DNS_INBOUND%", dataStore->fake_dns ? "tun-in" : "empty")
|
||||
.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
|
||||
QFile file;
|
||||
file.setFileName(QFileInfo(configFn).fileName());
|
||||
file.open(QIODevice::ReadWrite | QIODevice::Truncate);
|
||||
file.write(config.toUtf8());
|
||||
file.close();
|
||||
return QFileInfo(file).absoluteFilePath();
|
||||
}
|
||||
|
||||
QString WriteVPNLinuxScript(const QString &protectPath, const QString &configPath) {
|
||||
#ifdef Q_OS_WIN
|
||||
return {};
|
||||
#endif
|
||||
// gen script
|
||||
auto scriptFn = ":/neko/vpn/vpn-run-root.sh";
|
||||
if (QFile::exists("vpn/vpn-run-root.sh")) scriptFn = "vpn/vpn-run-root.sh";
|
||||
auto script = ReadFileText(scriptFn)
|
||||
.replace("./nekobox_core", QApplication::applicationDirPath() + "/nekobox_core")
|
||||
.replace("$PROTECT_LISTEN_PATH", protectPath)
|
||||
.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
|
||||
QFile file2;
|
||||
file2.setFileName(QFileInfo(scriptFn).fileName());
|
||||
file2.open(QIODevice::ReadWrite | QIODevice::Truncate);
|
||||
file2.write(script.toUtf8());
|
||||
file2.close();
|
||||
return QFileInfo(file2).absoluteFilePath();
|
||||
}
|
||||
|
||||
} // namespace NekoGui
|
||||
@ -52,8 +52,4 @@ namespace NekoGui {
|
||||
|
||||
QString BuildChainInternal(int chainId, const QList<std::shared_ptr<ProxyEntity>> &ents,
|
||||
const std::shared_ptr<BuildConfigStatus> &status);
|
||||
|
||||
QString WriteVPNSingBoxConfig();
|
||||
|
||||
QString WriteVPNLinuxScript(const QString &protectPath, const QString &configPath);
|
||||
} // namespace NekoGui
|
||||
|
||||
44
db/RouteRuleEntity.h
Normal file
44
db/RouteRuleEntity.h
Normal file
@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include "main/NekoGui.hpp"
|
||||
|
||||
namespace NekoGui {
|
||||
class RouteRule : public JsonStore {
|
||||
public:
|
||||
int ip_version = 0;
|
||||
QList<QString> network;
|
||||
QList<QString> protocol;
|
||||
QList<QString> domain;
|
||||
QList<QString> domain_suffix;
|
||||
QList<QString> domain_keyword;
|
||||
QList<QString> domain_regex;
|
||||
QList<QString> source_ip_cidr;
|
||||
bool* source_ip_is_private = nullptr;
|
||||
QList<QString> ip_cidr;
|
||||
bool* ip_is_private = nullptr;
|
||||
QList<QString> source_port;
|
||||
QList<QString> source_port_range;
|
||||
QList<QString> port;
|
||||
QList<QString> port_range;
|
||||
QList<QString> process_name;
|
||||
QList<QString> process_path;
|
||||
QList<QString> rule_set;
|
||||
bool invert = false;
|
||||
int outboundID = -1;
|
||||
|
||||
QList<QString> check_for_errors();
|
||||
|
||||
QJsonObject get_rule_json();
|
||||
};
|
||||
|
||||
class RoutingChain : public JsonStore {
|
||||
public:
|
||||
int id = -1;
|
||||
QString name = "";
|
||||
QList<std::shared_ptr<RouteRule>> Rules;
|
||||
|
||||
QJsonArray get_route_rules();
|
||||
|
||||
QJsonArray get_default_route_rules();
|
||||
};
|
||||
} // namespace NekoGui
|
||||
@ -1714,57 +1714,6 @@ void MainWindow::RegisterHotkey(bool unregister) {}
|
||||
void MainWindow::HotkeyEvent(const QString &key) {}
|
||||
|
||||
#endif
|
||||
|
||||
// VPN Launcher
|
||||
|
||||
bool MainWindow::StartVPNProcess() {
|
||||
//
|
||||
if (vpn_pid != 0) {
|
||||
return true;
|
||||
}
|
||||
//
|
||||
auto protectPath = QDir::currentPath() + "/protect";
|
||||
auto configPath = NekoGui::WriteVPNSingBoxConfig();
|
||||
auto scriptPath = NekoGui::WriteVPNLinuxScript(protectPath, configPath);
|
||||
//
|
||||
#ifdef Q_OS_WIN
|
||||
runOnNewThread([=] {
|
||||
vpn_pid = 1; // TODO get pid?
|
||||
WinCommander::runProcessElevated(QApplication::applicationDirPath() + "/nekobox_core.exe",
|
||||
{"--disable-color", "run", "-c", configPath}, "",
|
||||
NekoGui::dataStore->vpn_hide_console ? WinCommander::SW_HIDE : WinCommander::SW_SHOWMINIMIZED); // blocking
|
||||
vpn_pid = 0;
|
||||
runOnUiThread([=] { neko_set_spmode_vpn(false); });
|
||||
});
|
||||
#else
|
||||
QFile::remove(protectPath);
|
||||
if (QFile::exists(protectPath)) {
|
||||
MessageBoxWarning("Error", "protect cannot be removed");
|
||||
return false;
|
||||
}
|
||||
//
|
||||
auto vpn_process = new QProcess;
|
||||
QProcess::connect(vpn_process, &QProcess::stateChanged, this, [=](QProcess::ProcessState state) {
|
||||
if (state == QProcess::NotRunning) {
|
||||
vpn_pid = 0;
|
||||
vpn_process->deleteLater();
|
||||
GetMainWindow()->neko_set_spmode_vpn(false);
|
||||
}
|
||||
});
|
||||
//
|
||||
vpn_process->setProcessChannelMode(QProcess::ForwardedChannels);
|
||||
#ifdef Q_OS_MACOS
|
||||
vpn_process->start("osascript", {"-e", QString("do shell script \"%1\" with administrator privileges")
|
||||
.arg("bash " + scriptPath)});
|
||||
#else
|
||||
vpn_process->start("pkexec", {"bash", scriptPath});
|
||||
#endif
|
||||
vpn_process->waitForStarted();
|
||||
vpn_pid = vpn_process->processId(); // actually it's pkexec or bash PID
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MainWindow::StopVPNProcess(bool unconditional) {
|
||||
if (unconditional || vpn_pid != 0) {
|
||||
bool ok;
|
||||
|
||||
@ -179,8 +179,6 @@ private:
|
||||
|
||||
void HotkeyEvent(const QString &key);
|
||||
|
||||
bool StartVPNProcess();
|
||||
|
||||
// grpc and ...
|
||||
|
||||
static void setup_grpc();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user