Scope Podkop DNS to source interfaces

This commit is contained in:
ushan0v
2026-05-01 14:20:13 +03:00
parent b591524269
commit 5873b32ede
+190 -71
View File
@@ -436,7 +436,7 @@ get_remote_ruleset_update_interval() {
}
capture_reload_state() {
config_load "$PODKOP_CONFIG"
config_load "$PODKOP_CONFIG_NAME"
RELOAD_STATE_RESTART_SIGNATURE="$(build_restart_signature)"
RELOAD_STATE_DNSMASQ_SIGNATURE="$(build_dnsmasq_signature)"
RELOAD_STATE_SING_BOX_SIGNATURE="$(build_sing_box_signature)"
@@ -1030,7 +1030,7 @@ reload() {
[ "$reload_reason" = "on_config_change" ] || force_runtime_reload=1
migration
config_load "$PODKOP_CONFIG"
config_load "$PODKOP_CONFIG_NAME"
check_requirements
config_foreach process_validate_rule "rule"
ensure_runtime_dirs
@@ -1088,11 +1088,10 @@ reload() {
needs_zapret_restart=1
fi
if [ "$RELOAD_STATE_DNSMASQ_SIGNATURE" != "$previous_dnsmasq_signature" ] &&
[ "$RELOAD_STATE_DONT_TOUCH_DHCP" != "$previous_dont_touch_dhcp" ]; then
if [ "$RELOAD_STATE_DNSMASQ_SIGNATURE" != "$previous_dnsmasq_signature" ]; then
if [ "$RELOAD_STATE_DONT_TOUCH_DHCP" -eq 0 ]; then
needs_dnsmasq_configure=1
else
elif [ "$previous_dont_touch_dhcp" = "0" ]; then
needs_dnsmasq_restore=1
fi
fi
@@ -1790,8 +1789,153 @@ backup_dnsmasq_config_option() {
fi
}
list_has_item() {
local list="$1"
local needle="$2"
local item
for item in $list; do
[ "$item" = "$needle" ] && return 0
done
return 1
}
uci_add_list_unique() {
local package="$1"
local section="$2"
local option="$3"
local value="$4"
local current_values
current_values="$(uci_get "$package" "$section" "$option")"
list_has_item "$current_values" "$value" && return 0
uci_add_list "$package" "$section" "$option" "$value"
}
backup_dnsmasq_config_list_option() {
local key="$1"
local backup_key="$2"
local value
for value in $(uci_get "dhcp" "@dnsmasq[0]" "$key"); do
uci_add_list_unique "dhcp" "@dnsmasq[0]" "$backup_key" "$value"
done
}
restore_dnsmasq_config_option() {
local key="$1"
local backup_key="$2"
local default_value="${3:-}"
local value
value="$(uci_get "dhcp" "@dnsmasq[0]" "$backup_key")"
if [ -n "$value" ]; then
uci_set "dhcp" "@dnsmasq[0]" "$key" "$value"
uci_remove "dhcp" "@dnsmasq[0]" "$backup_key"
elif [ -n "$default_value" ]; then
uci_set "dhcp" "@dnsmasq[0]" "$key" "$default_value"
else
uci_remove "dhcp" "@dnsmasq[0]" "$key"
fi
}
restore_dnsmasq_config_list_option() {
local key="$1"
local backup_key="$2"
local value
uci_remove "dhcp" "@dnsmasq[0]" "$key"
for value in $(uci_get "dhcp" "@dnsmasq[0]" "$backup_key"); do
uci_add_list "dhcp" "@dnsmasq[0]" "$key" "$value"
done
uci_remove "dhcp" "@dnsmasq[0]" "$backup_key"
}
dnsmasq_server_list_has_podkop_dns() {
local server_list="$1"
local server
for server in $server_list; do
[ "$server" = "$SB_DNS_INBOUND_ADDRESS" ] && return 0
done
return 1
}
dnsmasq_default_has_podkop_dns() {
dnsmasq_server_list_has_podkop_dns "$(uci_get "dhcp" "@dnsmasq[0]" "server")"
}
dnsmasq_split_has_podkop_dns() {
dnsmasq_server_list_has_podkop_dns "$(uci_get "dhcp" "$PODKOP_DNSMASQ_SECTION" "server")"
}
dnsmasq_has_podkop_dns() {
uci -q show dhcp | grep -F ".server='$SB_DNS_INBOUND_ADDRESS'" >/dev/null 2>&1
dnsmasq_split_has_podkop_dns || dnsmasq_default_has_podkop_dns
}
dnsmasq_restore_default_instance() {
local server_list backup_servers server legacy_global_dns noresolv cachesize
server_list="$(uci_get "dhcp" "@dnsmasq[0]" "server")"
backup_servers="$(uci_get "dhcp" "@dnsmasq[0]" "podkop_server")"
legacy_global_dns=0
dnsmasq_server_list_has_podkop_dns "$server_list" && legacy_global_dns=1
uci_remove "dhcp" "@dnsmasq[0]" "server"
if [ -n "$backup_servers" ]; then
for server in $backup_servers; do
uci_add_list "dhcp" "@dnsmasq[0]" "server" "$server"
done
uci_remove "dhcp" "@dnsmasq[0]" "podkop_server"
else
for server in $server_list; do
[ "$server" = "$SB_DNS_INBOUND_ADDRESS" ] && continue
uci_add_list "dhcp" "@dnsmasq[0]" "server" "$server"
done
fi
noresolv="$(uci_get "dhcp" "@dnsmasq[0]" "podkop_noresolv")"
if [ -n "$noresolv" ]; then
restore_dnsmasq_config_option "noresolv" "podkop_noresolv"
elif [ "$legacy_global_dns" -eq 1 ]; then
uci_set "dhcp" "@dnsmasq[0]" "noresolv" 0
fi
cachesize="$(uci_get "dhcp" "@dnsmasq[0]" "podkop_cachesize")"
if [ -n "$cachesize" ]; then
restore_dnsmasq_config_option "cachesize" "podkop_cachesize"
elif [ "$legacy_global_dns" -eq 1 ]; then
uci_set "dhcp" "@dnsmasq[0]" "cachesize" 150
fi
}
dnsmasq_configure_split_instance() {
local source_network_interfaces interface
config_get source_network_interfaces "settings" "source_network_interfaces" "br-lan"
backup_dnsmasq_config_list_option "notinterface" "podkop_notinterface"
for interface in $source_network_interfaces; do
uci_add_list_unique "dhcp" "@dnsmasq[0]" "notinterface" "$interface"
done
uci -q delete "dhcp.$PODKOP_DNSMASQ_SECTION"
uci set "dhcp.$PODKOP_DNSMASQ_SECTION=dnsmasq"
uci_set "dhcp" "$PODKOP_DNSMASQ_SECTION" "noresolv" 1
uci_set "dhcp" "$PODKOP_DNSMASQ_SECTION" "cachesize" 0
uci_add_list "dhcp" "$PODKOP_DNSMASQ_SECTION" "server" "$SB_DNS_INBOUND_ADDRESS"
for interface in $source_network_interfaces; do
uci_add_list "dhcp" "$PODKOP_DNSMASQ_SECTION" "interface" "$interface"
done
}
dnsmasq_restore_split_instance() {
uci -q delete "dhcp.$PODKOP_DNSMASQ_SECTION"
restore_dnsmasq_config_list_option "notinterface" "podkop_notinterface"
}
dnsmasq_configure() {
@@ -1799,7 +1943,7 @@ dnsmasq_configure() {
local shutdown_correctly
config_get shutdown_correctly "settings" "shutdown_correctly"
if [ "$force" != "force" ] && [ "$shutdown_correctly" -eq 0 ]; then
if dnsmasq_has_podkop_dns; then
if dnsmasq_split_has_podkop_dns; then
log "Previous shutdown of podkop was not correct, dnsmasq is already configured"
return 0
fi
@@ -1807,24 +1951,16 @@ dnsmasq_configure() {
log "Previous shutdown of podkop was not correct, but dnsmasq is not configured. Applying Podkop DNS settings"
fi
log "Backup dnsmasq configuration"
current_servers="$(uci_get "dhcp" "@dnsmasq[0]" "server")"
if [ -n "$current_servers" ]; then
for server in $(uci_get "dhcp" "@dnsmasq[0]" "server"); do
if ! [ "$server" == "$SB_DNS_INBOUND_ADDRESS" ]; then
uci_add_list "dhcp" "@dnsmasq[0]" "podkop_server" "$server"
fi
done
uci_remove "dhcp" "@dnsmasq[0]" "server"
fi
backup_dnsmasq_config_option "noresolv" "podkop_noresolv"
backup_dnsmasq_config_option "cachesize" "podkop_cachesize"
log "Configure dnsmasq for sing-box"
uci_add_list "dhcp" "@dnsmasq[0]" "server" "$SB_DNS_INBOUND_ADDRESS"
uci_set "dhcp" "@dnsmasq[0]" "noresolv" 1
uci_set "dhcp" "@dnsmasq[0]" "cachesize" 0
if dnsmasq_split_has_podkop_dns; then
log "Refreshing existing interface-scoped Podkop DNS settings"
dnsmasq_restore_split_instance
fi
if dnsmasq_default_has_podkop_dns; then
log "Migrating legacy global dnsmasq DNS settings to interface-scoped Podkop DNS"
dnsmasq_restore_default_instance
fi
dnsmasq_configure_split_instance
uci_commit "dhcp"
/etc/init.d/dnsmasq restart
@@ -1844,45 +1980,8 @@ dnsmasq_restore() {
log "Previous shutdown of podkop was correct, but Podkop DNS is still present. Restoring dnsmasq"
fi
local cachesize noresolv backup_servers resolvfile
log "Restoring cachesize" "debug"
cachesize="$(uci_get "dhcp" "@dnsmasq[0]" "podkop_cachesize")"
if [ -z "$cachesize" ]; then
uci_remove "dhcp" "@dnsmasq[0]" "cachesize"
uci_set "dhcp" "@dnsmasq[0]" "cachesize" 150
else
uci_set "dhcp" "@dnsmasq[0]" "cachesize" "$cachesize"
uci_remove "dhcp" "@dnsmasq[0]" "podkop_cachesize"
fi
log "Restoring noresolv" "debug"
noresolv="$(uci_get "dhcp" "@dnsmasq[0]" "podkop_noresolv")"
if [ -z "$noresolv" ]; then
uci_set "dhcp" "@dnsmasq[0]" "noresolv" 0
else
uci_set "dhcp" "@dnsmasq[0]" "noresolv" "$noresolv"
uci_remove "dhcp" "@dnsmasq[0]" "podkop_noresolv"
fi
log "Restoring DNS servers" "debug"
uci_remove "dhcp" "@dnsmasq[0]" "server"
resolvfile="/tmp/resolv.conf.d/resolv.conf.auto"
backup_servers="$(uci_get "dhcp" "@dnsmasq[0]" "podkop_server")"
if [ -n "$backup_servers" ]; then
for server in $backup_servers; do
uci_add_list "dhcp" "@dnsmasq[0]" "server" "$server"
done
uci_remove "dhcp" "@dnsmasq[0]" "podkop_server"
elif file_exists "$resolvfile"; then
log "Backup DNS servers not found, using default resolvfile" "debug"
uci_set "dhcp" "@dnsmasq[0]" "resolvfile" "$resolvfile"
if [ -n "$noresolv" ] && [ "$noresolv" -eq 1 ]; then
log "Disabling noresolv option to use system resolvfile" "debug"
uci_set "dhcp" "@dnsmasq[0]" "noresolv" 0
fi
else
log "Backup DNS servers and default resolvfile not found, possible resolving issues" "warn"
fi
dnsmasq_restore_split_instance
dnsmasq_restore_default_instance
uci_commit "dhcp"
@@ -4388,25 +4487,32 @@ check_dns_available() {
fi
fi
# Check if /etc/config/dhcp has server 127.0.0.42
# Check if dnsmasq sends only selected source interfaces through Podkop DNS.
config_load dhcp
config_foreach check_dhcp_has_podkop_dns dnsmasq
config_load "$PODKOP_CONFIG"
check_dhcp_has_podkop_dns
config_load "$PODKOP_CONFIG_NAME"
echo "{\"dns_type\":\"$dns_type\",\"dns_server\":\"$display_dns_server\",\"dns_status\":$dns_status,\"dns_on_router\":$dns_on_router,\"bootstrap_dns_server\":\"$bootstrap_dns_server\",\"bootstrap_dns_status\":$bootstrap_dns_status,\"dhcp_config_status\":$dhcp_config_status}" | jq .
}
check_dhcp_has_podkop_dns() {
local server_list cachesize noresolv server_found
config_get server_list "$1" "server"
config_get cachesize "$1" "cachesize"
config_get noresolv "$1" "noresolv"
local source_network_interfaces podkop_interfaces default_notinterfaces server_list cachesize noresolv
local server server_found interface
source_network_interfaces="$(uci_get "$PODKOP_CONFIG_NAME" "settings" "source_network_interfaces")"
[ -n "$source_network_interfaces" ] || source_network_interfaces="br-lan"
server_list="$(uci_get "dhcp" "$PODKOP_DNSMASQ_SECTION" "server")"
cachesize="$(uci_get "dhcp" "$PODKOP_DNSMASQ_SECTION" "cachesize")"
noresolv="$(uci_get "dhcp" "$PODKOP_DNSMASQ_SECTION" "noresolv")"
podkop_interfaces="$(uci_get "dhcp" "$PODKOP_DNSMASQ_SECTION" "interface")"
default_notinterfaces="$(uci_get "dhcp" "@dnsmasq[0]" "notinterface")"
server_found=0
if [ -n "$server_list" ]; then
for server in $server_list; do
if [ "$server" = "127.0.0.42" ]; then
if [ "$server" = "$SB_DNS_INBOUND_ADDRESS" ]; then
server_found=1
break
fi
@@ -4415,6 +4521,19 @@ check_dhcp_has_podkop_dns() {
if [ "$cachesize" != "0" ] || [ "$noresolv" != "1" ] || [ "$server_found" != "1" ]; then
dhcp_config_status=0
return 0
fi
for interface in $source_network_interfaces; do
if ! list_has_item "$podkop_interfaces" "$interface" ||
! list_has_item "$default_notinterfaces" "$interface"; then
dhcp_config_status=0
return 0
fi
done
if dnsmasq_default_has_podkop_dns; then
dhcp_config_status=0
fi
}