updating dns override
All checks were successful
Check scripts syntax / check-scripts-syntax (push) Successful in 4s
All checks were successful
Check scripts syntax / check-scripts-syntax (push) Successful in 4s
This commit is contained in:
177
dns-override.sh
177
dns-override.sh
@@ -3,7 +3,8 @@
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
readonly SCRIPT_NAME="dns-override.sh"
|
readonly SCRIPT_NAME="dns-override.sh"
|
||||||
readonly SCRIPT_VERSION="1.0.0"
|
readonly SCRIPT_VERSION="1.0.2"
|
||||||
|
readonly IMMUTABLE_PROMPT_TIMEOUT_SEC=20
|
||||||
|
|
||||||
readonly NC='\033[0m'
|
readonly NC='\033[0m'
|
||||||
readonly RED='\033[1;31m'
|
readonly RED='\033[1;31m'
|
||||||
@@ -22,6 +23,8 @@ readonly EMOJI_NET='🌐'
|
|||||||
readonly EMOJI_LOCK='🔒'
|
readonly EMOJI_LOCK='🔒'
|
||||||
|
|
||||||
SUDO_BIN=""
|
SUDO_BIN=""
|
||||||
|
IS_REMOTE_SSH=0
|
||||||
|
IMMUTABLE_LOCK_REQUESTED=0
|
||||||
declare -a DNS_SERVERS=()
|
declare -a DNS_SERVERS=()
|
||||||
declare -a DETECTED_MANAGERS=()
|
declare -a DETECTED_MANAGERS=()
|
||||||
declare -a ACTIONS_ATTEMPTED=()
|
declare -a ACTIONS_ATTEMPTED=()
|
||||||
@@ -44,6 +47,27 @@ command_exists() {
|
|||||||
command -v "$1" >/dev/null 2>&1
|
command -v "$1" >/dev/null 2>&1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binary_or_path_exists() {
|
||||||
|
local bin_name="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
if command_exists "$bin_name"; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local path_candidate
|
||||||
|
for path_candidate in "$@"; do
|
||||||
|
[[ -x "$path_candidate" ]] && return 0
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
systemd_unit_exists() {
|
||||||
|
local unit_name="$1"
|
||||||
|
command_exists systemctl || return 1
|
||||||
|
systemctl list-unit-files "$unit_name" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
trim() {
|
trim() {
|
||||||
local value="$1"
|
local value="$1"
|
||||||
value="${value#"${value%%[![:space:]]*}"}"
|
value="${value#"${value%%[![:space:]]*}"}"
|
||||||
@@ -98,6 +122,15 @@ read_tty_input() {
|
|||||||
printf '%s' "$(trim "$value")"
|
printf '%s' "$(trim "$value")"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
read_tty_input_timeout() {
|
||||||
|
local prompt="$1"
|
||||||
|
local timeout_sec="$2"
|
||||||
|
local value
|
||||||
|
printf "%b" "$prompt" >/dev/tty
|
||||||
|
IFS= read -r -t "$timeout_sec" value </dev/tty || return $?
|
||||||
|
printf '%s' "$(trim "$value")"
|
||||||
|
}
|
||||||
|
|
||||||
run_root() {
|
run_root() {
|
||||||
if [[ -n "$SUDO_BIN" ]]; then
|
if [[ -n "$SUDO_BIN" ]]; then
|
||||||
"$SUDO_BIN" "$@"
|
"$SUDO_BIN" "$@"
|
||||||
@@ -144,6 +177,49 @@ ensure_root_context() {
|
|||||||
SUDO_BIN="sudo"
|
SUDO_BIN="sudo"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
detect_runtime_context() {
|
||||||
|
if [[ -n "${SSH_CONNECTION:-}" || -n "${SSH_TTY:-}" ]]; then
|
||||||
|
IS_REMOTE_SSH=1
|
||||||
|
log_warning "SSH session detected. Using safer apply behavior to reduce connection drops."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
has_systemd_resolved() {
|
||||||
|
binary_or_path_exists "resolvectl" "/usr/bin/resolvectl" "/bin/resolvectl" && return 0
|
||||||
|
systemd_unit_exists "systemd-resolved.service" && return 0
|
||||||
|
binary_or_path_exists "systemd-resolved" "/lib/systemd/systemd-resolved" "/usr/lib/systemd/systemd-resolved" && return 0
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
has_networkmanager() {
|
||||||
|
binary_or_path_exists "nmcli" "/usr/bin/nmcli" "/bin/nmcli" && return 0
|
||||||
|
binary_or_path_exists "NetworkManager" "/usr/sbin/NetworkManager" "/sbin/NetworkManager" && return 0
|
||||||
|
systemd_unit_exists "NetworkManager.service" && return 0
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
has_resolvconf_openresolv() {
|
||||||
|
binary_or_path_exists "resolvconf" "/sbin/resolvconf" "/usr/sbin/resolvconf" && return 0
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
has_dhclient() {
|
||||||
|
binary_or_path_exists "dhclient" "/sbin/dhclient" "/usr/sbin/dhclient" && return 0
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
has_systemd_networkd() {
|
||||||
|
systemd_unit_exists "systemd-networkd.service" && return 0
|
||||||
|
binary_or_path_exists "systemd-networkd" "/lib/systemd/systemd-networkd" "/usr/lib/systemd/systemd-networkd" && return 0
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
has_ifupdown() {
|
||||||
|
binary_or_path_exists "ifup" "/sbin/ifup" "/usr/sbin/ifup" && return 0
|
||||||
|
[[ -f /etc/network/interfaces || -d /etc/network/interfaces.d ]] && return 0
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
add_manager() {
|
add_manager() {
|
||||||
local manager="$1"
|
local manager="$1"
|
||||||
if ! contains_value "$manager" "${DETECTED_MANAGERS[@]}"; then
|
if ! contains_value "$manager" "${DETECTED_MANAGERS[@]}"; then
|
||||||
@@ -154,31 +230,27 @@ add_manager() {
|
|||||||
detect_managers() {
|
detect_managers() {
|
||||||
DETECTED_MANAGERS=()
|
DETECTED_MANAGERS=()
|
||||||
|
|
||||||
if command_exists systemctl && systemctl is-active --quiet systemd-resolved 2>/dev/null; then
|
if has_systemd_resolved; then
|
||||||
add_manager "systemd-resolved"
|
|
||||||
elif [[ -L /etc/resolv.conf ]] && readlink /etc/resolv.conf 2>/dev/null | grep -Eq 'systemd/resolve'; then
|
|
||||||
add_manager "systemd-resolved"
|
add_manager "systemd-resolved"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if command_exists nmcli || [[ -d /etc/NetworkManager ]]; then
|
if has_networkmanager; then
|
||||||
add_manager "NetworkManager"
|
add_manager "NetworkManager"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if command_exists resolvconf || [[ -d /etc/resolvconf ]] || [[ -f /etc/resolvconf.conf ]]; then
|
if has_resolvconf_openresolv; then
|
||||||
add_manager "resolvconf/openresolv"
|
add_manager "resolvconf/openresolv"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if command_exists dhclient || [[ -f /etc/dhcp/dhclient.conf ]]; then
|
if has_dhclient; then
|
||||||
add_manager "dhclient"
|
add_manager "dhclient"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if command_exists systemctl && systemctl is-active --quiet systemd-networkd 2>/dev/null; then
|
if has_systemd_networkd; then
|
||||||
add_manager "systemd-networkd"
|
|
||||||
elif [[ -d /etc/systemd/network ]]; then
|
|
||||||
add_manager "systemd-networkd"
|
add_manager "systemd-networkd"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -f /etc/network/interfaces ]] || [[ -d /etc/network/interfaces.d ]]; then
|
if has_ifupdown; then
|
||||||
add_manager "ifupdown"
|
add_manager "ifupdown"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
@@ -336,7 +408,7 @@ run_action() {
|
|||||||
rc=$?
|
rc=$?
|
||||||
if [[ "$rc" -eq 2 ]]; then
|
if [[ "$rc" -eq 2 ]]; then
|
||||||
ACTIONS_SKIPPED+=("$action")
|
ACTIONS_SKIPPED+=("$action")
|
||||||
log_info "$action not applicable on this system"
|
log_info "$action skipped: target manager is not present on this host"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -374,7 +446,8 @@ apply_static_resolv_conf() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
apply_systemd_resolved() {
|
apply_systemd_resolved() {
|
||||||
if ! command_exists systemctl && ! command_exists resolvectl && [[ ! -d /etc/systemd ]]; then
|
if ! has_systemd_resolved; then
|
||||||
|
log_info "Skipping systemd-resolved override: systemd-resolved is not present."
|
||||||
return 2
|
return 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -409,7 +482,8 @@ apply_systemd_resolved() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
apply_networkmanager() {
|
apply_networkmanager() {
|
||||||
if ! command_exists nmcli && [[ ! -d /etc/NetworkManager ]]; then
|
if ! has_networkmanager; then
|
||||||
|
log_info "Skipping NetworkManager override: NetworkManager is not present."
|
||||||
return 2
|
return 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -430,21 +504,37 @@ apply_networkmanager() {
|
|||||||
run_root nmcli connection modify "$conn" ipv6.ignore-auto-dns yes >/dev/null 2>&1 || true
|
run_root nmcli connection modify "$conn" ipv6.ignore-auto-dns yes >/dev/null 2>&1 || true
|
||||||
run_root nmcli connection modify "$conn" ipv4.dns "$dns_csv" >/dev/null 2>&1 || true
|
run_root nmcli connection modify "$conn" ipv4.dns "$dns_csv" >/dev/null 2>&1 || true
|
||||||
run_root nmcli connection modify "$conn" ipv6.dns "$dns_csv" >/dev/null 2>&1 || true
|
run_root nmcli connection modify "$conn" ipv6.dns "$dns_csv" >/dev/null 2>&1 || true
|
||||||
|
done < <(nmcli -g NAME connection show --active 2>/dev/null || true)
|
||||||
|
|
||||||
|
run_root nmcli connection reload >/dev/null 2>&1 || true
|
||||||
|
|
||||||
|
if [[ "$IS_REMOTE_SSH" -eq 1 ]]; then
|
||||||
|
log_warning "Skipping NetworkManager reconnect/restart operations in SSH session."
|
||||||
|
local dev
|
||||||
|
while IFS= read -r dev; do
|
||||||
|
[[ -n "$dev" && "$dev" != "lo" ]] || continue
|
||||||
|
run_root nmcli device reapply "$dev" >/dev/null 2>&1 || true
|
||||||
|
done < <(nmcli -t -f DEVICE,STATE device status 2>/dev/null | awk -F: '$2=="connected" || $2=="connecting" {print $1}')
|
||||||
|
else
|
||||||
|
while IFS= read -r conn; do
|
||||||
|
[[ -n "$conn" ]] || continue
|
||||||
run_root nmcli connection up "$conn" >/dev/null 2>&1 || true
|
run_root nmcli connection up "$conn" >/dev/null 2>&1 || true
|
||||||
done < <(nmcli -g NAME connection show --active 2>/dev/null || true)
|
done < <(nmcli -g NAME connection show --active 2>/dev/null || true)
|
||||||
|
fi
|
||||||
|
|
||||||
run_root nmcli general reload >/dev/null 2>&1 || true
|
run_root nmcli general reload >/dev/null 2>&1 || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if command_exists systemctl; then
|
if command_exists systemctl; then
|
||||||
run_root systemctl reload NetworkManager >/dev/null 2>&1 || run_root systemctl restart NetworkManager >/dev/null 2>&1 || true
|
run_root systemctl reload NetworkManager >/dev/null 2>&1 || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
apply_resolvconf_openresolv() {
|
apply_resolvconf_openresolv() {
|
||||||
if ! command_exists resolvconf && [[ ! -d /etc/resolvconf ]] && [[ ! -f /etc/resolvconf.conf ]]; then
|
if ! has_resolvconf_openresolv; then
|
||||||
|
log_info "Skipping resolvconf/openresolv override: resolvconf/openresolv is not present."
|
||||||
return 2
|
return 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -464,7 +554,8 @@ apply_resolvconf_openresolv() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
apply_dhclient() {
|
apply_dhclient() {
|
||||||
if ! command_exists dhclient && [[ ! -f /etc/dhcp/dhclient.conf ]] && [[ ! -d /etc/dhcp ]]; then
|
if ! has_dhclient; then
|
||||||
|
log_info "Skipping dhclient override: dhclient is not present."
|
||||||
return 2
|
return 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -485,7 +576,8 @@ apply_dhclient() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
apply_systemd_networkd() {
|
apply_systemd_networkd() {
|
||||||
if ! command_exists systemctl && [[ ! -d /etc/systemd/network ]]; then
|
if ! has_systemd_networkd; then
|
||||||
|
log_info "Skipping systemd-networkd override: systemd-networkd is not present."
|
||||||
return 2
|
return 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -515,7 +607,18 @@ apply_systemd_networkd() {
|
|||||||
|
|
||||||
if command_exists systemctl; then
|
if command_exists systemctl; then
|
||||||
run_root systemctl daemon-reload >/dev/null 2>&1 || true
|
run_root systemctl daemon-reload >/dev/null 2>&1 || true
|
||||||
|
if command_exists networkctl; then
|
||||||
|
run_root networkctl reload >/dev/null 2>&1 || true
|
||||||
|
if [[ "$IS_REMOTE_SSH" -eq 0 ]]; then
|
||||||
|
run_root networkctl reconfigure --all >/dev/null 2>&1 || true
|
||||||
|
else
|
||||||
|
log_warning "Skipping networkctl reconfigure --all in SSH session."
|
||||||
|
fi
|
||||||
|
elif [[ "$IS_REMOTE_SSH" -eq 0 ]]; then
|
||||||
run_root systemctl restart systemd-networkd >/dev/null 2>&1 || run_root systemctl try-restart systemd-networkd >/dev/null 2>&1 || true
|
run_root systemctl restart systemd-networkd >/dev/null 2>&1 || run_root systemctl try-restart systemd-networkd >/dev/null 2>&1 || true
|
||||||
|
else
|
||||||
|
log_warning "Skipping systemd-networkd restart in SSH session."
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
@@ -567,7 +670,8 @@ patch_ifupdown_file() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
apply_ifupdown() {
|
apply_ifupdown() {
|
||||||
if [[ ! -f /etc/network/interfaces ]] && [[ ! -d /etc/network/interfaces.d ]]; then
|
if ! has_ifupdown; then
|
||||||
|
log_info "Skipping ifupdown override: ifupdown is not present."
|
||||||
return 2
|
return 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -611,20 +715,39 @@ prompt_immutable_lock() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
local answer
|
local answer
|
||||||
answer="$(read_tty_input "${YELLOW}${EMOJI_LOCK} Make /etc/resolv.conf immutable with chattr +i? [y/N]: ${NC}")" || return 1
|
if ! answer="$(read_tty_input_timeout "${YELLOW}${EMOJI_LOCK} Make /etc/resolv.conf immutable with chattr +i? [y/N] (auto No in ${IMMUTABLE_PROMPT_TIMEOUT_SEC}s): ${NC}" "$IMMUTABLE_PROMPT_TIMEOUT_SEC")"; then
|
||||||
|
local rc=$?
|
||||||
|
if [[ "$rc" -gt 128 ]]; then
|
||||||
|
log_warning "No response received for immutable lock prompt; defaulting to No."
|
||||||
|
IMMUTABLE_LOCK_REQUESTED=0
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
case "$answer" in
|
case "$answer" in
|
||||||
y|Y|yes|YES)
|
y|Y|yes|YES)
|
||||||
|
IMMUTABLE_LOCK_REQUESTED=1
|
||||||
|
log_info "Immutable lock requested. It will be applied after DNS updates."
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
IMMUTABLE_LOCK_REQUESTED=0
|
||||||
|
log_info "Immutable lock skipped."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
apply_immutable_lock_if_requested() {
|
||||||
|
if [[ "$IMMUTABLE_LOCK_REQUESTED" -ne 1 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
if run_root chattr +i /etc/resolv.conf; then
|
if run_root chattr +i /etc/resolv.conf; then
|
||||||
log_success "Immutable lock applied to /etc/resolv.conf."
|
log_success "Immutable lock applied to /etc/resolv.conf."
|
||||||
log_warning "To edit DNS later, run: sudo chattr -i /etc/resolv.conf"
|
log_warning "To edit DNS later, run: sudo chattr -i /etc/resolv.conf"
|
||||||
else
|
else
|
||||||
log_warning "Failed to apply immutable lock."
|
log_warning "Failed to apply immutable lock."
|
||||||
fi
|
fi
|
||||||
;;
|
|
||||||
*)
|
|
||||||
log_info "Immutable lock skipped."
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
}
|
||||||
|
|
||||||
print_summary() {
|
print_summary() {
|
||||||
@@ -669,7 +792,9 @@ main() {
|
|||||||
|
|
||||||
require_tty
|
require_tty
|
||||||
ensure_root_context "$@"
|
ensure_root_context "$@"
|
||||||
|
detect_runtime_context
|
||||||
prompt_dns_servers
|
prompt_dns_servers
|
||||||
|
prompt_immutable_lock || log_warning "Immutable lock prompt failed; defaulting to unlocked."
|
||||||
run_connectivity_checks
|
run_connectivity_checks
|
||||||
detect_managers
|
detect_managers
|
||||||
|
|
||||||
@@ -681,7 +806,7 @@ main() {
|
|||||||
run_action "Apply ifupdown override" apply_ifupdown
|
run_action "Apply ifupdown override" apply_ifupdown
|
||||||
run_action "Write /etc/resolv.conf directly" apply_static_resolv_conf
|
run_action "Write /etc/resolv.conf directly" apply_static_resolv_conf
|
||||||
|
|
||||||
prompt_immutable_lock || log_warning "Immutable lock prompt failed; continuing."
|
run_action "Apply immutable /etc/resolv.conf lock (if requested)" apply_immutable_lock_if_requested
|
||||||
print_summary
|
print_summary
|
||||||
|
|
||||||
echo
|
echo
|
||||||
|
|||||||
Reference in New Issue
Block a user