diff options
author | Christian Roessner <c@roessner-network-solutions.com> | 2017-04-30 13:09:03 +0200 |
---|---|---|
committer | Christian Roessner <c@roessner-network-solutions.com> | 2017-05-02 21:11:18 +0200 |
commit | e86b9cbb8f208a50f10c231755db05b0369ddc64 (patch) | |
tree | 4ff9c7a85b8ac12ebdce077cdc1d8f3359bdbd01 | |
parent | 07159d72fe43537111cc2f030b986bb34a62a868 (diff) | |
download | rspamd-e86b9cbb8f208a50f10c231755db05b0369ddc64.tar.gz rspamd-e86b9cbb8f208a50f10c231755db05b0369ddc64.zip |
[Feature] Add Lua plugin spamtrap
-rw-r--r-- | conf/modules.d/spamtrap.conf | 50 | ||||
-rw-r--r-- | src/plugins/lua/spamtrap.lua | 146 |
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 |