Blackhole route for VPN configuration.

luci-app-ruantiblock: UI changes for settings.js.
ruantiblock-mod-lua, ruantiblock-mod-py: Added BLLIST_CIDR_EXCLUDED option.
This commit is contained in:
gSpot
2025-09-15 18:25:20 +03:00
parent 493cc103b8
commit 4f68d13026
15 changed files with 440 additions and 255 deletions
@@ -1,5 +1,5 @@
--[[
(с) 2020 gSpot <https://github.com/gSpotx2f>
(с) 2020 gSpot <https://github.com/gSpotx2f/iptool-lua>
Some functions for manipulating IPv4 addresses.
@@ -98,6 +98,7 @@ local function summarize_address_range(first, last)
end
local nbits = math.min(count_righthand_zero_bits(first, ip_bits), bit_length(last - first + 1) - 1)
ret_val = {[1] = first, [2] = (ip_bits - nbits)}
first = first + lshift(1, nbits)
if first - 1 == ipv4_capacity then
return
@@ -154,6 +155,50 @@ local function get_supernet(network, new_prefix)
return band(network_address, lshift(netmask, diff_prefixlen))
end
local function overlap_ip(ip, network)
local network_address, prefixlen
if type(network) == "string" then
network_address, prefixlen = get_network_addr(network)
elseif type(network) == "table" then
network_address, prefixlen = network[1], network[2]
else
return
end
ip = ip_to_int(ip)
if ip == nil then
return
end
local offset = ipv4_length - prefixlen
return (rshift(ip, offset) == rshift(network_address, offset))
end
local function check_network(net)
local network_address, prefixlen
if type(net) == "string" then
network_address, prefixlen = get_network_addr(net)
elseif type(net) == "table" then
network_address, prefixlen = net[1], net[2]
else
return
end
return network_address, prefixlen
end
local function overlap_net(subnet, network)
local network_address_1, prefixlen_1 = check_network(subnet)
local network_address_2, prefixlen_2 = check_network(network)
if (network_address_1 == nil or prefixlen_1 == nil or
network_address_2 == nil or prefixlen_2 == nil) then
return
end
if network_address_1 == network_address_2 then
return true
end
local offset = ipv4_length - math.min(prefixlen_1, prefixlen_2)
return (rshift(network_address_1, offset) == rshift(network_address_2, offset))
end
return {
validate_ip = validate_ip,
ip_to_int = ip_to_int,
@@ -162,4 +207,6 @@ return {
get_network_addr = get_network_addr,
hosts_from_network = hosts_from_network,
get_supernet = get_supernet,
overlap_ip = overlap_ip,
overlap_net = overlap_net,
}
@@ -83,6 +83,8 @@ local Config = Class(nil, {
["BLLIST_FQDN_EXCLUDED_FILE"] = true,
["BLLIST_IP_EXCLUDED_ENABLE"] = true,
["BLLIST_IP_EXCLUDED_FILE"] = true,
["BLLIST_CIDR_EXCLUDED_ENABLE"] = true,
["BLLIST_CIDR_EXCLUDED_FILE"] = true,
},
BLLIST_FQDN_FILTER_PATTERNS = {},
BLLIST_IP_FILTER_PATTERNS = {},
@@ -91,6 +93,7 @@ local Config = Class(nil, {
BLLIST_GR_EXCLUDED_NETS_PATTERNS = {},
BLLIST_FQDN_EXCLUDED_ITEMS = {},
BLLIST_IP_EXCLUDED_ITEMS = {},
BLLIST_CIDR_EXCLUDED_ITEMS = {},
-- iconv type: standalone iconv or lua-iconv (standalone, lua)
ICONV_TYPE = "standalone",
-- standalone iconv
@@ -99,7 +102,7 @@ local Config = Class(nil, {
encoding = "UTF-8",
site_encoding = "",
http_send_headers = {
["User-Agent"] = "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:130.0) Gecko/20100101 Firefox/130.0",
["User-Agent"] = "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:130.0) Gecko/20100101 Firefox/142.0",
},
connect_timeout = nil,
})
@@ -168,60 +171,7 @@ Config.BLLIST_SUMMARIZE_IP = remap_bool(Config.BLLIST_SUMMARIZE_IP)
Config.BLLIST_SUMMARIZE_CIDR = remap_bool(Config.BLLIST_SUMMARIZE_CIDR)
Config.BLLIST_FQDN_EXCLUDED_ENABLE = remap_bool(Config.BLLIST_FQDN_EXCLUDED_ENABLE)
Config.BLLIST_IP_EXCLUDED_ENABLE = remap_bool(Config.BLLIST_IP_EXCLUDED_ENABLE)
-- Loading filters
function Config:load_filter_files()
function load_file(file, t, is_array)
local file_handler = io.open(file, "r")
if file_handler then
for line in file_handler:lines() do
if #line > 0 and line:match("^[^#]") then
if is_array then
t[#t + 1] = line
else
t[line] = true
end
end
end
file_handler:close()
end
end
if self.BLLIST_FQDN_FILTER then
load_file(self.BLLIST_FQDN_FILTER_FILE, self.BLLIST_FQDN_FILTER_PATTERNS)
end
if self.BLLIST_IP_FILTER then
load_file(self.BLLIST_IP_FILTER_FILE, self.BLLIST_IP_FILTER_PATTERNS)
end
if self.BLLIST_GR_EXCLUDED_SLD_FILE then
load_file(self.BLLIST_GR_EXCLUDED_SLD_FILE, self.BLLIST_GR_EXCLUDED_SLD_PATTERNS)
end
if self.BLLIST_GR_EXCLUDED_SLD_MASKS_FILE then
load_file(self.BLLIST_GR_EXCLUDED_SLD_MASKS_FILE, self.BLLIST_GR_EXCLUDED_SLD_MASKS_PATTERNS, true)
end
if self.BLLIST_GR_EXCLUDED_NETS_FILE then
load_file(self.BLLIST_GR_EXCLUDED_NETS_FILE, self.BLLIST_GR_EXCLUDED_NETS_PATTERNS)
end
if self.BLLIST_FQDN_EXCLUDED_ENABLE then
load_file(self.BLLIST_FQDN_EXCLUDED_FILE, self.BLLIST_FQDN_EXCLUDED_ITEMS)
end
if self.BLLIST_IP_EXCLUDED_ENABLE then
load_file(self.BLLIST_IP_EXCLUDED_FILE, self.BLLIST_IP_EXCLUDED_ITEMS)
end
end
function Config:check_sld_masks(sld)
if #self.BLLIST_GR_EXCLUDED_SLD_MASKS_PATTERNS > 0 then
for _, pattern in ipairs(self.BLLIST_GR_EXCLUDED_SLD_MASKS_PATTERNS) do
if sld:find(pattern) then
return true
end
end
end
return false
end
Config:load_filter_files()
Config.BLLIST_CIDR_EXCLUDED_ENABLE = remap_bool(Config.BLLIST_CIDR_EXCLUDED_ENABLE)
-- Importing packages
@@ -250,6 +200,7 @@ end
if not it then
Config.BLLIST_SUMMARIZE_CIDR = false
Config.BLLIST_SUMMARIZE_IP = false
Config.BLLIST_CIDR_EXCLUDED_ENABLE = false
end
--[[
local zlib = prequire("zlib")
@@ -272,6 +223,113 @@ else
error("Config.ICONV_TYPE should be either 'lua' or 'standalone'")
end
-- Loading filters
function Config:load_filter_files()
function load_file(file, t, is_array, func)
local file_handler = io.open(file, "r")
if file_handler then
for line in file_handler:lines() do
if #line > 0 and not line:match("^#") then
if func then
line = func(line)
end
if line ~= nil then
if is_array then
t[#t + 1] = line
else
t[line] = true
end
end
end
end
file_handler:close()
end
end
if self.BLLIST_FQDN_FILTER then
load_file(self.BLLIST_FQDN_FILTER_FILE, self.BLLIST_FQDN_FILTER_PATTERNS, true)
end
if self.BLLIST_IP_FILTER then
load_file(self.BLLIST_IP_FILTER_FILE, self.BLLIST_IP_FILTER_PATTERNS, true)
end
if self.BLLIST_GR_EXCLUDED_SLD_FILE then
load_file(self.BLLIST_GR_EXCLUDED_SLD_FILE, self.BLLIST_GR_EXCLUDED_SLD_PATTERNS)
end
if self.BLLIST_GR_EXCLUDED_SLD_MASKS_FILE then
load_file(self.BLLIST_GR_EXCLUDED_SLD_MASKS_FILE, self.BLLIST_GR_EXCLUDED_SLD_MASKS_PATTERNS, true)
end
if self.BLLIST_GR_EXCLUDED_NETS_FILE then
load_file(self.BLLIST_GR_EXCLUDED_NETS_FILE, self.BLLIST_GR_EXCLUDED_NETS_PATTERNS)
end
if self.BLLIST_FQDN_EXCLUDED_ENABLE then
load_file(self.BLLIST_FQDN_EXCLUDED_FILE, self.BLLIST_FQDN_EXCLUDED_ITEMS)
end
if self.BLLIST_IP_EXCLUDED_ENABLE then
load_file(self.BLLIST_IP_EXCLUDED_FILE, self.BLLIST_IP_EXCLUDED_ITEMS)
end
if self.BLLIST_CIDR_EXCLUDED_ENABLE then
load_file(self.BLLIST_CIDR_EXCLUDED_FILE, self.BLLIST_CIDR_EXCLUDED_ITEMS, true,
function(l)
if l:match("^%d%d?%d?%.%d%d?%d?%.%d%d?%d?%.%d%d?%d?/%d%d?$") then
local a, p = it.get_network_addr(l)
if a ~= nil and p ~= nil then
return { [1] = a, [2] = p }
end
end
return
end
)
end
end
function Config:check_filter(str, filter_patterns, reverse)
if filter_patterns and str then
for _, pattern in ipairs(filter_patterns) do
if str:match(pattern) then
return not reverse
end
end
end
return reverse
end
function Config:check_sld_masks(sld)
if #self.BLLIST_GR_EXCLUDED_SLD_MASKS_PATTERNS > 0 then
for _, pattern in ipairs(self.BLLIST_GR_EXCLUDED_SLD_MASKS_PATTERNS) do
if sld:find(pattern) then
return true
end
end
end
return false
end
function Config:check_cidr_overlap_ip(ip)
if #self.BLLIST_CIDR_EXCLUDED_ITEMS > 0 then
for _, net in ipairs(self.BLLIST_CIDR_EXCLUDED_ITEMS) do
if it.overlap_ip(ip, net) then
return true
end
end
end
return false
end
function Config:check_cidr_overlap_net(ip)
if #self.BLLIST_CIDR_EXCLUDED_ITEMS > 0 then
for _, net in ipairs(self.BLLIST_CIDR_EXCLUDED_ITEMS) do
if it.overlap_net(ip, net) then
return true
end
end
end
return false
end
Config:load_filter_files()
------------------------------ Classes -------------------------------
local BlackListParser = Class(Config, {
@@ -323,17 +381,6 @@ function BlackListParser:convert_to_punycode(input)
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
@@ -707,6 +754,23 @@ function OptimizeConfig:new(t)
return instance
end
function OptimizeConfig:_exclude_nets()
local ip_table = {}
for ip, subnet in pairs(self.ip_table) do
if not self:check_cidr_overlap_ip(ip) then
ip_table[ip] = subnet
end
end
self.ip_table = ip_table
local cidr_table = {}
for net in pairs(self.cidr_table) do
if not self:check_cidr_overlap_net(net) then
cidr_table[net] = true
end
end
self.cidr_table = cidr_table
end
function OptimizeConfig:_remove_subdomains()
local tld_table = {}
for fqdn, sld in pairs(self.fqdn_table) do
@@ -792,6 +856,9 @@ function OptimizeConfig:optimize()
self:_union(self.fqdn_table, i.fqdn_table)
self:_union(self.sld_table, i.sld_table)
end
if self.BLLIST_CIDR_EXCLUDED_ENABLE then
self:_exclude_nets()
end
self:_remove_subdomains()
self:_optimize_fqdn_table()
self:_optimize_ip_table()
@@ -1146,6 +1213,7 @@ if parser_classes then
for _, i in ipairs(parser_instances) do
ret_list[i:run()] = true
end
local return_sum = 0
for i, _ in pairs(ret_list) do
return_sum = return_sum + i
@@ -1161,4 +1229,5 @@ if parser_classes then
else
error("Wrong configuration! (Config.BLLIST_MODE, Config.BLLIST_SOURCE)")
end
os.exit(ret_list[1] and 1 or (ret_list[2] and 2 or 0))