#!/bin/bash # *** [ Ansible managed file: DO NOT EDIT DIRECTLY ] *** # # fw-apply # # Generic firewall loader (Ansible-independent): # - Reads config from /etc/nftables.conf.d/nft-fw.conf (optional) # - Renders /etc/nftables.conf.in using envsubst # - Validates with: nft -c -f # - Applies by deleting ONLY table inet fw_static and loading the new definition # (keeps fail2ban tables intact) # # Usage: # fw-apply -> validate + apply # fw-apply --check -> validate only (no changes) # set -euo pipefail ############################ # Argument handling ############################ DO_APPLY=true if [[ "${1:-}" == "--check" ]]; then DO_APPLY=false elif [[ "${1:-}" != "" ]]; then echo "Usage: $0 [--check]" >&2 exit 2 fi ############################ # Config location ############################ CFG_DIR="/etc/nftables.conf.d" CFG_FILE="$CFG_DIR/nft-fw.conf" ############################ # Defaults (used if config missing/partial) ############################ EXT_IF="eth0" PRIV_IF="enp7s0" PRIV_NET="172.20.0.0/21" ALLOW_SSH_PUBLIC_IN="true" ALLOW_APT_PUBLIC_OUT="true" ALLOW_ICMP4_PUBLIC="true" ALLOW_ICMP6_PUBLIC="true" FORCE_ICMP6_ESSENTIAL="true" ############################ # Load config if present ############################ if [[ -r "$CFG_FILE" ]]; then # shellcheck disable=SC1090 source "$CFG_FILE" fi ############################ # Helpers ############################ normalize_bool() { # Robust against CRLF and leading/trailing whitespace. local v v="$(printf '%s' "${1:-}" | tr -d '\r' | xargs)" case "${v,,}" in true|yes|1) echo true ;; false|no|0|"") echo false ;; *) echo false ;; esac } ALLOW_SSH_PUBLIC_IN="$(normalize_bool "$ALLOW_SSH_PUBLIC_IN")" ALLOW_APT_PUBLIC_OUT="$(normalize_bool "$ALLOW_APT_PUBLIC_OUT")" ALLOW_ICMP4_PUBLIC="$(normalize_bool "$ALLOW_ICMP4_PUBLIC")" ALLOW_ICMP6_PUBLIC="$(normalize_bool "$ALLOW_ICMP6_PUBLIC")" FORCE_ICMP6_ESSENTIAL="$(normalize_bool "$FORCE_ICMP6_ESSENTIAL")" ############################ # Determine external usage ############################ # EXT_IF is considered "in use" if any externally-relevant feature is enabled. NEED_EXT=false if [[ "$ALLOW_SSH_PUBLIC_IN" == "true" || "$ALLOW_APT_PUBLIC_OUT" == "true" ]]; then NEED_EXT=true fi ############################ # Build envsubst blocks (must contain REAL newlines) ############################ SSH_PUBLIC_IN_RULE="" APT_PUBLIC_OUT_RULES="" ICMP_PUBLIC_IN_RULES="" ICMP_PUBLIC_OUT_RULES="" # SSH IN (public) if [[ "$ALLOW_SSH_PUBLIC_IN" == "true" ]]; then SSH_PUBLIC_IN_RULE="$(cat < "$TMP" # Replace only our table (keep fail2ban intact) nft delete table inet fw_static 2>/dev/null || true # Validate syntax nft -c -f "$TMP" if [[ "$DO_APPLY" == "true" ]]; then nft -f "$TMP" install -m 600 "$TMP" /etc/nftables.conf else echo "fw-apply: check mode" [[ -r "$CFG_FILE" ]] && echo "- config loaded: $CFG_FILE" || echo "- config loaded: defaults only" echo "- rendered nftables ruleset: OK" echo "- syntax check (nft -c): OK" echo "- no changes applied" fi