mirror of
https://github.com/gSpotx2f/ruantiblock_openwrt.git
synced 2026-05-14 06:30:59 +00:00
Refactoring: ruantiblock-mod-lua, ruantiblock-mod-py.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
--[[
|
||||
(с) 2023 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt)
|
||||
(с) 2024 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt)
|
||||
|
||||
lua == 5.1
|
||||
--]]
|
||||
@@ -66,6 +66,7 @@ local Config = Class(nil, {
|
||||
["UPDATE_STATUS_FILE"] = true,
|
||||
["RBL_ALL_URL"] = true,
|
||||
["RBL_IP_URL"] = true,
|
||||
["RBL_DPI_URL"] = true,
|
||||
["ZI_ALL_URL"] = true,
|
||||
["AF_IP_URL"] = true,
|
||||
["AF_FQDN_URL"] = true,
|
||||
@@ -92,7 +93,7 @@ local Config = Class(nil, {
|
||||
encoding = "UTF-8",
|
||||
site_encoding = "",
|
||||
http_send_headers = {
|
||||
--["User-Agent"] = "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0",
|
||||
["User-Agent"] = "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:120.0) Gecko/20100101 Firefox/120.0",
|
||||
},
|
||||
})
|
||||
Config.wget_user_agent = (Config.http_send_headers["User-Agent"]) and ' -U "' .. Config.http_send_headers["User-Agent"] .. '"' or ''
|
||||
@@ -211,7 +212,180 @@ else
|
||||
error("Config.ICONV_TYPE should be either 'lua' or 'standalone'")
|
||||
end
|
||||
|
||||
----------------------------- Summarize ------------------------------
|
||||
------------------------------ Classes -------------------------------
|
||||
|
||||
local BlackListParser = Class(Config, {
|
||||
ip_pattern = "%d%d?%d?%.%d%d?%d?%.%d%d?%d?%.%d%d?%d?",
|
||||
cidr_pattern = "%d%d?%d?%.%d%d?%d?%.%d%d?%d?%.%d%d?%d?/%d%d?",
|
||||
fqdn_pattern = "[a-z0-9_%.%-]-[a-z0-9_%-]+%.[a-z0-9%.%-]+",
|
||||
url = "http://127.0.0.1",
|
||||
records_separator = "\n",
|
||||
})
|
||||
|
||||
function BlackListParser:new(t)
|
||||
-- extended instance constructor
|
||||
local instance = self(t)
|
||||
instance.url = instance["url"] or self.url
|
||||
instance.records_separator = instance["records_separator"] or self.records_separator
|
||||
instance.site_encoding = instance["site_encoding"] or self.site_encoding
|
||||
instance.cidr_count = 0
|
||||
instance.cidr_table = {}
|
||||
instance.ip_subnet_table = {}
|
||||
instance.ip_records_count = 0
|
||||
instance.ip_count = 0
|
||||
instance.ip_table = {}
|
||||
instance.sld_table = {}
|
||||
instance.fqdn_count = 0
|
||||
instance.fqdn_records_count = 0
|
||||
instance.fqdn_table = {}
|
||||
instance.iconv_handler = iconv and iconv.open(instance.encoding, instance.site_encoding) or nil
|
||||
return instance
|
||||
end
|
||||
|
||||
function BlackListParser:convert_encoding(input)
|
||||
local output
|
||||
if self.ICONV_TYPE == "lua" and self.iconv_handler then
|
||||
output = self.iconv_handler:iconv(input)
|
||||
elseif self.ICONV_TYPE == "standalone" and self.ICONV_CMD then
|
||||
local iconv_handler = assert(io.popen('printf \'' .. input .. '\' | ' .. self.ICONV_CMD .. ' -f "' .. self.site_encoding .. '" -t "' .. self.encoding .. '"', 'r'))
|
||||
output = iconv_handler:read("*a")
|
||||
iconv_handler:close()
|
||||
end
|
||||
return (output)
|
||||
end
|
||||
|
||||
function BlackListParser:convert_to_punycode(input)
|
||||
if self.site_encoding and self.site_encoding ~= "" then
|
||||
input = self:convert_encoding(input)
|
||||
end
|
||||
return input and (idn.encode(input))
|
||||
end
|
||||
|
||||
function BlackListParser:check_filter(str, filter_patterns, reverse)
|
||||
if filter_patterns and str then
|
||||
for pattern in pairs(filter_patterns) do
|
||||
if str:match(pattern) then
|
||||
return not reverse
|
||||
end
|
||||
end
|
||||
end
|
||||
return reverse
|
||||
end
|
||||
|
||||
function BlackListParser:get_subnet(ip)
|
||||
return ip:match("^(%d+%.%d+%.%d+%.)%d+$")
|
||||
end
|
||||
|
||||
function BlackListParser:ip_value_processing(value)
|
||||
if value and value ~= "" then
|
||||
for ip_entry in value:gmatch(self.ip_pattern .. "/?%d?%d?") do
|
||||
if not self.BLLIST_IP_FILTER or (self.BLLIST_IP_FILTER and not self:check_filter(ip_entry, self.BLLIST_IP_FILTER_PATTERNS, self.BLLIST_IP_FILTER_TYPE)) then
|
||||
if ip_entry:match("^" .. self.ip_pattern .. "$") and not self.ip_table[ip_entry] then
|
||||
local subnet = self:get_subnet(ip_entry)
|
||||
if subnet and (self.BLLIST_GR_EXCLUDED_NETS[subnet] or ((not self.BLLIST_IP_LIMIT or self.BLLIST_IP_LIMIT == 0) or (not self.ip_subnet_table[subnet] or self.ip_subnet_table[subnet] <= self.BLLIST_IP_LIMIT))) then
|
||||
self.ip_table[ip_entry] = subnet
|
||||
self.ip_subnet_table[subnet] = (self.ip_subnet_table[subnet] or 0) + 1
|
||||
self.ip_count = self.ip_count + 1
|
||||
end
|
||||
elseif ip_entry:match("^" .. self.cidr_pattern .. "$") and not self.cidr_table[ip_entry] then
|
||||
self.cidr_table[ip_entry] = true
|
||||
self.cidr_count = self.cidr_count + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function BlackListParser:get_sld(fqdn)
|
||||
return fqdn:match("^[a-z0-9_%.%-]-([a-z0-9_%-]+%.[a-z0-9%-]+)$")
|
||||
end
|
||||
|
||||
function BlackListParser:fqdn_value_processing(value)
|
||||
value = value:gsub("%*%.", ""):gsub("%.$", ""):lower()
|
||||
if self.BLLIST_STRIP_WWW then
|
||||
value = value:gsub("^www[0-9]?%.", "")
|
||||
end
|
||||
if not self.BLLIST_FQDN_FILTER or (self.BLLIST_FQDN_FILTER and not self:check_filter(value, self.BLLIST_FQDN_FILTER_PATTERNS, self.BLLIST_FQDN_FILTER_TYPE)) then
|
||||
if value:match("^" .. self.fqdn_pattern .. "$") then
|
||||
elseif self.BLLIST_ENABLE_IDN and value:match("^[^\\/&%?]-[^\\/&%?%.]+%.[^\\/&%?%.]+%.?$") then
|
||||
value = self:convert_to_punycode(value)
|
||||
if not value then
|
||||
return false
|
||||
end
|
||||
else
|
||||
return false
|
||||
end
|
||||
local sld = self:get_sld(value)
|
||||
if sld and (self.BLLIST_GR_EXCLUDED_SLD[sld] or ((not self.BLLIST_SD_LIMIT or self.BLLIST_SD_LIMIT == 0) or (not self.sld_table[sld] or self.sld_table[sld] < self.BLLIST_SD_LIMIT))) then
|
||||
self.fqdn_table[value] = sld
|
||||
self.sld_table[sld] = (self.sld_table[sld] or 0) + 1
|
||||
self.fqdn_count = self.fqdn_count + 1
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function BlackListParser:parser_func()
|
||||
-- Must be overridden by a subclass
|
||||
error("Method BlackListParser:parser_func() must be overridden by a subclass!")
|
||||
end
|
||||
|
||||
function BlackListParser:chunk_buffer()
|
||||
local buff = ""
|
||||
local ret_value = ""
|
||||
local last_chunk
|
||||
return function(chunk)
|
||||
if last_chunk then
|
||||
return nil
|
||||
end
|
||||
if chunk then
|
||||
buff = buff .. chunk
|
||||
local last_rs_position = select(2, buff:find("^.*" .. self.records_separator))
|
||||
if last_rs_position then
|
||||
ret_value = buff:sub(1, last_rs_position)
|
||||
buff = buff:sub((last_rs_position + 1), -1)
|
||||
else
|
||||
ret_value = ""
|
||||
end
|
||||
else
|
||||
ret_value = buff
|
||||
last_chunk = true
|
||||
end
|
||||
return (ret_value)
|
||||
end
|
||||
end
|
||||
|
||||
function BlackListParser:get_http_data(url)
|
||||
local ret_val, ret_code, ret_headers
|
||||
local http_module = url:match("^https") and https or http
|
||||
if http_module then
|
||||
local http_sink = ltn12.sink.chain(self:chunk_buffer(), self:parser_func())
|
||||
ret_val, ret_code, ret_headers = http_module.request{url = url, sink = http_sink, headers = self.http_send_headers}
|
||||
if not ret_val or ret_code ~= 200 then
|
||||
ret_val = nil
|
||||
print(string.format("Connection error! (%s) URL: %s", ret_code, url))
|
||||
end
|
||||
else
|
||||
local wget_sink = ltn12.sink.chain(self:chunk_buffer(), self:parser_func())
|
||||
ret_val = ltn12.pump.all(ltn12.source.file(io.popen(self.WGET_CMD .. self.wget_user_agent .. ' "' .. url .. '"', 'r')), wget_sink)
|
||||
end
|
||||
return (ret_val == 1) and true or false
|
||||
end
|
||||
|
||||
function BlackListParser:run()
|
||||
local return_code = 0
|
||||
if self:get_http_data(self.url) then
|
||||
if (self.fqdn_count + self.ip_count + self.cidr_count) > self.BLLIST_MIN_ENTRIES then
|
||||
return_code = 0
|
||||
else
|
||||
return_code = 2
|
||||
end
|
||||
else
|
||||
return_code = 1
|
||||
end
|
||||
return return_code
|
||||
end
|
||||
|
||||
|
||||
local Summarize = {
|
||||
HOSTS_LIMIT = 0,
|
||||
@@ -407,127 +581,27 @@ function Summarize:summarize_nets(cidr_list, modify_raw_list)
|
||||
)
|
||||
end
|
||||
|
||||
------------------------------ Classes -------------------------------
|
||||
|
||||
local BlackListParser = Class(Config, {
|
||||
ip_pattern = "%d%d?%d?%.%d%d?%d?%.%d%d?%d?%.%d%d?%d?",
|
||||
cidr_pattern = "%d%d?%d?%.%d%d?%d?%.%d%d?%d?%.%d%d?%d?/%d%d?",
|
||||
fqdn_pattern = "[a-z0-9_%.%-]-[a-z0-9_%-]+%.[a-z0-9%.%-]",
|
||||
url = "http://127.0.0.1",
|
||||
records_separator = "\n",
|
||||
ips_separator = "|",
|
||||
local OptimizeConfig = Class(Config, {
|
||||
parsers_list = {},
|
||||
})
|
||||
|
||||
function BlackListParser:new(t)
|
||||
function OptimizeConfig:new(t)
|
||||
-- extended instance constructor
|
||||
local instance = self(t)
|
||||
instance.url = instance["url"] or self.url
|
||||
instance.records_separator = instance["records_separator"] or self.records_separator
|
||||
instance.ips_separator = instance["ips_separator"] or self.ips_separator
|
||||
instance.site_encoding = instance["site_encoding"] or self.site_encoding
|
||||
instance.ip_subnet_table = {}
|
||||
instance.parsers_list = instance.parsers_list or self.parsers_list
|
||||
instance.cidr_count = 0
|
||||
instance.cidr_table = {}
|
||||
instance.ip_subnet_table = {}
|
||||
instance.ip_records_count = 0
|
||||
instance.ip_count = 0
|
||||
instance.fqdn_count = 0
|
||||
instance.ip_table = {}
|
||||
instance.sld_table = {}
|
||||
instance.fqdn_records_count = 0
|
||||
instance.cidr_table = {}
|
||||
instance.ip_table = {}
|
||||
instance.fqdn_table = {}
|
||||
instance.iconv_handler = iconv and iconv.open(instance.encoding, instance.site_encoding) or nil
|
||||
return instance
|
||||
end
|
||||
|
||||
function BlackListParser:convert_encoding(input)
|
||||
local output
|
||||
if self.ICONV_TYPE == "lua" and self.iconv_handler then
|
||||
output = self.iconv_handler:iconv(input)
|
||||
elseif self.ICONV_TYPE == "standalone" and self.ICONV_CMD then
|
||||
local iconv_handler = assert(io.popen('printf \'' .. input .. '\' | ' .. self.ICONV_CMD .. ' -f "' .. self.site_encoding .. '" -t "' .. self.encoding .. '"', 'r'))
|
||||
output = iconv_handler:read("*a")
|
||||
iconv_handler:close()
|
||||
end
|
||||
return (output)
|
||||
end
|
||||
|
||||
function BlackListParser:convert_to_punycode(input)
|
||||
if self.site_encoding and self.site_encoding ~= "" then
|
||||
input = self:convert_encoding(input)
|
||||
end
|
||||
return input and (idn.encode(input))
|
||||
end
|
||||
|
||||
function BlackListParser:check_filter(str, filter_patterns, reverse)
|
||||
if filter_patterns and str then
|
||||
for pattern in pairs(filter_patterns) do
|
||||
if str:match(pattern) then
|
||||
return not reverse
|
||||
end
|
||||
end
|
||||
end
|
||||
return reverse
|
||||
end
|
||||
|
||||
function BlackListParser:get_subnet(ip)
|
||||
return ip:match("^(%d+%.%d+%.%d+%.)%d+$")
|
||||
end
|
||||
|
||||
function BlackListParser:fill_ip_tables(val)
|
||||
if val and val ~= "" then
|
||||
for ip_entry in val:gmatch(self.ip_pattern .. "/?%d?%d?") do
|
||||
if not self.BLLIST_IP_FILTER or (self.BLLIST_IP_FILTER and not self:check_filter(ip_entry, self.BLLIST_IP_FILTER_PATTERNS, self.BLLIST_IP_FILTER_TYPE)) then
|
||||
if ip_entry:match("^" .. self.ip_pattern .. "$") and not self.ip_table[ip_entry] then
|
||||
local subnet = self:get_subnet(ip_entry)
|
||||
if subnet and (self.BLLIST_GR_EXCLUDED_NETS[subnet] or ((not self.BLLIST_IP_LIMIT or self.BLLIST_IP_LIMIT == 0) or (not self.ip_subnet_table[subnet] or self.ip_subnet_table[subnet] <= self.BLLIST_IP_LIMIT))) then
|
||||
self.ip_table[ip_entry] = subnet
|
||||
self.ip_subnet_table[subnet] = (self.ip_subnet_table[subnet] or 0) + 1
|
||||
self.ip_count = self.ip_count + 1
|
||||
end
|
||||
elseif ip_entry:match("^" .. self.cidr_pattern .. "$") and not self.cidr_table[ip_entry] then
|
||||
self.cidr_table[ip_entry] = true
|
||||
self.cidr_count = self.cidr_count + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function BlackListParser:get_sld(fqdn)
|
||||
return fqdn:match("^[a-z0-9_%.%-]-([a-z0-9_%-]+%.[a-z0-9%-]+)$")
|
||||
end
|
||||
|
||||
function BlackListParser:fill_domain_tables(val)
|
||||
val = val:gsub("%*%.", ""):gsub("%.$", ""):lower()
|
||||
if self.BLLIST_STRIP_WWW then
|
||||
val = val:gsub("^www[0-9]?%.", "")
|
||||
end
|
||||
if not self.BLLIST_FQDN_FILTER or (self.BLLIST_FQDN_FILTER and not self:check_filter(val, self.BLLIST_FQDN_FILTER_PATTERNS, self.BLLIST_FQDN_FILTER_TYPE)) then
|
||||
if val:match("^" .. self.fqdn_pattern .. "+$") then
|
||||
elseif self.BLLIST_ENABLE_IDN and val:match("^[^\\/&%?]-[^\\/&%?%.]+%.[^\\/&%?%.]+%.?$") then
|
||||
val = self:convert_to_punycode(val)
|
||||
if not val then
|
||||
return false
|
||||
end
|
||||
else
|
||||
return false
|
||||
end
|
||||
local sld = self:get_sld(val)
|
||||
if sld and (self.BLLIST_GR_EXCLUDED_SLD[sld] or ((not self.BLLIST_SD_LIMIT or self.BLLIST_SD_LIMIT == 0) or (not self.sld_table[sld] or self.sld_table[sld] < self.BLLIST_SD_LIMIT))) then
|
||||
self.fqdn_table[val] = sld
|
||||
self.sld_table[sld] = (self.sld_table[sld] or 0) + 1
|
||||
self.fqdn_count = self.fqdn_count + 1
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function BlackListParser:sink()
|
||||
-- Must be overridden by a subclass
|
||||
error("Method BlackListParser:sink() must be overridden by a subclass!")
|
||||
end
|
||||
|
||||
function BlackListParser:optimize_ip_table()
|
||||
function OptimizeConfig:_optimize_ip_table()
|
||||
local optimized_table = {}
|
||||
for ipaddr, subnet in pairs(self.ip_table) do
|
||||
if self.ip_subnet_table[subnet] then
|
||||
@@ -544,8 +618,7 @@ function BlackListParser:optimize_ip_table()
|
||||
self.ip_table = optimized_table
|
||||
end
|
||||
|
||||
|
||||
function BlackListParser:optimize_fqdn_table()
|
||||
function OptimizeConfig:_optimize_fqdn_table()
|
||||
local optimized_table = {}
|
||||
if self.BLLIST_GR_EXCLUDED_MASKS and #self.BLLIST_GR_EXCLUDED_MASKS > 0 then
|
||||
for sld in pairs(self.sld_table) do
|
||||
@@ -571,19 +644,60 @@ function BlackListParser:optimize_fqdn_table()
|
||||
self.fqdn_table = optimized_table
|
||||
end
|
||||
|
||||
function BlackListParser:group_ip_ranges()
|
||||
function OptimizeConfig:_group_ip_ranges()
|
||||
for i in Summarize:summarize_ip_ranges(self.ip_table, true) do
|
||||
self.cidr_table[string.format("%s/%s", it.int_to_ip(i[1]), i[2])] = true
|
||||
end
|
||||
end
|
||||
|
||||
function BlackListParser:group_cidr_ranges()
|
||||
function OptimizeConfig:_group_cidr_ranges()
|
||||
for i in Summarize:summarize_nets(self.cidr_table, true) do
|
||||
self.cidr_table[string.format("%s/%s", it.int_to_ip(i[1]), i[2])] = true
|
||||
end
|
||||
end
|
||||
|
||||
function BlackListParser:write_ipset_config()
|
||||
function OptimizeConfig:_union(t1, t2)
|
||||
local new_items = 0
|
||||
for k, v in pairs(t2) do
|
||||
if t1[k] == nil then
|
||||
t1[k] = v
|
||||
new_items = new_items + 1
|
||||
end
|
||||
end
|
||||
return new_items
|
||||
end
|
||||
|
||||
function OptimizeConfig:optimize()
|
||||
for _, i in ipairs(self.parsers_list) do
|
||||
self:_union(self.cidr_table, i.cidr_table)
|
||||
self:_union(self.ip_table, i.ip_table)
|
||||
self:_union(self.ip_subnet_table, i.ip_subnet_table)
|
||||
self:_union(self.fqdn_table, i.fqdn_table)
|
||||
self:_union(self.sld_table, i.sld_table)
|
||||
end
|
||||
self:_optimize_fqdn_table()
|
||||
self:_optimize_ip_table()
|
||||
if self.BLLIST_SUMMARIZE_IP then
|
||||
self:_group_ip_ranges()
|
||||
end
|
||||
if self.BLLIST_SUMMARIZE_CIDR then
|
||||
self:_group_cidr_ranges()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local WriteConfigFiles = Class(Config, {})
|
||||
|
||||
function WriteConfigFiles:new(t)
|
||||
-- extended instance constructor
|
||||
local instance = self(t)
|
||||
instance.cidr_count = 0
|
||||
instance.ip_count = 0
|
||||
instance.fqdn_count = 0
|
||||
return instance
|
||||
end
|
||||
|
||||
function WriteConfigFiles:write_ipset_config(ip_table, cidr_table)
|
||||
local file_handler = assert(io.open(self.IP_DATA_FILE, "w"), "Could not open nftset config")
|
||||
for _, v in ipairs({ self.NFTSET_CIDR, self.NFTSET_IP }) do
|
||||
file_handler:write(string.format("flush set %s %s\n", self.NFT_TABLE, v))
|
||||
@@ -592,9 +706,9 @@ function BlackListParser:write_ipset_config()
|
||||
string.format("table %s {\n%s", self.NFT_TABLE, self.NFTSET_CIDR_CFG)
|
||||
)
|
||||
local c = 0
|
||||
if next(self.cidr_table) then
|
||||
if next(cidr_table) then
|
||||
file_handler:write("elements={")
|
||||
for cidr in pairs(self.cidr_table) do
|
||||
for cidr in pairs(cidr_table) do
|
||||
file_handler:write(string.format("%s,", cidr))
|
||||
c = c + 1
|
||||
end
|
||||
@@ -605,123 +719,59 @@ function BlackListParser:write_ipset_config()
|
||||
string.format("}\n%s", self.NFTSET_IP_CFG)
|
||||
)
|
||||
local i = 0
|
||||
if next(self.ip_table) then
|
||||
if next(ip_table) then
|
||||
file_handler:write("elements={")
|
||||
for ipaddr in pairs(self.ip_table) do
|
||||
for ipaddr in pairs(ip_table) do
|
||||
file_handler:write(string.format("%s,", ipaddr))
|
||||
i = i + 1
|
||||
end
|
||||
file_handler:write("};")
|
||||
end
|
||||
self.ip_records_count = i
|
||||
self.ip_count = i
|
||||
file_handler:write("}\n}\n")
|
||||
file_handler:close()
|
||||
end
|
||||
|
||||
function BlackListParser:write_dnsmasq_config()
|
||||
function WriteConfigFiles:write_dnsmasq_config(fqdn_table)
|
||||
local file_handler = assert(io.open(self.DNSMASQ_DATA_FILE, "w"), "Could not open dnsmasq config")
|
||||
for fqdn in pairs(self.fqdn_table) do
|
||||
local i = 0
|
||||
for fqdn in pairs(fqdn_table) do
|
||||
if self.BLLIST_ALT_NSLOOKUP then
|
||||
file_handler:write(string.format("server=/%s/%s\n", fqdn, self.BLLIST_ALT_DNS_ADDR))
|
||||
end
|
||||
file_handler:write(string.format("nftset=/%s/%s#%s\n", fqdn, self.NFT_TABLE_DNSMASQ, self.NFTSET_DNSMASQ))
|
||||
i = i + 1
|
||||
end
|
||||
self.fqdn_count = i
|
||||
file_handler:close()
|
||||
end
|
||||
|
||||
function BlackListParser:write_update_status()
|
||||
function WriteConfigFiles:write_update_status_file()
|
||||
local file_handler = assert(io.open(self.UPDATE_STATUS_FILE, "w"), "Could not open 'update_status' file")
|
||||
file_handler:write(string.format("%d %d %d", self.cidr_count, self.ip_records_count, self.fqdn_records_count))
|
||||
file_handler:write(string.format("%d %d %d", self.cidr_count, self.ip_count, self.fqdn_count))
|
||||
file_handler:close()
|
||||
end
|
||||
|
||||
function BlackListParser:chunk_buffer()
|
||||
local buff = ""
|
||||
local ret_value = ""
|
||||
local last_chunk
|
||||
return function(chunk)
|
||||
if last_chunk then
|
||||
return nil
|
||||
end
|
||||
if chunk then
|
||||
buff = buff .. chunk
|
||||
local last_rs_position = select(2, buff:find("^.*" .. self.records_separator))
|
||||
if last_rs_position then
|
||||
ret_value = buff:sub(1, last_rs_position)
|
||||
buff = buff:sub((last_rs_position + 1), -1)
|
||||
else
|
||||
ret_value = ""
|
||||
end
|
||||
else
|
||||
ret_value = buff
|
||||
last_chunk = true
|
||||
end
|
||||
return (ret_value)
|
||||
end
|
||||
end
|
||||
-- Parser subclasses
|
||||
|
||||
function BlackListParser:get_http_data(url)
|
||||
local ret_val, ret_code, ret_headers
|
||||
local http_module = url:match("^https") and https or http
|
||||
if http_module then
|
||||
local http_sink = ltn12.sink.chain(self:chunk_buffer(), self:sink())
|
||||
ret_val, ret_code, ret_headers = http_module.request{url = url, sink = http_sink, headers = self.http_send_headers}
|
||||
if not ret_val or ret_code ~= 200 then
|
||||
ret_val = nil
|
||||
print(string.format("Connection error! (%s) URL: %s", ret_code, url))
|
||||
end
|
||||
else
|
||||
local wget_sink = ltn12.sink.chain(self:chunk_buffer(), self:sink())
|
||||
ret_val = ltn12.pump.all(ltn12.source.file(io.popen(self.WGET_CMD .. self.wget_user_agent .. ' "' .. url .. '"', 'r')), wget_sink)
|
||||
end
|
||||
return (ret_val == 1) and true or false
|
||||
end
|
||||
|
||||
function BlackListParser:run()
|
||||
local return_code = 0
|
||||
if self:get_http_data(self.url) then
|
||||
if (self.fqdn_count + self.ip_count + self.cidr_count) > self.BLLIST_MIN_ENTRIES then
|
||||
self:optimize_fqdn_table()
|
||||
self:optimize_ip_table()
|
||||
if self.BLLIST_SUMMARIZE_IP then
|
||||
self:group_ip_ranges()
|
||||
end
|
||||
if self.BLLIST_SUMMARIZE_CIDR then
|
||||
self:group_cidr_ranges()
|
||||
end
|
||||
self:write_ipset_config()
|
||||
self:write_dnsmasq_config()
|
||||
return_code = 0
|
||||
else
|
||||
return_code = 2
|
||||
end
|
||||
else
|
||||
return_code = 1
|
||||
end
|
||||
self:write_update_status()
|
||||
return return_code
|
||||
end
|
||||
|
||||
-- Subclasses
|
||||
|
||||
local function ip_sink(self)
|
||||
local function ip_parser_func(self)
|
||||
return function(chunk)
|
||||
if chunk and chunk ~= "" then
|
||||
for ip_string in chunk:gmatch(self.ip_string_pattern) do
|
||||
self:fill_ip_tables(ip_string)
|
||||
self:ip_value_processing(ip_string)
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function fqdn_sink_func(self, ip_str, fqdn_str)
|
||||
local function fqdn_parser_func(self, ip_str, fqdn_str)
|
||||
if #fqdn_str > 0 and not fqdn_str:match("^" .. self.ip_pattern .. "$") then
|
||||
if self:fill_domain_tables(fqdn_str) then
|
||||
if self:fqdn_value_processing(fqdn_str) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
self:fill_ip_tables(ip_str)
|
||||
self:ip_value_processing(ip_str)
|
||||
end
|
||||
|
||||
-- rublacklist.net
|
||||
@@ -729,14 +779,13 @@ end
|
||||
local Rbl = Class(BlackListParser, {
|
||||
url = Config.RBL_ALL_URL,
|
||||
records_separator = '%{"appearDate": ',
|
||||
ips_separator = ", ",
|
||||
})
|
||||
|
||||
function Rbl:sink()
|
||||
function Rbl:parser_func()
|
||||
return function(chunk)
|
||||
if chunk and chunk ~= "" then
|
||||
for fqdn_str, ip_str in chunk:gmatch('"domains": %["?(.-)"?%].-"ips": %[([a-f0-9/.:", ]*)%].-') do
|
||||
fqdn_sink_func(self, ip_str, fqdn_str)
|
||||
fqdn_parser_func(self, ip_str, fqdn_str)
|
||||
end
|
||||
end
|
||||
return true
|
||||
@@ -747,9 +796,28 @@ local RblIp = Class(Rbl, {
|
||||
url = Config.RBL_IP_URL,
|
||||
records_separator = ",",
|
||||
ip_string_pattern = "([a-f0-9/.:]+)",
|
||||
sink = ip_sink,
|
||||
parser_func = ip_parser_func,
|
||||
})
|
||||
|
||||
local RblDPI = Class(BlackListParser, {
|
||||
url = Config.RBL_DPI_URL,
|
||||
BLLIST_MIN_ENTRIES = 0,
|
||||
records_separator = '%{"domains"',
|
||||
})
|
||||
|
||||
function RblDPI:parser_func()
|
||||
return function(chunk)
|
||||
if chunk and chunk ~= "" then
|
||||
for fqdn_list in chunk:gmatch(': %[(.-)%]') do
|
||||
for fqdn_str in fqdn_list:gmatch(self.fqdn_pattern) do
|
||||
self:fqdn_value_processing(fqdn_str)
|
||||
end
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-- zapret-info
|
||||
|
||||
local Zi = Class(BlackListParser, {
|
||||
@@ -757,11 +825,11 @@ local Zi = Class(BlackListParser, {
|
||||
site_encoding = Config.ZI_ENCODING,
|
||||
})
|
||||
|
||||
function Zi:sink()
|
||||
function Zi:parser_func()
|
||||
return function(chunk)
|
||||
if chunk and chunk ~= "" then
|
||||
for ip_str, fqdn_str in chunk:gmatch("([^;]-);([^;]-);.-" .. self.records_separator) do
|
||||
fqdn_sink_func(self, ip_str, fqdn_str)
|
||||
fqdn_parser_func(self, ip_str, fqdn_str)
|
||||
end
|
||||
end
|
||||
return true
|
||||
@@ -770,7 +838,7 @@ end
|
||||
|
||||
local ZiIp = Class(Zi, {
|
||||
ip_string_pattern = "([a-f0-9%.:/ |]+);.-\n",
|
||||
sink = ip_sink,
|
||||
parser_func = ip_parser_func,
|
||||
})
|
||||
|
||||
-- antifilter
|
||||
@@ -779,12 +847,12 @@ local Af = Class(BlackListParser, {
|
||||
url = Config.AF_FQDN_URL,
|
||||
})
|
||||
|
||||
function Af:sink()
|
||||
function Af:parser_func()
|
||||
local entry_pattern = "((.-))" .. self.records_separator
|
||||
return function(chunk)
|
||||
if chunk and chunk ~= "" then
|
||||
for fqdn_str, ip_str in chunk:gmatch(entry_pattern) do
|
||||
fqdn_sink_func(self, ip_str, fqdn_str)
|
||||
fqdn_parser_func(self, ip_str, fqdn_str)
|
||||
end
|
||||
end
|
||||
return true
|
||||
@@ -794,7 +862,7 @@ end
|
||||
local AfIp = Class(Af, {
|
||||
url = Config.AF_IP_URL,
|
||||
ip_string_pattern = "(.-)\n",
|
||||
sink = ip_sink,
|
||||
parser_func = ip_parser_func,
|
||||
})
|
||||
|
||||
-- ruantiblock
|
||||
@@ -821,7 +889,7 @@ function Ra:chunk_buffer()
|
||||
end
|
||||
end
|
||||
|
||||
function Ra:sink()
|
||||
function Ra:parser_func()
|
||||
return function(chunk)
|
||||
if chunk and chunk ~= "" then
|
||||
self.current_file_handler:write(chunk)
|
||||
@@ -850,17 +918,34 @@ local RaIp = Class(Ra, {
|
||||
|
||||
----------------------------- Main section ------------------------------
|
||||
|
||||
local ctx_table = {
|
||||
["ip"] = {["rublacklist"] = RblIp, ["zapret-info"] = ZiIp, ["antifilter"] = AfIp, ["ruantiblock"] = RaIp},
|
||||
["fqdn"] = {["rublacklist"] = Rbl, ["zapret-info"] = Zi, ["antifilter"] = Af, ["ruantiblock"] = Ra},
|
||||
local parsers_table = {
|
||||
["ip"] = {["rublacklist"] = {RblIp}, ["zapret-info"] = {ZiIp}, ["antifilter"] = {AfIp}, ["ruantiblock"] = {RaIp}},
|
||||
["fqdn"] = {["rublacklist"] = {Rbl, RblDPI}, ["zapret-info"] = {Zi}, ["antifilter"] = {Af}, ["ruantiblock"] = {Ra}},
|
||||
}
|
||||
|
||||
local return_code = 1
|
||||
local ctx = ctx_table[Config.BLLIST_MODE] and ctx_table[Config.BLLIST_MODE][Config.BLLIST_SOURCE]
|
||||
if ctx then
|
||||
return_code = ctx:new():run()
|
||||
local ret_list = {}
|
||||
local parser_classes = parsers_table[Config.BLLIST_MODE] and parsers_table[Config.BLLIST_MODE][Config.BLLIST_SOURCE]
|
||||
if parser_classes then
|
||||
local parser_instances = {}
|
||||
for _, i in ipairs(parser_classes) do
|
||||
parser_instances[#parser_instances + 1] = i:new()
|
||||
end
|
||||
for _, i in ipairs(parser_instances) do
|
||||
ret_list[i:run()] = true
|
||||
end
|
||||
return_sum = 0
|
||||
for i, _ in pairs(ret_list) do
|
||||
return_sum = return_sum + i
|
||||
end
|
||||
if return_sum == 0 and Config.BLLIST_SOURCE ~= "ruantiblock" then
|
||||
local oc_obj = OptimizeConfig:new({parsers_list = parser_instances})
|
||||
oc_obj:optimize()
|
||||
local write_cfg_obj = WriteConfigFiles:new()
|
||||
write_cfg_obj:write_dnsmasq_config(oc_obj.fqdn_table)
|
||||
write_cfg_obj:write_ipset_config(oc_obj.ip_table, oc_obj.cidr_table)
|
||||
write_cfg_obj:write_update_status_file()
|
||||
end
|
||||
else
|
||||
error("Wrong configuration! (Config.BLLIST_MODE or Config.BLLIST_SOURCE)")
|
||||
error("Wrong configuration! (Config.BLLIST_MODE, Config.BLLIST_SOURCE)")
|
||||
end
|
||||
|
||||
os.exit(return_code)
|
||||
os.exit(ret_list[1] and 1 or (ret_list[2] and 2 or 0))
|
||||
|
||||
Reference in New Issue
Block a user