From 4defb788ebec831f6a868f46b969755d7754cc4f Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Fri, 13 Jan 2017 15:23:34 -0700 Subject: [PATCH 1/3] rmilter service: Fix a couple of bugs * The module uses `stringSplit` but it should be `splitString` * `rmilter` doesn't actually support binding to multiple sockets. Therefore, bind to the last one specified if `socketActivation` is `false`. I also believe there is a bug in this module related to systemd `ListenStream`. If `socketActivation` is true, Postfix gets connection timeouts trying to connect to one of the `ListenStream` inet addresses. I don't know enough about `ListenStream` passing connections on to `fd:3` to understand what's going on. These changes are in production (with `socketActivation = false`) via NixOps. --- nixos/modules/services/mail/rmilter.nix | 45 +++++++++++++------------ 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/nixos/modules/services/mail/rmilter.nix b/nixos/modules/services/mail/rmilter.nix index 8f18b929c114..7fb4a5195821 100644 --- a/nixos/modules/services/mail/rmilter.nix +++ b/nixos/modules/services/mail/rmilter.nix @@ -7,32 +7,31 @@ let rspamdCfg = config.services.rspamd; cfg = config.services.rmilter; - inetSockets = map (sock: let s = stringSplit ":" sock; in "inet:${last s}:${head s}") cfg.bindInetSockets; + inetSockets = map (sock: let s = splitString ":" sock; in "inet:${last s}@${head s}") cfg.bindInetSockets; unixSockets = map (sock: "unix:${sock}") cfg.bindUnixSockets; allSockets = unixSockets ++ inetSockets; rmilterConf = '' -pidfile = /run/rmilter/rmilter.pid; -bind_socket = ${if cfg.socketActivation then "fd:3" else concatStringsSep ", " allSockets}; -tempdir = /tmp; - + pidfile = /run/rmilter/rmilter.pid; + bind_socket = ${if cfg.socketActivation then "fd:3" else last inetSockets}; + tempdir = /tmp; '' + (with cfg.rspamd; if enable then '' -spamd { - servers = ${concatStringsSep ", " servers}; - connect_timeout = 1s; - results_timeout = 20s; - error_time = 10; - dead_time = 300; - maxerrors = 10; - reject_message = "${rejectMessage}"; - ${optionalString (length whitelist != 0) "whitelist = ${concatStringsSep ", " whitelist};"} + spamd { + servers = ${concatStringsSep ", " servers}; + connect_timeout = 1s; + results_timeout = 20s; + error_time = 10; + dead_time = 300; + maxerrors = 10; + reject_message = "${rejectMessage}"; + ${optionalString (length whitelist != 0) "whitelist = ${concatStringsSep ", " whitelist};"} - # rspamd_metric - metric for using with rspamd - # Default: "default" - rspamd_metric = "default"; - ${extraConfig} -}; + # rspamd_metric - metric for using with rspamd + # Default: "default" + rspamd_metric = "default"; + ${extraConfig} + }; '' else "") + cfg.extraConfig; rmilterConfigFile = pkgs.writeText "rmilter.conf" rmilterConf; @@ -100,9 +99,11 @@ in default = true; description = '' Enable systemd socket activation for rmilter. - (disabling socket activation not recommended - when unix socket used, and follow to wrong - permissions on unix domain socket.) + + Disabling socket activation is not recommended when a Unix + domain socket is used and could lead to incorrect + permissions. Therefore, setting this to false will + configure rmilter to use an inet socket only. ''; }; From 8ab2d2ee27b84bfeb2e2077e87f5ccc7b0d129fe Mon Sep 17 00:00:00 2001 From: Franz Pletz Date: Sat, 28 Jan 2017 02:46:16 +0100 Subject: [PATCH 2/3] rmilter service: support only one socket --- nixos/doc/manual/release-notes/rl-1703.xml | 12 ++ nixos/modules/rename.nix | 3 + nixos/modules/services/mail/rmilter.nix | 157 ++++++++++++--------- 3 files changed, 103 insertions(+), 69 deletions(-) diff --git a/nixos/doc/manual/release-notes/rl-1703.xml b/nixos/doc/manual/release-notes/rl-1703.xml index fda46217144c..c03bf33de8bd 100644 --- a/nixos/doc/manual/release-notes/rl-1703.xml +++ b/nixos/doc/manual/release-notes/rl-1703.xml @@ -237,6 +237,18 @@ following incompatible changes: + + + The socket handling of the services.rmilter module + has been fixed and refactored. As rmilter doesn't support binding to + more than one socket, the options bindUnixSockets + and bindInetSockets have been replaced by + services.rmilter.bindSocket.*. The default is still + a unix socket in /run/rmilter/rmilter.sock. Refer to + the options documentation for more information. + + + diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix index af8b34b5e5cb..7b75ca85219c 100644 --- a/nixos/modules/rename.nix +++ b/nixos/modules/rename.nix @@ -35,6 +35,9 @@ with lib; (mkRemovedOptionModule [ "security" "setuidOwners" ] "Use security.wrappers instead") (mkRemovedOptionModule [ "security" "setuidPrograms" ] "Use security.wrappers instead") + (mkRemovedOptionModule [ "services" "rmilter" "bindInetSockets" ] "Use services.rmilter.bindSocket.* instead") + (mkRemovedOptionModule [ "services" "rmilter" "bindUnixSockets" ] "Use services.rmilter.bindSocket.* instead") + # Old Grub-related options. (mkRenamedOptionModule [ "boot" "initrd" "extraKernelModules" ] [ "boot" "initrd" "kernelModules" ]) (mkRenamedOptionModule [ "boot" "extraKernelParams" ] [ "boot" "kernelParams" ]) diff --git a/nixos/modules/services/mail/rmilter.nix b/nixos/modules/services/mail/rmilter.nix index 7fb4a5195821..3153b1c79124 100644 --- a/nixos/modules/services/mail/rmilter.nix +++ b/nixos/modules/services/mail/rmilter.nix @@ -7,14 +7,17 @@ let rspamdCfg = config.services.rspamd; cfg = config.services.rmilter; - inetSockets = map (sock: let s = splitString ":" sock; in "inet:${last s}@${head s}") cfg.bindInetSockets; - unixSockets = map (sock: "unix:${sock}") cfg.bindUnixSockets; + inetSocket = addr: port: "inet:[${toString port}@${addr}]"; + unixSocket = sock: "unix:${sock}"; - allSockets = unixSockets ++ inetSockets; + systemdSocket = if cfg.bindSocket.type == "unix" then cfg.bindSocket.path + else "${cfg.bindSocket.address}:${toString cfg.bindSocket.port}"; + rmilterSocket = if cfg.bindSocket.type == "unix" then unixSocket cfg.bindSocket.path + else inetSocket cfg.bindSocket.address cfg.bindSocket.port; rmilterConf = '' pidfile = /run/rmilter/rmilter.pid; - bind_socket = ${if cfg.socketActivation then "fd:3" else last inetSockets}; + bind_socket = ${if cfg.socketActivation then "fd:3" else rmilterSocket}; tempdir = /tmp; '' + (with cfg.rspamd; if enable then '' spamd { @@ -32,7 +35,7 @@ let rspamd_metric = "default"; ${extraConfig} }; - '' else "") + cfg.extraConfig; + '' else "") + cfg.extraConfig; rmilterConfigFile = pkgs.writeText "rmilter.conf" rmilterConf; @@ -47,11 +50,13 @@ in services.rmilter = { enable = mkOption { + type = types.bool; default = cfg.rspamd.enable; description = "Whether to run the rmilter daemon."; }; debug = mkOption { + type = types.bool; default = false; description = "Whether to run the rmilter daemon in debug mode."; }; @@ -72,25 +77,37 @@ in ''; }; - bindUnixSockets = mkOption { - type = types.listOf types.str; - default = ["/run/rmilter/rmilter.sock"]; + bindSocket.type = mkOption { + type = types.enum [ "unix" "inet" ]; + default = "unix"; description = '' - Unix domain sockets to listen for MTA requests. - ''; - example = '' - [ "/run/rmilter.sock"] + What kind of socket rmilter should listen on. Either "unix" + for an Unix domain socket or "inet" for a TCP socket. ''; }; - bindInetSockets = mkOption { - type = types.listOf types.str; - default = []; - description = '' - Inet addresses to listen (in format accepted by systemd.socket) + bindSocket.path = mkOption { + type = types.str; + default = "/run/rmilter/rmilter.sock"; + description = '' + Path to Unix domain socket to listen on. ''; - example = '' - ["127.0.0.1:11990"] + }; + + bindSocket.address = mkOption { + type = types.str; + default = "::1"; + example = "0.0.0.0"; + description = '' + Inet address to listen on. + ''; + }; + + bindSocket.port = mkOption { + type = types.int; + default = 11990; + description = '' + Inet port to listen on. ''; }; @@ -102,13 +119,13 @@ in Disabling socket activation is not recommended when a Unix domain socket is used and could lead to incorrect - permissions. Therefore, setting this to false will - configure rmilter to use an inet socket only. + permissions. ''; }; rspamd = { enable = mkOption { + type = types.bool; default = rspamdCfg.enable; description = "Whether to use rspamd to filter mails"; }; @@ -158,13 +175,9 @@ in type = types.str; description = "Addon to postfix configuration"; default = '' -smtpd_milters = ${head allSockets} -# or for TCP socket -# # smtpd_milters = inet:localhost:9900 -milter_protocol = 6 -milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_authen} -# skip mail without checks if milter will die -milter_default_action = accept + smtpd_milters = ${rmilterSocket} + milter_protocol = 6 + milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_authen} ''; }; }; @@ -176,52 +189,58 @@ milter_default_action = accept ###### implementation - config = mkIf cfg.enable { + config = mkMerge [ - users.extraUsers = singleton { - name = cfg.user; - description = "rspamd daemon"; - uid = config.ids.uids.rmilter; - group = cfg.group; - }; + (mkIf cfg.enable { - users.extraGroups = singleton { - name = cfg.group; - gid = config.ids.gids.rmilter; - }; - - systemd.services.rmilter = { - description = "Rmilter Service"; - - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - - serviceConfig = { - ExecStart = "${pkgs.rmilter}/bin/rmilter ${optionalString cfg.debug "-d"} -n -c ${rmilterConfigFile}"; - ExecReload = "${pkgs.coreutils}/bin/kill -USR1 $MAINPID"; - User = cfg.user; - Group = cfg.group; - PermissionsStartOnly = true; - Restart = "always"; - RuntimeDirectory = "rmilter"; - RuntimeDirectoryMode = "0755"; + users.extraUsers = singleton { + name = cfg.user; + description = "rmilter daemon"; + uid = config.ids.uids.rmilter; + group = cfg.group; }; - }; - - systemd.sockets.rmilter = mkIf cfg.socketActivation { - description = "Rmilter service socket"; - wantedBy = [ "sockets.target" ]; - socketConfig = { - ListenStream = cfg.bindUnixSockets ++ cfg.bindInetSockets; - SocketUser = cfg.user; - SocketGroup = cfg.group; - SocketMode = "0666"; + users.extraGroups = singleton { + name = cfg.group; + gid = config.ids.gids.rmilter; }; - }; - services.postfix.extraConfig = optionalString cfg.postfix.enable cfg.postfix.configFragment; - users.users.postfix.extraGroups = [ cfg.group ]; - }; + systemd.services.rmilter = { + description = "Rmilter Service"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + serviceConfig = { + ExecStart = "${pkgs.rmilter}/bin/rmilter ${optionalString cfg.debug "-d"} -n -c ${rmilterConfigFile}"; + ExecReload = "${pkgs.coreutils}/bin/kill -USR1 $MAINPID"; + User = cfg.user; + Group = cfg.group; + PermissionsStartOnly = true; + Restart = "always"; + RuntimeDirectory = "rmilter"; + RuntimeDirectoryMode = "0755"; + }; + + }; + + systemd.sockets.rmilter = mkIf cfg.socketActivation { + description = "Rmilter service socket"; + wantedBy = [ "sockets.target" ]; + socketConfig = { + ListenStream = systemdSocket; + SocketUser = cfg.user; + SocketGroup = cfg.group; + SocketMode = "0666"; + }; + }; + }) + + (mkIf (cfg.enable && cfg.postfix.enable) { + + services.postfix.extraConfig = cfg.postfix.configFragment; + users.users.postfix.extraGroups = [ cfg.group ]; + + }) + ]; } From 00239ce8e9baeef0ea55fd0995a55e0b15a25ac9 Mon Sep 17 00:00:00 2001 From: Franz Pletz Date: Fri, 17 Mar 2017 23:01:24 +0100 Subject: [PATCH 3/3] rmilter/rspamd service: tighten unix socket permissions --- nixos/modules/services/mail/rmilter.nix | 13 ++++++++----- nixos/modules/services/mail/rspamd.nix | 5 ++++- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/nixos/modules/services/mail/rmilter.nix b/nixos/modules/services/mail/rmilter.nix index 3153b1c79124..e17b7516bfff 100644 --- a/nixos/modules/services/mail/rmilter.nix +++ b/nixos/modules/services/mail/rmilter.nix @@ -5,6 +5,7 @@ with lib; let rspamdCfg = config.services.rspamd; + postfixCfg = config.services.postfix; cfg = config.services.rmilter; inetSocket = addr: port: "inet:[${toString port}@${addr}]"; @@ -219,7 +220,7 @@ in PermissionsStartOnly = true; Restart = "always"; RuntimeDirectory = "rmilter"; - RuntimeDirectoryMode = "0755"; + RuntimeDirectoryMode = "0750"; }; }; @@ -231,16 +232,18 @@ in ListenStream = systemdSocket; SocketUser = cfg.user; SocketGroup = cfg.group; - SocketMode = "0666"; + SocketMode = "0660"; }; }; }) + (mkIf (cfg.enable && cfg.rspamd.enable && rspamdCfg.enable) { + users.extraUsers.${cfg.user}.extraGroups = [ rspamdCfg.group ]; + }) + (mkIf (cfg.enable && cfg.postfix.enable) { - services.postfix.extraConfig = cfg.postfix.configFragment; - users.users.postfix.extraGroups = [ cfg.group ]; - + users.extraUsers.${postfixCfg.user}.extraGroups = [ cfg.group ]; }) ]; } diff --git a/nixos/modules/services/mail/rspamd.nix b/nixos/modules/services/mail/rspamd.nix index 98489df78517..6d403e448e04 100644 --- a/nixos/modules/services/mail/rspamd.nix +++ b/nixos/modules/services/mail/rspamd.nix @@ -53,8 +53,11 @@ in bindSocket = mkOption { type = types.listOf types.str; default = [ - "/run/rspamd/rspamd.sock mode=0666 owner=${cfg.user}" + "/run/rspamd/rspamd.sock mode=0660 owner=${cfg.user} group=${cfg.group}" ]; + defaultText = ''[ + "/run/rspamd/rspamd.sock mode=0660 owner=${cfg.user} group=${cfg.group}" + ]''; description = '' List of sockets to listen, in format acceptable by rspamd '';