diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2019-09-17 13:17:15 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-09-17 13:17:15 +0100 |
commit | 58b164cfeac4c8c9ed1a3a310a7bcd371c830aa4 (patch) | |
tree | 5bee952abefb8e0d67b7cba573b12e14196fbdec /src | |
parent | 002596d2963bfa83bb144330c05d928c8bf1e10d (diff) | |
parent | e4e8e675b610b49975c8b90d1d207f6f56ac6f93 (diff) | |
download | rspamd-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.lua | 24 | ||||
-rw-r--r-- | src/plugins/lua/p0f.lua | 117 |
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 |