aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Roessner <c@roessner-network-solutions.com>2017-04-30 13:09:03 +0200
committerChristian Roessner <c@roessner-network-solutions.com>2017-05-02 21:11:18 +0200
commite86b9cbb8f208a50f10c231755db05b0369ddc64 (patch)
tree4ff9c7a85b8ac12ebdce077cdc1d8f3359bdbd01
parent07159d72fe43537111cc2f030b986bb34a62a868 (diff)
downloadrspamd-e86b9cbb8f208a50f10c231755db05b0369ddc64.tar.gz
rspamd-e86b9cbb8f208a50f10c231755db05b0369ddc64.zip
[Feature] Add Lua plugin spamtrap
-rw-r--r--conf/modules.d/spamtrap.conf50
-rw-r--r--src/plugins/lua/spamtrap.lua146
2 files changed, 196 insertions, 0 deletions
diff --git a/conf/modules.d/spamtrap.conf b/conf/modules.d/spamtrap.conf
new file mode 100644
index 000000000..e6b676a5d
--- /dev/null
+++ b/conf/modules.d/spamtrap.conf
@@ -0,0 +1,50 @@
+# Please don't modify this file as your changes might be overwritten with
+# the next update.
+#
+# You can modify '$LOCAL_CONFDIR/rspamd.conf.local.override' to redefine
+# parameters defined on the top level
+#
+# You can modify '$LOCAL_CONFDIR/rspamd.conf.local' to add
+# parameters defined on the top level
+#
+# For specific modules or configuration you can also modify
+# '$LOCAL_CONFDIR/local.d/file.conf' - to add your options or rewrite defaults
+# '$LOCAL_CONFDIR/override.d/file.conf' - to override the defaults
+#
+# See https://rspamd.com/doc/tutorials/writing_rules.html for details
+
+# This module is *DISABLED* by default
+# If you need to enable it, then define the following line in
+# local.d/spamtrap.conf:
+#
+# enabled = true;
+#
+# You also need to define redis servers for this module
+
+spamtrap {
+ # Optionally set an action
+ #action = "no action";
+ # A map file containing regexp entries for spamtrap emails and domains
+ #map = file://$LOCAL_CONFDIR/maps.d/spamtrap.map
+ # Name of the symbol
+ #symbol = "SPAMTRAP";
+ # A score for this module
+ #score = 0.0;
+ # Flag to enable fuzzy learning
+ learn_fuzzy = false;
+ # Flag to enable bayes spam learning
+ learn_spam = false;
+ # Fuzzy flag
+ #fuzzy_flag = 1;
+ # Fuzzy weight
+ #fuzy_weight = 10;
+ # Redis key prefix
+ #key_prefix = 'sptr_';
+
+ # !!! Disabled by default !!!
+ enabled = false;
+
+ .include(try=true,priority=5) "${DBDIR}/dynamic/spamtrap.conf"
+ .include(try=true,priority=1,duplicate=merge) "$LOCAL_CONFDIR/local.d/spamtrap.conf"
+ .include(try=true,priority=10) "$LOCAL_CONFDIR/override.d/spamtrap.conf"
+}
diff --git a/src/plugins/lua/spamtrap.lua b/src/plugins/lua/spamtrap.lua
new file mode 100644
index 000000000..6ecd34270
--- /dev/null
+++ b/src/plugins/lua/spamtrap.lua
@@ -0,0 +1,146 @@
+--[[
+Copyright (c) 2016, Vsevolod Stakhov <vsevolod@highsecure.ru>
+Copyright (c) 2016, Andrew Lewis <nerf@judo.za.org>
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+]]--
+
+-- A plugin that triggers, if a spam trapped email address was detected
+
+local rspamd_logger = require "rspamd_logger"
+local redis_params
+local use_redis = false;
+
+local settings = {
+ symbol = 'SPAMTRAP',
+ score = 0.0,
+ learn_fuzzy = true,
+ learn_spam = true,
+ fuzzy_flag = 1,
+ fuzzy_weight = 10.0,
+ key_prefix = 'sptr_'
+}
+
+local function spamtrap_cb(task)
+ local rcpts = task:get_recipients('smtp')
+ local called_for_domain = false
+ local target = nil
+
+ local function do_action(rcpt)
+ if settings['learn_fuzzy'] then
+ rspamd_plugins.fuzzy_check.learn(task, settings['fuzzy_flag'], settings['fuzzy_weight'])
+ end
+ if settings['learn_spam'] then
+ task:set_flag("learn_spam")
+ end
+ task:insert_result(settings['symbol'], settings['score'], rcpt)
+ if settings['action'] then
+ task:set_pre_result(settings['action'],
+ string.format('spamtrap found: <%s>', rcpt))
+ end
+ end
+
+ local function redis_spamtrap_cb(err, data)
+ if err ~= nil then
+ rspamd_logger.errx(task, 'redis_spamtrap_cb received error: %1', err)
+ return
+ end
+
+ if data and type(data) ~= 'userdata' then
+ do_action(target)
+ else
+ if not called_for_domain then
+ -- Recurse for @catchall domain
+ target = rcpts[1]['domain']:lower()
+ local key = settings['key_prefix'] .. '@' .. target
+ local ret = rspamd_redis_make_request(task,
+ redis_params, -- connect params
+ key, -- hash key
+ false, -- is write
+ redis_spamtrap_cb, -- callback
+ 'GET', -- command
+ {key} -- arguments
+ )
+ if not ret then
+ rspamd_logger.errx(task, "redis request wasn't scheduled")
+ end
+ called_for_domain = true
+ else
+ return -- nothing found
+ end
+ end
+ end
+
+ -- Do not risk a FP by checking for more than one recipient
+ if rcpts and #rcpts == 1 then
+ target = rcpts[1]['addr']:lower()
+ if use_redis then
+ local key = settings['key_prefix'] .. target
+ local ret = rspamd_redis_make_request(task,
+ redis_params, -- connect params
+ key, -- hash key
+ false, -- is write
+ redis_spamtrap_cb, -- callback
+ 'GET', -- command
+ {key} -- arguments
+ )
+ if not ret then
+ rspamd_logger.errx(task, "redis request wasn't scheduled")
+ end
+ else
+ if settings['map']:get_key(target) then
+ do_action(target)
+ else
+ end
+ end
+end
+
+-- Module setup
+local opts = rspamd_config:get_all_opt('spamtrap')
+if not (opts and type(opts) == 'table') then
+ rspamd_logger.infox(rspamd_config, 'module is unconfigured')
+ return
+end
+if opts then
+ for k,v in pairs(opts) do
+ settings[k] = v
+ end
+ if settings['map'] then
+ settings['name'] = settings['map']
+ settings['map'] = rspamd_config:add_map({
+ url = settings['name'],
+ description = "Spamtrap map for %s", settings['symbol'],
+ type = "regexp"
+ })
+ else
+ redis_params = rspamd_parse_redis_server('spamtrap')
+ if not redis_params then
+ rspamd_logger.errx(
+ rspamd_config, 'no redis servers are specified, disabling module')
+ return
+ end
+ use_redis = true;
+ end
+
+ local id = rspamd_config:register_symbol({
+ name = "SPAMTRAP_CHECK",
+ type = "postfilter",
+ callback = spamtrap_cb
+ })
+ rspamd_config:register_symbol({
+ name = settings['symbol'],
+ parent = id,
+ type = 'virtual',
+ score = settings.score
+ })
+end