diff --git a/go/cmd/nekobox_core/go.mod b/go/cmd/nekobox_core/go.mod index 11bb8dc..db03d4a 100644 --- a/go/cmd/nekobox_core/go.mod +++ b/go/cmd/nekobox_core/go.mod @@ -3,14 +3,14 @@ module nekobox_core go 1.19 require ( - github.com/Mahdi-zarei/sing-box-extra v0.0.0-20240902015241-67553399f0d3 + github.com/Mahdi-zarei/sing-box-extra v0.0.0-20240904000146-e1145d011ef6 github.com/matsuridayo/libneko v0.0.0-20230913024055-5277a5bfc889 github.com/sagernet/sing v0.5.0-beta.1 github.com/sagernet/sing-box v1.10.0-beta.5 grpc_server v1.0.0 ) -replace github.com/sagernet/sing-box => github.com/Mahdi-zarei/sing-box v1.3.5-0.20240902015024-87ce1b5463e9 +replace github.com/sagernet/sing-box => github.com/Mahdi-zarei/sing-box v1.3.5-0.20240903235116-2a7756b546b9 require ( berty.tech/go-libtor v1.0.385 // indirect diff --git a/go/cmd/nekobox_core/go.sum b/go/cmd/nekobox_core/go.sum index 2a252e9..9c6d6d2 100644 --- a/go/cmd/nekobox_core/go.sum +++ b/go/cmd/nekobox_core/go.sum @@ -4,10 +4,10 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/Mahdi-zarei/sing-box v1.3.5-0.20240902015024-87ce1b5463e9 h1:w7wKaq2iez2/EOgM+sc3Ti5EKkUyXFWcbWRIZehPjPE= -github.com/Mahdi-zarei/sing-box v1.3.5-0.20240902015024-87ce1b5463e9/go.mod h1:VjyGsaBUZ32vwYx8zVXOti3FNfhHvf/ep/e5kDpkkM0= -github.com/Mahdi-zarei/sing-box-extra v0.0.0-20240902015241-67553399f0d3 h1:tPH8SfROa4mANNfzf6zCC4g4IUE+ZsP37o2URg1YQSs= -github.com/Mahdi-zarei/sing-box-extra v0.0.0-20240902015241-67553399f0d3/go.mod h1:WDV7JVlC/tzRBv0iOMNe8z9exRu0uSc79vT/8vnAbAQ= +github.com/Mahdi-zarei/sing-box v1.3.5-0.20240903235116-2a7756b546b9 h1:By3CYAqbFLkIWOxmpeg5jbd6gIY+qCM9PvuwcYCrcos= +github.com/Mahdi-zarei/sing-box v1.3.5-0.20240903235116-2a7756b546b9/go.mod h1:VjyGsaBUZ32vwYx8zVXOti3FNfhHvf/ep/e5kDpkkM0= +github.com/Mahdi-zarei/sing-box-extra v0.0.0-20240904000146-e1145d011ef6 h1:p/sgsZ98PukqosSZPVjAy3yxmymKDi2DrS0X2lPC7a4= +github.com/Mahdi-zarei/sing-box-extra v0.0.0-20240904000146-e1145d011ef6/go.mod h1:02D/Khg/+qB8Cc8LVy3g1PdzrmS9RBytU3xbNVIMuzw= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI= diff --git a/main/NekoGui.cpp b/main/NekoGui.cpp index 7dd8f27..f896f7b 100644 --- a/main/NekoGui.cpp +++ b/main/NekoGui.cpp @@ -394,6 +394,20 @@ namespace NekoGui { return fn; } + QString FindNekorayRealPath() { + auto fn = QApplication::applicationDirPath() + "/"; +#ifdef Q_OS_LINUX + fn += "launcher"; +#elif Q_OS_WIN + fn += "nekoray.exe" +#else + fn += "nekoray" +#endif + auto fi = QFileInfo(fn); + if (fi.isSymLink()) return fi.symLinkTarget(); + return fn; + } + short isAdminCache = -1; // IsAdmin 主要判断:有无权限启动 Tun @@ -405,7 +419,7 @@ namespace NekoGui { admin = Windows_IsInAdmin(); #else #ifdef Q_OS_LINUX - admin |= Linux_GetCapString(FindNekoBoxCoreRealPath()).contains("cap_net_admin"); + admin |= Linux_GetCapString(FindNekorayRealPath()).contains("cap_sys_admin"); #endif admin |= geteuid() == 0; #endif diff --git a/main/NekoGui.hpp b/main/NekoGui.hpp index 71a855e..0e9a14b 100644 --- a/main/NekoGui.hpp +++ b/main/NekoGui.hpp @@ -14,6 +14,8 @@ namespace NekoGui { QString FindNekoBoxCoreRealPath(); + QString FindNekorayRealPath(); + bool IsAdmin(); } // namespace NekoGui diff --git a/rpc/gRPC.cpp b/rpc/gRPC.cpp index f0d1860..3f21803 100644 --- a/rpc/gRPC.cpp +++ b/rpc/gRPC.cpp @@ -220,7 +220,7 @@ namespace NekoGui_rpc { return {reply.error().c_str()}; } else { NOT_OK - return ""; + return reply.error().c_str(); } } diff --git a/sys/ExternalProcess.cpp b/sys/ExternalProcess.cpp index d05065f..66abf95 100644 --- a/sys/ExternalProcess.cpp +++ b/sys/ExternalProcess.cpp @@ -53,7 +53,12 @@ namespace NekoGui_sys { } QProcess::setEnvironment(env); +#ifdef Q_OS_LINUX + if (NekoGui::IsAdmin()) QProcess::startCommand("sudo " + program + " " + arguments.join(" ")); + else QProcess::start(program, arguments); +#else QProcess::start(program, arguments); +#endif } void ExternalProcess::Kill() { diff --git a/ui/dialog_vpn_settings.cpp b/ui/dialog_vpn_settings.cpp index b772951..bdac3a3 100644 --- a/ui/dialog_vpn_settings.cpp +++ b/ui/dialog_vpn_settings.cpp @@ -53,6 +53,6 @@ void DialogVPNSettings::on_troubleshooting_clicked() { tr("Reset"), tr("Cancel"), "", 1, 1); if (r == 0) { - GetMainWindow()->StopVPNProcess(true); + GetMainWindow()->StopVPNProcess(); } } diff --git a/ui/mainwindow.cpp b/ui/mainwindow.cpp index af7c9f4..7ef3738 100644 --- a/ui/mainwindow.cpp +++ b/ui/mainwindow.cpp @@ -712,14 +712,12 @@ bool MainWindow::get_elevated_permissions() { MessageBoxWarning(software_name, "Please install \"pkexec\" first."); return false; } - auto ret = Linux_Pkexec_SetCapString(NekoGui::FindNekoBoxCoreRealPath(), "cap_net_admin=ep"); - if (ret == 0) { - this->exit_reason = 3; - on_menu_exit_triggered(); - } else { - MessageBoxWarning(software_name, "Setcap for Tun mode failed.\n\n1. You may canceled the dialog.\n2. You may be using an incompatible environment like AppImage."); - if (QProcessEnvironment::systemEnvironment().contains("APPIMAGE")) { - MW_show_log("If you are using AppImage, it's impossible to start a Tun. Please use other package instead."); + auto n = QMessageBox::warning(GetMessageBoxParent(), software_name, tr("Please run Nekoray as admin"), QMessageBox::Yes | QMessageBox::No); + if (n == QMessageBox::Yes) { + auto ret = Linux_Pkexec_SetCapString(NekoGui::FindNekorayRealPath(), "cap_sys_admin=ep"); + if (ret == 0) { + this->exit_reason = 3; + on_menu_exit_triggered(); } } #endif @@ -1755,10 +1753,10 @@ void MainWindow::RegisterHotkey(bool unregister) {} void MainWindow::HotkeyEvent(const QString &key) {} #endif -bool MainWindow::StopVPNProcess(bool unconditional) { - if (unconditional || vpn_pid != 0) { +bool MainWindow::StopVPNProcess() { + if (vpn_pid != 0) { bool ok; - core_process->processId(); + vpn_pid = core_process->processId(); #ifdef Q_OS_WIN auto ret = WinCommander::runProcessElevated("taskkill", {"/IM", "nekobox_core.exe", "/FI", @@ -1770,18 +1768,12 @@ bool MainWindow::StopVPNProcess(bool unconditional) { p.start("osascript", {"-e", QString("do shell script \"%1\" with administrator privileges") .arg("pkill -2 -U 0 nekobox_core")}); #else - if (unconditional) { - p.start("pkexec", {"killall", "-2", "nekobox_core"}); - } else { - p.start("pkexec", {"pkill", "-2", "-P", Int2String(vpn_pid)}); - } + p.start("pkexec", {"pkill", "-2", "-P", Int2String(vpn_pid)}); #endif p.waitForFinished(); ok = p.exitCode() == 0; #endif - if (!unconditional) { - ok ? vpn_pid = 0 : MessageBoxWarning(tr("Error"), tr("Failed to stop Tun process")); - } + ok ? vpn_pid = 0 : MessageBoxWarning(tr("Error"), tr("Failed to stop Tun process")); return ok; } return true; diff --git a/ui/mainwindow.h b/ui/mainwindow.h index f150398..0b3e3c2 100644 --- a/ui/mainwindow.h +++ b/ui/mainwindow.h @@ -68,7 +68,7 @@ public: void RegisterHotkey(bool unregister); - bool StopVPNProcess(bool unconditional = false); + bool StopVPNProcess(); void DownloadAssets(const QString &geoipUrl, const QString &geositeUrl); diff --git a/ui/mainwindow_grpc.cpp b/ui/mainwindow_grpc.cpp index 655756e..e148ca8 100644 --- a/ui/mainwindow_grpc.cpp +++ b/ui/mainwindow_grpc.cpp @@ -248,11 +248,11 @@ void MainWindow::neko_start(int _id) { if (error.contains("configure tun interface")) { runOnUiThread([=] { auto r = QMessageBox::information(this, tr("Tun device misbehaving"), - tr("If you have trouble starting VPN, you can force reset nekobox_core process here and then try starting the profile again."), + tr("If you have trouble starting VPN, you can force reset nekobox_core process here and then try starting the profile again. The error is %1").arg(error), tr("Reset"), tr("Cancel"), "", 1, 1); if (r == 0) { - GetMainWindow()->StopVPNProcess(true); + GetMainWindow()->StopVPNProcess(); } }); return false;