Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions nixos/modules/programs/nekobox.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
{
config,
pkgs,
lib,
...
}:

let
cfg = config.programs.nekobox;
in
{

options = {
programs.nekobox = {
enable = lib.mkEnableOption "NekoBox, the proxy tool";

package = lib.mkPackageOption pkgs "nekobox" { };

tunMode = {
enable = lib.mkEnableOption "TUN mode of NekoBox";

setuid = lib.mkEnableOption ''
Setting the suid bit for NekoBox is optional,
unless you want to avoid prompting for password.
The capabilities of the running process will be set
every time TUN mode checked.
'';
};
};
};

config = lib.mkIf cfg.enable {

environment.systemPackages = [ cfg.package ];

security.wrappers.nekobox-core = lib.mkIf cfg.tunMode.enable {
source = "${cfg.package}/libexec/Iblis/nekobox-core";
owner = "root";
group = "root";
setuid = lib.mkIf cfg.tunMode.setuid true;
# Taken from https://github.com/SagerNet/sing-box/blob/dev-next/release/config/sing-box.service
capabilities = lib.mkIf (
!cfg.tunMode.setuid
) "cap_net_admin,cap_net_raw,cap_net_bind_service,cap_sys_ptrace,cap_dac_read_search+ep";
};

# avoid resolvectl password prompt popping up three times
# credits: aleksana
security.polkit.extraConfig =
lib.mkIf (cfg.tunMode.enable && (!cfg.tunMode.setuid) && config.services.resolved.enable)
''
polkit.addRule(function(action, subject) {
const allowedActionIds = [
"org.freedesktop.resolve1.set-domains",
"org.freedesktop.resolve1.set-default-route",
"org.freedesktop.resolve1.set-dns-servers"
];

if (allowedActionIds.indexOf(action.id) !== -1) {
try {
var parentPid = polkit.spawn(["${lib.getExe' pkgs.procps "ps"}", "-o", "ppid=", subject.pid]).trim();
var parentCap = polkit.spawn(["${lib.getExe' pkgs.libcap "getpcaps"}", parentPid]).trim();
if (parentCap.includes("cap_net_admin") && parentCap.includes("cap_net_raw")) {
return polkit.Result.YES;
} else {
return polkit.Result.NOT_HANDLED;
}
} catch (e) {
return polkit.Result.NOT_HANDLED;
}
}
})
'';
};

meta.maintainers = with lib.maintainers; [ qr243vbi ];
}
67 changes: 67 additions & 0 deletions pkgs/by-name/ne/nekobox/package.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{
pkgconfig ? import <nixpkgs> {}.pkgconfig
, automake ? import <nixpkgs> {}.automake
, autoconf ? import <nixpkgs> {}.autoconf
, libtool ? import <nixpkgs> {}.libtool
, bash ? import <nixpkgs> {}.bash
, makeWrapper ? import <nixpkgs> {}.makeWrapper
, pkgs ? import <nixpkgs> {}
}:

pkgs.stdenv.mkDerivation rec {
pname = "nekobox";
version = "5.10.29";

src = pkgs.fetchurl {
url = "https://github.com/qr243vbi/nekobox/releases/download/5.10.29/nekobox-unified-source-5.10.29.tar.xz";
sha256 = "9fa7c21aeb4e62b6a9eda1bfdea9eb24d8448c7cda56c0e0010e93558f48514a";
};

nativeBuildInputs = [
pkgs.cmake
pkgs.ninja
pkgs.qt6.wrapQtAppsHook
];

buildInputs = [
pkgs.qt6.qtbase
pkgs.qt6.qtdeclarative
pkgs.qt6.qtsvg
pkgs.qt6.qttools
pkgs.thrift
pkgs.pkg-config
pkgs.go
pkgs.boost
pkgs.acl
];

GOFLAGS = "-modcacherw -mod=vendor";
CGO_ENABLED = "1";

preBuild = ''
export HOME=$TMPDIR
export GOTOOLCHAIN=local
export GOCACHE=$TMPDIR/go-cache
export GOMODCACHE=$TMPDIR/go-mod-cache

mkdir -p "$GOCACHE" "$GOMODCACHE"
'';

# configurePhase = ''
# '';

# buildPhase = ''
# '';

# installPhase = ''
# '';

meta = with pkgs.lib; {
description = "NyameBox, The Original NekoBox Rebranded, the cross-platform Qt proxy utility, empowered by sing-box and thrift";
homepage = "https://github.com/qr243vbi/nekobox";
license = licenses.gpl3Plus;
maintainers = with maintainers; [ qr243vbi ];
mainProgram = "nekobox";
platforms = lib.platforms.linux;
};
}
Loading