nekoray: make it possible to use setcap wrapper

This commit is contained in:
aleksana
2025-05-26 00:08:39 +08:00
parent b9e47d97ac
commit 162ce8a4ba
3 changed files with 100 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
diff --git a/server.go b/server.go
index c2a6be0..8aeca1c 100644
--- a/server.go
+++ b/server.go
@@ -11,6 +11,7 @@ import (
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/metadata"
"github.com/sagernet/sing/service"
+ "golang.org/x/sys/unix"
"log"
"nekobox_core/gen"
"nekobox_core/internal/boxbox"
@@ -359,13 +360,25 @@ func (s *server) CompileGeoSiteToSrs(ctx context.Context, in *gen.CompileGeoSite
}
func (s *server) IsPrivileged(ctx context.Context, _ *gen.EmptyReq) (*gen.IsPrivilegedResponse, error) {
- if runtime.GOOS == "windows" {
- return &gen.IsPrivilegedResponse{
- HasPrivilege: false,
- }, nil
+ ret := false
+ if runtime.GOOS == "windows" || os.Geteuid() == 0 {
+ ret = true
+ } else if runtime.GOOS == "linux" {
+ caps := unix.CapUserHeader{
+ Version: unix.LINUX_CAPABILITY_VERSION_3,
+ Pid: 0, // current
+ }
+ var data [2]unix.CapUserData
+ err := unix.Capget(&caps, &data[0])
+ if err != nil {
+ ret = false
+ } else {
+ // CAP_NET_ADMIN = 12
+ ret = (data[0].Effective & (1 << unix.CAP_NET_ADMIN)) != 0
+ }
}
- return &gen.IsPrivilegedResponse{HasPrivilege: os.Geteuid() == 0}, nil
+ return &gen.IsPrivilegedResponse{HasPrivilege: ret}, nil
}
func (s *server) SpeedTest(ctx context.Context, in *gen.SpeedTestRequest) (*gen.SpeedTestResponse, error) {

View File

@@ -0,0 +1,47 @@
diff --git a/src/global/NekoGui.cpp b/src/global/NekoGui.cpp
index 7943d7a..5bb20cc 100644
--- a/src/global/NekoGui.cpp
+++ b/src/global/NekoGui.cpp
@@ -355,6 +355,12 @@ namespace NekoGui {
// System Utils
QString FindNekoBoxCoreRealPath() {
+ // find in PATH first
+ QString path = QStandardPaths::findExecutable("nekobox_core");
+ if (!path.isEmpty()) {
+ return path;
+ }
+
auto fn = QApplication::applicationDirPath() + "/nekobox_core";
auto fi = QFileInfo(fn);
if (fi.isSymLink()) return fi.symLinkTarget();
diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp
index 9aa46b2..ba7137a 100644
--- a/src/ui/mainwindow.cpp
+++ b/src/ui/mainwindow.cpp
@@ -125,8 +125,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
NekoGui::dataStore->core_port = MkPort();
if (NekoGui::dataStore->core_port <= 0) NekoGui::dataStore->core_port = 19810;
- auto core_path = QApplication::applicationDirPath() + "/";
- core_path += "nekobox_core";
+ auto core_path = NekoGui::FindNekoBoxCoreRealPath();
QStringList args;
args.push_back("nekobox");
@@ -844,6 +843,15 @@ bool MainWindow::get_elevated_permissions(int reason) {
return true;
}
if (NekoGui::IsAdmin()) return true;
+ QMessageBox::critical(
+ GetMessageBoxParent(),
+ tr("Unable to elevate privileges when installed with Nix"),
+ tr("Due to the read-only property of Nix store, we cannot set suid for nekobox_core. If you are using NixOS, please set `programs.nekoray.tunMode.enable` option to elevate privileges."),
+ QMessageBox::Ok
+ );
+ return false;
+ // The following code isn't effective, preserve to avoid merge conflict
+
#ifdef Q_OS_LINUX
if (!Linux_HavePkexec()) {
MessageBoxWarning(software_name, "Please install \"pkexec\" first.");

View File

@@ -60,6 +60,11 @@ stdenv.mkDerivation (finalAttrs: {
# we already package those two files in nixpkgs
# we can't place file at that location using our builder so we must change the search directory to be relative to the built executable
./search-for-geodata-in-install-location.patch
# disable suid request as it cannot be applied to nekobox_core in nix store
# and prompt users to use NixOS module instead. And use nekobox_core from PATH
# to make use of security wrappers
./nixos-disable-setuid-request.patch
];
installPhase = ''
@@ -99,6 +104,11 @@ stdenv.mkDerivation (finalAttrs: {
inherit (finalAttrs) version src;
sourceRoot = "${finalAttrs.src.name}/core/server";
patches = [
# also check cap_net_admin so we don't have to set suid
./core-also-check-capabilities.patch
];
vendorHash = "sha256-CTI9wDPJ9dYpUwvszY2nRfi+NW0nO8imt9lsQ7Nd1Q8=";
# ldflags and tags are taken from script/build_go.sh