mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-10 20:27:02 +01:00
Two levels of pure taxonomy carrying no information, and a 2-directory
cap leaves no room for them. Categories now sit directly under
linux_configuration/: features, fixes, utils, misc, fresh-install,
installers, diagnostics, gaming, boot_recovery, periodic_background, lib,
meta, tests. A script's own lib/ and tests/ are exempt from the cap, so
those stay put.
Depth violations 248 -> 139; roughly 40 of the remainder are inside
digital_wellbeing and hosts, deferred until the guard-lib repoint.
The moves are the easy half. What breaks is every path that counted
levels, and three classes of it had to be found by resolving paths rather
than reading diffs:
- 52 relative `source` lines for lib/common.sh and lib/android.sh. The
correct prefix differs per file: 40 were ../../ and 12 were ../../../,
so a blanket replace would have fixed one set and broken the other.
- REPO_ROOT in 7 fixes/lib/tests harnesses and setup_syncyomi_guard.sh,
each walking up four levels from a directory now two levels shallower.
This caused a real regression -- the fixes suite went red with
"log_warn: command not found" -- caught by running it and comparing
against the pre-move baseline worktree.
- conftest.py's sys.path entries, which took the pytest gate down with
14 collection errors, and the `# shellcheck source=` directives, which
took shellcheck down with SC1091.
16 symlinks in $HOME broke, including the entire i3blocks bar. All
repointed, and cpu_monitor/memory/disk/time/volume were run to confirm
they emit real output rather than merely resolving.
Verified: 1798 tests pass at 100% coverage, 8 of 9 lib/tests suites pass
(the ninth needs the coverage jail, identically at baseline), pre-commit
is clean, and the two untracked secret configs are still ignored after
their gitignore paths changed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PJrqKERAo5QUeEHWS5Asgp
189 lines
7.2 KiB
Bash
Executable File
189 lines
7.2 KiB
Bash
Executable File
#!/bin/bash
|
|
# Static IP, DHCP server config and the status report.
|
|
#
|
|
# Sourced by setup_dns_blocker.sh; split out to keep it under the 250-line cap.
|
|
# Sourced rather than run, so it inherits the caller's strict mode.
|
|
|
|
configure_static_ip() {
|
|
has_cmd nmcli || die "nmcli (NetworkManager) not found; cannot pin a static IP automatically."
|
|
local con
|
|
con="$(nm_connection)"
|
|
[[ -n $con ]] || die "No active NetworkManager connection on ${LAN_IFACE}."
|
|
log_info "Pinning ${LAN_IFACE} to static ${LAN_IP}/24 (gw ${GATEWAY}) on '${con}'..."
|
|
nmcli con mod "$con" \
|
|
ipv4.method manual \
|
|
ipv4.addresses "${LAN_IP}/24" \
|
|
ipv4.gateway "$GATEWAY" \
|
|
ipv4.dns "$GATEWAY"
|
|
nmcli con up "$con" >/dev/null
|
|
# Safety self-check: if the static config broke connectivity, auto-revert to
|
|
# DHCP-client mode immediately so the machine never ends up stranded.
|
|
if ping -c1 -W3 "$GATEWAY" >/dev/null 2>&1; then
|
|
log_ok "Static IP applied; gateway reachable. ${LAN_IFACE} no longer needs external DHCP."
|
|
else
|
|
log_error "Gateway unreachable after static IP change -- auto-reverting to DHCP."
|
|
revert_nic_to_dhcp "$con"
|
|
die "Static IP self-check failed; reverted to DHCP. DHCP mode aborted (no changes kept)."
|
|
fi
|
|
}
|
|
|
|
write_dhcp_conf() {
|
|
local mac net_prefix
|
|
mac="$(cat "/sys/class/net/${LAN_IFACE}/address")"
|
|
net_prefix="${LAN_IP%.*}"
|
|
log_info "Writing ${DHCP_CONF} (range ${net_prefix}.${DHCP_START_HOST}-${net_prefix}.${DHCP_END_HOST}, DNS ${LAN_IP})."
|
|
cat >"$DHCP_CONF" <<EOF
|
|
# Managed by setup_dns_blocker.sh -- this PC is the LAN DHCP server.
|
|
# Only serve leases once the router's own DHCP is disabled (two servers clash).
|
|
dhcp-authoritative
|
|
dhcp-range=${net_prefix}.${DHCP_START_HOST},${net_prefix}.${DHCP_END_HOST},${DHCP_LEASE}
|
|
dhcp-option=option:router,${GATEWAY}
|
|
dhcp-option=option:dns-server,${LAN_IP}
|
|
# Reserve this PC's static address against its own MAC.
|
|
dhcp-host=${mac},${LAN_IP}
|
|
# Log every DHCP transaction (low volume; satisfies "log failures").
|
|
log-dhcp
|
|
EOF
|
|
}
|
|
|
|
cmd_dhcp() {
|
|
detect_lan
|
|
is_service_active dnsmasq ||
|
|
die "Run 'setup' first -- dnsmasq must be configured before enabling DHCP mode."
|
|
echo
|
|
log_warn "DHCP takeover: this PC (${LAN_IP}) will become the LAN's DHCP server."
|
|
log_warn "Disable the router's DHCP FIRST (untick 'wlacz serwer DHCP' -> Zapisz),"
|
|
log_warn "otherwise two DHCP servers will fight on the LAN."
|
|
if ! ask_yes_no "Have you already disabled the router's DHCP server?"; then
|
|
log_warn "Not activating -- two DHCP servers on one LAN conflict."
|
|
log_warn "Disable the router's DHCP ('wlacz serwer DHCP' -> Zapisz), then re-run: sudo ${SELF} dhcp"
|
|
return 0
|
|
fi
|
|
configure_static_ip
|
|
write_dhcp_conf
|
|
dnsmasq --test >/dev/null 2>&1 || die "dnsmasq config invalid after adding DHCP -- not restarting."
|
|
systemctl restart dnsmasq
|
|
log_ok "This PC is now the LAN DHCP server; new leases advertise ${LAN_IP} as DNS."
|
|
log_info "Reconnect a device's WiFi to pick up the new lease, then browse to a blocked site to confirm."
|
|
cat <<EOF
|
|
|
|
---- IF ANYTHING GOES WRONG (one command, cannot lock you out) ------------
|
|
sudo ${SELF} dhcp-off
|
|
-> stops serving DHCP, KEEPS this PC online on ${LAN_IP}.
|
|
Then re-tick the router's DHCP ('wlacz serwer DHCP' -> Zapisz) so other
|
|
devices get addresses again. This PC stays reachable throughout.
|
|
--------------------------------------------------------------------------
|
|
EOF
|
|
}
|
|
|
|
# Roll back DHCP mode: stop serving leases. KEEPS this PC on its static IP so
|
|
# running rollback can never strand the machine (the router reserves ${LAN_IP}
|
|
# anyway). Re-enable the router's DHCP afterwards for the other devices.
|
|
cmd_dhcp_off() {
|
|
detect_lan
|
|
if [[ -f $DHCP_CONF ]]; then
|
|
rm -f "$DHCP_CONF"
|
|
log_ok "Removed ${DHCP_CONF} (PC no longer serves DHCP)."
|
|
else
|
|
log_info "No DHCP config present; nothing to remove."
|
|
fi
|
|
is_service_active dnsmasq && systemctl restart dnsmasq
|
|
log_ok "DHCP serving stopped. This PC keeps its static IP (${LAN_IP}); still online."
|
|
log_warn "Now re-enable the router's DHCP ('wlacz serwer DHCP' -> Zapisz) so other devices get addresses."
|
|
log_info "Optional: to also put THIS PC back on router DHCP (after re-enabling it above), run:"
|
|
log_info " nmcli con mod '$(nm_connection)' ipv4.method auto ipv4.addresses '' ipv4.gateway '' ipv4.dns '' && nmcli con up '$(nm_connection)'"
|
|
}
|
|
|
|
# ---- Status ----------------------------------------------------------------
|
|
status_line() {
|
|
# $1 ok/bad flag ("0" ok), $2 message
|
|
if [[ $1 == "0" ]]; then log_ok "$2"; else log_warn "$2"; fi
|
|
}
|
|
|
|
cmd_status() {
|
|
detect_lan
|
|
echo "=== LAN DNS blocker status ==="
|
|
|
|
if is_service_active dnsmasq; then
|
|
status_line 0 "dnsmasq: active"
|
|
else
|
|
status_line 1 "dnsmasq: NOT active"
|
|
fi
|
|
if is_service_enabled dnsmasq; then
|
|
status_line 0 "dnsmasq: enabled at boot"
|
|
else
|
|
status_line 1 "dnsmasq: NOT enabled"
|
|
fi
|
|
if [[ -f $DNSMASQ_DROPIN ]]; then
|
|
status_line 0 "Restart=always drop-in present"
|
|
else
|
|
status_line 1 "Restart drop-in missing"
|
|
fi
|
|
if [[ -f $FEED ]]; then
|
|
status_line 0 "blocklist feed: $(wc -l <"$FEED") lines, updated $(date -r "$FEED" '+%Y-%m-%d %H:%M')"
|
|
else
|
|
status_line 1 "blocklist feed missing: ${FEED}"
|
|
fi
|
|
|
|
if ss -tulnp 2>/dev/null | grep -qE "${LAN_IP}:53|:53 "; then
|
|
status_line 0 "listening on ${LAN_IP}:53"
|
|
else
|
|
status_line 1 "not listening on ${LAN_IP}:53"
|
|
fi
|
|
|
|
local fw_input
|
|
fw_input="$(nft list chain inet filter input 2>/dev/null || true)"
|
|
if [[ $fw_input == *"policy drop"* ]]; then
|
|
if [[ $fw_input == *"dport 53"* ]]; then
|
|
status_line 0 "firewall: DNS/DHCP open for LAN"
|
|
else
|
|
status_line 1 "firewall loaded but DNS/DHCP NOT open -- run: sudo ${WG_SCRIPT} allow-dns"
|
|
fi
|
|
elif [[ $EUID -ne 0 ]]; then
|
|
log_info "firewall: run 'sudo $0 status' to inspect nftables (needs root)"
|
|
else
|
|
status_line 0 "firewall: no default-drop ruleset loaded (DNS/DHCP not filtered)"
|
|
fi
|
|
|
|
if systemctl is-active dns-blocklist-refresh.timer &>/dev/null; then
|
|
status_line 0 "refresh timer: active (next $(systemctl show -p NextElapseUSecRealtime --value dns-blocklist-refresh.timer 2>/dev/null))"
|
|
else
|
|
status_line 1 "refresh timer: NOT active"
|
|
fi
|
|
if [[ -f $DHCP_CONF ]]; then
|
|
if ss -ulnp 2>/dev/null | grep -q ':67 '; then
|
|
status_line 0 "DHCP mode: ON (serving leases; PC is the LAN DHCP server)"
|
|
else
|
|
status_line 1 "DHCP mode: config present but not serving -- restart dnsmasq"
|
|
fi
|
|
else
|
|
status_line 0 "DHCP mode: off (using router DHCP / manual per-device DNS)"
|
|
fi
|
|
|
|
echo
|
|
echo "=== Live resolution test (via ${LAN_IP}) ==="
|
|
if has_cmd dig; then
|
|
local blocked passthru
|
|
blocked="$(dig +short +time=2 +tries=1 @"${LAN_IP}" youtube.com 2>/dev/null | head -1)"
|
|
passthru="$(dig +short +time=2 +tries=1 @"${LAN_IP}" example.com 2>/dev/null | head -1)"
|
|
if [[ $blocked == "0.0.0.0" ]]; then
|
|
status_line 0 "youtube.com -> ${blocked} (BLOCKED, correct)"
|
|
else
|
|
status_line 1 "youtube.com -> ${blocked:-<no answer>} (expected 0.0.0.0)"
|
|
fi
|
|
if [[ -n $passthru && $passthru != "0.0.0.0" ]]; then
|
|
status_line 0 "example.com -> ${passthru} (passthrough, correct)"
|
|
else
|
|
status_line 1 "example.com -> ${passthru:-<no answer>} (expected a real IP)"
|
|
fi
|
|
else
|
|
log_warn "install 'dig' (bind) to run the live resolution test."
|
|
fi
|
|
|
|
if [[ -s $LOG_FILE ]]; then
|
|
echo
|
|
echo "=== Recent dnsmasq log (${LOG_FILE}) ==="
|
|
tail -5 "$LOG_FILE"
|
|
fi
|
|
}
|