summary refs log tree commit diff
path: root/nixos/modules/services
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/services')
-rw-r--r--nixos/modules/services/backup/duplicati.nix19
-rw-r--r--nixos/modules/services/networking/sslh.nix114
-rw-r--r--nixos/modules/services/security/munge.nix16
3 files changed, 128 insertions, 21 deletions
diff --git a/nixos/modules/services/backup/duplicati.nix b/nixos/modules/services/backup/duplicati.nix
index 9772ca4d20a7..379fde1fe038 100644
--- a/nixos/modules/services/backup/duplicati.nix
+++ b/nixos/modules/services/backup/duplicati.nix
@@ -9,6 +9,23 @@ in
   options = {
     services.duplicati = {
       enable = mkEnableOption "Duplicati";
+
+      port = mkOption {
+        default = 8200;
+        type = types.int;
+        description = ''
+          Port serving the web interface
+        '';
+      };
+
+      interface = mkOption {
+        default = "lo";
+        type = types.str;
+        description = ''
+          Listening interface for the web UI
+          Set it to "any" to listen on all available interfaces
+        '';
+      };
     };
   };
 
@@ -22,7 +39,7 @@ in
       serviceConfig = {
         User = "duplicati";
         Group = "duplicati";
-        ExecStart = "${pkgs.duplicati}/bin/duplicati-server --webservice-interface=any --webservice-port=8200 --server-datafolder=/var/lib/duplicati";
+        ExecStart = "${pkgs.duplicati}/bin/duplicati-server --webservice-interface=${cfg.interface} --webservice-port=${toString cfg.port} --server-datafolder=/var/lib/duplicati";
         Restart = "on-failure";
       };
     };
diff --git a/nixos/modules/services/networking/sslh.nix b/nixos/modules/services/networking/sslh.nix
index e3d65c49fbf2..0222e8ce8b58 100644
--- a/nixos/modules/services/networking/sslh.nix
+++ b/nixos/modules/services/networking/sslh.nix
@@ -4,15 +4,14 @@ with lib;
 
 let
   cfg = config.services.sslh;
+  user = "sslh";
   configFile = pkgs.writeText "sslh.conf" ''
     verbose: ${boolToString cfg.verbose};
     foreground: true;
     inetd: false;
     numeric: false;
-    transparent: false;
+    transparent: ${boolToString cfg.transparent};
     timeout: "${toString cfg.timeout}";
-    user: "nobody";
-    pidfile: "${cfg.pidfile}";
 
     listen:
     (
@@ -50,16 +49,16 @@ in
         description = "Timeout in seconds.";
       };
 
-      pidfile = mkOption {
-        type = types.path;
-        default = "/run/sslh.pid";
-        description = "PID file path for sslh daemon.";
+      transparent = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Will the services behind sslh (Apache, sshd and so on) see the external IP and ports as if the external world connected directly to them";
       };
 
       listenAddress = mkOption {
         type = types.str;
-        default = config.networking.hostName;
-        description = "Listening hostname.";
+        default = "0.0.0.0";
+        description = "Listening address or hostname.";
       };
 
       port = mkOption {
@@ -76,14 +75,91 @@ in
     };
   };
 
