11#! /bin/bash
22
33# Debian and Ubuntu Server Hardening Interactive Script
4- # Version: 0.81.2 | 2026-08-08
4+ # Version: 0.81.3 | 2026-08-09
55# Changelog:
6+ # - v0.81.3: Switch Fail2Ban UFW banaction to native nftables (nftables-allports) for maximum performance and modern standard compliance.
7+ # Ensure 'nftables' package is installed for minimal server compatibility.
68# - v0.81.2: Switch Fail2Ban UFW banaction to ipset for improved performance when handling large ban lists.
79# Update UFW SSH rule from allow to limit to provide native brute-force protection.
8- # - v0.81.1: Fix IPv6 connectivity issues with Secure DNS.
10+ # - v0.81.1: Fix IPv6 connectivity issues with Secure DNS.
911# Implement Docker-compatible IPv6 SLAAC sysctl configuration and enable native IPv6 networking in Docker daemon.
1012# - v0.81.0: Added optional encrypted DNS (DoT) setup using Quad9 and Cloudflare.
1113# Includes automatic installation of systemd-resolved if needed and configuration to block tracking protocols.
@@ -282,7 +284,7 @@ print_header() {
282284 printf ' %s\n' " ${CYAN} ╔═════════════════════════════════════════════════════════════════╗${NC} "
283285 printf ' %s\n' " ${CYAN} ║ ║${NC} "
284286 printf ' %s\n' " ${CYAN} ║ DEBIAN/UBUNTU SERVER SETUP AND HARDENING SCRIPT ║${NC} "
285- printf ' %s\n' " ${CYAN} ║ v0.81.2 | 2026-08-08 ║${NC} "
287+ printf ' %s\n' " ${CYAN} ║ v0.81.3 | 2026-08-09 ║${NC} "
286288 printf ' %s\n' " ${CYAN} ║ ║${NC} "
287289 printf ' %s\n' " ${CYAN} ╚═════════════════════════════════════════════════════════════════╝${NC} "
288290 printf ' \n'
@@ -4065,11 +4067,10 @@ configure_firewall() {
40654067configure_fail2ban () {
40664068 print_section " Fail2Ban Configuration"
40674069
4068- # Install Fail2Ban if not present
4069- if ! dpkg -l fail2ban | grep -q ^ii || ! dpkg -l ipset | grep -q ^ii; then
4070- print_info " Installing Fail2Ban and ipset..."
4071- if ! apt-get install -y -qq fail2ban ipset; then
4072- print_error " Failed to install Fail2Ban or ipset."
4070+ if ! dpkg -l fail2ban | grep -q ^ii || ! dpkg -l nftables | grep -q ^ii; then
4071+ print_info " Installing Fail2Ban and nftables..."
4072+ if ! apt-get install -y -qq fail2ban nftables; then
4073+ print_error " Failed to install Fail2Ban or nftables."
40734074 return 1
40744075 fi
40754076 fi
@@ -4176,6 +4177,20 @@ configure_fail2ban() {
41764177failregex = \[UFW BLOCK\] IN=.* OUT=.* SRC=<HOST>
41774178ignoreregex =
41784179EOF
4180+ )
4181+
4182+ local NFTABLES_ALLPORTS_LOCAL
4183+ NFTABLES_ALLPORTS_LOCAL=$( cat << 'EOF '
4184+ [Init]
4185+ # Ensure Fail2Ban silently drops packets
4186+ blocktype = drop
4187+ # Drop all protocols for a banned IP (older Fail2Ban versions)
4188+ nftables_match =
4189+
4190+ [Definition]
4191+ # Drop all protocols for a banned IP (newer Fail2Ban versions)
4192+ rule_match-allports =
4193+ EOF
41794194)
41804195
41814196 local JAIL_LOCAL_CONFIG
@@ -4185,7 +4200,7 @@ ignoreip = ${IGNORE_IPS[*]}
41854200bantime = 1d
41864201findtime = 10m
41874202maxretry = 5
4188- banaction = iptables-ipset-proto6 -allports
4203+ banaction = nftables -allports
41894204
41904205[sshd]
41914206enabled = true
@@ -4203,21 +4218,25 @@ EOF
42034218
42044219 local UFW_FILTER_PATH=" /etc/fail2ban/filter.d/ufw-probes.conf"
42054220 local JAIL_LOCAL_PATH=" /etc/fail2ban/jail.local"
4221+ local NFTABLES_LOCAL_PATH=" /etc/fail2ban/action.d/nftables-allports.local"
42064222
42074223 # --- Idempotency Check ---
4208- if [[ -f " $UFW_FILTER_PATH " && -f " $JAIL_LOCAL_PATH " ]] && \
4224+ if [[ -f " $UFW_FILTER_PATH " && -f " $JAIL_LOCAL_PATH " && -f " $NFTABLES_LOCAL_PATH " ]] && \
42094225 cmp -s " $UFW_FILTER_PATH " <<< " $UFW_PROBES_CONFIG" && \
4210- cmp -s " $JAIL_LOCAL_PATH " <<< " $JAIL_LOCAL_CONFIG" ; then
4226+ cmp -s " $JAIL_LOCAL_PATH " <<< " $JAIL_LOCAL_CONFIG" && \
4227+ cmp -s " $NFTABLES_LOCAL_PATH " <<< " $NFTABLES_ALLPORTS_LOCAL" ; then
42114228 print_info " Fail2Ban is already configured correctly. Skipping."
42124229 log " Fail2Ban configuration is already correct."
42134230 return 0
42144231 fi
42154232
42164233 # --- Apply Configuration ---
42174234 print_info " Applying new Fail2Ban configuration..."
4218- mkdir -p /etc/fail2ban/filter.d
4235+ mkdir -p /etc/fail2ban/filter.d /etc/fail2ban/action.d
4236+ rm -f /etc/fail2ban/action.d/nftables-common.local 2> /dev/null || true
42194237 echo " $UFW_PROBES_CONFIG " > " $UFW_FILTER_PATH "
42204238 echo " $JAIL_LOCAL_CONFIG " > " $JAIL_LOCAL_PATH "
4239+ echo " $NFTABLES_ALLPORTS_LOCAL " > " $NFTABLES_LOCAL_PATH "
42214240
42224241 # --- Ensure the log file exists BEFORE restarting the service ---
42234242 if [[ ! -f /var/log/ufw.log ]]; then
@@ -6173,7 +6192,7 @@ generate_summary() {
61736192 # Adjust verification commands based on selection
61746193 if [[ " $IDS_INSTALLED " == " fail2ban" ]]; then
61756194 printf " %-28s ${CYAN} %s${NC} \n" " - Fail2Ban sshd jail:" " sudo fail2ban-client status sshd"
6176- printf " %-28s ${CYAN} %s${NC} \n" " - IPSet banned IPs :" " sudo ipset list"
6195+ printf " %-28s ${CYAN} %s${NC} \n" " - nftables drop counters :" " sudo nft list table inet f2b-table "
61776196 elif [[ " $IDS_INSTALLED " == " crowdsec" ]]; then
61786197 printf " %-28s ${CYAN} %s${NC} \n" " - CrowdSec status:" " sudo cscli metrics"
61796198 printf " %-28s ${CYAN} %s${NC} \n" " - CrowdSec bans:" " sudo cscli decisions list"
0 commit comments