156 lines
3.7 KiB
Bash
Executable File
156 lines
3.7 KiB
Bash
Executable File
#!/usr//bin/env bash
|
|
set -euo pipefail
|
|
|
|
########################
|
|
# Args
|
|
########################
|
|
DO_APPLY=true
|
|
if [[ "${1:-}" == "--check" ]]; then
|
|
DO_APPLY=false
|
|
elif [[ "${1:-}" != "" ]]; then
|
|
echo "Usage: $0 [--check]" >&2
|
|
exit 2
|
|
fi
|
|
|
|
########################
|
|
# Defaults
|
|
########################
|
|
EXT_IF="eth0"
|
|
PRIV_IF="enp7s0"
|
|
PRIV_NET="172.20.0.0/21"
|
|
|
|
ALLOW_SSH_PUBLIC_IN=false
|
|
ALLOW_APT_PUBLIC_OUT=false
|
|
|
|
ALLOW_ICMP4_PUBLIC=true
|
|
ALLOW_ICMP6_PUBLIC=true
|
|
|
|
########################
|
|
# Optional config file
|
|
########################
|
|
CFG="/etc/default/nft-fw"
|
|
if [[ -r "$CFG" ]]; then
|
|
# shellcheck disable=SC1090
|
|
source "$CFG"
|
|
fi
|
|
|
|
########################
|
|
# Normalize booleans
|
|
########################
|
|
normalize_bool() {
|
|
# trim whitespace + remove CR (Windows line endings)
|
|
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_ICMP4_PUBLIC="$(normalize_bool "${ALLOW_ICMP4_PUBLIC:-true}")"
|
|
ALLOW_ICMP6_PUBLIC="$(normalize_bool "${ALLOW_ICMP6_PUBLIC:-true}")"
|
|
ALLOW_SSH_PUBLIC_IN="$(normalize_bool "${ALLOW_SSH_PUBLIC_IN:-false}")"
|
|
ALLOW_APT_PUBLIC_OUT="$(normalize_bool "${ALLOW_APT_PUBLIC_OUT:-false}")"
|
|
|
|
|
|
NEED_EXT=false
|
|
if [[ "$ALLOW_SSH_PUBLIC_IN" == "true" || "$ALLOW_APT_PUBLIC_OUT" == "true" || "$ALLOW_ICMP4_PUBLIC" == "true" || "$ALLOW_ICMP6_PUBLIC" == "true" ]]; then
|
|
NEED_EXT=true
|
|
fi
|
|
|
|
EFFECTIVE_ALLOW_ICMP6_PUBLIC="$ALLOW_ICMP6_PUBLIC"
|
|
if [[ "$NEED_EXT" == "true" ]]; then
|
|
EFFECTIVE_ALLOW_ICMP6_PUBLIC=true
|
|
fi
|
|
|
|
########################
|
|
# Build optional rule blocks
|
|
########################
|
|
ICMP_PUBLIC_IN_RULES=""
|
|
ICMP_PUBLIC_OUT_RULES=""
|
|
SSH_PUBLIC_IN_RULE=""
|
|
APT_PUBLIC_OUT_RULES=""
|
|
|
|
|
|
# ICMPv4 optional
|
|
if [[ "$ALLOW_ICMP4_PUBLIC" == "true" ]]; then
|
|
ICMP_PUBLIC_IN_RULES="$(cat <<EOF
|
|
iif "$EXT_IF" ip protocol icmp accept
|
|
EOF
|
|
)"
|
|
ICMP_PUBLIC_OUT_RULES="$(cat <<EOF
|
|
oif "$EXT_IF" ip protocol icmp accept
|
|
EOF
|
|
)"
|
|
fi
|
|
|
|
# ICMPv6 optional (oder erzwungen über EFFECTIVE_ALLOW_ICMP6_PUBLIC)
|
|
if [[ "$EFFECTIVE_ALLOW_ICMP6_PUBLIC" == "true" ]]; then
|
|
# Falls schon was drin ist, füge sauber eine Leerzeile/Zeilenumbruch hinzu
|
|
[[ -n "$ICMP_PUBLIC_IN_RULES" ]] && ICMP_PUBLIC_IN_RULES+=$'\n'
|
|
[[ -n "$ICMP_PUBLIC_OUT_RULES" ]] && ICMP_PUBLIC_OUT_RULES+=$'\n'
|
|
|
|
ICMP_PUBLIC_IN_RULES+=$(cat <<EOF
|
|
iif "$EXT_IF" ip6 nexthdr icmpv6 accept
|
|
EOF
|
|
)
|
|
ICMP_PUBLIC_OUT_RULES+=$(cat <<EOF
|
|
oif "$EXT_IF" ip6 nexthdr icmpv6 accept
|
|
EOF
|
|
)
|
|
fi
|
|
|
|
|
|
if [[ "$ALLOW_SSH_PUBLIC_IN" == "true" ]]; then
|
|
SSH_PUBLIC_IN_RULE="$(cat <<EOF
|
|
iif "$EXT_IF" tcp dport 22 accept
|
|
EOF
|
|
)"
|
|
fi
|
|
|
|
if [[ "$ALLOW_APT_PUBLIC_OUT" == "true" ]]; then
|
|
APT_PUBLIC_OUT_RULES="$(cat <<EOF
|
|
oif "$EXT_IF" udp dport 53 accept
|
|
oif "$EXT_IF" tcp dport 53 accept
|
|
oif "$EXT_IF" tcp dport { 80, 443 } accept
|
|
EOF
|
|
)"
|
|
fi
|
|
|
|
|
|
export EXT_IF PRIV_IF PRIV_NET
|
|
export ICMP_PUBLIC_IN_RULES ICMP_PUBLIC_OUT_RULES
|
|
export SSH_PUBLIC_IN_RULE APT_PUBLIC_OUT_RULES
|
|
|
|
########################
|
|
# Render
|
|
########################
|
|
TMP="$(mktemp -p /run nft-fw.XXXXXX)"
|
|
trap 'rm -f "$TMP"' EXIT
|
|
|
|
envsubst < /etc/nftables.conf.in > "$TMP"
|
|
|
|
########################
|
|
# Remove only our table (do NOT touch fail2ban)
|
|
########################
|
|
nft delete table inet fw_static 2>/dev/null || true
|
|
|
|
########################
|
|
# Validate + apply
|
|
########################
|
|
nft -c -f "$TMP"
|
|
|
|
if [[ "$DO_APPLY" == "true" ]]; then
|
|
nft -f "$TMP"
|
|
install -m 600 "$TMP" /etc/nftables.conf
|
|
else
|
|
echo ""
|
|
echo " fw-apply: check mode"
|
|
[[ -r "$CFG" ]] && echo " - config loaded: $CFG" || echo " - config loaded: defaults only"
|
|
echo " - rendered nftables ruleset: OK"
|
|
echo " - syntax check (nft -c): OK"
|
|
echo " - no changes applied"
|
|
echo ""
|
|
fi
|