-- -- Copyright (c) 2013, Alexey Savelyev -- E-mail: info@homeweb.ru -- WWW: http://homeweb.ru -- -- Weight for checks_hellohost and checks_hello: 5 - very hard, 4 - hard, 3 - meduim, 2 - low, 1 - very low. -- From HFILTER_HELO_* and HFILTER_HOSTNAME_* symbols the maximum weight is selected in case of their actuating. local checks_hellohost = { ['[.-]dynamic[.-]'] = 5, ['dynamic[.-][0-9]'] = 5, ['[0-9][.-]?dynamic'] = 5, ['[.-]dyn[.-]'] = 5, ['dyn[.-][0-9]'] = 5, ['[0-9][.-]?dyn'] = 5, ['[.-]clients?[.-]'] = 5, ['clients?[.-][0-9]'] = 5, ['[0-9][.-]?clients?'] = 5, ['[.-]dynip[.-]'] = 5, ['dynip[.-][0-9]'] = 5, ['[0-9][.-]?dynip'] = 5, ['[.-]broadband[.-]'] = 5, ['broadband[.-][0-9]'] = 5, ['[0-9][.-]?broadband'] = 5, ['[.-]broad[.-]'] = 5, ['broad[.-][0-9]'] = 5, ['[0-9][.-]?broad'] = 5, ['[.-]bredband[.-]'] = 5, ['bredband[.-][0-9]'] = 5, ['[0-9][.-]?bredband'] = 5, ['[.-]nat[.-]'] = 5, ['nat[.-][0-9]'] = 5, ['[0-9][.-]?nat'] = 5, ['[.-]pptp[.-]'] = 5, ['pptp[.-][0-9]'] = 5, ['[0-9][.-]?pptp'] = 5, ['[.-]pppoe[.-]'] = 5, ['pppoe[.-][0-9]'] = 5, ['[0-9][.-]?pppoe'] = 5, ['[.-]ppp[.-]'] = 5, ['ppp[.-][0-9]'] = 5, ['[0-9][.-]?ppp'] = 5, ['[.-][a|x]?dsl[.-]'] = 4, ['[a|x]?dsl[.-]?[0-9]'] = 4, ['[0-9][.-]?[a|x]?dsl'] = 4, ['[.-][a|x]?dsl-dynamic[.-]'] = 5, ['[a|x]?dsl-dynamic[.-]?[0-9]'] = 5, ['[0-9][.-]?[a|x]?dsl-dynamic'] = 5, ['[.-][a|x]?dsl-line[.-]'] = 4, ['[a|x]?dsl-line[.-]?[0-9]'] = 4, ['[0-9][.-]?[a|x]?dsl-line'] = 4, ['[.-]dhcp[.-]'] = 5, ['dhcp[.-][0-9]'] = 5, ['[0-9][.-]?dhcp'] = 5, ['[.-]catv[.-]'] = 5, ['catv[.-][0-9]'] = 5, ['[0-9][.-]?catv'] = 5, ['[.-]wifi[.-]'] = 5, ['wifi[.-][0-9]'] = 5, ['[0-9][.-]?wifi'] = 5, ['[.-]unused-addr[.-]'] = 3, ['unused-addr[.-][0-9]'] = 3, ['[0-9][.-]?unused-addr'] = 3, ['[.-]dial-?up[.-]'] = 5, ['dial-?up[.-][0-9]'] = 5, ['[0-9][.-]?dial-?up'] = 5, ['[.-]gprs[.-]'] = 5, ['gprs[.-][0-9]'] = 5, ['[0-9][.-]?gprs'] = 5, ['[.-]cdma[.-]'] = 5, ['cdma[.-][0-9]'] = 5, ['[0-9][.-]?cdma'] = 5, ['[.-]homeuser[.-]'] = 5, ['homeuser[.-][0-9]'] = 5, ['[0-9][.-]?homeuser'] = 5, ['[.-]in-?addr[.-]'] = 4, ['in-?addr[.-][0-9]'] = 4, ['[0-9][.-]?in-?addr'] = 4, ['[.-]pool[.-]'] = 4, ['pool[.-][0-9]'] = 4, ['[0-9][.-]?pool'] = 4, ['[.-]cable[.-]'] = 3, ['cable[.-][0-9]'] = 3, ['[0-9][.-]?cable'] = 3, ['[.-]host[.-]'] = 2, ['host[.-][0-9]'] = 2, ['[0-9][.-]?host'] = 2, ['[.-]customers[.-]'] = 1, ['customers[.-][0-9]'] = 1, ['[0-9][.-]?customers'] = 1 } local checks_hello = { ['localhost$'] = 5, ['\\.hfilter\\.ru'] = 5, ['^\\[*84\\.47\\.176\\.(70|71)'] = 5, ['^\\[*81\\.26\\.148\\.(66|67|68|69|70|71|72|73|74|75|76|77|79)'] = 5, ['^(dsl)?(device|speedtouch)\\.lan$'] = 5, ['\\.(lan|local|home|localdomain|intra|in-addr.arpa|priv|online|user|veloxzon)$'] = 5, ['^\\[*127\\.'] = 5, ['^\\[*10\\.'] = 5, ['^\\[*172\\.16\\.'] = 5, ['^\\[*192\\.168\\.'] = 5, --bareip ['^\\[*\\d+[x.-]\\d+[x.-]\\d+[x.-]\\d+\\]*$'] = 4 } local function trim1(s) return (s:gsub("^%s*(.-)%s*$", "%1")) end local function check_regexp(str, regexp_text) local re = regexp.get_cached(regexp_text) if not re then re = regexp.create(regexp_text, 'i') end if re:match(str) then return true end return false end local function split(str, delim, maxNb) -- Eliminate bad cases... if string.find(str, delim) == nil then return { str } end if maxNb == nil or maxNb < 1 then maxNb = 0 -- No limit end local result = {} local pat = "(.-)" .. delim .. "()" local nb = 0 local lastPos for part, pos in string.gmatch(str, pat) do nb = nb + 1 result[nb] = part lastPos = pos if nb == maxNb then break end end -- Handle the last field if nb ~= maxNb then result[nb + 1] = string.sub(str, lastPos) end return result end local function check_fqdn(domain) if check_regexp(domain, '(?=^.{4,255}$)(^((?!-)[a-zA-Z0-9-]{1,63}(? weight_helo then weight_helo = weight end break end end --FQDN check HELO if ip and helo then check_host(task, helo, 'HELO', ip, hostname) end end -- Check's HOSTNAME local weight_hostname = 0 if hostname then -- Check regexp HOSTNAME for regexp,weight in pairs(checks_hellohost) do if check_regexp(hostname, regexp) then weight_hostname = weight break end end else task:insert_result('HFILTER_HOSTNAME_NOPTR', 1.00) end --Insert weight's for HELO or HOSTNAME if weight_helo > 0 and weight_helo >= weight_hostname then task:insert_result('HFILTER_HELO_' .. weight_helo, 1.0) elseif weight_hostname > 0 and weight_hostname > weight_helo then task:insert_result('HFILTER_HOSTNAME_' .. weight_hostname, 1.0) end -- MAILFROM checks -- local from = task:get_from() if from then --FROM host check for _,fr in ipairs(from) do local fr_split = split(fr['addr'], '@', 0) if table.maxn(fr_split) == 2 then check_host(task, fr_split[2], 'FROMHOST', '', '') end end end --Message ID host check local message_id = task:get_message_id() if message_id then local mid_split = split(message_id, '@', 0) if table.maxn(mid_split) == 2 and not string.find(mid_split[2], "local") and not check_fqdn(mid_split[2]) then task:insert_result('HFILTER_MID_NOT_FQDN', 1.00) end end -- Links checks local parts = task:get_text_parts() if parts then --One text part-- if table.maxn(parts) > 0 and parts[1]:get_content() then local part_text = trim1(parts[1]:get_content()) local total_part_len = string.len(part_text) if total_part_len > 0 then local urls = task:get_urls() if urls then local total_url_len = 0 for _,url in ipairs(urls) do total_url_len = total_url_len + string.len(url:get_text()) end if total_url_len > 0 then if total_url_len + 7 > total_part_len then task:insert_result('HFILTER_URL_ONLY', 1.00) else if not string.find(part_text, "\n") then task:insert_result('HFILTER_URL_ONELINE', 1.00) end end end end end end end return false end rspamd_config:register_symbols(hfilter, 1.0, "HFILTER_HELO_1", "HFILTER_HELO_2", "HFILTER_HELO_3", "HFILTER_HELO_4", "HFILTER_HELO_5", "HFILTER_HOSTNAME_1", "HFILTER_HOSTNAME_2", "HFILTER_HOSTNAME_3", "HFILTER_HOSTNAME_4", "HFILTER_HOSTNAME_5", "HFILTER_HELO_NORESOLVE_MX", "HFILTER_HELO_NORES_A_OR_MX", "HFILTER_HELO_IP_A", "HFILTER_HELO_NOT_FQDN", "HFILTER_FROMHOST_NORESOLVE_MX", "HFILTER_FROMHOST_NORES_A_OR_MX", "HFILTER_FROMHOST_NOT_FQDN", "HFILTER_MID_NOT_FQDN", "HFILTER_HOSTNAME_NOPTR", "HFILTER_URL_ONLY", "HFILTER_URL_ONELINE");