aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--conf/modules.conf2
-rw-r--r--doc/markdown/modules/rbl.md10
-rw-r--r--src/lua/lua_config.c57
-rw-r--r--src/plugins/lua/rbl.lua60
4 files changed, 90 insertions, 39 deletions
diff --git a/conf/modules.conf b/conf/modules.conf
index 2f291de79..1a4185c97 100644
--- a/conf/modules.conf
+++ b/conf/modules.conf
@@ -89,6 +89,8 @@ rbl {
default_exclude_users = true;
default_exclude_private_ips = true;
+ private_ips = "127.0.0.0/8 10.0.0.0/8 192.168.0.0/16 169.254.0.0/16 172.16.0.0/12 100.64.0.0/10 fc00::/7 fe80::/10 fec0::/10 ::1";
+
rbls {
spamhaus {
diff --git a/doc/markdown/modules/rbl.md b/doc/markdown/modules/rbl.md
index 8748f4617..bff67e31d 100644
--- a/doc/markdown/modules/rbl.md
+++ b/doc/markdown/modules/rbl.md
@@ -55,7 +55,11 @@ If set to true, do not use this RBL if the message sender is authenticated.
- default_exclude_private_ips (false)
-If set to true, from/received RBL checks will ignore private IP address space.
+If true & private_ips is set appropriately, from/received RBL checks will ignore private IP address space.
+
+- default_exclude_local (true)
+
+If true, and local_exclude_ip_map has been set - exclude specified addresses/subnets from received/from RBL checks.
Other parameters which can be set here are:
@@ -63,6 +67,10 @@ Other parameters which can be set here are:
Can be set to a URL of a list of IPv4/IPv6 addresses & subnets not to be processed by from/received RBL checks.
+- private_ips
+
+Should be set to a space/comma/semicolon-delimited list of addresses & subnets to be considered private by exclude_private_ips checks.
+
RBL-specific subsection is structured as follows:
~~~nginx
diff --git a/src/lua/lua_config.c b/src/lua/lua_config.c
index 089a4b1bd..4fdf4a236 100644
--- a/src/lua/lua_config.c
+++ b/src/lua/lua_config.c
@@ -109,6 +109,24 @@ end
*/
LUA_FUNCTION_DEF (config, add_radix_map);
/***
+ * @method rspamd_config:radix_from_config(mname, optname)
+ * Creates new static map of IP/mask addresses from config.
+ * @param {string} mname name of module
+ * @param {string} optname option to get
+ * @return {radix} radix tree object
+ * @example
+local ip_map = rspamd_config:radix_from_config ('mymodule', 'ips')
+...
+local function foo(task)
+ local ip = task:get_from_ip()
+ if ip_map:get_key(ip) then
+ return true
+ end
+ return false
+end
+ */
+LUA_FUNCTION_DEF (config, radix_from_config);
+/***
* @method rspamd_config:add_hash_map(mapline[, description])
* Creates new dynamic map string objects.
* @param {string} mapline URL for a map
@@ -298,6 +316,7 @@ static const struct luaL_reg configlib_m[] = {
LUA_INTERFACE_DEF (config, get_all_opt),
LUA_INTERFACE_DEF (config, register_function),
LUA_INTERFACE_DEF (config, add_radix_map),
+ LUA_INTERFACE_DEF (config, radix_from_config),
LUA_INTERFACE_DEF (config, add_hash_map),
LUA_INTERFACE_DEF (config, add_kv_map),
LUA_INTERFACE_DEF (config, add_map),
@@ -755,6 +774,44 @@ lua_config_add_radix_map (lua_State *L)
}
static gint
+lua_config_radix_from_config (lua_State *L)
+{
+ struct rspamd_config *cfg = lua_check_config (L);
+ const gchar *mname, *optname;
+ const ucl_object_t *obj;
+ radix_compressed_t **r, ***ud;
+
+ if (!cfg) {
+ lua_pushnil (L);
+ return 1;
+ }
+
+ mname = luaL_checkstring (L, 2);
+ optname = luaL_checkstring (L, 3);
+
+ if (mname && optname) {
+ obj = rspamd_config_get_module_opt (cfg, mname, optname);
+ if (obj) {
+ r = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (radix_compressed_t *));
+ *r = radix_create_compressed ();
+ radix_add_generic_iplist (ucl_obj_tostring (obj), r);
+ ud = lua_newuserdata (L, sizeof (radix_compressed_t *));
+ *ud = r;
+ rspamd_lua_setclass (L, "rspamd{radix}", -1);
+ return 1;
+ } else {
+ msg_warn ("Couldnt find config option [%s][%s]", mname, optname);
+ lua_pushnil (L);
+ return 1;
+ }
+ } else {
+ msg_warn ("Couldnt find config option");
+ lua_pushnil (L);
+ return 1;
+ }
+}
+
+static gint
lua_config_add_hash_map (lua_State *L)
{
struct rspamd_config *cfg = lua_check_config (L);
diff --git a/src/plugins/lua/rbl.lua b/src/plugins/lua/rbl.lua
index 6fa7d25cc..82955f13c 100644
--- a/src/plugins/lua/rbl.lua
+++ b/src/plugins/lua/rbl.lua
@@ -31,6 +31,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
local rbls = {}
local local_exclusions = nil
+local private_ips = nil
local rspamd_logger = require "rspamd_logger"
local rspamd_ip = require "rspamd_ip"
@@ -48,39 +49,9 @@ local function validate_dns(lstr, rstr)
return true
end
-local private_ranges_v4 = {
- {[1] = rspamd_ip.from_string("127.0.0.0"), [2] = 8},
- {[1] = rspamd_ip.from_string("10.0.0.0"), [2] = 8},
- {[1] = rspamd_ip.from_string("192.168.0.0"), [2] = 16},
- {[1] = rspamd_ip.from_string("169.254.0.0"), [2] = 16},
- {[1] = rspamd_ip.from_string("172.16.0.0"), [2] = 12},
- {[1] = rspamd_ip.from_string("100.64.0.0"), [2] = 10},
-}
-
-local private_ranges_v6 = {
- {[1] = rspamd_ip.from_string("fc00::"), [2] = 7},
- {[1] = rspamd_ip.from_string("fe80::"), [2] = 10},
- {[1] = rspamd_ip.from_string("fec0::"), [2] = 10},
-}
-
-local ipv6_loopback = rspamd_ip.from_string("::1")
-
local function is_private_ip(rip)
- if rip:get_version() == 4 then
- for _, r in pairs(private_ranges_v4) do
- if r[1] == rip:apply_mask(r[2]) then
- return true
- end
- end
- elseif rip:get_version() == 6 then
- if rip == ipv6_loopback then
- return true
- end
- for _, r in pairs(private_ranges_v6) do
- if r[1] == rip:apply_mask(r[2]) then
- return true
- end
- end
+ if private_ips and private_ips:get_key(rip) then
+ return true
end
return false
end
@@ -207,13 +178,15 @@ local function rbl_cb (task)
end
if not havegot['from'] then
havegot['from'] = task:get_from_ip()
- if not havegot['from']:is_valid() or
- (rbl['exclude_private_ips'] and is_private_ip(havegot['from']))
- or is_excluded_ip(havegot['from']) then
+ if not havegot['from']:is_valid() then
notgot['from'] = true
return
end
end
+ if (rbl['exclude_private_ips'] and is_private_ip(havegot['from']))
+ or (is_excluded_ip(havegot['from']) and rbl['exclude_local']) then
+ return
+ end
if (havegot['from']:get_version() == 6 and rbl['ipv6']) or
(havegot['from']:get_version() == 4 and rbl['ipv4']) then
task:get_resolver():resolve_a(task:get_session(), task:get_mempool(),
@@ -239,7 +212,8 @@ local function rbl_cb (task)
if ((rh['real_ip']:get_version() == 6 and rbl['ipv6']) or
(rh['real_ip']:get_version() == 4 and rbl['ipv4'])) and
((rbl['exclude_private_ips'] and not is_private_ip(rh['real_ip'])) or
- not rbl['exclude_private_ips']) and not is_excluded_ip(rh['real_ip']) then
+ not rbl['exclude_private_ips']) and ((rbl['exclude_local_ips'] and
+ not is_excluded_ip(rh['real_ip'])) or not rbl['exclude_local_ips']) then
task:get_resolver():resolve_a(task:get_session(), task:get_mempool(),
ip_to_rbl(rh['real_ip'], rbl['rbl']), rbl_dns_cb, k)
end
@@ -265,6 +239,8 @@ if type(rspamd_config.get_api_version) ~= 'nil' then
rspamd_config:register_module_option('rbl', 'default_exclude_users', 'string')
rspamd_config:register_module_option('rbl', 'default_exclude_private_ips', 'string')
rspamd_config:register_module_option('rbl', 'local_exclude_ip_map', 'string')
+ rspamd_config:register_module_option('rbl', 'default_exclude_local', 'string')
+ rspamd_config:register_module_option('rbl', 'private_ips', 'string')
end
end
@@ -300,13 +276,21 @@ end
if(opts['default_exclude_private_ips'] == nil) then
opts['default_exclude_private_ips'] = false
end
-
+if(opts['default_exclude_local'] == nil) then
+ opts['default_exclude_local'] = true
+end
if(opts['local_exclude_ip_map'] ~= nil) then
local_exclusions = rspamd_config:add_radix_map(opts['local_exclude_ip_map'])
end
+if(opts['private_ips'] ~= nil) then
+ private_ips = rspamd_config:radix_from_config('rbl', 'private_ips')
+end
for key,rbl in pairs(opts['rbls']) do
- local o = { "ipv4", "ipv6", "from", "received", "unknown", "rdns", "helo", "exclude_users", "exclude_private_ips" }
+ local o = {
+ "ipv4", "ipv6", "from", "received", "unknown", "rdns", "helo", "exclude_users",
+ "exclude_private_ips", "exclude_local"
+ }
for i=1,table.maxn(o) do
if(rbl[o[i]] == nil) then
rbl[o[i]] = opts['default_' .. o[i]]