diff --git a/.github/workflows/perseus.yaml b/.github/workflows/perseus.yaml index 2c36191..5ccc270 100644 --- a/.github/workflows/perseus.yaml +++ b/.github/workflows/perseus.yaml @@ -37,6 +37,7 @@ jobs: } EOF + - run: nix flake update oisd - run: nix flake check - run: nix flake show - run: echo "=== user-config.nix content ===" && cat user-config.nix diff --git a/.github/workflows/trufflehog.yaml b/.github/workflows/trufflehog.yaml index 36ac43d..5d92fcf 100644 --- a/.github/workflows/trufflehog.yaml +++ b/.github/workflows/trufflehog.yaml @@ -14,22 +14,9 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 - - name: Install TruffleHog - run: | - python -m pip install --upgrade pip - pip install truffleHog - - name: Run TruffleHog and Check Output - run: | - trufflehog --json . --exclude-path flake.lock > trufflehog_report.json || true - if [ -s trufflehog_report.json ]; then - echo No secrets found - cat trufflehog_report.json - exit 1 - else - echo No secrets found - fi - - name: Upload Report - uses: actions/upload-artifact@v4 with: - name: trufflehog-report - path: trufflehog_report.json \ No newline at end of file + fetch-depth: 0 + - name: TruffleHog Scan + uses: trufflesecurity/trufflehog@main + with: + extra_args: --only-verified diff --git a/flake.lock b/flake.lock index 244a3a0..fb49a5c 100644 --- a/flake.lock +++ b/flake.lock @@ -46,7 +46,47 @@ "url": "https://flakehub.com/f/ipetkov/crane/0" } }, + "danksearch": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1766814755, + "narHash": "sha256-iVZHhERnR07PMLSjVMW/72ah7ezyqaxdADmJQ8FdToU=", + "owner": "AvengeMedia", + "repo": "danksearch", + "rev": "2356124150c7a35a735d88a3d54a941b6cfe3a02", + "type": "github" + }, + "original": { + "owner": "AvengeMedia", + "repo": "danksearch", + "type": "github" + } + }, "dgop": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1765838956, + "narHash": "sha256-A3a2ZfvjirX8VIdIPI+nAyukWs6vx4vet3fU0mpr7lU=", + "owner": "AvengeMedia", + "repo": "dgop", + "rev": "0ff697a4e3418966caa714c838fc73f1ef6ba59b", + "type": "github" + }, + "original": { + "owner": "AvengeMedia", + "repo": "dgop", + "type": "github" + } + }, + "dgop_2": { "inputs": { "nixpkgs": [ "dms", @@ -89,7 +129,7 @@ }, "dms": { "inputs": { - "dgop": "dgop", + "dgop": "dgop_2", "nixpkgs": [ "nixpkgs" ], @@ -363,6 +403,18 @@ "type": "github" } }, + "oisd": { + "flake": false, + "locked": { + "narHash": "sha256-KY+xqXiLrT5yMRURAndbO4R66k0Dk/tAXC84SCTR4q4=", + "type": "file", + "url": "https://big.oisd.nl/domainswild" + }, + "original": { + "type": "file", + "url": "https://big.oisd.nl/domainswild" + } + }, "quickshell": { "inputs": { "nixpkgs": [ @@ -389,12 +441,15 @@ "inputs": { "betterfox": "betterfox", "catppuccin-firefox": "catppuccin-firefox", + "danksearch": "danksearch", + "dgop": "dgop", "disko": "disko", "dms": "dms", "flakehub": "flakehub", "home-manager": "home-manager", "nixpkgs": "nixpkgs_2", "nixvim": "nixvim", + "oisd": "oisd", "sops-nix": "sops-nix", "thunderbird-catppuccin": "thunderbird-catppuccin" } diff --git a/flake.nix b/flake.nix index a3ce907..81daf1c 100644 --- a/flake.nix +++ b/flake.nix @@ -5,12 +5,17 @@ nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; nixvim.url = "github:nix-community/nixvim/nixos-25.11"; + dgop.url = "github:AvengeMedia/dgop"; + dgop.inputs.nixpkgs.follows = "nixpkgs"; + disko.url = "github:nix-community/disko"; disko.inputs.nixpkgs.follows = "nixpkgs"; + flakehub.url = "github:DeterminateSystems/fh"; + sops-nix.url = "github:Mic92/sops-nix"; sops-nix.inputs.nixpkgs.follows = "nixpkgs"; - thunderbird-catppuccin.url = "github:catppuccin/thunderbird"; + home-manager.url = "github:nix-community/home-manager/release-25.11"; home-manager.inputs.nixpkgs.follows = "nixpkgs"; @@ -18,10 +23,20 @@ dms.url = "github:AvengeMedia/DankMaterialShell"; dms.inputs.nixpkgs.follows = "nixpkgs"; + danksearch.url = "github:AvengeMedia/danksearch"; + danksearch.inputs.nixpkgs.follows = "nixpkgs"; + + oisd = { + url = "https://big.oisd.nl/domainswild"; + flake = false; + }; + + thunderbird-catppuccin.url = "github:catppuccin/thunderbird"; catppuccin-firefox = { url = "github:catppuccin/firefox"; flake = false; }; + betterfox = { url = "github:yokoffing/Betterfox"; flake = false; @@ -30,7 +45,7 @@ outputs = { nixpkgs, flakehub, home-manager, ... }@inputs: let - version = "1.2.0"; + version = "1.3.0"; userConfig = import ./user-config.nix; lib = nixpkgs.lib; diff --git a/home/firefox/default.nix b/home/firefox/default.nix index fc2c5d0..661bb41 100644 --- a/home/firefox/default.nix +++ b/home/firefox/default.nix @@ -2,7 +2,7 @@ { programs.firefox = { enable = true; - package = pkgs.firefox; # Use the standard Firefox package + package = pkgs.firefox; policies = import ./policies.nix { inherit lib; }; diff --git a/home/firefox/policies.nix b/home/firefox/policies.nix index 976d6a3..c866e02 100644 --- a/home/firefox/policies.nix +++ b/home/firefox/policies.nix @@ -26,7 +26,7 @@ DisableFeedbackCommands = true; DontCheckDefaultBrowser = true; DNSOverHTTPS = { - Enabled = true; + Enabled = false; }; EnableTrackingProtection = { Value = true; diff --git a/home/firefox/settings.nix b/home/firefox/settings.nix index afd6188..06f68df 100644 --- a/home/firefox/settings.nix +++ b/home/firefox/settings.nix @@ -20,6 +20,12 @@ in "privacy.userContext.ui.enabled" = true; "privacy.userContext.longPressBehavior" = 2; + "media.peerconnection.enabled" = false; + "media.peerconnection.ice.default_address_only" = true; + "media.peerconnection.ice.no_host" = true; + "network.dns.echconfig.enabled" = true; + "network.dns.use_https_rr_as_altsvc" = true; + # Smooth Scroll "general.smoothScroll" = true; "general.smoothScroll.lines.durationMaxMS" = 125; diff --git a/modules/app-telemetry-deny.nix b/modules/app-telemetry-deny.nix index d5107da..e25e51c 100644 --- a/modules/app-telemetry-deny.nix +++ b/modules/app-telemetry-deny.nix @@ -63,6 +63,22 @@ "codewhisperer.aws.amazon.com" "ai.jetbrains.com" "ai-assistant.jetbrains.com" + + # DoH/DoT bypass prevention - force apps to use system DNS + "mozilla.cloudflare-dns.com" + "dns.google" + "dns.google.com" + "cloudflare-dns.com" + "one.one.one.one" + "1dot1dot1dot1.cloudflare-dns.com" + "dns.quad9.net" + "dns9.quad9.net" + "dns10.quad9.net" + "dns11.quad9.net" + "doh.opendns.com" + "doh.cleanbrowsing.org" + "dns.adguard.com" + "dns.nextdns.io" ]; }; diff --git a/modules/dms.nix b/modules/dms.nix index c54342b..2549688 100644 --- a/modules/dms.nix +++ b/modules/dms.nix @@ -1,16 +1,27 @@ -{ pkgs, userConfig, ... }: +{ pkgs, userConfig, inputs, ... }: { + environment.systemPackages = with pkgs; [ + cliphist + wl-clipboard + ]; + home-manager.users.${userConfig.username} = { - home.file.".config/DankMaterialShell/settings.json".text = builtins.toJSON { - blurredWallpaperLayer = false; - currentThemeName = "blue"; - use24HourClock = true; - cornerRadius = 12; - fontFamily = "Inter Variable"; - monoFontFamily = "Fira Code"; - barOpacity = 0; - widgetOpacity = 54; + imports = [ inputs.danksearch.homeModules.dsearch ]; + + + programs.dsearch.enable = true; + xdg.mimeApps = { + enable = true; + defaultApplications = { + "text/html" = "firefox.desktop"; + "x-scheme-handler/http" = "firefox.desktop"; + "x-scheme-handler/https" = "firefox.desktop"; + "x-scheme-handler/about" = "firefox.desktop"; + "x-scheme-handler/unknown" = "firefox.desktop"; + "application/xhtml+xml" = "firefox.desktop"; + "application/pdf" = "firefox.desktop"; + }; }; }; } diff --git a/modules/environment.nix b/modules/environment.nix index 31b54d9..9e3ae7c 100644 --- a/modules/environment.nix +++ b/modules/environment.nix @@ -89,7 +89,7 @@ in }; gnome.gnome-keyring.enable = true; # TLP is primary - upower.enable = false; + upower.enable = true; # Security opensnitch = { diff --git a/modules/firejail.nix b/modules/firejail.nix new file mode 100644 index 0000000..79b859e --- /dev/null +++ b/modules/firejail.nix @@ -0,0 +1,13 @@ +{ pkgs, ... }: + +{ + programs.firejail = { + enable = true; + wrappedBinaries = { + firfox ={ + executable = "${pkgs.firefox}/bin/firefox"; + profile = "${pkgs.firejail}/etc/firejail/firefox.profile"; + }; + }; + }; +} diff --git a/modules/gammastep.nix b/modules/gammastep.nix deleted file mode 100644 index 267e5e7..0000000 --- a/modules/gammastep.nix +++ /dev/null @@ -1,55 +0,0 @@ -{ pkgs, userConfig ? null, ... }: -let - # Use coordinates from userConfig or fallback to Amsterdam - latitude = if userConfig != null then toString userConfig.latitude else "52.37"; - longitude = if userConfig != null then toString userConfig.longitude else "4.89"; - - gammastep-toggle = pkgs.writeShellScriptBin "gammastep-toggle" '' - if systemctl --user is-active --quiet gammastep.service; then - systemctl --user stop gammastep.service - notify-send "Gammastep Off" -i display-brightness - echo "Gammastep Off" - else - systemctl --user start gammastep.service - notify-send "Gammastep On" -i display-brightness - echo "Gammastep On" - fi - ''; -in -{ - environment.systemPackages = [ gammastep-toggle ]; - - # Gammastep blue light filter service (Wayland native) - systemd.user.services.gammastep = { - description = "Gammastep blue light filter"; - wantedBy = [ "graphical-session.target" ]; - partOf = [ "graphical-session.target" ]; - after = [ "graphical-session.target" ]; - serviceConfig = { - Type = "simple"; - ExecStart = "${pkgs.gammastep}/bin/gammastep -l 52.37:4.89 -t 6500:3500 -b 1.0:0.9 -P -v"; - Restart = "always"; - RestartSec = 3; - }; - }; - - # Create a custom gammastep config - environment.etc."gammastep.conf" = { - text = '' - [gammastep] - temp-day=6500 - temp-night=3500 - transition=1 - brightness-day=1.0 - brightness-night=0.9 - location-provider=manual - adjustment-method=wayland - dawn-time=06:00-07:00 - dusk-time=22:00-23:00 - - [manual] - lat=${latitude} - lon=${longitude} - ''; - }; -} diff --git a/modules/greetd.nix b/modules/greetd.nix index 552b2af..86a92d1 100644 --- a/modules/greetd.nix +++ b/modules/greetd.nix @@ -9,7 +9,7 @@ security.pam.services = { greetd = { - fprintAuth = true; + fprintAuth = false; nodelay = true; enableGnomeKeyring = false; }; diff --git a/modules/niri.nix b/modules/niri.nix index 5b941e3..dd1eb74 100644 --- a/modules/niri.nix +++ b/modules/niri.nix @@ -1,14 +1,18 @@ { pkgs, userConfig, inputs, ... }: -let - # Lock command matching your sway config - lockCommand = "${pkgs.swaylock-effects}/bin/swaylock -f --screenshots --clock --indicator --indicator-radius 120 --indicator-thickness 8 --effect-blur 7x5 --effect-vignette 0.5:0.5 --ring-color e94560 --key-hl-color 0f3460 --line-color 00000000 --inside-color 1a1a2e88 --separator-color 00000000 --grace 3 --fade-in 0.1"; -in { programs.niri.enable = true; # Niri config in KDL format environment.etc."niri/config.kdl".text = '' + // ===================== + // DMS INTEGRATION + // ===================== + // Include DMS-managed configuration files + include "dms/colors.kdl" + include "dms/layout.kdl" + include "dms/binds.kdl" + // ===================== // INPUT CONFIGURATION // ===================== @@ -30,9 +34,6 @@ in mouse { // accel-speed 0.0 } - - // Hide cursor after 2 seconds of inactivity - // (niri doesn't have this yet, but leaving comment) } // ===================== @@ -41,7 +42,8 @@ in layout { gaps 8 - background-color "#1a1a2e" + // IMPORTANT: transparent for DMS overview wallpaper integration + background-color "transparent" center-focused-column "never" preset-column-widths { @@ -56,7 +58,7 @@ in focus-ring { width 2 active-color "#CAD3F5" - inactive-color "#5B6078" + inactive-color "#5B6078" } border { @@ -70,6 +72,21 @@ in } } + // ===================== + // LAYER RULES (DMS Integration) + // ===================== + // Place quickshell wallpaper on overview + layer-rule { + match namespace="^quickshell$" + place-within-backdrop true + } + + // Place blurred wallpaper on overview (if blur enabled) + layer-rule { + match namespace="dms:blurwallpaper" + place-within-backdrop true + } + // ===================== // CURSOR CONFIGURATION // ===================== @@ -105,6 +122,29 @@ in clip-to-geometry true } + // Open DMS windows as floating by default + window-rule { + match app-id=r#"org.quickshell$"# + open-floating true + } + + // GNOME apps styling + window-rule { + match app-id=r#"^org\.gnome\."# + draw-border-with-background false + geometry-corner-radius 12 + clip-to-geometry true + } + + // Terminal apps - no borders + window-rule { + match app-id=r#"^org\.wezfurlong\.wezterm$"# + match app-id="Alacritty" + match app-id="com.mitchellh.ghostty" + match app-id="kitty" + draw-border-with-background false + } + // ===================== // KEY BINDINGS // ===================== @@ -118,8 +158,25 @@ in // ===== VPN ===== Mod+Shift+V { spawn "mullvad-toggle"; } - // ===== APPLICATION LAUNCHERS ===== - Mod+D { spawn "rofi" "-show" "drun"; } + // ===== DMS APPLICATION LAUNCHERS ===== + Mod+Space hotkey-overlay-title="Application Launcher" { + spawn "dms" "ipc" "call" "spotlight" "toggle"; + } + Mod+D { spawn "dms" "ipc" "call" "spotlight" "toggle"; } + Mod+V hotkey-overlay-title="Clipboard Manager" { + spawn "dms" "ipc" "call" "clipboard" "toggle"; + } + Mod+Comma hotkey-overlay-title="Settings" { + spawn "dms" "ipc" "call" "settings" "focusOrToggle"; + } + Mod+N hotkey-overlay-title="Notification Center" { + spawn "dms" "ipc" "call" "notifications" "toggle"; + } + Mod+Y hotkey-overlay-title="Browse Wallpapers" { + spawn "dms" "ipc" "call" "dankdash" "wallpaper"; + } + + // ===== OTHER APP LAUNCHERS ===== Mod+B { spawn "firefox"; } Mod+C { spawn "slack"; } Mod+M { spawn "nemo"; } @@ -150,14 +207,14 @@ in Mod+Shift+Up { move-window-up; } // ===== COLUMN MANAGEMENT ===== - Mod+Comma { consume-window-into-column; } - Mod+Period { expel-window-from-column; } + Mod+Period { consume-window-into-column; } + Mod+Slash { expel-window-from-column; } // ===== LAYOUT ===== Mod+F { maximize-column; } Mod+Shift+F { fullscreen-window; } Mod+Shift+Space { toggle-window-floating; } - Mod+Space { switch-focus-between-floating-and-tiling; } + Mod+Tab { switch-focus-between-floating-and-tiling; } // Column width presets Mod+R { switch-preset-column-width; } @@ -198,14 +255,24 @@ in Mod+Ctrl+Shift+Left { move-column-to-monitor-left; } Mod+Ctrl+Shift+Right { move-column-to-monitor-right; } - // ===== MEDIA KEYS ===== - XF86AudioRaiseVolume { spawn "pactl" "set-sink-volume" "@DEFAULT_SINK@" "+5%"; } - XF86AudioLowerVolume { spawn "pactl" "set-sink-volume" "@DEFAULT_SINK@" "-5%"; } - XF86AudioMute { spawn "pactl" "set-sink-mute" "@DEFAULT_SINK@" "toggle"; } + // ===== MEDIA KEYS (via DMS) ===== + XF86AudioRaiseVolume allow-when-locked=true { + spawn "dms" "ipc" "call" "audio" "increment" "3"; + } + XF86AudioLowerVolume allow-when-locked=true { + spawn "dms" "ipc" "call" "audio" "decrement" "3"; + } + XF86AudioMute allow-when-locked=true { + spawn "dms" "ipc" "call" "audio" "mute"; + } - // ===== BRIGHTNESS ===== - XF86MonBrightnessUp { spawn "brightnessctl" "set" "+5%"; } - XF86MonBrightnessDown { spawn "brightnessctl" "set" "5%-"; } + // ===== BRIGHTNESS (via DMS) ===== + XF86MonBrightnessUp allow-when-locked=true { + spawn "dms" "ipc" "call" "brightness" "increment" "5" ""; + } + XF86MonBrightnessDown allow-when-locked=true { + spawn "dms" "ipc" "call" "brightness" "decrement" "5" ""; + } // ===== SCREENSHOTS ===== Print { screenshot-screen; } @@ -213,7 +280,9 @@ in Mod+Shift+Print { screenshot-window; } // ===== LOCK SCREEN (DMS) ===== - Mod+Ctrl+L { spawn "dms" "ipc" "call" "lock" "lock"; } // MOVED from Mod+L + Mod+Alt+L hotkey-overlay-title="Lock Screen" { + spawn "dms" "ipc" "call" "lock" "lock"; + } // ===== POWER ===== XF86PowerOff { quit; } @@ -222,9 +291,13 @@ in // ===================== // AUTOSTART // ===================== - spawn-at-startup "dms" "run" + spawn-at-startup "dms" "run" spawn-at-startup "opensnitch-ui" spawn-at-startup "clammy-start-session" + spawn-at-startup "ntl-daemon" + + // Clipboard history (for DMS clipboard widget) + spawn-at-startup "bash" "-c" "wl-paste --watch cliphist store &" // Environment for portals environment { @@ -232,13 +305,16 @@ in XDG_CURRENT_DESKTOP "niri" XDG_SESSION_TYPE "wayland" XDG_SESSION_DESKTOP "niri" + QT_QPA_PLATFORM "wayland" + ELECTRON_OZONE_PLATFORM_HINT "auto" + QT_QPA_PLATFORMTHEME "gtk3" } // ===================== // MISC // ===================== prefer-no-csd - + screenshot-path "~/screenshot-%Y%m%d-%H%M%S.png" hotkey-overlay { @@ -259,7 +335,7 @@ in }; }; - # PAM for swaylock + # PAM for swaylock (backup if DMS lock fails) security.pam.services.swaylock = { text = '' auth required pam_unix.so nullok @@ -268,10 +344,22 @@ in ''; }; - # Symlink config to user directory - system.userActivationScripts.niri-configs = '' + # Create DMS config directories and placeholder kdl files + # These will be populated by DMS at runtime + system.userActivationScripts.niri-dms-configs = '' + mkdir -p ~/.config/niri/dms mkdir -p ~/.config/niri + + # Create placeholder kdl files if they don't exist + # DMS will populate these with actual values + touch ~/.config/niri/dms/colors.kdl + touch ~/.config/niri/dms/layout.kdl + touch ~/.config/niri/dms/binds.kdl + + # Symlink main config ln -sf /etc/niri/config.kdl ~/.config/niri/config.kdl - cp ${inputs.self}/${userConfig.wallpaperPath} ~/.config/sway/wallpaper.png + + # Copy wallpaper + cp ${inputs.self}/${userConfig.wallpaperPath} ~/.config/sway/wallpaper.png 2>/dev/null || true ''; } diff --git a/modules/privacy.nix b/modules/privacy.nix index 9a7c2a4..50ba24c 100644 --- a/modules/privacy.nix +++ b/modules/privacy.nix @@ -1,47 +1,42 @@ -{ lib, ... }: +{ lib, pkgs, inputs, ... }: +let + blocklist_txt = pkgs.writeText "blocklist.txt" (builtins.readFile inputs.oisd); + StateDirName = "dnscrypt-proxy"; + StatePath = "/var/lib/${StateDirName}"; +in { - # DNS Privacy with dnscrypt-proxy services.dnscrypt-proxy = { enable = true; settings = { - # Use multiple resolvers for redundancy - server_names = [ "cloudflare" "quad9-dnscrypt-ip4-nofilter-pri" ]; - - # Listen on localhost listen_addresses = [ "127.0.0.1:53" "[::1]:53" ]; - - # Privacy settings - require_dnssec = true; - require_nolog = true; - require_nofilter = false; # We want filtering - timeout = 2500; - keepalive = 30; - - # Block lists for ads/trackers/malware + server_names = [ "cloudflare" "quad9-doh-ip4-port443-nofilter-pri" ]; + sources.public-resolvers = { urls = [ "https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/public-resolvers.md" ]; - cache_file = "public-resolvers.md"; + cache_file = "${StatePath}/public-resolvers.md"; minisign_key = "RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3"; }; - - # Additional privacy features - anonymized_dns.routes = [ - { - server_name = "cloudflare"; - via = [ "anon-cs-fr" "anon-cs-ireland" "anon-cs-germany" "anon-cs-nl" "anon-cs-se" ]; - } - ]; + + blocked_names.blocked_names_file = "${blocklist_txt}"; + + require_dnssec = true; + require_nolog = true; + require_nofilter = false; + timeout = 2500; + keepalive = 30; + ipv6_servers = true; + block_ipv6 = false; }; }; - - # Configure NetworkManager to use dnscrypt-proxy2 + + systemd.services.dnscrypt-proxy2.serviceConfig.StateDirectory = StateDirName; + networking = { - nftables.enable = true; # for opensnitch + nftables.enable = true; networkmanager = { insertNameservers = [ "127.0.0.1" "::1" ]; - dns = "none"; # Don't let NetworkManager override DNS - - # Enable MAC address randomization + dns = "none"; + wifi.macAddress = "stable"; ethernet.macAddress = "stable"; settings = { @@ -54,8 +49,7 @@ }; }; }; - - # Additional firewall hardening + firewall = { enable = false; allowPing = false; @@ -63,75 +57,44 @@ }; nftables.ruleset = '' - # --- TABLE 1: MANGLE (Traffic Control & OpenSnitch) --- table inet mangle { chain output { type route hook output priority mangle; policy accept; - # [A] CRITICAL BYPASS: VPN INTERFACE - # Allow applications to talk to the VPN interface locally. - # Without this, OpenSnitch deadlocks the tunnel. oifname "mullvad" accept - - # [B] CRITICAL BYPASS: ENCRYPTED TRANSPORT - # Allow the encrypted "envelope" to leave your physical card. - # We allow both standard port (51820) and fallback (443). - ip daddr 45.129.56.67 accept comment "Bypass: VPN Endpoint IP" udp dport { 51820, 443 } accept comment "Bypass: WireGuard Ports" meta mark 0xca6c accept comment "Bypass: WireGuard fwmark" - - # [C] SYSTEM ALLOWLIST oifname "lo" accept meta l4proto { icmp, icmpv6 } accept - # [D] OPENSNITCH QUEUE - # Everything else is queued for user approval. meta l4proto != tcp ct state related,new queue flags bypass to 0 tcp flags & (fin | syn | rst | ack) == syn queue flags bypass to 0 } } - # --- TABLE 2: FILTER (Security & Blocking) --- table inet filter { chain input { - type filter hook input priority filter; policy drop; - - # 1. TRUSTED TRAFFIC - ct state established,related accept - iifname "lo" accept - iifname "mullvad" accept - - # 2. VPN RETURN TRAFFIC - # Accept responses from the VPN server on both likely ports. - udp sport { 51820, 443 } accept - ip saddr 45.129.56.67 accept - - # 3. LAN / DHCP - udp dport { 67, 68 } accept - ip6 daddr fe80::/64 udp dport 546 accept - - # 4. SSH / HTTPS / LOCAL DEV (Your open ports) - tcp dport { 7889, 443, 7775 } accept + type filter hook input priority filter; policy accept; + udp sport 53 queue flags bypass to 0 + ct state invalid drop } chain output { type filter hook output priority filter; policy accept; - ct state established,related accept jump opensnitch } - + chain opensnitch {} } ''; }; - - # Fail2ban for intrusion prevention + services.fail2ban = { enable = true; maxretry = 3; bantime = "24h"; bantime-increment.enable = true; - + jails.sshd = lib.mkForce '' enabled = true port = 7889 @@ -139,88 +102,43 @@ maxretry = 3 ''; }; - - # Disable telemetry in various applications + environment.variables = { - # Disable .NET telemetry DOTNET_CLI_TELEMETRY_OPTOUT = "1"; - - # Disable PowerShell telemetry POWERSHELL_TELEMETRY_OPTOUT = "1"; - - # Disable Homebrew analytics HOMEBREW_NO_ANALYTICS = "1"; - - # Disable Next.js telemetry NEXT_TELEMETRY_DISABLED = "1"; - - # Disable Gatsby telemetry GATSBY_TELEMETRY_DISABLED = "1"; - - # Disable Azure Functions Core Tools telemetry FUNCTIONS_CORE_TOOLS_TELEMETRY_OPTOUT = "1"; - - # Disable VS Code telemetry VSCODE_TELEMETRY_LEVEL = "off"; }; - - # Kernel hardening + boot.kernel.sysctl = { - # Disable IP forwarding "net.ipv4.ip_forward" = 0; "net.ipv6.conf.all.forwarding" = 0; - - # Ignore ICMP redirects "net.ipv4.conf.all.accept_redirects" = 0; "net.ipv6.conf.all.accept_redirects" = 0; - - # Ignore send redirects "net.ipv4.conf.all.send_redirects" = 0; - - # Disable source packet routing "net.ipv4.conf.all.accept_source_route" = 0; "net.ipv6.conf.all.accept_source_route" = 0; - - # Log Martians "net.ipv4.conf.all.log_martians" = 1; - - # Ignore ICMP ping requests "net.ipv4.icmp_echo_ignore_all" = 1; - - # Protection against SYN flood attacks "net.ipv4.tcp_syncookies" = 1; - - # # Disable Strict Reverse Path Filtering. - # Essential for WireGuard to receive handshake packets on physical interface "net.ipv4.conf.all.rp_filter" = 2; "net.ipv4.conf.default.rp_filter" = 2; - - # Disable IPv6 if not needed - # "net.ipv6.conf.all.disable_ipv6" = 1; - # "net.ipv6.conf.default.disable_ipv6" = 1; }; - - # Disable unnecessary services that could leak data + services = { - # Disable Avahi daemon (mDNS) avahi.enable = false; - - # Disable location services geoclue2.enable = false; - - # Disable CUPS browsing printing.browsing = false; }; - - # AppArmor for additional application sandboxing + security.apparmor = { enable = true; killUnconfinedConfinables = true; }; - - # Ensure no swap file/partition is created - swapDevices = lib.mkForce [ ]; - # Disable swap entirely + swapDevices = lib.mkForce [ ]; zramSwap.enable = false; } diff --git a/modules/system-packages.nix b/modules/system-packages.nix index 9a3cf98..f611efa 100644 --- a/modules/system-packages.nix +++ b/modules/system-packages.nix @@ -5,6 +5,8 @@ let sandboxed-steam = import ../pkgs/sandboxed-steam.nix { inherit pkgs; }; perseus-net = pkgs.callPackage ../pkgs/perseus-net.nix {}; dms = inputs.dms.packages.${pkgs.system}.default; + dgop = inputs.dgop.packages.${pkgs.system}.default; + ntl-daemon = pkgs.callPackage ../pkgs/ntl-daemon.nix {}; in { # Global software packages to install @@ -19,6 +21,7 @@ in # System utilities dms + dgop quickshell direnv btop @@ -33,8 +36,11 @@ in usbutils iw bolt + upower v4l-utils libcamera + networkmanagerapplet + ntl-daemon # ipu6 gst_all_1.gstreamer @@ -59,14 +65,10 @@ in gnupg libnotify mdcat - networkmanagerapplet - gammastep xwayland-satellite # Wayland-specific tools wl-clipboard - grim - slurp xdg-desktop-portal xdg-desktop-portal-wlr sweet # GTK theme @@ -145,6 +147,11 @@ in fira-code-symbols papirus-icon-theme bibata-cursors + adwaita-icon-theme + hicolor-icon-theme + tela-icon-theme + + libayatana-appindicator # Pandoc and live MD rendering script pandoc diff --git a/modules/techoverlord_protection.nix b/modules/techoverlord_protection.nix index d6d7d46..15875f4 100644 --- a/modules/techoverlord_protection.nix +++ b/modules/techoverlord_protection.nix @@ -4,7 +4,7 @@ let ntlCli = pkgs.writeShellScriptBin "ntl" '' #!/usr/bin/env bash - + GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' @@ -24,12 +24,13 @@ let echo -e " ''${BLUE}status''${NC} Show daemon status" echo -e " ''${BLUE}report''${NC} View latest audit summary" echo -e " ''${BLUE}logs''${NC} Follow live system logs" + echo -e " ''${BLUE}tray''${NC} Output JSON for system tray" echo "" } case "$1" in run) - echo -e "''${GREEN}๐Ÿ›ก๏ธ Starting NastyTechLords Audit...''${NC}" + echo -e "''${GREEN}๓ฐ’˜ Starting NastyTechLords Audit...''${NC}" if [ "$2" = "--full" ]; then sudo $BINARY --full --verbose else @@ -44,7 +45,6 @@ let if [ -f "$LOG_DIR/latest-summary.txt" ]; then cat "$LOG_DIR/latest-summary.txt" else - # Fallback to finding the newest log LATEST=$(ls -t $LOG_DIR/audit-*.log 2>/dev/null | head -1) if [ -n "$LATEST" ]; then cat "$LATEST" @@ -56,12 +56,31 @@ let logs) sudo journalctl -u nastyTechLords -f ;; + tray) + # JSON output for system tray integration + if ! systemctl is-active --quiet nastyTechLords.timer; then + echo '{"icon": "๓ฐฆž", "status": "inactive"}' + exit 0 + fi + if [ ! -f "$LOG_DIR/latest-summary.txt" ]; then + echo '{"icon": "๓ฐ”Ÿ", "status": "pending"}' + exit 0 + fi + CRITICAL=$(grep -c "^\[CRITICAL\]" "$LOG_DIR/latest-summary.txt" 2>/dev/null || echo "0") + WARNING=$(grep -c "^\[WARNING\]" "$LOG_DIR/latest-summary.txt" 2>/dev/null || echo "0") + if [ "$CRITICAL" -gt 0 ]; then + echo "{\"icon\": \"๓ฐ€ฆ\", \"status\": \"critical\", \"critical\": $CRITICAL, \"warning\": $WARNING}" + elif [ "$WARNING" -gt 0 ]; then + echo "{\"icon\": \"๓ฐ€ช\", \"status\": \"warning\", \"critical\": 0, \"warning\": $WARNING}" + else + echo '{"icon": "๓ฐ’˜", "status": "ok", "critical": 0, "warning": 0}' + fi + ;; *) show_help ;; esac ''; - uid = toString config.users.users.${userConfig.username}.uid; in { diff --git a/modules/tuigreeter.nix b/modules/tuigreeter.nix deleted file mode 100644 index 6a81e00..0000000 --- a/modules/tuigreeter.nix +++ /dev/null @@ -1,66 +0,0 @@ -{ pkgs, userConfig, ... }: -{ - services.greetd = { - enable = true; - settings = { - default_session = { - command = "${pkgs.tuigreet}/bin/tuigreet --time --remember --remember-user-session --asterisks --greeting 'Welcome to Perseus' --cmd sway"; - user = "greeter"; - }; - }; - }; - - console = { - earlySetup = true; - colors = [ - "0a0a14" # black (dark navy) - "ff6b6b" # red - "4ecdc4" # green - "45b7d1" # yellow (blue-ish) - "96ceb4" # blue (mint) - "feca57" # magenta (warm yellow) - "48dbfb" # cyan (bright blue) - "f8f8f2" # white - "44475a" # bright black (darker navy) - "ff7979" # bright red - "55efc4" # bright green - "74b9ff" # bright yellow (blue) - "a29bfe" # bright blue (purple) - "fd79a8" # bright magenta (pink) - "81ecec" # bright cyan - "ffffff" # bright white - ]; - }; - - boot.kernelParams = [ - # "mem_sleep_default=deep" - "console=tty1" - "quiet" - "loglevel=3" - "rd.systemd.show_status=false" - "rd.udev.log_level=3" - "vt.global_cursor_default=0" - ]; - - environment.etc."motd".text = '' - - - โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— - โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• - โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— - โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ•šโ•โ•โ•โ•โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ•šโ•โ•โ•โ•โ–ˆโ–ˆโ•‘ - โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•‘ - โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ• โ•šโ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ• - - แด˜แดœส€แด˜แดsแด‡ ส™แดœษชสŸแด› า“แดส€ แด˜ส€ษชแด แด€แด„ส แด€ษดแด… แด…แด‡แด แด‡สŸแดแด˜แดแด‡ษดแด› - - ''; - - systemd.services."getty@tty1" = { - overrideStrategy = "asDropin"; - serviceConfig.ExecStart = [ - "" - "@${pkgs.util-linux}/sbin/agetty agetty --noclear --keep-baud tty1 115200,38400,9600 $TERM" - ]; - }; -} diff --git a/modules/usb.nix b/modules/usb.nix new file mode 100644 index 0000000..364f682 --- /dev/null +++ b/modules/usb.nix @@ -0,0 +1,17 @@ +{ ... }: +{ + services.usbguard = { + enable = true; + presentDevicePolicy = "allow"; + rules = '' + # Allow internal devices (adjust for your hardware) + allow with-interface equals { 03:*:* } # HID (keyboard/mouse) + allow with-interface equals { 08:*:* } # Mass storage + allow with-interface equals { 09:*:* } # Hub + allow with-interface equals { 0e:*:* } # Video + + # Block everything else by default + reject + ''; + }; +} diff --git a/pkgs/ntl-daemon.nix b/pkgs/ntl-daemon.nix new file mode 100644 index 0000000..ee0bcb6 --- /dev/null +++ b/pkgs/ntl-daemon.nix @@ -0,0 +1,29 @@ +{ pkgs, lib }: + +let + src = builtins.path { path = ../programs/ntl-daemon; }; +in +pkgs.rustPlatform.buildRustPackage { + pname = "ntl-daemon"; + version = "0.1.0"; + + inherit src; + + cargoLock = { + lockFile = "${src}/Cargo.lock"; + }; + + nativeBuildInputs = with pkgs; [ + pkg-config + ]; + + buildInputs = with pkgs; [ + dbus + ]; + + meta = with lib; { + description = "NTL system tray daemon"; + platforms = platforms.linux; + mainProgram = "ntl-daemon"; + }; +} diff --git a/programs/ntl-daemon/Cargo.lock b/programs/ntl-daemon/Cargo.lock new file mode 100644 index 0000000..6e2edec --- /dev/null +++ b/programs/ntl-daemon/Cargo.lock @@ -0,0 +1,1276 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-broadcast" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "pin-project-lite", + "slab", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-lock" +version = "3.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-process" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-signal" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43c070bbf59cd3570b6b2dd54cd772527c7c3620fce8be898406dd3ed6adc64c" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix", + "signal-hook-registry", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bitflags" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" + +[[package]] +name = "blocking" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + +[[package]] +name = "bumpalo" +version = "3.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" + +[[package]] +name = "bytes" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "endi" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" + +[[package]] +name = "enumflags2" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "env_filter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "event-listener" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "indexmap" +version = "2.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itoa" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" + +[[package]] +name = "jiff" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a87d9b8105c23642f50cbbae03d1f75d8422c5cb98ce7ee9271f7ff7505be6b8" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", +] + +[[package]] +name = "jiff-static" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b787bebb543f8969132630c51fd0afab173a86c6abae56ff3b9e5e3e3f9f6e58" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "js-sys" +version = "0.3.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.178" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" + +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mio" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "nix" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", + "memoffset", +] + +[[package]] +name = "ntl-daemon" +version = "0.1.0" +dependencies = [ + "env_logger", + "log", + "serde", + "serde_json", + "tokio", + "zbus", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "piper" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "portable-atomic" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "proc-macro-crate" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9695f8df41bb4f3d222c95a67532365f569318332d03d5f3f67f37b20e6ebdf0" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + +[[package]] +name = "rustix" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.148" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3084b546a1dd6289475996f182a22aba973866ea8e8b02c51d9f46b1336a22da" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "slab" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "syn" +version = "2.0.112" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21f182278bf2d2bcb3c88b1b08a37df029d71ce3d3ae26168e3c653b213b99d4" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c" +dependencies = [ + "fastrand", + "getrandom", + "once_cell", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio" +version = "1.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +dependencies = [ + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-macros" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "toml_datetime" +version = "0.7.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.23.10+spec-1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.0.6+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" +dependencies = [ + "winnow", +] + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "uds_windows" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" +dependencies = [ + "memoffset", + "tempfile", + "winapi", +] + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uuid" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" +dependencies = [ + "js-sys", + "serde_core", + "wasm-bindgen", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winnow" +version = "0.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "zbus" +version = "5.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b622b18155f7a93d1cd2dc8c01d2d6a44e08fb9ebb7b3f9e6ed101488bad6c91" +dependencies = [ + "async-broadcast", + "async-executor", + "async-io", + "async-lock", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "enumflags2", + "event-listener", + "futures-core", + "futures-lite", + "hex", + "nix", + "ordered-stream", + "serde", + "serde_repr", + "tracing", + "uds_windows", + "uuid", + "windows-sys 0.61.2", + "winnow", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "5.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cdb94821ca8a87ca9c298b5d1cbd80e2a8b67115d99f6e4551ac49e42b6a314" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", + "zbus_names", + "zvariant", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7be68e64bf6ce8db94f63e72f0c7eb9a60d733f7e0499e628dfab0f84d6bcb97" +dependencies = [ + "serde", + "static_assertions", + "winnow", + "zvariant", +] + +[[package]] +name = "zmij" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3280a1b827474fcd5dbef4b35a674deb52ba5c312363aef9135317df179d81b" + +[[package]] +name = "zvariant" +version = "5.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2be61892e4f2b1772727be11630a62664a1826b62efa43a6fe7449521cb8744c" +dependencies = [ + "endi", + "enumflags2", + "serde", + "winnow", + "zvariant_derive", + "zvariant_utils", +] + +[[package]] +name = "zvariant_derive" +version = "5.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da58575a1b2b20766513b1ec59d8e2e68db2745379f961f86650655e862d2006" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6949d142f89f6916deca2232cf26a8afacf2b9fdc35ce766105e104478be599" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "syn", + "winnow", +] diff --git a/programs/ntl-daemon/Cargo.toml b/programs/ntl-daemon/Cargo.toml new file mode 100644 index 0000000..e06f4b9 --- /dev/null +++ b/programs/ntl-daemon/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "ntl-daemon" +version = "0.1.0" +edition = "2021" + +[dependencies] +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +log = "0.4" +env_logger = "0.11" +zbus = "5" +tokio = { version = "1", features = ["full"] } diff --git a/programs/ntl-daemon/src/main.rs b/programs/ntl-daemon/src/main.rs new file mode 100644 index 0000000..91d41a3 --- /dev/null +++ b/programs/ntl-daemon/src/main.rs @@ -0,0 +1,156 @@ +use log::{debug, error, info}; +use serde::Deserialize; +use std::collections::HashMap; +use std::process::Command; +use std::sync::{Arc, Mutex}; +use zbus::{connection, interface, Connection}; + +#[derive(Debug, Deserialize, Clone)] +struct NtlStatus { + icon: String, + status: String, + #[serde(default)] + critical: u32, + #[serde(default)] + warning: u32, +} + +impl Default for NtlStatus { + fn default() -> Self { + Self { + icon: "๓ฐ”Ÿ".to_string(), + status: "pending".to_string(), + critical: 0, + warning: 0, + } + } +} + +fn update_status(status: &Arc>) { + debug!("Running ntl tray..."); + match Command::new("ntl").arg("tray").output() { + Ok(output) => { + if let Ok(stdout) = String::from_utf8(output.stdout) { + debug!("stdout: {}", stdout.trim()); + if let Ok(new_status) = serde_json::from_str::(&stdout) { + debug!("Parsed status: {:?}", new_status); + let mut s = status.lock().unwrap(); + *s = new_status; + } + } + } + Err(e) => error!("Failed to run ntl tray: {}", e), + } +} + +struct StatusNotifierItem { + status: Arc>, +} + +#[interface(name = "org.kde.StatusNotifierItem")] +impl StatusNotifierItem { + #[zbus(property)] + fn category(&self) -> String { + "SystemServices".to_string() + } + + #[zbus(property)] + fn id(&self) -> String { + "ntl-daemon".to_string() + } + + #[zbus(property)] + fn title(&self) -> String { + "NTL Security Monitor".to_string() + } + + #[zbus(property)] + fn status(&self) -> String { + "Active".to_string() + } + + #[zbus(property)] + fn icon_name(&self) -> String { + let status = self.status.lock().unwrap(); + match status.status.as_str() { + "ok" => "security-high-symbolic", + "warning" => "security-medium-symbolic", + "critical" => "security-low-symbolic", + "inactive" => "security-low-symbolic", + _ => "dialog-question-symbolic", + }.to_string() + } + + #[zbus(property)] + fn icon_theme_path(&self) -> String { + String::new() + } + + #[zbus(property)] + fn menu(&self) -> zbus::zvariant::OwnedObjectPath { + zbus::zvariant::OwnedObjectPath::try_from("/MenuBar").unwrap() + } + + fn activate(&self, _x: i32, _y: i32) { + info!("Tray icon activated"); + let _ = Command::new("alacritty") + .args(["-e", "ntl", "report"]) + .spawn(); + } + + fn secondary_activate(&self, _x: i32, _y: i32) { + info!("Tray icon secondary activated"); + let _ = Command::new("alacritty") + .args(["-e", "ntl", "run"]) + .spawn(); + } +} + +#[tokio::main] +async fn main() -> Result<(), Box> { + env_logger::Builder::from_env( + env_logger::Env::default().default_filter_or("debug") + ).init(); + + info!("NTL Daemon starting..."); + + let status = Arc::new(Mutex::new(NtlStatus::default())); + update_status(&status); + info!("Status: {:?}", *status.lock().unwrap()); + + let conn = Connection::session().await?; + info!("Connected to session bus"); + + let sni = StatusNotifierItem { + status: status.clone(), + }; + + let object_path = "/StatusNotifierItem"; + conn.object_server().at(object_path, sni).await?; + info!("Registered object at {}", object_path); + + // Request a unique name + let well_known_name = format!("org.kde.StatusNotifierItem-{}-1", std::process::id()); + conn.request_name(&*well_known_name).await?; + info!("Acquired name: {}", well_known_name); + + // Register with the watcher + let watcher = conn.call_method( + Some("org.kde.StatusNotifierWatcher"), + "/StatusNotifierWatcher", + Some("org.kde.StatusNotifierWatcher"), + "RegisterStatusNotifierItem", + &(well_known_name.as_str()), + ).await; + + match watcher { + Ok(_) => info!("Registered with StatusNotifierWatcher"), + Err(e) => error!("Failed to register with watcher: {}", e), + } + + info!("Running event loop..."); + loop { + tokio::time::sleep(tokio::time::Duration::from_secs(300)).await; + update_status(&status); + } +} diff --git a/programs/ntl/src/scanners/privacy.rs b/programs/ntl/src/scanners/privacy.rs index cbeb366..87ddc1f 100644 --- a/programs/ntl/src/scanners/privacy.rs +++ b/programs/ntl/src/scanners/privacy.rs @@ -5,6 +5,7 @@ use crate::Args; use anyhow::Result; use std::fs; use std::net::ToSocketAddrs; +use std::process::Command; pub struct PrivacyScanner; @@ -21,6 +22,9 @@ impl Scanner for PrivacyScanner { // 3. HARDWARE TRACKING CHECK check_mac_privacy(report); + // 4. [NEW] RUNTIME DNS LEAK CHECK + check_runtime_dns_leaks(report); + Ok(()) } } @@ -99,3 +103,59 @@ fn check_mac_privacy(report: &mut Report) { } } } + + +fn check_runtime_dns_leaks(report: &mut Report) { + report.increment_checked(); + + // Check for established connections to port 53 + if let Ok(output) = Command::new("ss") + .args(["-tunp", "state", "established"]) + .output() + { + let stdout = String::from_utf8_lossy(&output.stdout); + for line in stdout.lines() { + let parts: Vec<&str> = line.split_whitespace().collect(); + if parts.len() >= 5 { + let remote = parts[4]; + if remote.ends_with(":53") + && !remote.starts_with("127.0.0.1:") + && !remote.starts_with("[::1]:") + && !remote.starts_with("127.0.0.53:") + { + report.add_issue( + ScanLevel::Critical, + "DNSLeak", + &format!("Active DNS connection bypassing localhost: {}", line.trim()) + ); + } + } + } + } + + // Check for UDP sockets to port 53 + if let Ok(output) = Command::new("ss") + .args(["-unp"]) + .output() + { + let stdout = String::from_utf8_lossy(&output.stdout); + for line in stdout.lines() { + let parts: Vec<&str> = line.split_whitespace().collect(); + if parts.len() >= 5 { + let remote = parts[4]; + if remote.ends_with(":53") + && !remote.starts_with("127.0.0.1:") + && !remote.starts_with("[::1]:") + && !remote.starts_with("127.0.0.53:") + && !remote.starts_with("*:") + { + report.add_issue( + ScanLevel::Warning, + "DNSLeak", + &format!("Process with external DNS socket: {}", line.trim()) + ); + } + } + } + } +} diff --git a/system/configuration.nix b/system/configuration.nix index 1bd1a4a..21f7c28 100644 --- a/system/configuration.nix +++ b/system/configuration.nix @@ -25,9 +25,6 @@ # clamshell action "${inputs.self}/modules/clammy.nix" - # Desktop environment - "${inputs.self}/modules/gammastep.nix" - # General programming languages "${inputs.self}/modules/gpl.nix" @@ -35,9 +32,9 @@ "${inputs.self}/modules/privacy.nix" "${inputs.self}/modules/techoverlord_protection.nix" "${inputs.self}/modules/app-telemetry-deny.nix" - # "${inputs.self}/modules/tuigreeter.nix" "${inputs.self}/modules/greetd.nix" - + "${inputs.self}/modules/usb.nix" + "${inputs.self}/modules/firejail.nix" # Conditionally import nvidia.nix based on the hasGPU flag ] ++ lib.optionals userConfig.hasGPU [