summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2019-09-17 13:17:15 +0100
committerGitHub <noreply@github.com>2019-09-17 13:17:15 +0100
commit58b164cfeac4c8c9ed1a3a310a7bcd371c830aa4 (patch)
tree5bee952abefb8e0d67b7cba573b12e14196fbdec /src
parent002596d2963bfa83bb144330c05d928c8bf1e10d (diff)
parente4e8e675b610b49975c8b90d1d207f6f56ac6f93 (diff)
downloadrspamd-58b164cfeac4c8c9ed1a3a310a7bcd371c830aa4.tar.gz
rspamd-58b164cfeac4c8c9ed1a3a310a7bcd371c830aa4.zip
Merge pull request #3037 from denpaforks/p0f
[Feature] Add p0f scanner
Diffstat (limited to 'src')
-rw-r--r--src/plugins/lua/milter_headers.lua24
-rw-r--r--src/plugins/lua/p0f.lua117
2 files changed, 141 insertions, 0 deletions
diff --git a/src/plugins/lua/milter_headers.lua b/src/plugins/lua/milter_headers.lua
index 332625d7c..5d8d24c91 100644
--- a/src/plugins/lua/milter_headers.lua
+++ b/src/plugins/lua/milter_headers.lua
@@ -78,6 +78,10 @@ local settings = {
symbols_fail = {},
symbols = {}, -- needs config
},
+ ['x-os-fingerprint'] = {
+ header = 'X-OS-Fingerprint',
+ remove = 0,
+ },
['x-spamd-bar'] = {
header = 'X-Spamd-Bar',
positive = '+',
@@ -413,6 +417,26 @@ local function milter_headers(task)
end
end
+ routines['x-os-fingerprint'] = function()
+ if skip_wanted('x-os-fingerprint') then return end
+
+ local os_string, link_type, uptime_min, distance =
+ task:get_mempool():get_variable('os_fingerprint',
+ 'string, string, int, int');
+
+ if not os_string then return end
+
+ local value = string.format('%s, (up: %u min), (distance %i, link: %s)',
+ os_string, uptime_min, distance, link_type)
+
+ if settings.routines['x-os-fingerprint'].remove then
+ remove[settings.routines['x-os-fingerprint'].header]
+ = settings.routines['x-os-fingerprint'].remove
+ end
+
+ add_header(settings.routines['x-os-fingerprint'].header, value)
+ end
+
routines['x-spam-status'] = function()
if skip_wanted('x-spam-status') then return end
if not common['metric_score'] then
diff --git a/src/plugins/lua/p0f.lua b/src/plugins/lua/p0f.lua
new file mode 100644
index 000000000..84c525536
--- /dev/null
+++ b/src/plugins/lua/p0f.lua
@@ -0,0 +1,117 @@
+--[[
+Copyright (c) 2019, Vsevolod Stakhov <vsevolod@highsecure.ru>
+Copyright (c) 2019, Denis Paavilainen <denpa@denpa.pro>
+
+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.
+]]--
+
+-- Detect remote OS via passive fingerprinting
+
+local lua_util = require "lua_util"
+local lua_redis = require "lua_redis"
+local rspamd_logger = require "rspamd_logger"
+local p0f = require("lua_scanners").filter('p0f').p0f
+
+local N = 'p0f'
+
+if confighelp then
+ rspamd_config:add_example(nil, N,
+ 'Detect remote OS via passive fingerprinting',
+ [[
+p0f {
+ # Enable module
+ enabled = true
+
+ # Path to the unix socket that p0f listens on
+ socket = '/tmp/p0f.sock';
+
+ # Connection timeout
+ timeout = 5s;
+
+ # If defined, insert symbol with lookup results
+ symbol = 'P0F';
+
+ # Patterns to match against results returned by p0f
+ # Symbol will be yielded on OS string, link type or distance matches
+ patterns = {
+ WINDOWS = '^Windows.*';
+ #DSL = '^DSL$';
+ #DISTANCE10 = '^distance:10$';
+ }
+
+ # Cache lifetime in seconds (default - 2 hours)
+ expire = 7200;
+
+ # Cache key prefix
+ prefix = 'p0f';
+}
+]])
+ return
+end
+
+local rule
+
+local function check_p0f(task)
+ local ip = task:get_from_ip()
+
+ if not (ip and ip:is_valid()) or ip:is_local() then
+ return
+ end
+
+ p0f.check(task, ip, rule)
+end
+
+local opts = rspamd_config:get_all_opt(N)
+
+rule = p0f.configure(opts)
+
+if rule then
+ rule.redis_params = lua_redis.parse_redis_server(N)
+
+ local id = rspamd_config:register_symbol({
+ name = 'P0F_CHECK',
+ type = 'prefilter,nostat',
+ callback = check_p0f,
+ priority = 8,
+ flags = 'empty',
+ group = N
+ })
+
+ if rule.symbol then
+ rspamd_config:register_symbol({
+ name = rule.symbol,
+ parent = id,
+ type = 'virtual',
+ flags = 'empty',
+ group = N
+ })
+ end
+
+ for sym in pairs(rule.patterns) do
+ rspamd_logger.debugm(N, rspamd_config, 'registering: %1', {
+ type = 'virtual',
+ name = sym,
+ parent = id,
+ group = N
+ })
+ rspamd_config:register_symbol({
+ type = 'virtual',
+ name = sym,
+ parent = id,
+ group = N
+ })
+ end
+else
+ lua_util.disable_module(N, 'config')
+ rspamd_logger.infox('p0f module not configured');
+end