Make IPv4 firewall nftables ready.

This commit is contained in:
2026-01-14 17:46:20 +01:00
parent fd2d792d88
commit cea43cd7fa
3 changed files with 598 additions and 301 deletions

View File

@@ -13,7 +13,6 @@ default_per_IP_connection_limit=111
standard_checkmk_port=6556
standard_cpan_wait_port=1404
standard_cups_port=$standard_ipp_port
standard_dns_port=53
standard_ftp_port=21
standard_ftp_data_port=20
@@ -23,6 +22,7 @@ standard_http_port=80
standard_https_port=443
standard_ident_port=113
standard_ipp_port=631
standard_cups_port=$standard_ipp_port
standard_irc_port=6667
standard_jabber_port=5222
standard_ldap_port=389

View File

@@ -1,5 +1,13 @@
#!/usr/bin/env bash
# - Set firewall command (either iptables or ip6tables)
#
if [[ -x "${ip6t}" ]] ; then
fw_command="${ip6t}"
elif [[ -x "${ipt}" ]] ; then
fw_command="${ipt}"
fi
# -------------
# --- Some functions
# -------------
@@ -82,3 +90,167 @@ trim() {
echo -n "$var"
}
is_container() {
command -v systemd-detect-virt >/dev/null 2>&1 && systemd-detect-virt --container >/dev/null 2>&1
}
# -------------
# - IPv6 handling
# -------------
ENABLE_IPV6="auto" # auto | yes | no
IPV6_ACTIVE=0
ipv6_sysctl_enabled() {
sysctl -n net.ipv6.conf.all.disable_ipv6 2>/dev/null | grep -qx 0
}
has_ipv6_addr() {
ip -6 addr show scope global 2>/dev/null | grep -q "inet6"
}
detect_ipv6() {
case "$ENABLE_IPV6" in
yes) return 0 ;;
no) return 1 ;;
auto) ipv6_sysctl_enabled ;;
*) return 1 ;;
esac
}
# -------------
# - Fail2ban
# -------------
FAIL2BAN_CONFIG_FILE="/etc/fail2ban/jail.local"
FAIL2BAN_WAS_RUNNING=false
fail2ban_client="$(command -v fail2ban-client 2>/dev/null)"
has_fail2ban() {
command -v fail2ban-client >/dev/null 2>&1
}
fail2ban_running() {
systemctl is-active --quiet fail2ban >/dev/null 2>&1
}
# -------------
# - Debian 12/13 compatibility helpers (best effort)
# -------------
ensure_mod() {
# ---
# Load a kernel module if possible (no hard failure).
# NOTE: In containers module loading is not possible; modules must be loaded on the host.
# ---
local m="$1"
# Already loaded?
if lsmod 2>/dev/null | awk '{print $1}' | grep -qx "$m" ; then
return 0
fi
# Skip in containers/guests without module loading capability
#
is_container && return 0
# Best effort modprobe
/sbin/modprobe "$m" >/dev/null 2>&1 || warn "Loading module '$m' failed (ok if not needed on this host)."
}
# --- Feature detection helpers (Debian 12/13 + containers)
module_loaded() {
lsmod 2>/dev/null | awk '{print $1}' | grep -qx "$1"
}
can_use_recent() {
# xt_recent is the kernel module behind "-m recent"
# In containers lsmod may be restricted; also accept presence of /proc/net/xt_recent.
module_loaded xt_recent && return 0
[ -d /proc/net/xt_recent ] && return 0
# As a last resort, ask iptables to parse the match (works if userspace has it)
"$ipt" -m recent -h >/dev/null 2>&1 && return 0
return 1
}
can_use_hashlimit() {
# xt_hashlimit is the kernel module behind "-m hashlimit"
module_loaded xt_hashlimit && return 0
[ -d /proc/net/xt_hashlimit ] && return 0
"${fw_command}" -m hashlimit -h >/dev/null 2>&1 && return 0
return 1
}
can_use_connlimit() {
# xt_connlimit is the kernel module behind "-m connlimit"
module_loaded xt_connlimit && return 0
"${fw_command}" -m connlimit -h >/dev/null 2>&1 && return 0
return 1
}
can_use_owner() {
# xt_owner is the kernel module behind "-m owner"
module_loaded xt_owner && return 0
"${fw_command}" -m owner -h >/dev/null 2>&1 && return 0
return 1
}
can_use_ct_target() {
# Check if iptables CT target exists (iptables-nft should support it when kernel has nf_tables CT support)
"${fw_command}" -t raw -j CT -h >/dev/null 2>&1 && return 0
return 1
}
can_use_helper_match() {
# Check if helper match exists
"${fw_command}" -m helper -h >/dev/null 2>&1 && return 0
return 1
}
can_use_nft() {
command -v nft >/dev/null 2>&1 && return 0
return 1
}
setup_ftp_conntrack_helper_output() {
# Prefer explicit helper assignment (safe with nf_conntrack_helper=0)
if can_use_ct_target ; then
"${fw_command}" -A OUTPUT -t raw -p tcp --dport "$standard_ftp_port" -j CT --helper ftp
return 0
fi
# nft fallback (nft-native helper assignment); keeps us "nft-ready"
if can_use_nft ; then
# Best-effort; may fail in containers without CAP_NET_ADMIN
nft add table ip fwhelper >/dev/null 2>&1 || true
nft add chain ip fwhelper output '{ type filter hook output priority raw; policy accept; }' >/dev/null 2>&1 || true
nft add ct helper ip fwhelper ftp '{ type "ftp" protocol tcp; }' >/dev/null 2>&1 || true
nft add rule ip fwhelper output tcp dport "$standard_ftp_port" ct helper set "ftp" >/dev/null 2>&1 && return 0
fi
warn "No CT helper assignment available (iptables CT target and nft fallback both unavailable). FTP active/passive may fail; FTPS workaround relies on recent/port rules."
return 1
}
setup_ftp_conntrack_helper_prerouting() {
# Prefer explicit helper assignment (safe with nf_conntrack_helper=0)
if can_use_ct_target ; then
"$ipt" -A PREROUTING -t raw -p tcp --dport "$standard_ftp_port" -j CT --helper ftp
return 0
fi
# nft fallback (nft-native helper assignment); keeps us "nft-ready"
if can_use_nft ; then
nft add table ip fwhelper >/dev/null 2>&1 || true
nft add chain ip fwhelper prerouting '{ type filter hook prerouting priority raw; policy accept; }' >/dev/null 2>&1 || true
nft add ct helper ip fwhelper ftp '{ type "ftp" protocol tcp; }' >/dev/null 2>&1 || true
nft add rule ip fwhelper prerouting tcp dport "$standard_ftp_port" ct helper set "ftp" >/dev/null 2>&1 && return 0
fi
warn "No CT helper assignment available (iptables CT target and nft fallback both unavailable). FTP server traffic may fail; consider enabling passive port ranges."
return 1
}

File diff suppressed because it is too large Load Diff