From dbc6479974f720a1313a467f70cc40ad2e558025 Mon Sep 17 00:00:00 2001 From: Jesse Norell Date: Thu, 8 Apr 2021 13:17:41 -0600 Subject: [PATCH 1/8] rspamd: add multimap.conf template --- install/lib/installer_base.lib.php | 1 + install/tpl/rspamd_multimap.conf.master | 15 +++++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 install/tpl/rspamd_multimap.conf.master diff --git a/install/lib/installer_base.lib.php b/install/lib/installer_base.lib.php index 43d226aab5..e8b3cb0087 100644 --- a/install/lib/installer_base.lib.php +++ b/install/lib/installer_base.lib.php @@ -1897,6 +1897,7 @@ class installer_base { 'neural_group.conf', 'users.conf', 'groups.conf', + 'multimap.conf', ); foreach ($local_d as $f) { if(file_exists($conf['ispconfig_install_dir']."/server/conf-custom/install/rspamd_${f}.master")) { diff --git a/install/tpl/rspamd_multimap.conf.master b/install/tpl/rspamd_multimap.conf.master new file mode 100644 index 0000000000..295d0bcd89 --- /dev/null +++ b/install/tpl/rspamd_multimap.conf.master @@ -0,0 +1,15 @@ +# from https://rspamd.com/doc/configuration/selectors.html +INVALUEMENT_SENDGRID_ID { + type = "selector"; + selector = 'header("X-SG-EID").id;from("smtp","orig").regexp("/^ Date: Thu, 8 Apr 2021 16:14:39 -0600 Subject: [PATCH 2/8] rspamd: add ip whitelist map --- install/lib/installer_base.lib.php | 17 +++++++++++ install/tpl/rspamd_multimap.conf.master | 11 +++++++ .../plugins-available/rspamd_plugin.inc.php | 29 +++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/install/lib/installer_base.lib.php b/install/lib/installer_base.lib.php index e8b3cb0087..a8573a0a64 100644 --- a/install/lib/installer_base.lib.php +++ b/install/lib/installer_base.lib.php @@ -1935,6 +1935,23 @@ class installer_base { } } + # generated local.d/maps.d files + $filename = '/etc/rspamd/local.d/maps.d/ip_whitelist.inc.ispc'; + @unlink($filename); + $records = $this->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'client' AND `access` = 'OK' AND `active` = 'y' AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + if (count($records) > 0) { + if ($fp = fopen($filename, 'w')) { + fwrite($fp, "# ISPConfig whitelisted ip addresses\n\n"); + foreach($records as $record) { + fwrite($fp, $record['source'] . "\n"); + } + fclose($fp); + } else { + $this->error("Error: cannot open $filename for writing"); + } + } + + # rename rspamd templates we no longer use if(file_exists("/etc/rspamd/local.d/greylist.conf")) { rename("/etc/rspamd/local.d/greylist.conf", "/etc/rspamd/local.d/greylist.old"); diff --git a/install/tpl/rspamd_multimap.conf.master b/install/tpl/rspamd_multimap.conf.master index 295d0bcd89..b9712afe93 100644 --- a/install/tpl/rspamd_multimap.conf.master +++ b/install/tpl/rspamd_multimap.conf.master @@ -1,3 +1,14 @@ +ISPC_WHITELIST_IP { + description = "Whitelisted ip address"; + group = "ISPConfig"; + type = "ip"; + map = [ "$LOCAL_CONFDIR/local.d/maps.d/ip_whitelist.inc.ispc", "$LOCAL_CONFDIR/local.d/maps.d/ip_whitelist.inc.local" ]; + prefilter = "true"; + action = "accept"; +} + +# ISPC_BLACKLIST_IP: Postfix blocks blacklisted IP's, no need to configure those here. + # from https://rspamd.com/doc/configuration/selectors.html INVALUEMENT_SENDGRID_ID { type = "selector"; diff --git a/server/plugins-available/rspamd_plugin.inc.php b/server/plugins-available/rspamd_plugin.inc.php index 9d34ac8a36..062450a144 100644 --- a/server/plugins-available/rspamd_plugin.inc.php +++ b/server/plugins-available/rspamd_plugin.inc.php @@ -119,6 +119,9 @@ class rspamd_plugin { $app->plugins->registerEvent('mail_access_insert', $this->plugin_name, 'spamfilter_wblist_insert'); $app->plugins->registerEvent('mail_access_update', $this->plugin_name, 'spamfilter_wblist_update'); $app->plugins->registerEvent('mail_access_delete', $this->plugin_name, 'spamfilter_wblist_delete'); + $app->plugins->registerEvent('mail_access_insert', $this->plugin_name, 'mail_access_update'); + $app->plugins->registerEvent('mail_access_update', $this->plugin_name, 'mail_access_update'); + $app->plugins->registerEvent('mail_access_delete', $this->plugin_name, 'mail_access_update'); //* server $app->plugins->registerEvent('server_insert', $this->plugin_name, 'server_update'); @@ -498,6 +501,32 @@ class rspamd_plugin { } } + function mail_access_update($event_name, $data) { + global $app, $conf; + + if(!is_dir('/etc/rspamd')) { + return; + } + + $mail_config = $app->getconf->get_server_config($conf['server_id'], 'mail'); + + # generated local.d/maps.d files + $filename = '/etc/rspamd/local.d/maps.d/ip_whitelist.inc.ispc'; + @unlink($filename); + $records = $app->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'client' AND `access` = 'OK' AND `active` = 'y' AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + if (count($records) > 0) { + if ($fp = fopen($filename, 'w')) { + fwrite($fp, "# ISPConfig whitelisted ip addresses\n\n"); + foreach($records as $record) { + fwrite($fp, $record['source'] . "\n"); + } + fclose($fp); + } else { + $app->log("Error: cannot open $filename for writing", LOGLEVEL_WARN); + } + } + } + function server_update($event_name, $data) { global $app, $conf; -- GitLab From 3d5339baa8d06149329c75067e9068f8e7637737 Mon Sep 17 00:00:00 2001 From: Jesse Norell Date: Wed, 14 Apr 2021 12:04:47 -0600 Subject: [PATCH 3/8] rspamd: add sender whitelist/blacklist maps --- install/lib/installer_base.lib.php | 61 +++++++++++ install/tpl/rspamd_force_actions.conf.master | 18 +++ install/tpl/rspamd_multimap.conf.master | 62 +++++++++++ install/tpl/rspamd_whitelist.conf.master | 8 +- .../plugins-available/rspamd_plugin.inc.php | 103 ++++++++++++++++-- 5 files changed, 239 insertions(+), 13 deletions(-) create mode 100644 install/tpl/rspamd_force_actions.conf.master diff --git a/install/lib/installer_base.lib.php b/install/lib/installer_base.lib.php index a8573a0a64..1eec164d5f 100644 --- a/install/lib/installer_base.lib.php +++ b/install/lib/installer_base.lib.php @@ -1898,6 +1898,7 @@ class installer_base { 'users.conf', 'groups.conf', 'multimap.conf', + 'force_actions.conf', ); foreach ($local_d as $f) { if(file_exists($conf['ispconfig_install_dir']."/server/conf-custom/install/rspamd_${f}.master")) { @@ -1951,6 +1952,66 @@ class installer_base { } } + $filename = '/etc/rspamd/local.d/maps.d/sender_whitelist.inc.ispc'; + @unlink($filename); + $records = $this->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'sender' AND `source` LIKE '%@%' AND `access` = 'OK' AND `active` = 'y' AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + if (count($records) > 0) { + if ($fp = fopen($filename, 'w')) { + fwrite($fp, "# ISPConfig whitelisted sender addresses\n\n"); + foreach($records as $record) { + fwrite($fp, $record['source'] . "\n"); + } + fclose($fp); + } else { + $this->error("Error: cannot open $filename for writing"); + } + } + + $filename = '/etc/rspamd/local.d/maps.d/sender_blacklist.inc.ispc'; + @unlink($filename); + $records = $this->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'sender' AND `source` LIKE '%@%' AND `access` LIKE 'REJECT%' AND `active` = 'y' AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + if (count($records) > 0) { + if ($fp = fopen($filename, 'w')) { + fwrite($fp, "# ISPConfig blacklisted sender addresses\n\n"); + foreach($records as $record) { + fwrite($fp, $record['source'] . "\n"); + } + fclose($fp); + } else { + $this->error("Error: cannot open $filename for writing"); + } + } + + $filename = '/etc/rspamd/local.d/maps.d/sender_domain_whitelist.inc.ispc'; + @unlink($filename); + $records = $this->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'sender' AND `source` NOT LIKE '%@%' AND `access` = 'OK' AND `active` = 'y' AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + if (count($records) > 0) { + if ($fp = fopen($filename, 'w')) { + fwrite($fp, "# ISPConfig whitelisted sender domains\n\n"); + foreach($records as $record) { + fwrite($fp, ltrim($record['source'], '.') . "\n"); + } + fclose($fp); + } else { + $this->error("Error: cannot open $filename for writing"); + } + } + + $filename = '/etc/rspamd/local.d/maps.d/sender_domain_blacklist.inc.ispc'; + @unlink($filename); + $records = $this->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'sender' AND `source` NOT LIKE '%@%' AND `access` LIKE 'REJECT%' AND `active` = 'y' AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + if (count($records) > 0) { + if ($fp = fopen($filename, 'w')) { + fwrite($fp, "# ISPConfig blacklisted sender domains\n\n"); + foreach($records as $record) { + fwrite($fp, ltrim($record['source'], '.') . "\n"); + } + fclose($fp); + } else { + $this->error("Error: cannot open $filename for writing"); + } + } + # rename rspamd templates we no longer use if(file_exists("/etc/rspamd/local.d/greylist.conf")) { diff --git a/install/tpl/rspamd_force_actions.conf.master b/install/tpl/rspamd_force_actions.conf.master new file mode 100644 index 0000000000..5cd2edf90b --- /dev/null +++ b/install/tpl/rspamd_force_actions.conf.master @@ -0,0 +1,18 @@ +rules { + + ISPC_WHITELIST_SENDER { + expression = "(ISPC_WHITELIST_ENVFROM and (R_DKIM_ALLOW or R_SPF_ALLOW)) or (ISPC_WHITELIST_FROM and R_DKIM_ALLOW) and !CLAM_VIRUS and !JUST_EICAR"; + action = "no action"; + } + + ISPC_BLACKLIST_SENDER { + expression = "(ISPC_BLACKLIST_FROM or ISPC_BLACKLIST_FROM_DOMAIN) and R_DKIM_ALLOW and !ISPC_WHITELIST_SENDER and !ISPC_WHITELIST_SENDER_DOMAIN"; + action = "reject"; + } + + ISPC_WHITELIST_SENDER_DOMAIN { + expression = "(ISPC_WHITELIST_ENVFROM_DOMAIN and (ISPC_WHITELIST_DKIM or ISPC_WHITELIST_SPF)) or (ISPC_WHITELIST_FROM_DOMAIN and ISPC_WHITELIST_DKIM) and !CLAM_VIRUS and !JUST_EICAR"; + action = "no action"; + } + +} diff --git a/install/tpl/rspamd_multimap.conf.master b/install/tpl/rspamd_multimap.conf.master index b9712afe93..fbeab4317d 100644 --- a/install/tpl/rspamd_multimap.conf.master +++ b/install/tpl/rspamd_multimap.conf.master @@ -9,6 +9,68 @@ ISPC_WHITELIST_IP { # ISPC_BLACKLIST_IP: Postfix blocks blacklisted IP's, no need to configure those here. +ISPC_WHITELIST_ENVFROM { + type = "from"; + filter = "email"; + map = [ "$LOCAL_CONFDIR/local.d/maps.d/sender_whitelist.inc.ispc", "$LOCAL_CONFDIR/local.d/maps.d/sender_whitelist.inc.local" ]; + score = -7.0; + description = "Whitelisted sender address"; + group = "ispconfig"; +} + +# ISPC_BLACKLIST_ENVFROM: Postfix blocks blacklisted senders, no need to configure those here. + +ISPC_WHITELIST_ENVFROM_DOMAIN { + type = "from"; + filter = "email:domain"; + map = [ "$LOCAL_CONFDIR/local.d/maps.d/sender_domain_whitelist.inc.ispc", "$LOCAL_CONFDIR/local.d/maps.d/sender_domain_whitelist.inc.local" ]; + score = -7.0; + description = "Whitelisted sender domain"; + group = "ispconfig"; +} + +# ISPC_BLACKLIST_ENVFROM_DOMAIN: Postfix blocks blacklisted sender domains, no need to configure those here. + +ISPC_WHITELIST_FROM { + type = "selector"; + selector = "from('mime')"; + map = [ "$LOCAL_CONFDIR/local.d/maps.d/sender_whitelist.inc.ispc", "$LOCAL_CONFDIR/local.d/maps.d/sender_whitelist.inc.local" ]; + # trivial to spoof so primarily used via composite expression in force_actions.conf + score = -1.0; + description = "From: header address in sender whitelist."; + group = "ispconfig"; +} + +ISPC_BLACKLIST_FROM { + type = "selector"; + selector = "from('mime')"; + map = [ "$LOCAL_CONFDIR/local.d/maps.d/sender_blacklist.inc.ispc", "$LOCAL_CONFDIR/local.d/maps.d/sender_blacklist.inc.local" ]; + score = 12.0; + description = "From: header address in sender blacklist."; + group = "ispconfig"; +} + +ISPC_WHITELIST_FROM_DOMAIN { + type = "selector"; + selector = "from('mime'):domain"; + map = [ "$LOCAL_CONFDIR/local.d/maps.d/sender_domain_whitelist.inc.ispc", "$LOCAL_CONFDIR/local.d/maps.d/sender_domain_whitelist.inc.local" ]; + # trivial to spoof so primarily used via composite expression in force_actions.conf + score = -1.0; + description = "From: header domain in sender whitelist."; + group = "ispconfig"; +} + +ISPC_BLACKLIST_FROM_DOMAIN { + type = "selector"; + selector = "from('mime'):domain"; + map = [ "$LOCAL_CONFDIR/local.d/maps.d/sender_domain_blacklist.inc.ispc", "$LOCAL_CONFDIR/local.d/maps.d/sender_domain_blacklist.inc.local" ]; + score = 12.0; + description = "From: header domain in sender blacklist."; + group = "ispconfig"; +} + + +# Invaluement.com Service Provider DNSBLs # from https://rspamd.com/doc/configuration/selectors.html INVALUEMENT_SENDGRID_ID { type = "selector"; diff --git a/install/tpl/rspamd_whitelist.conf.master b/install/tpl/rspamd_whitelist.conf.master index 6b4647a948..d61e735d78 100644 --- a/install/tpl/rspamd_whitelist.conf.master +++ b/install/tpl/rspamd_whitelist.conf.master @@ -2,7 +2,9 @@ rules { "ISPC_WHITELIST_SPF" = { valid_spf = true; domains = [ - "$LOCAL_CONFDIR/local.d/maps.d/spf_whitelist.inc.ispc" + "$LOCAL_CONFDIR/local.d/maps.d/spf_whitelist.inc.ispc", + "$LOCAL_CONFDIR/local.d/maps.d/sender_domain_whitelist.inc.ispc", + "$LOCAL_CONFDIR/local.d/maps.d/sender_domain_whitelist.inc.local" ]; score = -2.0 inverse_symbol = "ISPC_BLACKLIST_SPF"; @@ -11,7 +13,9 @@ rules { "ISPC_WHITELIST_DKIM" = { valid_dkim = true; domains = [ - "$LOCAL_CONFDIR/local.d/maps.d/dkim_whitelist.inc.ispc" + "$LOCAL_CONFDIR/local.d/maps.d/dkim_whitelist.inc.ispc", + "$LOCAL_CONFDIR/local.d/maps.d/sender_domain_whitelist.inc.ispc", + "$LOCAL_CONFDIR/local.d/maps.d/sender_domain_whitelist.inc.local" ]; score = -2.0; inverse_symbol = "ISPC_BLACKLIST_DKIM"; diff --git a/server/plugins-available/rspamd_plugin.inc.php b/server/plugins-available/rspamd_plugin.inc.php index 062450a144..d1ee97fc4a 100644 --- a/server/plugins-available/rspamd_plugin.inc.php +++ b/server/plugins-available/rspamd_plugin.inc.php @@ -510,19 +510,100 @@ class rspamd_plugin { $mail_config = $app->getconf->get_server_config($conf['server_id'], 'mail'); + +/* + [new] => Array + ( + [access_id] => 5 + [sys_userid] => 1 + [sys_groupid] => 1 + [sys_perm_user] => riud + [sys_perm_group] => riud + [sys_perm_other] => + [server_id] => 1 + [source] => 1.2.3.5 + [access] => OK + [type] => client + [active] => y + ) + */ # generated local.d/maps.d files - $filename = '/etc/rspamd/local.d/maps.d/ip_whitelist.inc.ispc'; - @unlink($filename); - $records = $app->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'client' AND `access` = 'OK' AND `active` = 'y' AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); - if (count($records) > 0) { - if ($fp = fopen($filename, 'w')) { - fwrite($fp, "# ISPConfig whitelisted ip addresses\n\n"); - foreach($records as $record) { - fwrite($fp, $record['source'] . "\n"); + if ($data['old']['type'] == 'client' || $data['new']['type'] == 'client') { + $filename = '/etc/rspamd/local.d/maps.d/ip_whitelist.inc.ispc'; + @unlink($filename); + $records = $app->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'client' AND `access` = 'OK' AND `active` = 'y' AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + if (count($records) > 0) { + if ($fp = fopen($filename, 'w')) { + fwrite($fp, "# ISPConfig whitelisted ip addresses\n\n"); + foreach($records as $record) { + fwrite($fp, $record['source'] . "\n"); + } + fclose($fp); + } else { + $app->log("Error: cannot open $filename for writing", LOGLEVEL_WARN); + } + } + } + + if ($data['old']['type'] == 'sender' || $data['new']['type'] == 'sender') { + $filename = '/etc/rspamd/local.d/maps.d/sender_whitelist.inc.ispc'; + @unlink($filename); + $records = $app->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'sender' AND `source` LIKE '%@%' AND `access` = 'OK' AND `active` = 'y' AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + if (count($records) > 0) { + if ($fp = fopen($filename, 'w')) { + fwrite($fp, "# ISPConfig whitelisted sender addresses\n\n"); + foreach($records as $record) { + fwrite($fp, $record['source'] . "\n"); + } + fclose($fp); + } else { + $app->log("Error: cannot open $filename for writing", LOGLEVEL_WARN); + } + } + + $filename = '/etc/rspamd/local.d/maps.d/sender_blacklist.inc.ispc'; + @unlink($filename); + $records = $app->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'sender' AND `source` LIKE '%@%' AND `access` LIKE 'REJECT%' AND `active` = 'y' AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + if (count($records) > 0) { + if ($fp = fopen($filename, 'w')) { + fwrite($fp, "# ISPConfig blacklisted sender addresses\n\n"); + foreach($records as $record) { + fwrite($fp, $record['source'] . "\n"); + } + fclose($fp); + } else { + $app->log("Error: cannot open $filename for writing", LOGLEVEL_WARN); + } + } + + $filename = '/etc/rspamd/local.d/maps.d/sender_domain_whitelist.inc.ispc'; + @unlink($filename); + $records = $app->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'sender' AND `source` NOT LIKE '%@%' AND `access` = 'OK' AND `active` = 'y' AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + if (count($records) > 0) { + if ($fp = fopen($filename, 'w')) { + fwrite($fp, "# ISPConfig whitelisted sender domains\n\n"); + foreach($records as $record) { + fwrite($fp, ltrim($record['source'], '.') . "\n"); + } + fclose($fp); + } else { + $app->log("Error: cannot open $filename for writing", LOGLEVEL_WARN); + } + } + + $filename = '/etc/rspamd/local.d/maps.d/sender_domain_blacklist.inc.ispc'; + @unlink($filename); + $records = $app->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'sender' AND `source` NOT LIKE '%@%' AND `access` LIKE 'REJECT%' AND `active` = 'y' AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + if (count($records) > 0) { + if ($fp = fopen($filename, 'w')) { + fwrite($fp, "# ISPConfig blacklisted sender domains\n\n"); + foreach($records as $record) { + fwrite($fp, ltrim($record['source'], '.') . "\n"); + } + fclose($fp); + } else { + $app->log("Error: cannot open $filename for writing", LOGLEVEL_WARN); } - fclose($fp); - } else { - $app->log("Error: cannot open $filename for writing", LOGLEVEL_WARN); } } } -- GitLab From e27a978415cee7cf79cac025da880140a93c2064 Mon Sep 17 00:00:00 2001 From: Jesse Norell Date: Wed, 14 Apr 2021 17:01:18 -0600 Subject: [PATCH 4/8] rspamd: add recipient whitelist/blacklist maps --- install/lib/installer_base.lib.php | 70 ++++++++++++++-- install/tpl/rspamd_force_actions.conf.master | 17 +++- install/tpl/rspamd_multimap.conf.master | 81 +++++++++++++++---- .../plugins-available/rspamd_plugin.inc.php | 72 +++++++++++++++-- 4 files changed, 212 insertions(+), 28 deletions(-) diff --git a/install/lib/installer_base.lib.php b/install/lib/installer_base.lib.php index 1eec164d5f..392daccd4c 100644 --- a/install/lib/installer_base.lib.php +++ b/install/lib/installer_base.lib.php @@ -1939,7 +1939,7 @@ class installer_base { # generated local.d/maps.d files $filename = '/etc/rspamd/local.d/maps.d/ip_whitelist.inc.ispc'; @unlink($filename); - $records = $this->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'client' AND `access` = 'OK' AND `active` = 'y' AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + $records = $this->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'client' AND `access` = 'OK' AND `active` = 'y' AND `sys_userid` IN (SELECT `userid` FROM `sys_user` WHERE `sys_groupid` = 0) AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); if (count($records) > 0) { if ($fp = fopen($filename, 'w')) { fwrite($fp, "# ISPConfig whitelisted ip addresses\n\n"); @@ -1954,7 +1954,7 @@ class installer_base { $filename = '/etc/rspamd/local.d/maps.d/sender_whitelist.inc.ispc'; @unlink($filename); - $records = $this->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'sender' AND `source` LIKE '%@%' AND `access` = 'OK' AND `active` = 'y' AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + $records = $this->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'sender' AND `source` LIKE '%@%' AND `access` = 'OK' AND `active` = 'y' AND `sys_userid` IN (SELECT `userid` FROM `sys_user` WHERE `sys_groupid` = 0) AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); if (count($records) > 0) { if ($fp = fopen($filename, 'w')) { fwrite($fp, "# ISPConfig whitelisted sender addresses\n\n"); @@ -1969,7 +1969,7 @@ class installer_base { $filename = '/etc/rspamd/local.d/maps.d/sender_blacklist.inc.ispc'; @unlink($filename); - $records = $this->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'sender' AND `source` LIKE '%@%' AND `access` LIKE 'REJECT%' AND `active` = 'y' AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + $records = $this->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'sender' AND `source` LIKE '%@%' AND `access` LIKE 'REJECT%' AND `active` = 'y' AND `sys_userid` IN (SELECT `userid` FROM `sys_user` WHERE `sys_groupid` = 0) AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); if (count($records) > 0) { if ($fp = fopen($filename, 'w')) { fwrite($fp, "# ISPConfig blacklisted sender addresses\n\n"); @@ -1984,7 +1984,7 @@ class installer_base { $filename = '/etc/rspamd/local.d/maps.d/sender_domain_whitelist.inc.ispc'; @unlink($filename); - $records = $this->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'sender' AND `source` NOT LIKE '%@%' AND `access` = 'OK' AND `active` = 'y' AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + $records = $this->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'sender' AND `source` NOT LIKE '%@%' AND `access` = 'OK' AND `active` = 'y' AND `sys_userid` IN (SELECT `userid` FROM `sys_user` WHERE `sys_groupid` = 0) AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); if (count($records) > 0) { if ($fp = fopen($filename, 'w')) { fwrite($fp, "# ISPConfig whitelisted sender domains\n\n"); @@ -1999,7 +1999,7 @@ class installer_base { $filename = '/etc/rspamd/local.d/maps.d/sender_domain_blacklist.inc.ispc'; @unlink($filename); - $records = $this->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'sender' AND `source` NOT LIKE '%@%' AND `access` LIKE 'REJECT%' AND `active` = 'y' AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + $records = $this->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'sender' AND `source` NOT LIKE '%@%' AND `access` LIKE 'REJECT%' AND `active` = 'y' AND `sys_userid` IN (SELECT `userid` FROM `sys_user` WHERE `sys_groupid` = 0) AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); if (count($records) > 0) { if ($fp = fopen($filename, 'w')) { fwrite($fp, "# ISPConfig blacklisted sender domains\n\n"); @@ -2012,6 +2012,66 @@ class installer_base { } } + $filename = '/etc/rspamd/local.d/maps.d/recipient_whitelist.inc.ispc'; + @unlink($filename); + $records = $this->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'recipient' AND `source` LIKE '%@%' AND `access` = 'OK' AND `active` = 'y' AND `sys_userid` IN (SELECT `userid` FROM `sys_user` WHERE `sys_groupid` = 0) AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + if (count($records) > 0) { + if ($fp = fopen($filename, 'w')) { + fwrite($fp, "# ISPConfig whitelisted recipient addresses\n\n"); + foreach($records as $record) { + fwrite($fp, $record['source'] . "\n"); + } + fclose($fp); + } else { + $this->error("Error: cannot open $filename for writing"); + } + } + + $filename = '/etc/rspamd/local.d/maps.d/recipient_blacklist.inc.ispc'; + @unlink($filename); + $records = $this->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'recipient' AND `source` LIKE '%@%' AND `access` LIKE 'REJECT%' AND `active` = 'y' AND `sys_userid` IN (SELECT `userid` FROM `sys_user` WHERE `sys_groupid` = 0) AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + if (count($records) > 0) { + if ($fp = fopen($filename, 'w')) { + fwrite($fp, "# ISPConfig blacklisted recipient addresses\n\n"); + foreach($records as $record) { + fwrite($fp, $record['source'] . "\n"); + } + fclose($fp); + } else { + $this->error("Error: cannot open $filename for writing"); + } + } + + $filename = '/etc/rspamd/local.d/maps.d/recipient_domain_whitelist.inc.ispc'; + @unlink($filename); + $records = $this->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'recipient' AND `source` NOT LIKE '%@%' AND `access` = 'OK' AND `active` = 'y' AND `sys_userid` IN (SELECT `userid` FROM `sys_user` WHERE `sys_groupid` = 0) AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + if (count($records) > 0) { + if ($fp = fopen($filename, 'w')) { + fwrite($fp, "# ISPConfig whitelisted recipient domains\n\n"); + foreach($records as $record) { + fwrite($fp, ltrim($record['source'], '.') . "\n"); + } + fclose($fp); + } else { + $this->error("Error: cannot open $filename for writing"); + } + } + + $filename = '/etc/rspamd/local.d/maps.d/recipient_domain_blacklist.inc.ispc'; + @unlink($filename); + $records = $this->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'recipient' AND `source` NOT LIKE '%@%' AND `access` LIKE 'REJECT%' AND `active` = 'y' AND `sys_userid` IN (SELECT `userid` FROM `sys_user` WHERE `sys_groupid` = 0) AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + if (count($records) > 0) { + if ($fp = fopen($filename, 'w')) { + fwrite($fp, "# ISPConfig blacklisted recipient domains\n\n"); + foreach($records as $record) { + fwrite($fp, ltrim($record['source'], '.') . "\n"); + } + fclose($fp); + } else { + $this->error("Error: cannot open $filename for writing"); + } + } + # rename rspamd templates we no longer use if(file_exists("/etc/rspamd/local.d/greylist.conf")) { diff --git a/install/tpl/rspamd_force_actions.conf.master b/install/tpl/rspamd_force_actions.conf.master index 5cd2edf90b..183cea0391 100644 --- a/install/tpl/rspamd_force_actions.conf.master +++ b/install/tpl/rspamd_force_actions.conf.master @@ -6,7 +6,7 @@ rules { } ISPC_BLACKLIST_SENDER { - expression = "(ISPC_BLACKLIST_FROM or ISPC_BLACKLIST_FROM_DOMAIN) and R_DKIM_ALLOW and !ISPC_WHITELIST_SENDER and !ISPC_WHITELIST_SENDER_DOMAIN"; + expression = "(ISPC_BLACKLIST_FROM or ISPC_BLACKLIST_FROM_DOMAIN) and R_DKIM_ALLOW and !ISPC_WHITELIST_SENDER and !ISPC_WHITELIST_SENDER_DOMAIN and !ISPC_WHITELIST_RECIPIENT"; action = "reject"; } @@ -15,4 +15,19 @@ rules { action = "no action"; } + ISPC_WHITELIST_RECIPIENT { + expression = "ISPC_WHITELIST_ENVRCPT and !CLAM_VIRUS and !JUST_EICAR"; + action = "no action"; + } + + ISPC_BLACKLIST_RECIPIENT { + expression = "(ISPC_BLACKLIST_TO or ISPC_BLACKLIST_TO_DOMAIN) and !ISPC_WHITELIST_SENDER and !ISPC_WHITELIST_SENDER_DOMAIN and !ISPC_WHITELIST_RECIPIENT"; + action = "reject"; + } + + ISPC_WHITELIST_RECIPIENT_DOMAIN { + expression = "ISPC_WHITELIST_ENVRCPT_DOMAIN and !CLAM_VIRUS and !JUST_EICAR"; + action = "no action"; + } + } diff --git a/install/tpl/rspamd_multimap.conf.master b/install/tpl/rspamd_multimap.conf.master index fbeab4317d..0239e8ffdc 100644 --- a/install/tpl/rspamd_multimap.conf.master +++ b/install/tpl/rspamd_multimap.conf.master @@ -1,6 +1,6 @@ ISPC_WHITELIST_IP { - description = "Whitelisted ip address"; group = "ISPConfig"; + description = "Whitelisted ip address."; type = "ip"; map = [ "$LOCAL_CONFDIR/local.d/maps.d/ip_whitelist.inc.ispc", "$LOCAL_CONFDIR/local.d/maps.d/ip_whitelist.inc.local" ]; prefilter = "true"; @@ -10,63 +10,110 @@ ISPC_WHITELIST_IP { # ISPC_BLACKLIST_IP: Postfix blocks blacklisted IP's, no need to configure those here. ISPC_WHITELIST_ENVFROM { - type = "from"; - filter = "email"; + group = "ISPConfig"; + description = "Whitelisted sender address."; + type = "selector"; + filter = "from('smtp')"; map = [ "$LOCAL_CONFDIR/local.d/maps.d/sender_whitelist.inc.ispc", "$LOCAL_CONFDIR/local.d/maps.d/sender_whitelist.inc.local" ]; score = -7.0; - description = "Whitelisted sender address"; - group = "ispconfig"; } # ISPC_BLACKLIST_ENVFROM: Postfix blocks blacklisted senders, no need to configure those here. ISPC_WHITELIST_ENVFROM_DOMAIN { - type = "from"; - filter = "email:domain"; + group = "ISPConfig"; + description = "Whitelisted sender domain."; + type = "selector"; + filter = "from('smtp'):domain"; map = [ "$LOCAL_CONFDIR/local.d/maps.d/sender_domain_whitelist.inc.ispc", "$LOCAL_CONFDIR/local.d/maps.d/sender_domain_whitelist.inc.local" ]; score = -7.0; - description = "Whitelisted sender domain"; - group = "ispconfig"; } # ISPC_BLACKLIST_ENVFROM_DOMAIN: Postfix blocks blacklisted sender domains, no need to configure those here. ISPC_WHITELIST_FROM { + group = "ISPConfig"; + description = "From: header address in sender whitelist."; type = "selector"; selector = "from('mime')"; map = [ "$LOCAL_CONFDIR/local.d/maps.d/sender_whitelist.inc.ispc", "$LOCAL_CONFDIR/local.d/maps.d/sender_whitelist.inc.local" ]; # trivial to spoof so primarily used via composite expression in force_actions.conf score = -1.0; - description = "From: header address in sender whitelist."; - group = "ispconfig"; } ISPC_BLACKLIST_FROM { + group = "ISPConfig"; + description = "From: header address in sender blacklist."; type = "selector"; selector = "from('mime')"; map = [ "$LOCAL_CONFDIR/local.d/maps.d/sender_blacklist.inc.ispc", "$LOCAL_CONFDIR/local.d/maps.d/sender_blacklist.inc.local" ]; score = 12.0; - description = "From: header address in sender blacklist."; - group = "ispconfig"; } ISPC_WHITELIST_FROM_DOMAIN { + group = "ISPConfig"; + description = "From: header domain in sender whitelist."; type = "selector"; selector = "from('mime'):domain"; map = [ "$LOCAL_CONFDIR/local.d/maps.d/sender_domain_whitelist.inc.ispc", "$LOCAL_CONFDIR/local.d/maps.d/sender_domain_whitelist.inc.local" ]; # trivial to spoof so primarily used via composite expression in force_actions.conf score = -1.0; - description = "From: header domain in sender whitelist."; - group = "ispconfig"; } ISPC_BLACKLIST_FROM_DOMAIN { + group = "ISPConfig"; + description = "From: header domain in sender blacklist."; type = "selector"; selector = "from('mime'):domain"; map = [ "$LOCAL_CONFDIR/local.d/maps.d/sender_domain_blacklist.inc.ispc", "$LOCAL_CONFDIR/local.d/maps.d/sender_domain_blacklist.inc.local" ]; score = 12.0; - description = "From: header domain in sender blacklist."; - group = "ispconfig"; +} + +# Reminder: test if whitelisted sender bypasses dkim signing for sender +# Reminder: test if whitelisted recipient address bypasses dkim signing for sender + +ISPC_WHITELIST_ENVRCPT { + group = "ISPConfig"; + description = "Whitelisted recipient address."; + type = "selector"; + filter = "rcpts('smtp')"; + map = [ "$LOCAL_CONFDIR/local.d/maps.d/recipient_whitelist.inc.ispc", "$LOCAL_CONFDIR/local.d/maps.d/recipient_whitelist.inc.local" ]; + score = -7.0; +} + +# ISPC_BLACKLIST_ENVRCPT: Postfix blocks blacklisted recipients, no need to configure those here. + +ISPC_WHITELIST_ENVRCPT_DOMAIN { + group = "ISPConfig"; + description = "Whitelisted recipient domain."; + type = "selector"; + filter = "rcpts('smtp'):domain"; + map = [ "$LOCAL_CONFDIR/local.d/maps.d/recipient_domain_whitelist.inc.ispc", "$LOCAL_CONFDIR/local.d/maps.d/recipient_domain_whitelist.inc.local" ]; + score = -7.0; +} + +# ISPC_BLACKLIST_ENVRCPT_DOMAIN: Postfix blocks blacklisted recipient domains, no need to configure those here. + +# ISPC_WHITELIST_TO: headers are trivial to forge, no whitelisting based on them + +ISPC_BLACKLIST_TO { + group = "ISPConfig"; + description = "To:/Cc: header address in recipient blacklist."; + type = "selector"; + selector = "rcpts('mime')"; + map = [ "$LOCAL_CONFDIR/local.d/maps.d/recipient_blacklist.inc.ispc", "$LOCAL_CONFDIR/local.d/maps.d/recipient_blacklist.inc.local" ]; + score = 12.0; +} + +# ISPC_WHITELIST_TO_DOMAIN: headers are trivial to forge, no whitelisting based on them + +ISPC_BLACKLIST_TO_DOMAIN { + group = "ISPConfig"; + description = "To:/Cc: header domain in recipient blacklist."; + type = "selector"; + selector = "rcpts('mime'):domain"; + map = [ "$LOCAL_CONFDIR/local.d/maps.d/recipient_domain_blacklist.inc.ispc", "$LOCAL_CONFDIR/local.d/maps.d/recipient_domain_blacklist.inc.local" ]; + score = 12.0; } diff --git a/server/plugins-available/rspamd_plugin.inc.php b/server/plugins-available/rspamd_plugin.inc.php index d1ee97fc4a..a0856869b2 100644 --- a/server/plugins-available/rspamd_plugin.inc.php +++ b/server/plugins-available/rspamd_plugin.inc.php @@ -531,7 +531,7 @@ class rspamd_plugin { if ($data['old']['type'] == 'client' || $data['new']['type'] == 'client') { $filename = '/etc/rspamd/local.d/maps.d/ip_whitelist.inc.ispc'; @unlink($filename); - $records = $app->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'client' AND `access` = 'OK' AND `active` = 'y' AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + $records = $app->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'client' AND `access` = 'OK' AND `active` = 'y' AND `sys_userid` IN (SELECT `userid` FROM `sys_user` WHERE `sys_groupid` = 0) AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); if (count($records) > 0) { if ($fp = fopen($filename, 'w')) { fwrite($fp, "# ISPConfig whitelisted ip addresses\n\n"); @@ -548,7 +548,7 @@ class rspamd_plugin { if ($data['old']['type'] == 'sender' || $data['new']['type'] == 'sender') { $filename = '/etc/rspamd/local.d/maps.d/sender_whitelist.inc.ispc'; @unlink($filename); - $records = $app->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'sender' AND `source` LIKE '%@%' AND `access` = 'OK' AND `active` = 'y' AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + $records = $app->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'sender' AND `source` LIKE '%@%' AND `access` = 'OK' AND `active` = 'y' AND `sys_userid` IN (SELECT `userid` FROM `sys_user` WHERE `sys_groupid` = 0) AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); if (count($records) > 0) { if ($fp = fopen($filename, 'w')) { fwrite($fp, "# ISPConfig whitelisted sender addresses\n\n"); @@ -563,7 +563,7 @@ class rspamd_plugin { $filename = '/etc/rspamd/local.d/maps.d/sender_blacklist.inc.ispc'; @unlink($filename); - $records = $app->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'sender' AND `source` LIKE '%@%' AND `access` LIKE 'REJECT%' AND `active` = 'y' AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + $records = $app->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'sender' AND `source` LIKE '%@%' AND `access` LIKE 'REJECT%' AND `active` = 'y' AND `sys_userid` IN (SELECT `userid` FROM `sys_user` WHERE `sys_groupid` = 0) AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); if (count($records) > 0) { if ($fp = fopen($filename, 'w')) { fwrite($fp, "# ISPConfig blacklisted sender addresses\n\n"); @@ -578,7 +578,7 @@ class rspamd_plugin { $filename = '/etc/rspamd/local.d/maps.d/sender_domain_whitelist.inc.ispc'; @unlink($filename); - $records = $app->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'sender' AND `source` NOT LIKE '%@%' AND `access` = 'OK' AND `active` = 'y' AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + $records = $app->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'sender' AND `source` NOT LIKE '%@%' AND `access` = 'OK' AND `active` = 'y' AND `sys_userid` IN (SELECT `userid` FROM `sys_user` WHERE `sys_groupid` = 0) AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); if (count($records) > 0) { if ($fp = fopen($filename, 'w')) { fwrite($fp, "# ISPConfig whitelisted sender domains\n\n"); @@ -593,7 +593,7 @@ class rspamd_plugin { $filename = '/etc/rspamd/local.d/maps.d/sender_domain_blacklist.inc.ispc'; @unlink($filename); - $records = $app->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'sender' AND `source` NOT LIKE '%@%' AND `access` LIKE 'REJECT%' AND `active` = 'y' AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + $records = $app->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'sender' AND `source` NOT LIKE '%@%' AND `access` LIKE 'REJECT%' AND `active` = 'y' AND `sys_userid` IN (SELECT `userid` FROM `sys_user` WHERE `sys_groupid` = 0) AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); if (count($records) > 0) { if ($fp = fopen($filename, 'w')) { fwrite($fp, "# ISPConfig blacklisted sender domains\n\n"); @@ -606,6 +606,68 @@ class rspamd_plugin { } } } + + if ($data['old']['type'] == 'recipient' || $data['new']['type'] == 'recipient') { + $filename = '/etc/rspamd/local.d/maps.d/recipient_whitelist.inc.ispc'; + @unlink($filename); + $records = $app->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'recipient' AND `source` LIKE '%@%' AND `access` = 'OK' AND `active` = 'y' AND `sys_userid` IN (SELECT `userid` FROM `sys_user` WHERE `sys_groupid` = 0) AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + if (count($records) > 0) { + if ($fp = fopen($filename, 'w')) { + fwrite($fp, "# ISPConfig whitelisted recipient addresses\n\n"); + foreach($records as $record) { + fwrite($fp, $record['source'] . "\n"); + } + fclose($fp); + } else { + $app->log("Error: cannot open $filename for writing", LOGLEVEL_WARN); + } + } + + $filename = '/etc/rspamd/local.d/maps.d/recipient_blacklist.inc.ispc'; + @unlink($filename); + $records = $app->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'recipient' AND `source` LIKE '%@%' AND `access` LIKE 'REJECT%' AND `active` = 'y' AND `sys_userid` IN (SELECT `userid` FROM `sys_user` WHERE `sys_groupid` = 0) AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + if (count($records) > 0) { + if ($fp = fopen($filename, 'w')) { + fwrite($fp, "# ISPConfig blacklisted recipient addresses\n\n"); + foreach($records as $record) { + fwrite($fp, $record['source'] . "\n"); + } + fclose($fp); + } else { + $app->log("Error: cannot open $filename for writing", LOGLEVEL_WARN); + } + } + + $filename = '/etc/rspamd/local.d/maps.d/recipient_domain_whitelist.inc.ispc'; + @unlink($filename); + $records = $app->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'recipient' AND `source` NOT LIKE '%@%' AND `access` = 'OK' AND `active` = 'y' AND `sys_userid` IN (SELECT `userid` FROM `sys_user` WHERE `sys_groupid` = 0) AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + if (count($records) > 0) { + if ($fp = fopen($filename, 'w')) { + fwrite($fp, "# ISPConfig whitelisted recipient domains\n\n"); + foreach($records as $record) { + fwrite($fp, ltrim($record['source'], '.') . "\n"); + } + fclose($fp); + } else { + $app->log("Error: cannot open $filename for writing", LOGLEVEL_WARN); + } + } + + $filename = '/etc/rspamd/local.d/maps.d/recipient_domain_blacklist.inc.ispc'; + @unlink($filename); + $records = $app->db->queryAllRecords("SELECT `source` FROM ?? WHERE `type` = 'recipient' AND `source` NOT LIKE '%@%' AND `access` LIKE 'REJECT%' AND `active` = 'y' AND `sys_userid` IN (SELECT `userid` FROM `sys_user` WHERE `sys_groupid` = 0) AND `server_id` = ? ORDER BY `source` ASC", $conf['mysql']['database'] . '.mail_access', $conf['server_id']); + if (count($records) > 0) { + if ($fp = fopen($filename, 'w')) { + fwrite($fp, "# ISPConfig blacklisted recipient domains\n\n"); + foreach($records as $record) { + fwrite($fp, ltrim($record['source'], '.') . "\n"); + } + fclose($fp); + } else { + $app->log("Error: cannot open $filename for writing", LOGLEVEL_WARN); + } + } + } } function server_update($event_name, $data) { -- GitLab From 7bbf870a20fb9e256eb81d4f36420965d7e695ec Mon Sep 17 00:00:00 2001 From: Jesse Norell Date: Thu, 15 Apr 2021 10:05:09 -0600 Subject: [PATCH 5/8] rspamd: add Reply-To rules for sender blacklist --- install/tpl/rspamd_force_actions.conf.master | 7 ++++++- install/tpl/rspamd_multimap.conf.master | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/install/tpl/rspamd_force_actions.conf.master b/install/tpl/rspamd_force_actions.conf.master index 183cea0391..98adfaed85 100644 --- a/install/tpl/rspamd_force_actions.conf.master +++ b/install/tpl/rspamd_force_actions.conf.master @@ -1,12 +1,15 @@ rules { + # ISPConfig whitelist/blacklist passthrough actions + # (always combine authentication tests (dkim/spf) with sender whitelisting). + ISPC_WHITELIST_SENDER { expression = "(ISPC_WHITELIST_ENVFROM and (R_DKIM_ALLOW or R_SPF_ALLOW)) or (ISPC_WHITELIST_FROM and R_DKIM_ALLOW) and !CLAM_VIRUS and !JUST_EICAR"; action = "no action"; } ISPC_BLACKLIST_SENDER { - expression = "(ISPC_BLACKLIST_FROM or ISPC_BLACKLIST_FROM_DOMAIN) and R_DKIM_ALLOW and !ISPC_WHITELIST_SENDER and !ISPC_WHITELIST_SENDER_DOMAIN and !ISPC_WHITELIST_RECIPIENT"; + expression = "(ISPC_BLACKLIST_FROM or ISPC_BLACKLIST_FROM_DOMAIN or ISPC_BLACKLIST_REPLYTO or ISPC_BLACKLIST_REPLYTO_DOMAIN) and !ISPC_WHITELIST_SENDER and !ISPC_WHITELIST_SENDER_DOMAIN and !ISPC_WHITELIST_RECIPIENT"; action = "reject"; } @@ -15,6 +18,8 @@ rules { action = "no action"; } + # test multiple recipients, does forced action only apply to the whitelisted recipient or all? + # if all, combine this with RCPT_COUNT_ONE ISPC_WHITELIST_RECIPIENT { expression = "ISPC_WHITELIST_ENVRCPT and !CLAM_VIRUS and !JUST_EICAR"; action = "no action"; diff --git a/install/tpl/rspamd_multimap.conf.master b/install/tpl/rspamd_multimap.conf.master index 0239e8ffdc..8cd4d28c43 100644 --- a/install/tpl/rspamd_multimap.conf.master +++ b/install/tpl/rspamd_multimap.conf.master @@ -69,6 +69,26 @@ ISPC_BLACKLIST_FROM_DOMAIN { score = 12.0; } +ISPC_BLACKLIST_REPLYTO { + group = "ISPConfig"; + description = "Reply-To: header address in sender blacklist."; + type = "header"; + header = "Reply-To"; + filter = "email"; + map = [ "$LOCAL_CONFDIR/local.d/maps.d/sender_blacklist.inc.ispc", "$LOCAL_CONFDIR/local.d/maps.d/sender_blacklist.inc.local" ]; + score = 12.0; +} + +ISPC_BLACKLIST_REPLYTO_DOMAIN { + group = "ISPConfig"; + description = "Reply-To: header domain in sender blacklist."; + type = "header"; + header = "Reply-To"; + filter = "email:domain"; + map = [ "$LOCAL_CONFDIR/local.d/maps.d/sender_domain_blacklist.inc.ispc", "$LOCAL_CONFDIR/local.d/maps.d/sender_domain_blacklist.inc.local" ]; + score = 12.0; +} + # Reminder: test if whitelisted sender bypasses dkim signing for sender # Reminder: test if whitelisted recipient address bypasses dkim signing for sender -- GitLab From 7b5c706f87af11c7234800c945055a7caf376771 Mon Sep 17 00:00:00 2001 From: Jesse Norell Date: Fri, 16 Apr 2021 11:09:04 -0600 Subject: [PATCH 6/8] rspamd: fix multimap selectors --- install/tpl/rspamd_multimap.conf.master | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/install/tpl/rspamd_multimap.conf.master b/install/tpl/rspamd_multimap.conf.master index 8cd4d28c43..ad03ee8d3a 100644 --- a/install/tpl/rspamd_multimap.conf.master +++ b/install/tpl/rspamd_multimap.conf.master @@ -13,7 +13,7 @@ ISPC_WHITELIST_ENVFROM { group = "ISPConfig"; description = "Whitelisted sender address."; type = "selector"; - filter = "from('smtp')"; + selector = "from('smtp')"; map = [ "$LOCAL_CONFDIR/local.d/maps.d/sender_whitelist.inc.ispc", "$LOCAL_CONFDIR/local.d/maps.d/sender_whitelist.inc.local" ]; score = -7.0; } @@ -24,7 +24,7 @@ ISPC_WHITELIST_ENVFROM_DOMAIN { group = "ISPConfig"; description = "Whitelisted sender domain."; type = "selector"; - filter = "from('smtp'):domain"; + selector = "from('smtp'):domain"; map = [ "$LOCAL_CONFDIR/local.d/maps.d/sender_domain_whitelist.inc.ispc", "$LOCAL_CONFDIR/local.d/maps.d/sender_domain_whitelist.inc.local" ]; score = -7.0; } @@ -96,7 +96,7 @@ ISPC_WHITELIST_ENVRCPT { group = "ISPConfig"; description = "Whitelisted recipient address."; type = "selector"; - filter = "rcpts('smtp')"; + selector = "rcpts('smtp')"; map = [ "$LOCAL_CONFDIR/local.d/maps.d/recipient_whitelist.inc.ispc", "$LOCAL_CONFDIR/local.d/maps.d/recipient_whitelist.inc.local" ]; score = -7.0; } @@ -107,7 +107,7 @@ ISPC_WHITELIST_ENVRCPT_DOMAIN { group = "ISPConfig"; description = "Whitelisted recipient domain."; type = "selector"; - filter = "rcpts('smtp'):domain"; + selector = "rcpts('smtp'):domain"; map = [ "$LOCAL_CONFDIR/local.d/maps.d/recipient_domain_whitelist.inc.ispc", "$LOCAL_CONFDIR/local.d/maps.d/recipient_domain_whitelist.inc.local" ]; score = -7.0; } -- GitLab From a9721f5eeab795e7b7538d2bb103aacdbc4a75a4 Mon Sep 17 00:00:00 2001 From: Jesse Norell Date: Fri, 16 Apr 2021 11:10:52 -0600 Subject: [PATCH 7/8] rspamd: all force_actions rules must have 'message' --- install/tpl/rspamd_force_actions.conf.master | 22 ++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/install/tpl/rspamd_force_actions.conf.master b/install/tpl/rspamd_force_actions.conf.master index 98adfaed85..3a1d3b1ad0 100644 --- a/install/tpl/rspamd_force_actions.conf.master +++ b/install/tpl/rspamd_force_actions.conf.master @@ -6,33 +6,47 @@ rules { ISPC_WHITELIST_SENDER { expression = "(ISPC_WHITELIST_ENVFROM and (R_DKIM_ALLOW or R_SPF_ALLOW)) or (ISPC_WHITELIST_FROM and R_DKIM_ALLOW) and !CLAM_VIRUS and !JUST_EICAR"; action = "no action"; + message = "Whitelisted sender"; } ISPC_BLACKLIST_SENDER { - expression = "(ISPC_BLACKLIST_FROM or ISPC_BLACKLIST_FROM_DOMAIN or ISPC_BLACKLIST_REPLYTO or ISPC_BLACKLIST_REPLYTO_DOMAIN) and !ISPC_WHITELIST_SENDER and !ISPC_WHITELIST_SENDER_DOMAIN and !ISPC_WHITELIST_RECIPIENT"; + expression = "(ISPC_BLACKLIST_FROM or ISPC_BLACKLIST_FROM_DOMAIN or ISPC_BLACKLIST_REPLYTO or ISPC_BLACKLIST_REPLYTO_DOMAIN) and !FORCE_ACTION_ISPC_WHITELIST_SENDER and !FORCE_ACTION_ISPC_WHITELIST_SENDER_DOMAIN and !FORCE_ACTION_ISPC_WHITELIST_RECIPIENT and !FORCE_ACTION_WHITELIST_RECIPIENT_DOMAIN"; action = "reject"; + message = "Blacklisted sender"; } ISPC_WHITELIST_SENDER_DOMAIN { expression = "(ISPC_WHITELIST_ENVFROM_DOMAIN and (ISPC_WHITELIST_DKIM or ISPC_WHITELIST_SPF)) or (ISPC_WHITELIST_FROM_DOMAIN and ISPC_WHITELIST_DKIM) and !CLAM_VIRUS and !JUST_EICAR"; action = "no action"; + message = "Whitelisted sender domain"; } - # test multiple recipients, does forced action only apply to the whitelisted recipient or all? - # if all, combine this with RCPT_COUNT_ONE +# test multiple recipients, does forced action only apply to the whitelisted recipient or all? +# if all, combine this with RCPT_COUNT_ONE +# do all recipients have to be matched in whitelist for symbol to be added, or any ? ISPC_WHITELIST_RECIPIENT { expression = "ISPC_WHITELIST_ENVRCPT and !CLAM_VIRUS and !JUST_EICAR"; action = "no action"; + message = "Whitelisted recipient"; } +# ISPC_TEST { +# #expression = "ISPC_BLACKLIST_TO"; +# expression = "ISPC_WHITELIST_ENVRCPT"; +# action = "no action"; +# message = "TEST RULE"; +# } + ISPC_BLACKLIST_RECIPIENT { - expression = "(ISPC_BLACKLIST_TO or ISPC_BLACKLIST_TO_DOMAIN) and !ISPC_WHITELIST_SENDER and !ISPC_WHITELIST_SENDER_DOMAIN and !ISPC_WHITELIST_RECIPIENT"; + expression = "(ISPC_BLACKLIST_TO or ISPC_BLACKLIST_TO_DOMAIN) and !FORCE_ACTION_ISPC_WHITELIST_SENDER and !FORCE_ACTION_ISPC_WHITELIST_SENDER_DOMAIN and !FORCE_ACTION_ISPC_WHITELIST_RECIPIENT and !FORCE_ACTION_WHITELIST_RECIPIENT_DOMAIN"; action = "reject"; + message = "Blacklisted recipient"; } ISPC_WHITELIST_RECIPIENT_DOMAIN { expression = "ISPC_WHITELIST_ENVRCPT_DOMAIN and !CLAM_VIRUS and !JUST_EICAR"; action = "no action"; + message = "Whitelisted recipient domain"; } } -- GitLab From 7e75dcb6307c554cc35eb1dfdfb5815a5ffa4a1e Mon Sep 17 00:00:00 2001 From: Jesse Norell Date: Thu, 27 May 2021 17:07:27 -0600 Subject: [PATCH 8/8] missing whitelist.conf in template list --- install/lib/installer_base.lib.php | 1 + 1 file changed, 1 insertion(+) diff --git a/install/lib/installer_base.lib.php b/install/lib/installer_base.lib.php index 392daccd4c..d6d2f50652 100644 --- a/install/lib/installer_base.lib.php +++ b/install/lib/installer_base.lib.php @@ -1899,6 +1899,7 @@ class installer_base { 'groups.conf', 'multimap.conf', 'force_actions.conf', + 'whitelist.conf', ); foreach ($local_d as $f) { if(file_exists($conf['ispconfig_install_dir']."/server/conf-custom/install/rspamd_${f}.master")) { -- GitLab