mirror of
https://github.com/itdoginfo/podkop.git
synced 2025-12-08 12:36:50 +03:00
feat: Add local subnet lists support with UI and backend integration (#156)
This commit is contained in:
@@ -370,7 +370,7 @@ function createConfigSection(section, map, network) {
|
|||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
o.ucisection = s.section;
|
o.ucisection = s.section;
|
||||||
|
|
||||||
o = s.taboption('basic', form.DynamicList, 'local_domain_lists', _('Local Domain Lists Path'), _('Enter the list file path'));
|
o = s.taboption('basic', form.DynamicList, 'local_domain_lists', _('Local Domain List Paths'), _('Enter the list file path'));
|
||||||
o.placeholder = '/path/file.lst';
|
o.placeholder = '/path/file.lst';
|
||||||
o.depends('local_domain_lists_enabled', '1');
|
o.depends('local_domain_lists_enabled', '1');
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
@@ -399,6 +399,25 @@ function createConfigSection(section, map, network) {
|
|||||||
return validateUrl(value);
|
return validateUrl(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
o = s.taboption('basic', form.Flag, 'local_subnet_lists_enabled', _('Local Subnet Lists'), _('Use the list from the router filesystem'));
|
||||||
|
o.default = '0';
|
||||||
|
o.rmempty = false;
|
||||||
|
o.ucisection = s.section;
|
||||||
|
|
||||||
|
o = s.taboption('basic', form.DynamicList, 'local_subnet_lists', _('Local Subnet List Paths'), _('Enter the list file path'));
|
||||||
|
o.placeholder = '/path/file.lst';
|
||||||
|
o.depends('local_subnet_lists_enabled', '1');
|
||||||
|
o.rmempty = false;
|
||||||
|
o.ucisection = s.section;
|
||||||
|
o.validate = function (section_id, value) {
|
||||||
|
if (!value || value.length === 0) return true;
|
||||||
|
const pathRegex = /^\/[a-zA-Z0-9_\-\/\.]+$/;
|
||||||
|
if (!pathRegex.test(value)) {
|
||||||
|
return _('Invalid path format. Path must start with "/" and contain valid characters');
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
o = s.taboption('basic', form.ListValue, 'user_subnet_list_type', _('User Subnet List Type'), _('Select how to add your custom subnets'));
|
o = s.taboption('basic', form.ListValue, 'user_subnet_list_type', _('User Subnet List Type'), _('Select how to add your custom subnets'));
|
||||||
o.value('disabled', _('Disabled'));
|
o.value('disabled', _('Disabled'));
|
||||||
o.value('dynamic', _('Dynamic List'));
|
o.value('dynamic', _('Dynamic List'));
|
||||||
|
|||||||
@@ -97,8 +97,8 @@ msgstr "Локальные списки доменов"
|
|||||||
msgid "Use the list from the router filesystem"
|
msgid "Use the list from the router filesystem"
|
||||||
msgstr "Использовать список из файловой системы роутера"
|
msgstr "Использовать список из файловой системы роутера"
|
||||||
|
|
||||||
msgid "Local Domain Lists Path"
|
msgid "Local Domain List Paths"
|
||||||
msgstr "Путь к локальным спискам доменов"
|
msgstr "Пути к локальным спискам доменов"
|
||||||
|
|
||||||
msgid "Enter to the list file path"
|
msgid "Enter to the list file path"
|
||||||
msgstr "Введите путь к файлу списка"
|
msgstr "Введите путь к файлу списка"
|
||||||
@@ -897,3 +897,9 @@ msgstr "Задержка в миллисекундах перед перезаг
|
|||||||
|
|
||||||
msgid "Delay value cannot be empty"
|
msgid "Delay value cannot be empty"
|
||||||
msgstr "Значение не может быть пустым"
|
msgstr "Значение не может быть пустым"
|
||||||
|
|
||||||
|
msgid "Local Subnet Lists"
|
||||||
|
msgstr "Локальные списки подсетей"
|
||||||
|
|
||||||
|
msgid "Local Subnet List Paths"
|
||||||
|
msgstr "Пути к локальным спискам доменов"
|
||||||
@@ -97,7 +97,7 @@ msgstr ""
|
|||||||
msgid "Use the list from the router filesystem"
|
msgid "Use the list from the router filesystem"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Local Domain Lists Path"
|
msgid "Local Domain List Paths"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Enter to the list file path"
|
msgid "Enter to the list file path"
|
||||||
@@ -1251,3 +1251,9 @@ msgstr ""
|
|||||||
|
|
||||||
msgid "Delay value cannot be empty"
|
msgid "Delay value cannot be empty"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Local Subnet Lists"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Local Subnet List Paths"
|
||||||
|
msgstr ""
|
||||||
@@ -16,6 +16,8 @@ config main 'main'
|
|||||||
option user_subnet_list_type 'disable'
|
option user_subnet_list_type 'disable'
|
||||||
#list user_subnets ''
|
#list user_subnets ''
|
||||||
#option user_subnets_text ''
|
#option user_subnets_text ''
|
||||||
|
option local_subnet_lists_enabled '0'
|
||||||
|
#list local_subnet_lists ''
|
||||||
option remote_subnet_lists_enabled '0'
|
option remote_subnet_lists_enabled '0'
|
||||||
#list remote_subnet_lists ''
|
#list remote_subnet_lists ''
|
||||||
option all_traffic_from_ip_enabled '0'
|
option all_traffic_from_ip_enabled '0'
|
||||||
|
|||||||
@@ -870,13 +870,15 @@ exclude_source_ip_from_routing_handler() {
|
|||||||
|
|
||||||
configure_routing_for_section_lists() {
|
configure_routing_for_section_lists() {
|
||||||
local section="$1"
|
local section="$1"
|
||||||
local community_lists_enabled local_domain_lists_enabled remote_domain_lists_enabled remote_subnet_lists_enabled
|
local community_lists_enabled local_domain_lists_enabled remote_domain_lists_enabled remote_subnet_lists_enabled \
|
||||||
|
local_subnet_lists_enabled
|
||||||
local user_domain_list_type user_subnet_list_type route_rule_tag
|
local user_domain_list_type user_subnet_list_type route_rule_tag
|
||||||
config_get_bool community_lists_enabled "$section" "community_lists_enabled" 0
|
config_get_bool community_lists_enabled "$section" "community_lists_enabled" 0
|
||||||
config_get user_domain_list_type "$section" "user_domain_list_type" "disabled"
|
config_get user_domain_list_type "$section" "user_domain_list_type" "disabled"
|
||||||
config_get_bool local_domain_lists_enabled "$section" "local_domain_lists_enabled" 0
|
config_get_bool local_domain_lists_enabled "$section" "local_domain_lists_enabled" 0
|
||||||
config_get_bool remote_domain_lists_enabled "$section" "remote_domain_lists_enabled" 0
|
config_get_bool remote_domain_lists_enabled "$section" "remote_domain_lists_enabled" 0
|
||||||
config_get user_subnet_list_type "$section" "user_subnet_list_type" "disabled"
|
config_get user_subnet_list_type "$section" "user_subnet_list_type" "disabled"
|
||||||
|
config_get_bool local_subnet_lists_enabled "$section" "local_subnet_lists_enabled" 0
|
||||||
config_get_bool remote_subnet_lists_enabled "$section" "remote_subnet_lists_enabled" 0
|
config_get_bool remote_subnet_lists_enabled "$section" "remote_subnet_lists_enabled" 0
|
||||||
|
|
||||||
if [ "$community_lists_enabled" -eq 0 ] && \
|
if [ "$community_lists_enabled" -eq 0 ] && \
|
||||||
@@ -884,6 +886,7 @@ configure_routing_for_section_lists() {
|
|||||||
[ "$local_domain_lists_enabled" -eq 0 ] && \
|
[ "$local_domain_lists_enabled" -eq 0 ] && \
|
||||||
[ "$remote_domain_lists_enabled" -eq 0 ] && \
|
[ "$remote_domain_lists_enabled" -eq 0 ] && \
|
||||||
[ "$user_subnet_list_type" == "disabled" ] && \
|
[ "$user_subnet_list_type" == "disabled" ] && \
|
||||||
|
[ "$local_subnet_lists_enabled" -eq 0 ] && \
|
||||||
[ "$remote_subnet_lists_enabled" == 0 ] ; then
|
[ "$remote_subnet_lists_enabled" == 0 ] ; then
|
||||||
log "Section $section does not have any enabled list, skipping..." "warn"
|
log "Section $section does not have any enabled list, skipping..." "warn"
|
||||||
return 0
|
return 0
|
||||||
@@ -906,7 +909,7 @@ configure_routing_for_section_lists() {
|
|||||||
|
|
||||||
if [ "$local_domain_lists_enabled" -eq 1 ]; then
|
if [ "$local_domain_lists_enabled" -eq 1 ]; then
|
||||||
log "Processing local domains routing rules for $section section"
|
log "Processing local domains routing rules for $section section"
|
||||||
configure_local_domain_lists "$section" "$route_rule_tag"
|
configure_local_domain_or_subnet_lists "$section" "domains" "$route_rule_tag"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$remote_domain_lists_enabled" -eq 1 ]; then
|
if [ "$remote_domain_lists_enabled" -eq 1 ]; then
|
||||||
@@ -921,6 +924,11 @@ configure_routing_for_section_lists() {
|
|||||||
# configure_user_subnet_list_handler
|
# configure_user_subnet_list_handler
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$local_subnet_lists_enabled" -eq 1 ]; then
|
||||||
|
log "Processing local subnets routing rules for $section section"
|
||||||
|
configure_local_domain_or_subnet_lists "$section" "subnets" "$route_rule_tag"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$remote_subnet_lists_enabled" -eq 1 ]; then
|
if [ "$remote_subnet_lists_enabled" -eq 1 ]; then
|
||||||
log "Processing remote subnets routing rules for $section section"
|
log "Processing remote subnets routing rules for $section section"
|
||||||
config_list_foreach "$section" "remote_subnet_lists" configure_remote_domain_or_subnet_list_handler \
|
config_list_foreach "$section" "remote_subnet_lists" configure_remote_domain_or_subnet_list_handler \
|
||||||
@@ -950,58 +958,81 @@ configure_user_domain_list_handler() {
|
|||||||
# TODO(ampetelin): it is necessary to implement
|
# TODO(ampetelin): it is necessary to implement
|
||||||
}
|
}
|
||||||
|
|
||||||
configure_local_domain_lists() {
|
configure_local_domain_or_subnet_lists() {
|
||||||
local section="$1"
|
local section="$1"
|
||||||
local route_rule_tag="$2"
|
local type="$2"
|
||||||
|
local route_rule_tag="$3"
|
||||||
|
|
||||||
local ruleset_tag ruleset_filename ruleset_filepath
|
local ruleset_tag ruleset_filename ruleset_filepath
|
||||||
ruleset_tag="$(get_ruleset_tag "$section" "local" "domains")"
|
ruleset_tag="$(get_ruleset_tag "$section" "local" "$type")"
|
||||||
ruleset_filename="$ruleset_tag.json"
|
ruleset_filename="$ruleset_tag.json"
|
||||||
ruleset_filepath="$TMP_FOLDER/$ruleset_filename"
|
ruleset_filepath="$TMP_FOLDER/$ruleset_filename"
|
||||||
|
|
||||||
sing_box_cm_create_local_source_ruleset "$ruleset_filepath"
|
sing_box_cm_create_local_source_ruleset "$ruleset_filepath"
|
||||||
config=$(sing_box_cm_add_local_ruleset "$config" "$ruleset_tag" "source" "$ruleset_filepath")
|
config=$(sing_box_cm_add_local_ruleset "$config" "$ruleset_tag" "source" "$ruleset_filepath")
|
||||||
config=$(sing_box_cm_patch_route_rule "$config" "$route_rule_tag" "rule_set" "$ruleset_tag")
|
config=$(sing_box_cm_patch_route_rule "$config" "$route_rule_tag" "rule_set" "$ruleset_tag")
|
||||||
_add_ruleset_to_dns_rules "$ruleset_tag" "$route_rule_tag"
|
|
||||||
|
|
||||||
config_list_foreach "$section" "local_domains_list" import_local_domain_list_to_ruleset "$section" "$ruleset_filepath"
|
case "$type" in
|
||||||
|
domains)
|
||||||
|
config_list_foreach "$section" "local_domain_lists" import_local_domain_or_subnet_list_to_ruleset "$type" \
|
||||||
|
"$section" "$ruleset_filepath"
|
||||||
|
_add_ruleset_to_dns_rules "$ruleset_tag" "$route_rule_tag" ;;
|
||||||
|
subnets)
|
||||||
|
config_list_foreach "$section" "local_subnet_lists" import_local_domain_or_subnet_list_to_ruleset "$type" \
|
||||||
|
"$section" "$ruleset_filepath";;
|
||||||
|
*) log "Unsupported local rule set type: $type" "warn" ;;
|
||||||
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
import_local_domain_list_to_ruleset() {
|
import_local_domain_or_subnet_list_to_ruleset() {
|
||||||
local filepath="$1"
|
local filepath="$1"
|
||||||
local section="$2"
|
local type="$2"
|
||||||
local ruleset_filepath="$3"
|
local section="$3"
|
||||||
|
local ruleset_filepath="$4"
|
||||||
|
|
||||||
if ! file_exists "$filepath"; then
|
if ! file_exists "$filepath"; then
|
||||||
log "File $filepath not found" "warn"
|
log "File $filepath not found" "warn"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local domains=""
|
local items=""
|
||||||
while IFS= read -r domain; do
|
while IFS= read -r item; do
|
||||||
if [ -z "$domain" ]; then
|
if [ -z "$item" ]; then
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! is_domain "$domain"; then
|
case "$type" in
|
||||||
log "$domain is not domain" "debug"
|
domains)
|
||||||
|
if ! is_domain "$item"; then
|
||||||
|
log "$item is not domain" "debug"
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
;;
|
||||||
|
subnets)
|
||||||
|
if ! is_ipv4 "$item" && ! is_ipv4_cidr "$item"; then
|
||||||
|
log "$item is not IPv4 IP or CIDR" "debug"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
if [ -z "$domains" ]; then
|
if [ -z "$items" ]; then
|
||||||
domains="$domain"
|
items="$item"
|
||||||
else
|
else
|
||||||
domains="$domains,$domain"
|
items="$items,$item"
|
||||||
fi
|
fi
|
||||||
done < "$filepath"
|
done < "$filepath"
|
||||||
|
|
||||||
if [ -z "$domains" ]; then
|
if [ -z "$items" ]; then
|
||||||
log "No valid domains found in $filepath"
|
log "No valid $type found in $filepath"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
domains="$(comma_string_to_json_array "$domains")"
|
items="$(comma_string_to_json_array "$items")"
|
||||||
sing_box_cm_patch_local_source_ruleset_rules "$ruleset_filepath" "domain_suffix" "$domains"
|
case "$type" in
|
||||||
|
domains) sing_box_cm_patch_local_source_ruleset_rules "$ruleset_filepath" "domain_suffix" "$items" ;;
|
||||||
|
subnets) sing_box_cm_patch_local_source_ruleset_rules "$ruleset_filepath" "ip_cidr" "$items" ;;
|
||||||
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
configure_remote_domain_or_subnet_list_handler() {
|
configure_remote_domain_or_subnet_list_handler() {
|
||||||
|
|||||||
@@ -12,11 +12,10 @@ is_ipv4_cidr() {
|
|||||||
[[ "$ip" =~ $regex ]]
|
[[ "$ip" =~ $regex ]]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Check if string is valid domain
|
||||||
is_domain() {
|
is_domain() {
|
||||||
local str="$1"
|
local str="$1"
|
||||||
#local regex="^(?=.{1,253}(?:\/|$))(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)\.)+(?:[a-zA-Z]{2,}|xn--[a-zA-Z0-9-]{1,59}[a-zA-Z0-9])(?:\/[^\s]*)?$"
|
|
||||||
echo "$str" | grep -Eq '^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])(\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9]))+$'
|
echo "$str" | grep -Eq '^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])(\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9]))+$'
|
||||||
#[[ $str =~ $regex ]]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Checks if the given string is a valid base64-encoded sequence
|
# Checks if the given string is a valid base64-encoded sequence
|
||||||
|
|||||||
Reference in New Issue
Block a user