From 75925de96941686e8b41a526c926152be4678694 Mon Sep 17 00:00:00 2001 From: Eric Lesiuta Date: Fri, 14 Apr 2023 22:07:09 -0400 Subject: [PATCH 1/3] maintainers: add elesiuta --- maintainers/maintainer-list.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/maintainers/maintainer-list.nix b/maintainers/maintainer-list.nix index 3fb9d7e304f7..9ebee7cbf140 100644 --- a/maintainers/maintainer-list.nix +++ b/maintainers/maintainer-list.nix @@ -4407,6 +4407,12 @@ githubId = 103082; name = "Ed Brindley"; }; + elesiuta = { + email = "elesiuta@gmail.com"; + github = "elesiuta"; + githubId = 8146662; + name = "Eric Lesiuta"; + }; eliandoran = { email = "contact@eliandoran.me"; name = "Elian Doran"; From a4eebda62e3eb8b08a9ca9f4fe1e73f44436f967 Mon Sep 17 00:00:00 2001 From: Eric Lesiuta Date: Fri, 14 Apr 2023 22:08:13 -0400 Subject: [PATCH 2/3] picosnitch: init at 0.12.0 --- pkgs/tools/networking/picosnitch/default.nix | 38 ++++++ .../networking/picosnitch/picosnitch.patch | 111 ++++++++++++++++++ pkgs/top-level/all-packages.nix | 2 + 3 files changed, 151 insertions(+) create mode 100644 pkgs/tools/networking/picosnitch/default.nix create mode 100644 pkgs/tools/networking/picosnitch/picosnitch.patch diff --git a/pkgs/tools/networking/picosnitch/default.nix b/pkgs/tools/networking/picosnitch/default.nix new file mode 100644 index 000000000000..03df8639d182 --- /dev/null +++ b/pkgs/tools/networking/picosnitch/default.nix @@ -0,0 +1,38 @@ +{ lib +, python3 +, bcc +}: + +python3.pkgs.buildPythonApplication rec { + pname = "picosnitch"; + version = "0.12.0"; + + src = python3.pkgs.fetchPypi { + inherit pname version; + sha256 = "b87654b4b92e28cf5418388ba1d3165b9fa9b17ba91af2a1a942f059128f68bc"; + }; + + propagatedBuildInputs = with python3.pkgs; [ + setuptools + bcc + psutil + dbus-python + requests + pandas + plotly + dash + ]; + + patches = [ ./picosnitch.patch ]; + + pythonImportsCheck = [ "picosnitch" ]; + + meta = with lib; { + description = "Monitor network traffic per executable with hashing"; + homepage = "https://github.com/elesiuta/picosnitch"; + changelog = "https://github.com/elesiuta/picosnitch/releases"; + license = licenses.gpl3Plus; + maintainers = [ maintainers.elesiuta ]; + platforms = platforms.linux; + }; +} diff --git a/pkgs/tools/networking/picosnitch/picosnitch.patch b/pkgs/tools/networking/picosnitch/picosnitch.patch new file mode 100644 index 000000000000..fb4433a6f4b8 --- /dev/null +++ b/pkgs/tools/networking/picosnitch/picosnitch.patch @@ -0,0 +1,111 @@ +diff --git a/picosnitch.py b/picosnitch.py +index a3dbb07..2b74f3e 100755 +--- a/picosnitch.py ++++ b/picosnitch.py +@@ -1356,7 +1356,7 @@ def ui_loop(stdscr: curses.window, splash: str, con: sqlite3.Connection) -> int: + update_query = False + if execute_query: + try: +- with open("/run/picosnitch.pid", "r") as f: ++ with open("/run/picosnitch/picosnitch.pid", "r") as f: + run_status = "pid: " + f.read().strip() + except Exception: + run_status = "not running" +@@ -1603,7 +1603,7 @@ def ui_dash(): + return cmdline + def serve_layout(): + try: +- with open("/run/picosnitch.pid", "r") as f: ++ with open("/run/picosnitch/picosnitch.pid", "r") as f: + run_status = "pid: " + f.read().strip() + except Exception: + run_status = "not running" +@@ -1771,7 +1771,7 @@ def main(): + # master copy of the snitch dictionary, all subprocesses only receive a static copy of it from this point in time + snitch = read_snitch() + # start picosnitch process monitor +- with open("/run/picosnitch.pid", "r") as f: ++ with open("/run/picosnitch/picosnitch.pid", "r") as f: + assert int(f.read().strip()) == os.getpid() + if __name__ == "__main__" or sys.argv[1] == "start-no-daemon": + sys.exit(main_process(snitch)) +@@ -1818,7 +1818,7 @@ def start_picosnitch(): + RestartSec=5 + Environment="SUDO_UID={os.getenv("SUDO_UID")}" "SUDO_USER={os.getenv("SUDO_USER")}" "DBUS_SESSION_BUS_ADDRESS={os.getenv("DBUS_SESSION_BUS_ADDRESS")}" "PYTHON_USER_SITE={site.USER_SITE}" + ExecStart={sys.executable} "{os.path.abspath(__file__)}" start-no-daemon +- PIDFile=/run/picosnitch.pid ++ PIDFile=/run/picosnitch/picosnitch.pid + + [Install] + WantedBy=multi-user.target +@@ -1832,12 +1832,12 @@ def start_picosnitch(): + subprocess.Popen(["bash", "-c", f'let i=0; rm {BASE_PATH}/dash; while [[ ! -f {BASE_PATH}/dash || "$i" -gt 30 ]]; do let i++; sleep 1; done; rm {BASE_PATH}/dash && /usr/bin/env python3 -m webbrowser -t http://{os.getenv("HOST", "localhost")}:{os.getenv("PORT", "5100")}'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + if os.getuid() != 0: + args = ["sudo", "-E", sys.executable, os.path.abspath(__file__), sys.argv[1]] +- os.execvp("sudo", args) ++ assert sys.argv[1] not in ["start", "stop", "restart", "start-no-daemon"], "picosnitch requires root privileges to run" + with open("/proc/self/status", "r") as f: + proc_status = f.read() + capeff = int(proc_status[proc_status.find("CapEff:")+8:].splitlines()[0].strip(), base=16) + cap_sys_admin = 2**21 +- assert capeff & cap_sys_admin, "Missing capability CAP_SYS_ADMIN" ++ assert sys.argv[1] not in ["start", "stop", "restart", "start-no-daemon"] or (capeff & cap_sys_admin), "Missing capability CAP_SYS_ADMIN" + assert importlib.util.find_spec("bcc"), "Requires BCC https://github.com/iovisor/bcc/blob/master/INSTALL.md" + tmp_snitch = read_snitch() + con = sqlite3.connect(os.path.join(BASE_PATH, "snitch.db")) +@@ -1883,8 +1883,8 @@ def start_picosnitch(): + except Exception as e: + print("Warning: %s%s on line %s" % (type(e).__name__, str(e.args), sys.exc_info()[2].tb_lineno), file=sys.stderr) + if sys.argv[1] in ["start", "stop", "restart"]: +- if os.path.exists("/usr/lib/systemd/system/picosnitch.service"): +- print("Found /usr/lib/systemd/system/picosnitch.service but you are not using systemctl") ++ if os.path.exists("/usr/lib/systemd/system/picosnitch.service") or os.path.exists("/etc/systemd/system/picosnitch.service"): ++ print("Found picosnitch.service but you are not using systemctl") + if sys.stdin.isatty(): + confirm = input(f"Did you intend to run `systemctl {sys.argv[1]} picosnitch` (y/N)? ") + if confirm.lower().startswith("y"): +@@ -1893,15 +1893,15 @@ def start_picosnitch(): + class PicoDaemon(Daemon): + def run(self): + main() +- daemon = PicoDaemon("/run/picosnitch.pid") ++ daemon = PicoDaemon("/run/picosnitch/picosnitch.pid") + if sys.argv[1] == "start": +- print("starting picosnitch daemon") ++ print("starting picosnitch daemon, WARNING: built in daemon mode is not supported on Nix, use picosnitch start-no-daemon or systemctl instead") + daemon.start() + elif sys.argv[1] == "stop": +- print("stopping picosnitch daemon") ++ print("stopping picosnitch daemon, WARNING: built in daemon mode is not supported on Nix, use picosnitch start-no-daemon or systemctl instead") + daemon.stop() + elif sys.argv[1] == "restart": +- print("restarting picosnitch daemon") ++ print("restarting picosnitch daemon, WARNING: built in daemon mode is not supported on Nix, use picosnitch start-no-daemon or systemctl instead") + daemon.restart() + elif sys.argv[1] == "status": + daemon.status() +@@ -1912,11 +1912,12 @@ def start_picosnitch(): + print("Wrote /usr/lib/systemd/system/picosnitch.service\nYou can now run picosnitch using systemctl") + return 0 + elif sys.argv[1] == "start-no-daemon": +- assert not os.path.exists("/run/picosnitch.pid") ++ assert not os.path.exists("/run/picosnitch/picosnitch.pid") + def delpid(): +- os.remove("/run/picosnitch.pid") ++ os.remove("/run/picosnitch/picosnitch.pid") + atexit.register(delpid) +- with open("/run/picosnitch.pid", "w") as f: ++ os.makedirs("/run/picosnitch", exist_ok=True) ++ with open("/run/picosnitch/picosnitch.pid", "w") as f: + f.write(str(os.getpid()) + "\n") + print("starting picosnitch in simple mode") + print(f"using config and log files from: {BASE_PATH}") +@@ -1927,7 +1928,7 @@ def start_picosnitch(): + assert dash.__version__ and pandas.__version__ and plotly.__version__ + print(f"serving web gui on http://{os.getenv('HOST', 'localhost')}:{os.getenv('PORT', '5100')}") + args = ["bash", "-c", f"sudo -i -u {os.getenv('SUDO_USER')} touch {BASE_PATH}/dash; nohup {sys.executable} \"{os.path.abspath(__file__)}\" start-dash > /dev/null 2>&1 &"] +- os.execvp("bash", args) ++ return ui_dash() + elif sys.argv[1] == "start-dash": + return ui_dash() + elif sys.argv[1] == "view": diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 2a89ff3dcc29..84614654940a 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -32929,6 +32929,8 @@ with pkgs; picoloop = callPackage ../applications/audio/picoloop { }; + picosnitch = callPackage ../tools/networking/picosnitch { }; + pidgin = callPackage ../applications/networking/instant-messengers/pidgin { withOpenssl = config.pidgin.openssl or true; withGnutls = config.pidgin.gnutls or false; From acfed642249887ce8b5a0401e0bfcdb864622a06 Mon Sep 17 00:00:00 2001 From: Eric Lesiuta Date: Fri, 14 Apr 2023 22:09:48 -0400 Subject: [PATCH 3/3] nixos/picosnitch: init --- nixos/modules/module-list.nix | 1 + .../services/networking/picosnitch.nix | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 nixos/modules/services/networking/picosnitch.nix diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index bac096efac2c..08b9100ea0fd 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -955,6 +955,7 @@ ./services/networking/pdns-recursor.nix ./services/networking/pdnsd.nix ./services/networking/peroxide.nix + ./services/networking/picosnitch.nix ./services/networking/pixiecore.nix ./services/networking/pleroma.nix ./services/networking/polipo.nix diff --git a/nixos/modules/services/networking/picosnitch.nix b/nixos/modules/services/networking/picosnitch.nix new file mode 100644 index 000000000000..c9b38c1929ca --- /dev/null +++ b/nixos/modules/services/networking/picosnitch.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.picosnitch; +in +{ + options.services.picosnitch = { + enable = mkEnableOption (lib.mdDoc "picosnitch daemon"); + }; + config = mkIf cfg.enable { + environment.systemPackages = [ pkgs.picosnitch ]; + systemd.services.picosnitch = { + description = "picosnitch"; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Type = "simple"; + Restart = "always"; + RestartSec = 5; + ExecStart = "${pkgs.picosnitch}/bin/picosnitch start-no-daemon"; + PIDFile = "/run/picosnitch/picosnitch.pid"; + }; + }; + }; +}