diff --git a/ip6t-firewall-server b/ip6t-firewall-server index b10c3d8..4855387 100755 --- a/ip6t-firewall-server +++ b/ip6t-firewall-server @@ -1,14 +1,4 @@ #!/usr/bin/env bash -### BEGIN INIT INFO -# Provides: ip6t-firewall -# Required-Start: $local_fs $remote_fs $syslog $network $time -# Required-Stop: $local_fs $remote_fs $syslog $network -# Should-Start: -# Should-Stop: -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: IPv6 Firewall -### END INIT INFO # ------------- @@ -28,17 +18,8 @@ conf_main=${ipt_conf_dir}/main_ipv6.conf conf_post_declarations=${ipt_conf_dir}/post_decalrations.conf conf_ban_ipv6_list="${ipt_conf_dir}/ban_ipv6.list" -ip6t=$(which ip6tables) - -if [[ -z "$fail2ban_client" ]]; then - fail2ban_client="$(which fail2ban-client)" -fi - - -# ------------- -# - Some checks and preloads.. -# ------------- +ip6t="$(command -v ip6tables 2>/dev/null)" if [[ -z "$ip6t" ]] ; then echo "" @@ -49,6 +30,17 @@ if [[ -z "$ip6t" ]] ; then exit 1 fi + +# ------------- +# - Load Default Settings and Functions +# ------------- + +if [[ ! -f "$conf_default_settings" ]]; then + fatal "Missing configuration for default_settings - file '$conf_default_settings'" +else + source $conf_default_settings +fi + if [[ ! -f "$inc_functions_file" ]] ; then echo "" echo -e "\tMissing include file '$inc_functions_file'" @@ -61,6 +53,37 @@ else fi +# ------------- +# - Some checks and preloads.. +# ------------- + +# Check IPv6 presence +if detect_ipv6; then + IPV6_ACTIVE=1 + if has_ipv6_addr; then + info "IPv6 enabled (global address present)." + else + warn "IPv6 enabled but no global address configured yet." + fi +else + IPV6_ACTIVE=0 + warn "IPv6 disabled via sysctl." +fi + +# Fail if ip6tables points to legacy (helps avoid surprises on dual-stack hosts / fail2ban) +if command -v ip6tables >/dev/null 2>&1; then + if ! ip6tables --version 2>/dev/null | grep -q "nf_tables"; then + echo "" + echo "ERROR: ip6tables is NOT using nf_tables backend (ip6tables-nft)." + echo "Fix (on the host, as root):" + echo " update-alternatives --set ip6tables /usr/sbin/ip6tables-nft" + echo "" + echo "Current: $(ip6tables --version 2>/dev/null || echo 'unknown')" + exit 1 + fi +fi + + # - Check if running inside a container # - host_is_vm=false @@ -88,22 +111,34 @@ else fi -if [[ ! -f "$load_modules_file" ]] ; then - warn "No modules for loading configured. Missing file '$load_modules_file'!" +# ------------- +# --- Ensure required modules for this script (best effort; host-side in containers) +# ------------- + + +echo +echononl "\tEnsure required modules are loaded.." +if is_container ; then + echo_skipped else + echo_done +fi - if ! $host_is_vm ; then +ensure_mod nf_conntrack +ensure_mod nf_nat +ensure_mod nf_conntrack_ftp +ensure_mod nf_nat_ftp +ensure_mod xt_recent +ensure_mod xt_hashlimit +ensure_mod xt_connlimit +ensure_mod xt_owner +ensure_mod xt_helper +ensure_mod br_netfilter - while read -r module ; do - if ! lsmod | grep -q -E "^$module\s+" ; then - /sbin/modprobe $module > /dev/null 2>&1 - if [[ "$?" != "0" ]]; then - warn "Loading module '$module' failed!" - fi - fi - done < <(sed -ne 's/^[[:space:]]*\([^#].*\)[[:space:]]*/\1/p' $load_modules_file) - fi +# Disable automatic conntrack helper assignment (keep explicit CT --helper rules) +if ! $host_is_vm ; then + sysctl -w net.netfilter.nf_conntrack_helper=0 >/dev/null 2>&1 || true fi if [[ ! -f "$conf_logging" ]]; then @@ -112,12 +147,6 @@ else source $conf_logging fi -if [[ ! -f "$conf_default_settings" ]]; then - fatal "Missing configuration for default_settings - file '$conf_default_settings'" -else - source $conf_default_settings -fi - if [[ ! -f "$conf_interfaces" ]]; then fatal "Missing interface configurations - file '$conf_interfaces'" else @@ -198,14 +227,25 @@ fi # if ! $host_is_vm # ------------- Stop Fail2Ban if installed ------------- # -if [ -x "$fail2ban_client" ]; then - echononl "\tStopping fail2ban.." - $fail2ban_client stop > /dev/null 2>&1 - if [ "$?" = "0" ];then - echo_done +echo +echononl "\tCheck presence and configuration of Fail2ban .." +echo_done +if ! has_fail2ban ; then + warn "Fail2ban is not installed.." +elif ! fail2ban_running ; then + warn "Fail2ban is installed but not running.." +else + CURRENT_BANACTION=$(grep -E '^\s*banaction\s*=' "$FAIL2BAN_CONFIG_FILE" | head -1 | tr -d ' ' | cut -d'=' -f2) + if [[ -n ${CURRENT_BANACTION} ]] ; then + if [ "$CURRENT_BANACTION" = "nftables" ]; then + info "Fail2ban is running, banaction is et to nftables." + else + warn "Change banaction from ${CURRENT_BANACTION} to \033[1mbanaction=nftables\033[m" + fi else - echo_warning + warn "banaction seems not to be configured. Take care that \033[1mbanaction=nftables\033[m" fi + FAIL2BAN_WAS_RUNNING=true fi # # ------------- Ende: Stop Fail2Ban if installed ------------- @@ -708,14 +748,12 @@ echo_done # --- echononl "\tDrop all ICMP traffic.." +echo_skipped + if [[ -n "$drop_icmp" ]] && $drop_icmp ; then - if $log_rejected || $log_all ; then - $ip6t -t mangle -A PREROUTING -p icmpv6 --icmpv6-type echo-request -j $LOG_TARGET $tag_log_prefix "$log_prefix Drop all ICMP traffic: " - fi - $ip6t -t mangle -A PREROUTING -p icmpv6 --icmpv6-type echo-request -j DROP - echo_done -else - echo_skipped + + warn " No ICMPv6 packets were dropped - they are essential." + fi @@ -858,6 +896,28 @@ fi echo_done +echononl "\tICMPv6 - mandatory for IPv6 to work correctly!" + +# ICMPv6 essentials (numbers to be compatible with ip6tables-nft) +# 1 = destination-unreachable +# 2 = packet-too-big +# 3 = time-exceeded +# 4 = parameter-problem +# 128= echo-request +# 129= echo-reply +# 133= router-solicitation +# 134= router-advertisement +# 135= neighbor-solicitation +# 136= neighbor-advertisement +for t in 1 2 3 4 128 129 133 134 135 136; do + $ip6t -A INPUT -p ipv6-icmp --icmpv6-type $t -j ACCEPT + $ip6t -A OUTPUT -p ipv6-icmp --icmpv6-type $t -j ACCEPT + if $kernel_forward_between_interfaces ; then + $ip6t -A FORWARD -p ipv6-icmp --icmpv6-type "$t" -j ACCEPT + fi +done + +echo_done # --- # - Protection against syn-flooding @@ -2836,20 +2896,31 @@ echo_done # ------------- -# ------------- Start Fail2Ban if installed +# ------------- Reload Fail2Ban if installed # ------------- -if [ -x "$fail2ban_client" ]; then +if ${FAIL2BAN_WAS_RUNNING}; then echo - echononl "\tStarting fail2ban.." - $fail2ban_client start > /dev/null 2>&1 - if [ "$?" = "0" ];then + echononl "\tReloading fail2ban.." + $fail2ban_client reload > /dev/null 2>&1 + if [ "$?" = "0" ]; then echo_done else - echo_failed + # Fallback: reload + restart jails if needed + $fail2ban_client reload --restart > /dev/null 2>&1 + if [ "$?" = "0" ]; then + echo_done + else + echo_skipped + warn "Fail2ban reload failed. Leaving fail2ban unchanged. Check: fail2ban-client -d and /var/log/fail2ban.log" + fi fi +else + # fail2ban not running before; do not start it here + : fi + echo exit 0