-  config = mkIf cfg.enable {
-    systemd.services.sslh = {
-      description = "Applicative Protocol Multiplexer (e.g. share SSH and HTTPS on the same port)";
-      after = [ "network.target" ];
-      wantedBy = [ "multi-user.target" ];
-      serviceConfig.ExecStart = "${pkgs.sslh}/bin/sslh -F${configFile}";
-      serviceConfig.KillMode = "process";
-      serviceConfig.PIDFile = "${cfg.pidfile}";
-    };
-  };
+  config = mkMerge [
+    (mkIf cfg.enable {
+      users.users.${user} = {
+        description = "sslh daemon user";
+        isSystemUser = true;
+      };
+
+      systemd.services.sslh = {
+        description = "Applicative Protocol Multiplexer (e.g. share SSH and HTTPS on the same port)";
+        after = [ "network.target" ];
+        wantedBy = [ "multi-user.target" ];
+
+        serviceConfig = {
+          User                 = user;
+          Group                = "nogroup";
+          PermissionsStartOnly = true;
+          Restart              = "always";
+          RestartSec           = "1s";
+          ExecStart            = "${pkgs.sslh}/bin/sslh -F${configFile}";
+          KillMode             = "process";
+          AmbientCapabilities  = "CAP_NET_BIND_SERVICE CAP_NET_ADMIN CAP_SETGID CAP_SETUID";
+          PrivateTmp           = true;
+          PrivateDevices       = true;
+          ProtectSystem        = "full";
+          ProtectHome          = true;
+        };
+      };
+    })
+
+    # code from https://github.com/yrutschle/sslh#transparent-proxy-support
+    # the only difference is using iptables mark 0x2 instead of 0x1 to avoid conflicts with nixos/nat module
+    (mkIf (cfg.enable && cfg.transparent) {
+      # Set route_localnet = 1 on all interfaces so that ssl can use "localhost" as destination
+      boot.kernel.sysctl."net.ipv4.conf.default.route_localnet" = 1;
+      boot.kernel.sysctl."net.ipv4.conf.all.route_localnet"     = 1;
+
+      systemd.services.sslh = let
+        iptablesCommands = [
+          # DROP martian packets as they would have been if route_localnet was zero
+          # Note: packets not leaving the server aren't affected by this, thus sslh will still work
+          { table = "raw";    command = "PREROUTING  ! -i lo -d 127.0.0.0/8 -j DROP"; }
+          { table = "mangle"; command = "POSTROUTING ! -o lo -s 127.0.0.0/8 -j DROP"; }
+          # Mark all connections made by ssl for special treatment (here sslh is run as user ${user})
+          { table = "nat";    command = "OUTPUT -m owner --uid-owner ${user} -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -j CONNMARK --set-xmark 0x02/0x0f"; }
+          # Outgoing packets that should go to sslh instead have to be rerouted, so mark them accordingly (copying over the connection mark)
+          { table = "mangle"; command = "OUTPUT ! -o lo -p tcp -m connmark --mark 0x02/0x0f -j CONNMARK --restore-mark --mask 0x0f"; }
+        ];
+        ip6tablesCommands = [
+          { table = "raw";    command = "PREROUTING  ! -i lo -d ::1/128     -j DROP"; }
+          { table = "mangle"; command = "POSTROUTING ! -o lo -s ::1/128     -j DROP"; }
+          { table = "nat";    command = "OUTPUT -m owner --uid-owner ${user} -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -j CONNMARK --set-xmark 0x02/0x0f"; }
+          { table = "mangle"; command = "OUTPUT ! -o lo -p tcp -m connmark --mark 0x02/0x0f -j CONNMARK --restore-mark --mask 0x0f"; }
+        ];
+      in {
+        path = [ pkgs.iptables pkgs.iproute pkgs.procps ];
+
+        preStart = ''
+          # Cleanup old iptables entries which might be still there
+          ${concatMapStringsSep "\n" ({table, command}: "while iptables -w -t ${table} -D ${command} 2>/dev/null; do echo; done") iptablesCommands}
+          ${concatMapStringsSep "\n" ({table, command}:       "iptables -w -t ${table} -A ${command}"                           ) iptablesCommands}
+
+          # Configure routing for those marked packets
+          ip rule  add fwmark 0x2 lookup 100
+          ip route add local 0.0.0.0/0 dev lo table 100
+
+        '' + optionalString config.networking.enableIPv6 ''
+          ${concatMapStringsSep "\n" ({table, command}: "while ip6tables -w -t ${table} -D ${command} 2>/dev/null; do echo; done") ip6tablesCommands}
+          ${concatMapStringsSep "\n" ({table, command}:       "ip6tables -w -t ${table} -A ${command}"                           ) ip6tablesCommands}
+
+          ip -6 rule  add fwmark 0x2 lookup 100
+          ip -6 route add local ::/0 dev lo table 100
+        '';
+
+        postStop = ''
+          ${concatMapStringsSep "\n" ({table, command}: "iptables -w -t ${table} -D ${command}") iptablesCommands}
+
+          ip rule  del fwmark 0x2 lookup 100
+          ip route del local 0.0.0.0/0 dev lo table 100
+        '' + optionalString config.networking.enableIPv6 ''
+          ${concatMapStringsSep "\n" ({table, command}: "ip6tables -w -t ${table} -D ${command}") ip6tablesCommands}
+
+          ip -6 rule  del fwmark 0x2 lookup 100
+          ip -6 route del local ::/0 dev lo table 100
+        '';
+      };
+    })
+  ];
 }
diff --git a/nixos/modules/services/security/munge.nix b/nixos/modules/services/security/munge.nix
index 919c2c2b0e15..5bca15833544 100644
--- a/nixos/modules/services/security/munge.nix
+++ b/nixos/modules/services/security/munge.nix
@@ -35,7 +35,15 @@ in
 
     environment.systemPackages = [ pkgs.munge ];
 
-    systemd.services.munged = { 
+    users.users.munge = {
+      description   = "Munge daemon user";
+      isSystemUser  = true;
+      group         = "munge";
+    };
+
+    users.groups.munge = {};
+
+    systemd.services.munged = {
       wantedBy = [ "multi-user.target" ];
       after = [ "network.target" ];
 
@@ -44,14 +52,20 @@ in
       preStart = ''
         chmod 0700 ${cfg.password}
         mkdir -p /var/lib/munge -m 0711
+        chown -R munge:munge /var/lib/munge
         mkdir -p /var/log/munge -m 0700
+        chown -R munge:munge /var/log/munge
         mkdir -p /run/munge -m 0755
+        chown -R munge:munge /run/munge
       '';
 
       serviceConfig = {
         ExecStart = "${pkgs.munge}/bin/munged --syslog --key-file ${cfg.password}";
         PIDFile = "/run/munge/munged.pid";
         ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+        PermissionsStartOnly = "true";
+        User = "munge";
+        Group = "munge";
       };
 
     };