< 自用文 OS 有关 > (续)发现正在被攻击 后的自救 Fail2ban + IPset + UFW 工作流程详解

继上编:< 自用文 主机 USC 记录:> 发现正在被攻击 后的自救-CSDN博客

环境:

改进:

以下是把代码,懒得写,扔给了 AI ,让它出的:

Fail2ban + IPset + UFW 工作流程详解

工具概述

1. UFW (Uncomplicated Firewall)

  • 作用: iptables 的简化前端
  • 功能: 基础防火墙规则管理
  • 特点: 用户友好的规则语法

2. IPset

  • 作用: IP地址集合管理工具
  • 功能: 高效存储和匹配大量IP地址
  • 特点: 比传统iptables规则更高效

3. Fail2ban

  • 作用: 入侵检测和自动封禁系统
  • 功能: 分析日志、检测攻击、触发封禁动作
  • 特点: 智能攻击模式识别

完整工作流程

阶段1: 初始化和基础防护

[系统启动] → [UFW启动] → [建立基础防火墙规则]↓
[IPset工具初始化] → [创建IP集合]↓
[Fail2ban启动] → [读取配置] → [开始监控日志]

阶段2: 攻击检测流程

[攻击者连接] → [服务日志记录] → [Fail2ban监控]↓
[模式匹配] → [计数器增加] → [达到阈值?]↓              ↓              ↓[继续监控]    [重置计数器]     [触发封禁]

阶段3: 封禁执行流程

[Fail2ban检测到攻击] ↓
[调用Action脚本]↓
[IPset添加恶意IP] → [ipset add fail2ban-ssh 192.168.1.100]↓
[UFW规则生效] → [DROP来自IPset集合的流量]↓
[攻击者被阻断]

技术架构图

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   网络流量      │────│   UFW/iptables  │────│   目标服务       │
│                 │    │                 │    │   (SSH/HTTP)    │
└─────────────────┘    └─────────────────┘    └─────────────────┘│                         ││                         │┌─────────────┐            ┌─────────────┐│   IPset     │            │   日志文件   ││  (IP集合)    │            │             │└─────────────┘            └─────────────┘│                         │└──────┬──────────────────┘│┌─────────────┐│  Fail2ban   ││  (监控分析)  │└─────────────┘

详细配置示例

1. UFW基础配置

# 启用UFW
sudo ufw enable# 默认策略
sudo ufw default deny incoming
sudo ufw default allow outgoing# 允许SSH (在配置fail2ban之前)
sudo ufw allow ssh# 创建IPset规则 (UFW会自动处理)
# 实际在iptables中创建规则引用IPset

2. IPset配置

# 创建IP集合
sudo ipset create fail2ban-ssh hash:ip timeout 86400# 手动添加IP到集合 (通常由fail2ban自动执行)
sudo ipset add fail2ban-ssh 192.168.1.100# 查看集合内容
sudo ipset list fail2ban-ssh

3. Fail2ban配置 (/etc/fail2ban/jail.local)

[DEFAULT]
# 使用ipset作为封禁后端
banaction = iptables-ipset-proto6[name=fail2ban-ssh][sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 86400
findtime = 600# 使用ipset action
action = iptables-ipset-proto6[name=fail2ban-ssh, port=ssh, protocol=tcp]

数据流详解

1. 正常流量处理

外部请求 → UFW检查 → 基础规则匹配 → 允许通过 → 到达服务↓检查IPset集合↓IP不在黑名单 → 继续处理

2. 恶意流量处理

攻击流量 → UFW检查 → IPset集合匹配 → 发现恶意IP → 直接丢弃↓记录封禁日志

3. 新攻击检测

新攻击 → 到达服务 → 认证失败 → 写入日志↓Fail2ban监控 → 模式匹配 → 计数增加↓达到阈值 → 调用action → 添加IP到IPset↓下次请求 → UFW/IPset阻断

性能优势分析

传统iptables方式

# 每个被封IP都要一条规则
iptables -I INPUT -s 192.168.1.100 -j DROP
iptables -I INPUT -s 192.168.1.101 -j DROP
iptables -I INPUT -s 192.168.1.102 -j DROP
# ... 可能有数千条规则

问题: 规则数量多时,匹配效率低下

IPset优化方式

# 只需一条规则引用整个集合
iptables -I INPUT -m set --match-set fail2ban-ssh src -j DROP# 所有IP存储在高效的哈希表中
ipset add fail2ban-ssh 192.168.1.100
ipset add fail2ban-ssh 192.168.1.101
ipset add fail2ban-ssh 192.168.1.102

优势: O(1) 时间复杂度查找,支持数万IP

实际工作示例

场景:SSH暴力破解攻击

  1. 攻击开始

    攻击者IP: 203.0.113.100
    连续尝试SSH登录,密码错误
    
  2. 日志记录

    /var/log/auth.log:
    Failed password for root from 203.0.113.100 port 22 ssh2
    Failed password for admin from 203.0.113.100 port 22 ssh2
    Failed password for user from 203.0.113.100 port 22 ssh2
    
  3. Fail2ban检测

    fail2ban监控到3次失败
    达到maxretry=3的阈值
    触发封禁action
    
  4. IPset执行

    # Fail2ban执行命令
    ipset add fail2ban-ssh 203.0.113.100
    
  5. UFW/iptables生效

    # 现有规则开始匹配IPset
    iptables -I INPUT -m set --match-set fail2ban-ssh src -j DROP
    
  6. 结果

    攻击者IP被立即阻断
    后续请求直接在内核层面丢弃
    不再到达SSH服务
    

监控和管理

查看当前状态

# 查看fail2ban状态
sudo fail2ban-client status sshd# 查看IPset内容
sudo ipset list fail2ban-ssh# 查看UFW状态
sudo ufw status verbose# 查看iptables规则
sudo iptables -L INPUT -n -v

手动管理

# 手动解封IP
sudo fail2ban-client set sshd unbanip 203.0.113.100# 直接从IPset移除
sudo ipset del fail2ban-ssh 203.0.113.100# 查看封禁历史
sudo tail -f /var/log/fail2ban.log

优势总结

  1. 高效性: IPset提供O(1)查找效率,支持大规模IP封禁
  2. 自动化: Fail2ban自动检测和响应,减少人工干预
  3. 灵活性: UFW提供简单的规则管理界面
  4. 可扩展: 支持多种服务和攻击模式检测
  5. 持久化: IPset支持超时和持久化存储
  6. 资源节约: 比传统方法消耗更少系统资源

这种组合为Linux系统提供了一套完整、高效的自动化安全防护解决方案。

代码:仅 fail2ban+ipset 

这是我自用的装机 bash script, 之前有分享过,因为有两个 V 没过审核,留着自已来。

主要功能:

现在这个脚本 15千行:

这里包含几个 filter,测试脚本 ,还有硬写的日志文件名(这需要替换),参考时要记得修改。

# 13. Install Fail2Ban
install_fail2ban() {log_function_start "Installing Fail2Ban with IPSet integration"log_info "Installing Fail2Ban with IPSet and UFW integration for enhanced security..."# Verify nobody user exists for service isolationverify_nobody_user || log_warning "Nobody user not available for service isolation"# Safe to stop and disable Fail2Ban if already runningsafe_stop_and_disable_service "fail2ban" "Fail2Ban service"# Remove any existing Fail2Ban packageslog_info "Removing any existing Fail2Ban packages..."apt remove --purge -y fail2ban || truelog_success "Existing Fail2Ban packages removed"# Clean up orphaned dependencieslog_info "Cleaning up orphaned dependencies..."apt autoremove -y || trueapt autoclean -y || truelog_success "Orphaned dependencies cleaned up"# Remove any existing Fail2Ban configuration fileslog_info "Removing any existing Fail2Ban configuration files..."rm -rf /etc/fail2ban/* 2>/dev/null || truelog_info "Removed existing Fail2Ban configuration files"rm -rf /var/lib/fail2ban/* 2>/dev/null || truelog_info "Removed existing Fail2Ban data files"rm -rf /var/log/fail2ban.log 2>/dev/null || truelog_info "Removed existing Fail2Ban log file"log_success "Existing Fail2Ban configuration files removed"# Check system requirements for Fail2Banlog_info "Checking system requirements for Fail2Ban..."# Check log filesif [ ! -f /var/log/auth.log ]; thenlog_warning "Auth log file not found at /var/log/auth.log"touch /var/log/auth.logchmod 640 /var/log/auth.logchown root:adm /var/log/auth.logsleep 1log_info "Created missing auth log file at /var/log/auth.log with correct permissions"log_success "Auth log file created successfully"elselog_success "Auth log file found at /var/log/auth.log"fi# Check UFW statusif ! command -v ufw >/dev/null; thenlog_error "UFW is not installed. Installing it now..."if configure_ufw; thenlog_success "UFW installed and configured successfully"elselog_error "Failed to install UFW. Fail2Ban installation cannot proceed."log_function_end "Installing Fail2Ban" 1return 1fielselog_success "UFW is installed and available"fi# Install and configure IPSetlog_info "Installing IPSet package..."if apt install -y ipset; thenlog_success "IPSet installed successfully"elselog_error "Failed to install IPSet"log_function_end "Installing Fail2Ban with IPSet" 1return 1fi# Clean up any existing ipsetslog_info "Cleaning up any existing fail2ban ipsets..."ipset destroy fail2ban-banned 2>/dev/null || trueipset destroy fail2ban-recidive 2>/dev/null || truelog_info "Existing fail2ban ipsets cleaned up"# Create IPSet for fail2banlog_info "Creating IPSet for fail2ban..."if ipset create fail2ban-banned hash:ip timeout 0 2>/dev/null; thenlog_success "Created IPSet 'fail2ban-banned'"elselog_error "Failed to create IPSet 'fail2ban-banned'"log_function_end "Creating IPSet for fail2ban" 1return 1fi# Create additional IPSet for recidive (repeat offenders)log_info "Creating IPSet for repeat offenders..."if ipset create fail2ban-recidive hash:ip timeout 0 2>/dev/null; thenlog_success "Created IPSet 'fail2ban-recidive'"elselog_warning "Failed to create IPSet 'fail2ban-recidive' (may already exist)"fi# Create the initial persistent file for IPSet ruleslog_info "Creating the initial persistent file for IPSet rules..."if ipset save > /etc/ipset.rules; thenlog_success "Created the initial persistent file for IPSet rules"elselog_error "Failed to create the initial persistent file for IPSet rules"log_function_end "Creating the initial persistent file for IPSet rules" 1return 1fi# Create IPSet persistence servicelog_info "Creating IPSet persistence service..."cat > /etc/systemd/system/ipset-persistent.service << 'EOF'
[Unit]
Description=IPSet persistent rule service
Before=netfilter-persistent.service network-pre.target ufw.service fail2ban.service
ConditionFileNotEmpty=/etc/ipset.rules[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/sbin/ipset restore -exist -file /etc/ipset.rules
ExecStop=/sbin/ipset save -file /etc/ipset.rules
ExecReload=/sbin/ipset save -file /etc/ipset.rules[Install]
WantedBy=multi-user.target
EOFlog_success "Created IPSet persistence service"# Enable IPSet persistencesystemctl daemon-reloadsystemctl enable ipset-persistent.servicelog_success "Enabled IPSet persistence via systemd"# Create IPSet save script for graceful shutdownlog_info "Creating IPSet save script..."cat > /etc/systemd/system/ipset-save.service << 'EOF'
[Unit]
Description=Save IPSet rules on shutdown
DefaultDependencies=false
Before=shutdown.target reboot.target halt.target[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/bin/true
ExecStop=/sbin/ipset save -file /etc/ipset.rules
TimeoutStopSec=30[Install]
WantedBy=multi-user.target
EOFsystemctl enable ipset-save.servicelog_success "Created IPSet save script for graceful shutdown"# Replace /etc/ufw/before.rules to integrate with IPSetlog_info "Updating /etc/ufw/before.rules to integrate with IPSet..."cp /etc/ufw/before.rules /etc/ufw/before.rules.backup.$(date +%s)log_info "Backed up existing /etc/ufw/before.rules"cat > /etc/ufw/before.rules << 'EOF'
#
# rules.before
#
# Rules that should be run before the ufw command line added rules. Custom
# rules should be added to one of these chains:
#   ufw-before-input
#   ufw-before-output
#   ufw-before-forward
## Don't delete these required lines, otherwise there will be errors
*filter
:ufw-before-input - [0:0]
:ufw-before-output - [0:0]
:ufw-before-forward - [0:0]
:ufw-not-local - [0:0]# Fail2Ban IPSet integration
# Block all traffic from fail2ban banned IPs
-A ufw-before-input -m set --match-set fail2ban-banned src -j DROP
-A ufw-before-input -m set --match-set fail2ban-recidive src -j DROP# End required lines# allow all on loopback
-A ufw-before-input -i lo -j ACCEPT
-A ufw-before-output -o lo -j ACCEPT# quickly process packets for which we already have a connection
-A ufw-before-input -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A ufw-before-output -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A ufw-before-forward -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT# drop INVALID packets (logs these in loglevel medium and higher)
-A ufw-before-input -m conntrack --ctstate INVALID -j ufw-logging-deny
-A ufw-before-input -m conntrack --ctstate INVALID -j DROP# ok icmp codes for INPUT
-A ufw-before-input -p icmp --icmp-type destination-unreachable -j ACCEPT
-A ufw-before-input -p icmp --icmp-type time-exceeded -j ACCEPT
-A ufw-before-input -p icmp --icmp-type parameter-problem -j ACCEPT
-A ufw-before-input -p icmp --icmp-type echo-request -j ACCEPT# ok icmp code for FORWARD
-A ufw-before-forward -p icmp --icmp-type destination-unreachable -j ACCEPT
-A ufw-before-forward -p icmp --icmp-type time-exceeded -j ACCEPT
-A ufw-before-forward -p icmp --icmp-type parameter-problem -j ACCEPT
-A ufw-before-forward -p icmp --icmp-type echo-request -j ACCEPT# allow dhcp client to work
-A ufw-before-input -p udp --sport 67 --dport 68 -j ACCEPT#
# ufw-not-local
#
-A ufw-before-input -j ufw-not-local# if LOCAL, RETURN
-A ufw-not-local -m addrtype --dst-type LOCAL -j RETURN# if MULTICAST, RETURN
-A ufw-not-local -m addrtype --dst-type MULTICAST -j RETURN# if BROADCAST, RETURN
-A ufw-not-local -m addrtype --dst-type BROADCAST -j RETURN# all other non-local packets are dropped
-A ufw-not-local -m limit --limit 3/min --limit-burst 10 -j ufw-logging-deny
-A ufw-not-local -j DROP# allow MULTICAST mDNS for service discovery (be sure the MULTICAST line above
# is uncommented)
-A ufw-before-input -p udp -d 224.0.0.251 --dport 5353 -j ACCEPT# allow MULTICAST UPnP for service discovery (be sure the MULTICAST line above
# is uncommented)
-A ufw-before-input -p udp -d 239.255.255.250 --dport 1900 -j ACCEPT# don't delete the 'COMMIT' line or these rules won't be processed
COMMIT
EOFlog_success "Updated /etc/ufw/before.rules with IPSet integration"# Install Fail2Banlog_info "Installing Fail2Ban package..."if apt install -y fail2ban; thenlog_success "Fail2Ban installed successfully"elselog_error "Failed to install Fail2Ban"log_function_end "Installing Fail2Ban" 1return 1fi# Create /etc/fail2ban/action.d/ipset-block.conflog_info "Creating Persistent /etc/fail2ban/action.d/ipset-block.conf"cat > /etc/fail2ban/action.d/ipset-block.conf << 'EOF'
# Fail2Ban action file for ipset
#
# This action blocks/unblocks an IP address using ipset.
#
[INCLUDES]before =[Definition]# The name of the ipset set to use.
setname = fail2ban-banned# Action startup (creates the set if it doesn't exist)
actionstart = /usr/sbin/ipset create <setname> hash:ip timeout 0 exist# Action shutdown (flushes the set when Fail2Ban stops)
#actionstop = ipset flush <setname>
actionstop = # Action to ban an IP
actionban = /usr/sbin/ipset add <setname> <ip> timeout 0 exist# Action to unban an IP
actionunban = /usr/sbin/ipset del <setname> <ip> exist[Init]
EOFlog_success "Created /etc/fail2ban/action.d/ipset-block.conf"# Create IPSet action for fail2banlog_info "Creating Fail2Ban IPSet action configuration..."mkdir -p /etc/fail2ban/action.dcat > /etc/fail2ban/action.d/ipset-ban.conf << 'EOF'
[INCLUDES]
before = iptables-common.conf[Definition]
# Option: actionstart
# Notes.: command executed once at the start of Fail2Ban.
actionstart = ipset create <ipmset> hash:ip timeout <default-timeout> <family># Option: actionstop
# Notes.: command executed once at the end of Fail2Ban
actionstop = ipset destroy <ipmset># Option: actionban
# Notes.: command executed when banning an IP.
actionban = ipset add <ipmset> <ip> timeout <timeout> -exist# Option: actionunban
# Notes.: command executed when unbanning an IP.
actionunban = ipset del <ipmset> <ip> -exist[Init]
# Default name of the ipset
ipmset = fail2ban-<name># Option: timeout
# Notes.: timeout for the ban, in seconds
timeout = 0# Option: default-timeout  
# Notes.: default timeout for ipset creation
default-timeout = 0# Option: family
# Notes.: IP family, can be inet or inet6
family = inet
EOF# Create enhanced IPSet action for permanent banscat > /etc/fail2ban/action.d/ipset-persistent.conf << 'EOF'
[INCLUDES]
before = iptables-common.conf[Definition]
actionstart = ipset create <ipmset> hash:ip timeout 0 -existipset restore -file /etc/ipset.rules -existactionstop = ipset save -file /etc/ipset.rulesipset destroy <ipmset>actionban = ipset add <ipmset> <ip> timeout 0 -existipset save -file /etc/ipset.rulesactionunban = ipset del <ipmset> <ip> -existipset save -file /etc/ipset.rules[Init]
ipmset = fail2ban-banned
EOF# Create recidive action for repeat offenderscat > /etc/fail2ban/action.d/ipset-recidive.conf << 'EOF'
[INCLUDES]
before = iptables-common.conf[Definition]
actionstart = ipset create <ipmset> hash:ip timeout 0 -existactionstop = ipset save -file /etc/ipset.rulesactionban = ipset add <ipmset> <ip> timeout 0 -existipset save -file /etc/ipset.rulesactionunban = ipset del <ipmset> <ip> -existipset save -file /etc/ipset.rules[Init]
ipmset = fail2ban-recidive
EOFlog_success "Created Fail2Ban IPSet action configurations"# Create jail configurationlog_info "Configuring Fail2Ban jails with IPSet integration..."cat > /etc/fail2ban/jail.local << EOF
[DEFAULT]
# Ban settings
bantime = -1
findtime = 1800
maxretry = 3
backend = auto# IPSet integration
banaction = ipset-persistent
banaction_allports = ipset-persistent# Network settings
allowipv6 = auto
ignoreip = 127.0.0.1/8 ::1usw.daven.us jpt.daven.us bjn.daven.us bjt.daven.us usc.daven.us# Email settings (optional)
# destemail = admin@yourdomain.com
# sendername = Fail2Ban
# mta = sendmail[recidive]
enabled = true
logpath = /var/log/fail2ban.log
banaction = ipset-recidive
bantime = -1
findtime = 86400
maxretry = 3
filter = recidive[sshd]
enabled = true
port = $SSH_PORT
filter = sshd
logpath = /var/log/auth.log
backend = auto
bantime = 72000
findtime = 600
maxretry = 5[ssh-scanner]
enabled = true
port = $SSH_PORT
filter = ssh-scanner
logpath = /var/log/auth.log
maxretry = 5
bantime = 72000
findtime = 600[nginx-scan]
enabled = true
port = http,https,6033
logpath = /var/log/nginx/access.log/var/log/nginx/*.access.log
filter = nginx-scan
maxretry = 5
bantime = -1
findtime = 600[nginx-404-scan]
enabled = true
port = http,https,6033
logpath = /var/log/nginx/access.log/var/log/nginx/*.access.log
filter = nginx-404-scan
maxretry = 20
bantime = -1
findtime = 600[nginx-login-bruteforce]
enabled = true
port = http,https,6033
logpath = /var/log/nginx/access.log
filter = nginx-login-bruteforce
maxretry = 5
bantime = -1
findtime = 600[nginx-bad-useragent]
enabled = true
port = http,https,6033
logpath = /var/log/nginx/access.log
filter = nginx-bad-useragent
maxretry = 5
bantime = -1
findtime = 600[nginx-ray-abuse]
enabled = true
port = http,https,6033
logpath = /var/log/nginx/access.log
filter = nginx-ray-abuse
maxretry = 12
bantime = -1
findtime = 60[nginx-status-abuse]
enabled = true
port = http,https,6033
logpath = /var/log/nginx/access.log/var/log/nginx/*.access.log
filter = nginx-status-abuse
maxretry = 30
bantime = -1
findtime = 600[nginx-attacks]
enabled = true
port = http,https
filter = nginx-attack
logpath = /var/log/nginx/access.log
maxretry = 3
bantime = -1
findtime = 60[nginx-web-attacks]
enabled = true
port = http,https
filter = nginx-web-attacks
logpath = /var/log/nginx/*.daven.us.access.log
maxretry = 12
bantime = -1
findtime = 600
EOFlog_success "Created /etc/fail2ban/jail.local configuration file"# fail2ban for sshd and ssh-scanner local filterlog_success "Fail2Ban jails configured successfully"mkdir -p /etc/fail2ban/filter.dlog_info "Creating Fail2Ban filter for sshd and ssh-scanner..."# Create sshd local filter configurationlog_info "Creating sshd.local filter configuration..."cat > /etc/fail2ban/filter.d/sshd.local << 'EOF'
[Definition]
allowipv6 = auto
failregex = ^<HOST> .* "[^"]*" .*" "(?:Go-http-client|wget|curl|python-requests|masscan|zgrab|sqlmap|nikto|dirb|gobuster)" .*$^<HOST> .* "[^"]*" .*" ".*(?:Mozi\.m|scamanje|stresserit)" .*$^<HOST> .* "[^"]*" .*" "xfa1" .*$
ignoreregex = ^<HOST> .* "[^"]*" .*" ".*(?:Googlebot|Bingbot|YandexBot|DuckDuckBot)" .*$
EOFlog_success "sshd.local filter configuration created"# Create ssh-scanner filterlog_info "Creating Fail2Ban filter for SSH scanner..."cat > /etc/fail2ban/filter.d/ssh-scanner.conf << 'EOF'
[INCLUDES]
before = common.conf
[Definition]
_daemon = sshd
allowipv6 = auto
failregex = ^%(__prefix_line)sConnection from <HOST> port \d+ on \S+ port \d+$^%(__prefix_line)sConnection closed by <HOST> port \d+ \[preauth\]$^%(__prefix_line)sConnection closed by authenticating user .* <HOST> port \d+ \[preauth\]$^%(__prefix_line)sDisconnected from .* <HOST> port \d+ \[preauth\]$^%(__prefix_line)sReceived disconnect from <HOST> port \d+:\d+: .* \[preauth\]$^%(__prefix_line)sbanner exchange: Connection from <HOST> port \d+: invalid format$
ignoreregex =
EOFlog_success "ssh-scanner filter created"# Create Fail2Ban jail for nginx scanners# Create nginx-scan filterlog_info "Creating Fail2Ban filter for Nginx scanner..."cat > /etc/fail2ban/filter.d/nginx-scan.conf << 'EOF'
[Definition]
allowipv6 = auto
failregex = ^<HOST> .* "(GET|POST|PUT) [^"]*(?:\.env|\.git|phpinfo|eval-stdin\.php|shell\?|admin/login\.asp|boaform/admin|login\.cgi)" .*$^<HOST> .* "(GET|POST) [^"]*(?:wget\+|chmod\+|/tmp/|Mozi\.m|scamanje\.stresserit\.pro)" .*$^<HOST> .* "(GET|POST) [^"]*(?:/SDK/webLanguage|/actuator|/console|/geoserver|/solr/admin)" .*$^<HOST> .* "(GET|POST) [^"]*(?:phpunit|vendor/phpunit|_ignition)" .*$^<HOST> .* "[^"]*(?:27;wget|mstshash=)" .*$
ignoreregex = ^<HOST> .* "GET /(?:favicon\.ico|robots\.txt|sitemap\.xml) .*$
EOFlog_success "nginx-scan filter created"# Create nginx-404-scan filterlog_info "Creating Fail2Ban filter for Nginx 404 scanner..."cat > /etc/fail2ban/filter.d/nginx-404-scan.conf << 'EOF'
[Definition]
allowipv6 = auto
failregex = ^<HOST> - - \[.*\] "(?:GET|POST) /(?:admin|wp-admin|\.php|\.asp|phpinfo|\.env|config|backup|uploads|test|debug|system_info|diagnostics)" .*" 404 .*$^<HOST> - - \[.*\] "(?:GET|POST) [^"]*/(?:partymgr|jasperserver|solr|owncloud|geoserver|WebInterface)" .*" 404 .*$^<HOST> - - \[.*\] "(?:GET|POST|HEAD|OPTIONS|PUT|DELETE|CONNECT|TRACE|PATCH) /[a-zA-Z0-9]{4,8}(?:\s|/|$)" .*" 404 .*$
ignoreregex = ^<HOST> - - \[.*\] "GET /(?:favicon\.ico|robots\.txt|sitemap\.xml|apple-touch-icon|\.well-known/)" .*" 404 .*$
EOFlog_success "nginx-404-scan filter created"# Create login scanner filterlog_info "Creating Fail2Ban filter for nginx login bruteforce scanner..."cat > /etc/fail2ban/filter.d/nginx-login-bruteforce.conf << 'EOF'
[Definition]
allowipv6 = auto
failregex = ^<HOST> .* "(?:GET|POST) /login\.cgi\?username=.*&psd=" .*$^<HOST> .* "POST /boaform/admin/formLogin" .*$^<HOST> .* "GET /boaform/admin/formLogin\?username=.*&psd=" .*$^<HOST> .* "POST /admin/login\." .*$
ignoreregex =
EOFlog_success "nginx-login-bruteforce filter created"# Create nginx bad User-Agent filterlog_info "Creating Fail2Ban filter for Nginx bad User-Agent..."cat > /etc/fail2ban/filter.d/nginx-bad-useragent.conf << 'EOF'
[Definition]
allowipv6 = auto
failregex = ^<HOST> .* "[^"]*" .*" "(?:Go-http-client|wget|curl|python-requests|masscan|zgrab|sqlmap|nikto|dirb|gobuster)" .*$^<HOST> .* "[^"]*" .*" ".*(?:Mozi\.m|scamanje|stresserit)" .*$^<HOST> .* "[^"]*" .*" "xfa1" .*$
ignoreregex = ^<HOST> .* "[^"]*" .*" ".*(?:Googlebot|Bingbot|YandexBot|DuckDuckBot)" .*$
EOFlog_success "nginx-bad-useragent filter created"# Create nginx ray abuse filterlog_info "Creating Fail2Ban filter for Nginx Ray abuse..."cat > /etc/fail2ban/filter.d/nginx-ray-abuse.conf << 'EOF'
[Definition]
allowipv6 = auto
failregex = ^<HOST> .* "GET /api HTTP/1\.1" 101 .*$
ignoreregex =
EOFlog_success "nginx-ray-abuse filter created"# Create nginx status abuse filterlog_info "Creating Fail2Ban filter for Nginx status abuse..."cat > /etc/fail2ban/filter.d/nginx-status-abuse.conf << 'EOF'
[Definition]
allowipv6 = auto
failregex = ^<HOST> - - \[.*\] "(?:GET|POST|HEAD) .* HTTP/1\.[01]" 40[0-3] \d+ ".*" ".*"$
ignoreregex = ^<HOST> .* "GET /(?:favicon\.ico|robots\.txt)" 40[0-3] .*$
EOFlog_success "nginx-status-abuse filter created"# Create nginx status abuse filterlog_info "Creating Fail2Ban filter for Nginx attack abuse..."cat > /etc/fail2ban/filter.d/nginx-attack.conf << 'EOF'
[Definition]
allowipv6 = auto
failregex = ^<HOST> -.*"GET .*(.env|.git|.well-known/security\.txt|\/phpmyadmin|\/wp-login\.php|\/wp-admin|\/cgi-bin|\/phpinfo|\.sql|\.log|\.ini|\.conf|\.bak).* HTTP.*" (40[0-4]|444|499|500)^<HOST> -.*"GET .*(?:\x09hink|\x09pp).*shell_exec.*wget.*" 400.*
ignoreregex =
EOFlog_success "nginx-attack filter created"# Create nginx status abuse filterlog_info "Creating Fail2Ban filter for Nginx web attacks abuse..."cat > /etc/fail2ban/filter.d/nginx-web-attacks.conf << 'EOF'
[Definition]
allowipv6 = auto
failregex = ^<HOST> -.*"GET .*(?:\.env|\.git|\.well-known/security\.txt|\/phpmyadmin|\/wp-admin|\/cgi-bin|\/webui|\/geoserver|\/remote/login|onvif|PSIA|boaform|owa/auth/logon\.aspx|PROPFIND|\+CSCOE\+).*HTTP.*" (40[0-4]|444|499|500)^<HOST> -.*"GET .*(?:\x09hink|\x07pp).*shell_exec.*wget.*" 400.*^<HOST> -.*"POST .*cgi-bin/(\.\./).*bin/sh HTTP.*" (400|404|301|302)^<HOST> -.*"GET .*HTTP.*" (40[0-4]|444|499).*"(?:zgrab|CMS-Checker|libredtail-http|WanScannerBot|Odin|GenomeCrawlerd)"
ignoreregex =
EOFlog_success "nginx-web-attacks filter created"# Disable conflicting default configuration fileslog_info "Disabling conflicting default configuration files..."if [ -f /etc/fail2ban/jail.d/defaults-debian.conf ]; thenif mv /etc/fail2ban/jail.d/defaults-debian.conf /etc/fail2ban/jail.d/defaults-debian.disabled; thenlog_success "Conflicting default configuration files disabled"elselog_warning "Failed to disable conflicting default configuration files"fifi# Restart services in proper orderlog_info "Starting services in proper order..."# Start IPSet persistence firstsystemctl start ipset-persistent.service# Reload UFW to pick up the new before.ruleslog_info "Reloading UFW to apply IPSet integration..."ufw --force reloadlog_success "UFW reloaded with IPSet integration"# Enable and start Fail2Bansystemctl enable fail2bansystemctl start fail2banlog_info "Fail2Ban service started"# Wait for fail2ban to initializesleep 3# Verify IPSet integrationlog_info "Verifying IPSet integration..."if ipset list fail2ban-banned >/dev/null 2>&1; thenlog_success "IPSet 'fail2ban-banned' is active"elselog_error "IPSet 'fail2ban-banned' is not active"fi# Verify UFW integrationif iptables -L ufw-before-input -n | grep -q fail2ban-banned; thenlog_success "UFW is integrated with IPSet"elselog_warning "UFW integration with IPSet may not be working"fi# Create management toolscreate_ipset_management_tools# Create fail2ban-tester.shlog_info "Creating /usr/bin/fail2ban-tester.sh..."cat > /usr/bin/fail2ban-tester.sh << 'EOF'
#!/bin/bash
# A script to automatically test all enabled Fail2ban jails using fail2ban-regex.
# It fetches the filter and logpath for each active jail and runs the test.
# By Dave Nian on 25Aug25# --- Configuration ---
# Colors for better readability
C_RESET='\033[0m'
C_RED='\033[0;31m'
C_GREEN='\033[0;32m'
C_YELLOW='\033[0;33m'
C_BLUE='\033[0;34m'
C_CYAN='\033[0;36m'
C_BOLD='\033[1m'# --- Pre-flight Checks ---
# Check if running as root
if [[ $EUID -ne 0 ]]; thenecho -e "${C_RED}This script must be run as root.${C_RESET}"exit 1
fi# Check if fail2ban-client is available
if ! command -v fail2ban-client &> /dev/null; thenecho -e "${C_RED}Error: 'fail2ban-client' command not found.${C_RESET}"echo "Please ensure Fail2ban is installed and you are running this on the correct server."exit 1
fi# --- Main Logic ---
echo -e "${C_BOLD}${C_BLUE}--- Starting Fail2ban Filter Test ---${C_RESET}"# Get the list of enabled jails from fail2ban-client
# The sed command cleans up the output to get just the jail names
ENABLED_JAILS=$(fail2ban-client status | grep "Jail list:" | sed -e 's/.*Jail list:\s*//' -e 's/,//g')if [ -z "$ENABLED_JAILS" ]; thenecho -e "${C_RED}Could not find any enabled jails. Exiting.${C_RESET}"exit 1
fiecho -e "Found enabled jails: ${C_YELLOW}${ENABLED_JAILS}${C_RESET}\n"# Loop through each enabled jail
for jail in $ENABLED_JAILS; doecho -e "${C_BOLD}${C_CYAN}========================================${C_RESET}"echo -e "${C_BOLD}${C_CYAN} Testing Jail: [${jail}] ${C_RESET}"echo -e "${C_BOLD}${C_CYAN}========================================${C_RESET}"# Get the filter name for the current jail.# Redirect stderr to /dev/null to keep the output clean.filter_name=$(fail2ban-client get "$jail" filter 2>/dev/null)# ** FIX **: Check if the command failed or returned a known error message.# Some versions of fail2ban-client output this error to stdout.# If it fails, we assume the filter name is the same as the jail name.if [ $? -ne 0 ] || [[ "$filter_name" == *"Invalid command"* ]] || [ -z "$filter_name" ]; thenecho -e "  ${C_YELLOW}Warning: Could not dynamically get filter for [${jail}].${C_RESET}"echo -e "  ${C_YELLOW}Assuming filter name matches jail name.${C_RESET}"filter_name=$jailfifilter_file="/etc/fail2ban/filter.d/${filter_name}.conf"# ** FIX **: Get the log path(s) and parse the multi-line output correctly.# This command now specifically extracts lines that are file paths.log_paths_output=$(fail2ban-client get "$jail" logpath)log_paths=$(echo "$log_paths_output" | grep -E '^[|`]-' | sed -E 's/^[|`]- //')# If the above fails (for single-line outputs), use the raw output but clean it.if [ -z "$log_paths" ]; thenlog_paths=$(echo "$log_paths_output" | sed 's/Current monitored log file(s)://g' | tr -d '`-' | tr -d '|')fi# Check if the filter file actually existsif [ ! -f "$filter_file" ]; thenecho -e "  ${C_RED}Filter file not found:${C_RESET} ${filter_file}"# Try to find it with a .local extension as a fallbackfilter_file_local="/etc/fail2ban/filter.d/${filter_name}.local"if [ -f "$filter_file_local" ]; thenecho -e "  ${C_YELLOW}Found fallback filter:${C_RESET} ${filter_file_local}"filter_file=$filter_file_localelseecho -e "  ${C_RED}Skipping jail [${jail}] as no valid filter was found.${C_RESET}\n"continuefifiecho -e "  ${C_BOLD}Filter:${C_RESET} ${filter_file}"echo -e "  ${C_BOLD}Log(s):${C_RESET}\n${log_paths}" # Print the cleaned listecho ""# Loop through each log path (a jail can have multiple)for log_path in $log_paths; do# Expand wildcards in log pathsexpanded_logs=$(eval echo $log_path)for expanded_log_path in $expanded_logs; do# Check if the log file exists and is readableif [ ! -r "$expanded_log_path" ]; thenecho -e "  -> Testing log: ${C_YELLOW}${expanded_log_path}${C_RESET}"echo -e "     ${C_RED}Result: Log file not found or not readable. Skipping.${C_RESET}\n"continuefiecho -e "  -> Testing log: ${C_GREEN}${expanded_log_path}${C_RESET}"# Run the fail2ban-regex command and capture the outputtest_output=$(fail2ban-regex "$expanded_log_path" "$filter_file")# ** FIX **: More robustly extract the number of matched lines.# This specifically finds the number preceding "matched".matches=0 # Default to 0matches_line=$(echo "$test_output" | grep "Lines:")if [[ -n "$matches_line" ]]; then# Use grep with Perl-compatible regex to extract the numbermatches=$(echo "$matches_line" | grep -oP '\d+(?=\s+matched)')fi# Print the summaryif [ "$matches" -gt 0 ]; thenecho -e "     ${C_GREEN}${C_BOLD}Result: Found ${matches} matching lines!${C_RESET}"elseecho -e "     ${C_YELLOW}Result: Found 0 matching lines.${C_RESET}"fiecho ""donedone
doneecho -e "${C_BOLD}${C_BLUE}--- Test Complete ---${C_RESET}"EOFif [ -f "/usr/bin/fail2ban-tester.sh" ];then log_info "fail2ban-tester.sh created in /usr/bin/"elselog_warning "fail2ban-tester.sh didn't exist in /usr/bin/"return 1fiif chmod 777 /usr/bin/fail2ban-tester.sh;thenlog_info "/usr/bin/fail2ban-tester.sh has been given execute permission"elselog_warning "Ran chmode on /usr/bin/fail2ban-tester.sh failed"return 1fiif ln -s /usr/bin/fail2ban-tester.sh /usr/bin/fail2ban-tester;thenlog_info "Linked /usr/bin/fail2ban-tester.sh to /usr/bin/fail2ban-tester"elselog_warning "Failed to link /usr/bin/fail2ban-tester"return 1fi# Fixing the WARNING 'allowipv6' not defined in 'Definition'if fail2ban_sshd_local_allowipv6; thenlog_success "'allowipv6' configuration fixed in sshd.local"elselog_warning "'allowipv6' configuration not fixed in sshd.local"fi# Final restart to apply all changeslog_info "Performing final restart of services..."systemctl daemon-reloadsystemctl restart fail2banif systemctl is-active --quiet fail2ban; thenlog_success "Fail2Ban restarted successfully with IPSet integration"elselog_error "Failed to restart Fail2Ban"systemctl status fail2ban --no-pager -l || truelog_function_end "Installing Fail2Ban with IPSet" 1return 1fi# Create Fail2Ban management toolslog_info "Creating Fail2Ban management tools..."    create_fail2ban_tools# Verify installationif verify_fail2ban_installation; thenlog_success "🎉 Fail2Ban with IPSet integration completed successfully!"show_fail2ban_summarylog_function_end "Installing Fail2Ban with IPSet" 0return 0elselog_warning "⚠️  Fail2Ban with IPSet installed but some issues detected"show_fail2ban_troubleshootinglog_function_end "Installing Fail2Ban with IPSet" 1return 1fi
}# Function to create IPSet management tools
create_ipset_management_tools() {log_info "Creating IPSet management tools..."# Create IPSet status scriptcat > /usr/local/bin/ipset-status << 'EOF'
#!/bin/bash
# IPSet Status Display Scriptecho "=== IPSet Status ==="
echo "Active IPSets:"
ipset list -nameecho ""
echo "=== Fail2Ban IPSets ==="
for set in $(ipset list -name | grep fail2ban); doecho "--- $set ---"echo "Members: $(ipset list $set | grep -c '^[0-9]')"ipset list $set | head -20echo ""
doneecho "=== IPSet Rules in iptables ==="
iptables -L ufw-before-input -n | grep set
EOFchmod +x /usr/local/bin/ipset-statuslog_success "Created IPSet status script"# Create IPSet backup scriptcat > /usr/local/bin/ipset-backup << 'EOF'
#!/bin/bash
# IPSet Backup ScriptBACKUP_DIR="/etc/ipset-backups"
mkdir -p "$BACKUP_DIR"BACKUP_FILE="$BACKUP_DIR/ipset-backup-$(date +%Y%m%d-%H%M%S).rules"
ipset save > "$BACKUP_FILE"echo "IPSet rules backed up to: $BACKUP_FILE"# Keep only last 10 backups
ls -t "$BACKUP_DIR"/ipset-backup-*.rules | tail -n +11 | xargs rm -f 2>/dev/null
EOFchmod +x /usr/local/bin/ipset-backuplog_success "Created IPSet backup script"
}fail2ban_sshd_local_allowipv6() {local source_file="/etc/fail2ban/filter.d/sshd.conf"local local_file="/etc/fail2ban/filter.d/sshd.local"if [ -f "$source_file" ]; thenlog_info "Setting up sshd.local filter configuration..."# Backup existing sshd.local if it existsif [ -f "$local_file" ]; thenlog_info "Backing up existing sshd.local..."cp "$local_file" "${local_file}.backup.$(date +%s)"fi# Copy and set permissionsif cp -f "$source_file" "$local_file"; thenchmod 644 "$local_file"# Verify copy resultif [ -s "$local_file" ]; thenlog_success "sshd.conf copied to sshd.local successfully"elselog_error "Copied file is empty"return 1fielselog_error "Failed to copy sshd.conf to sshd.local"return 1fi# Fix 'allowipv6' configurationlog_info "Fixing 'allowipv6' warning in sshd.local..."if sed -n '/^\[Definition\]/,/^\[/p' "$local_file" | grep -q "^[[:space:]]*allowipv6[[:space:]]*=[[:space:]]*\(auto\|yes\)"; thenlog_success "'allowipv6' already correctly configured in sshd.local"elseif sed -n '/^\[Definition\]/,/^\[/p' "$local_file" | grep -q "^[[:space:]]*allowipv6[[:space:]]*="; thenlog_info "Updating existing 'allowipv6' configuration to 'auto'"sed -i '/^\[Definition\]/,/^\[/{ s/^[[:space:]]*allowipv6[[:space:]]*=.*/allowipv6 = auto/; }' "$local_file"elselog_info "Adding 'allowipv6 = auto' to sshd.local"sed -i '/^\[Definition\]/a allowipv6 = auto' "$local_file"fi# Verify modification resultif grep -A 5 "^\[Definition\]" "$local_file" | grep -q "^allowipv6[[:space:]]*=[[:space:]]*auto"; thenlog_success "✅ allowipv6 successfully configured in sshd.local"elselog_warning "⚠️  allowipv6 configuration may not be correct"fifielselog_error "Source file does not exist: $source_file"return 1fi
}# Unified verification function that handles both standard and IPSet installations
verify_fail2ban_installation() {log_info "Verifying Fail2Ban installation and configuration..."local verification_passed=truelocal tools_dir="/usr/local/bin/fail2ban-tools"local has_ipset=false# Detect if IPSet integration is being usedif command -v ipset >/dev/null 2>&1 && ipset list fail2ban-banned >/dev/null 2>&1; thenhas_ipset=truelog_info "IPSet integration detected, performing enhanced verification..."elselog_info "Standard Fail2Ban installation detected..."fi# 1. Check Fail2Ban service statusif systemctl is-active --quiet fail2ban; thenlog_success "✅ Fail2Ban service is running"elselog_error "❌ Fail2Ban service is not running"verification_passed=falsefi# 2. IPSet-specific checks (only if IPSet integration detected)if [ "$has_ipset" = true ]; then# Check IPSet persistence serviceif systemctl is-active --quiet ipset-persistent; thenlog_success "✅ IPSet persistence service is active"elselog_warning "⚠️  IPSet persistence service may not be active"fi# Check IPSets existif ipset list fail2ban-banned >/dev/null 2>&1; thenlog_success "✅ IPSet 'fail2ban-banned' exists"elselog_error "❌ IPSet 'fail2ban-banned' does not exist"verification_passed=falsefi# Check for recidive IPSet (optional)if ipset list fail2ban-recidive >/dev/null 2>&1; thenlog_success "✅ IPSet 'fail2ban-recidive' exists"elselog_info "ℹ️  IPSet 'fail2ban-recidive' not found (optional)"fi# Check UFW integration with IPSetif iptables -L ufw-before-input -n | grep -q fail2ban-banned; thenlog_success "✅ UFW is integrated with IPSet"elselog_error "❌ UFW is not integrated with IPSet"verification_passed=falsefi# Check IPSet action fileslocal ipset_actions=("/etc/fail2ban/action.d/ipset-ban.conf""/etc/fail2ban/action.d/ipset-persistent.conf""/etc/fail2ban/action.d/ipset-recidive.conf")for action_file in "${ipset_actions[@]}"; doif [ -f "$action_file" ]; thenlog_success "✅ IPSet action file exists: $(basename "$action_file")"elselog_warning "⚠️  IPSet action file missing: $action_file"fidone# Check IPSet rules fileif [ -f "/etc/ipset.rules" ]; thenlog_success "✅ IPSet rules file exists: /etc/ipset.rules"elselog_warning "⚠️  IPSet rules file missing: /etc/ipset.rules"fifi# 3. Check jail statuslocal active_jails=$(fail2ban-client status 2>/dev/null | grep "Jail list:" | cut -d: -f2 | tr ',' '\n' | wc -w)if [ "$active_jails" -gt 0 ]; thenlog_success "✅ $active_jails jail(s) active"# Check specific jailsfor jail in sshd ssh-scanner; doif fail2ban-client status "$jail" >/dev/null 2>&1; thenlog_success "✅ $jail jail is active"elselog_warning "⚠️  $jail jail is not active"fidoneelselog_error "❌ No active jails found"verification_passed=falsefi# 4. Check configuration fileslocal config_files=("/etc/fail2ban/jail.local""/etc/fail2ban/filter.d/sshd.local""/etc/fail2ban/filter.d/ssh-scanner.conf""/etc/fail2ban/filter.d/nginx-scan.conf""/etc/fail2ban/filter.d/nginx-404-scan.conf""/etc/fail2ban/filter.d/nginx-login-bruteforce.conf""/etc/fail2ban/filter.d/nginx-bad-useragent.conf""/etc/fail2ban/filter.d/nginx-ray-abuse.conf""/etc/fail2ban/filter.d/nginx-status-abuse.conf""/etc/fail2ban/filter.d/nginx-attack.conf""/etc/fail2ban/filter.d/nginx-web-attacks.conf")local missing_configs=0for config_file in "${config_files[@]}"; doif [ -f "$config_file" ]; thenlog_success "✅ Configuration file exists: $(basename "$config_file")"elselog_error "❌ Configuration file missing: $config_file"verification_passed=false((missing_configs++))fidoneif [ "$missing_configs" -eq 0 ]; thenlog_success "✅ All configuration files are present"elselog_error "❌ $missing_configs configuration file(s) missing"fi# 5. Check log fileif [ -f "/var/log/fail2ban.log" ]; thenlocal recent_errors=$(tail -50 /var/log/fail2ban.log 2>/dev/null | grep -c "ERROR" || echo "0")if [ "$recent_errors" -eq 0 ]; thenlog_success "✅ No recent errors in Fail2Ban log"elselog_warning "⚠️  Found $recent_errors recent errors in Fail2Ban log"fielselog_warning "⚠️  Fail2Ban log file not found at /var/log/fail2ban.log"fi# 6. Check tool filesif [ -d "$tools_dir" ]; thenlog_success "✅ Fail2Ban tools directory exists ($tools_dir)"if [ -f "$tools_dir/fail2ban-checking.sh" ]; thenlog_success "✅ Fail2Ban check script exists"if [ -f "$tools_dir/fail2ban-status.sh" ]; thenlog_success "✅ Fail2Ban status script exists"elselog_error "❌ Fail2Ban status script missing"verification_passed=falsefielselog_error "❌ Fail2Ban check script missing"verification_passed=falsefielselog_error "❌ Fail2Ban tools directory missing"verification_passed=falsefi# 7. Check tool symlinksif [ -f "/usr/local/bin/fail2ban-checking" ]; thenlog_success "✅ Fail2Ban checking symlink exists"if [ -f "/usr/local/bin/fail2ban-status" ]; thenlog_success "✅ Fail2Ban status symlink exists"elselog_error "❌ Fail2Ban status symlink missing"verification_passed=falsefielselog_error "❌ Fail2Ban checking symlink missing"verification_passed=falsefi# 8. Check fail2ban-tester scriptif [ -f "/usr/bin/fail2ban-tester.sh" ] && [ -f "/usr/bin/fail2ban-tester" ]; thenlog_success "✅ Fail2Ban tester script exists"elselog_warning "⚠️  Fail2Ban tester script missing"fi# 9. Additional IPSet management tools check (if IPSet detected)if [ "$has_ipset" = true ]; thenif [ -f "/usr/local/bin/ipset-status" ]; thenlog_success "✅ IPSet status script exists"elselog_warning "⚠️  IPSet status script missing"fiif [ -f "/usr/local/bin/ipset-backup" ]; thenlog_success "✅ IPSet backup script exists"elselog_warning "⚠️  IPSet backup script missing"fifi# Summaryif [ "$has_ipset" = true ]; thenlog_info "Verification completed for Fail2Ban with IPSet integration"elselog_info "Verification completed for standard Fail2Ban installation"fireturn $([ "$verification_passed" = true ] && echo 0 || echo 1)
}show_fail2ban_summary() {local has_ipset=false# Detect if IPSet integration is being usedif command -v ipset >/dev/null 2>&1 && ipset list fail2ban-banned >/dev/null 2>&1; thenhas_ipset=truefiechoif [ "$has_ipset" = true ]; thenlog_info "📋 Fail2Ban with IPSet Integration Summary"echo "============================================="echo "🔐 SSH Port: $SSH_PORT"echo "🚫 Ban Policy: Permanent bans via IPSet"echo "🕒 SSH Attempts: 3 failures in 30 minutes"echo "🕒 Scanner Detection: 2 connections in 5 minutes"echo "🔧 Firewall Integration: UFW + IPSet"echo "💾 IPSet Persistence: Enabled"echoecho "📁 Key Configuration Files:"echo "  • Main config: /etc/fail2ban/jail.local"echo "  • IPSet actions: /etc/fail2ban/action.d/ipset-*.conf"echo "  • IPSet rules: /etc/ipset.rules"echo "  • UFW before rules: /etc/ufw/before.rules"echo "  • SSH filter: /etc/fail2ban/filter.d/sshd.local"echo "  • Scanner filter: /etc/fail2ban/filter.d/ssh-scanner.conf"echo "  • Nginx filters: /etc/fail2ban/filter.d/nginx-*.conf"echoecho "🔧 Management Commands:"echo "  • Fail2Ban status: fail2ban-client status"echo "  • IPSet status: ipset-status"echo "  • IPSet backup: ipset-backup"echo "  • View banned IPs: ipset list fail2ban-banned"echo "  • Unban IP: fail2ban-client set <jail> unbanip <IP>"echo "  • Manual IPSet ban: ipset add fail2ban-banned <IP>"echo "  • Manual IPSet unban: ipset del fail2ban-banned <IP>"echoecho "🔧 Service Management:"echo "  • Restart Fail2Ban: systemctl restart fail2ban"echo "  • Reload UFW: ufw reload"echo "  • Save IPSet: ipset save > /etc/ipset.rules"echo "============================================="elselog_info "📋 Fail2Ban Configuration Summary"echo "=================================="echo "🔐 SSH Port: $SSH_PORT"echo "🚫 Ban Policy: Permanent bans"echo "🕒 SSH Attempts: 3 failures in 30 minutes"echo "🕒 Scanner Detection: 2 connections in 5 minutes"  echo "🔧 Firewall Integration: UFW"echoecho "📁 Configuration Files:"echo "  • Main config: /etc/fail2ban/jail.local"echo "  • SSH filter: /etc/fail2ban/filter.d/sshd.local"echo "  • Scanner filter: /etc/fail2ban/filter.d/ssh-scanner.conf"echo "  • Nginx filters: /etc/fail2ban/filter.d/nginx-*.conf"echoecho "🔧 Management Commands:"echo "  • Check status: fail2ban-client status"echo "  • Check SSH jail: fail2ban-client status sshd"echo "  • View logs: tail -f /var/log/fail2ban.log"echo "  • Unban IP: fail2ban-client set sshd unbanip <IP>"echo "  • Restart service: systemctl restart fail2ban"echo "=================================="fiechoecho "🔧 Additional Tools:"echo "  • Security check: fail2ban-checking"echo "  • Status display: fail2ban-status" echo "  • Filter tester: fail2ban-tester"echoecho "🔧 Troubleshooting:"echo "  • Check service status: systemctl status fail2ban"echo "  • View logs: journalctl -u fail2ban -f"echo "  • Test configuration: fail2ban-client -d"echo "  • Check log files: tail -f /var/log/fail2ban.log"echo "  • Manual restart: systemctl restart fail2ban"echo "  • Check UFW integration: ufw status"if [ "$has_ipset" = true ]; thenecho "  • Check IPSet rules: ipset list"echo "  • Check firewall rules: iptables -L ufw-before-input -n"elseecho "  • Check firewall rules: iptables -L -n"fiecho "=================================="
}

总结:

因为我使用的 -1 永久封,造成内存中有几百条 iptables 记录,严重影响性能。 现在使用 IPset 做为一个池来集中管理。 也在修改之前的策略改为封20小时,这个脚本中可改。

这三个工具构成了一套层次化的网络安全防护体系,它们的协同工作过程如下:

角色分工

UFW (Uncomplicated Firewall):作为 iptables 的简化前端,负责基础防火墙规则管理和流量过滤的最终执行。

IPset:高效的 IP 地址集合管理工具,使用哈希表存储大量 IP 地址,提供 O(1) 时间复杂度的查找效率。

Fail2ban:智能入侵检测系统,监控日志文件、分析攻击模式、触发自动封禁动作。

核心工作流程

检测阶段

  1. 攻击者尝试连接服务(如SSH)
  2. 服务记录认证失败日志到 /var/log/auth.log
  3. Fail2ban 实时监控日志文件,使用正则表达式匹配攻击模式
  4. 计数器跟踪每个IP的失败次数

封禁阶段

  1. 当失败次数达到阈值(如 maxretry=3),Fail2ban 触发封禁动作
  2. 执行 IPset 命令:ipset add fail2ban-ssh 攻击者IP
  3. IP被添加到预先创建的IPset集合中
  4. UFW/iptables 规则立即生效:iptables -I INPUT -m set --match-set fail2ban-ssh src -j DROP

防护阶段

  1. 后续来自该IP的所有请求在内核层面被直接丢弃
  2. 不再消耗应用服务资源
  3. 根据配置的 bantime 自动解封或永久封禁

关键性能优势

传统方式的问题是每个被封IP需要单独的 iptables 规则,当封禁IP数量达到数千个时,规则匹配效率急剧下降。

IPset 优化方式只需要一条 iptables 规则引用整个IP集合,无论集合中有多少IP,查找效率都保持恒定。这种方式可以高效处理数万个封禁IP而不影响网络性能。

实际数据流

正常流量:外部请求 → UFW检查 → IPset查询(未命中) → 通过基础规则 → 到达服务

恶意流量:攻击请求 → UFW检查 → IPset查询(命中) → 直接丢弃数据包

这种架构的核心优势是将被动防护(UFW/iptables)与主动检测(Fail2ban)相结合,同时通过IPset解决了大规模IP封禁的性能瓶颈问题。整个系统实现了从攻击检测到自动响应的完全自动化,大大降低了管理员的工作负担。

收到 CSDN 消息:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/96081.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/96081.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux —— 虚拟进程地址空间

&#x1f381;个人主页&#xff1a;工藤新一 &#x1f50d;系列专栏&#xff1a;C面向对象&#xff08;类和对象篇&#xff09; &#x1f31f;心中的天空之城&#xff0c;终会照亮我前方的路 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 文章目录虚…

简单聊一聊js

JavaScript 是一种高级的、解释型的编程语言。它是现代 Web 开发的三大核心基石之一&#xff0c;与 HTML 和 CSS 并列。​HTML​&#xff1a;负责网页的结构和内容​&#xff08;如标题、段落、图片&#xff09;。​CSS​&#xff1a;负责网页的样式和布局​&#xff08;如颜色…

造粒机cad+设计说明书

摘要 随着现代化工业的快速发展&#xff0c;生产出大量的固体废弃物。这些废弃物对环境造成了很大的污染&#xff0c;因此需要采取有效的措施进行处理。机械强压式造粒机就是一种非常有效的处理工具&#xff0c;它可以将废渣、废料、饲料和化肥等材料通过机械强力挤压&#xff…

第五课 C#语言基本元素概览,初始类型,变量与方法,算法简介

熟悉C#语言要求&#xff1a;对构成C#语言的基本元素&#xff0c;随便拿出一个你都认识&#xff0c;对于常见基本元素&#xff0c;都能正确使用它 精通C#语言要求&#xff1a;对于构成C#语言的基本元素&#xff0c;随便拿出一个都会使用&#xff0c;对于常用基本元素&#xff0…

LLM学习:大模型基础——视觉大模型以及autodl使用

1、常见的VLM 在大模型中,VLM 是视觉语言模型(Vision-Language Model)的缩写,是一种多模态、生成式 AI 模型,能够理解和处理视频、图像和文本。 VLM 通过将大语言模型(LLM)与视觉编码器相结合构建而成,使 LLM 具有 “看” 的能力,从而可以处理并提供对提示中的…

Vue—路由配置中设置了meta.title,但页面标题仍然显示为“Vite App“?【让我来看看~】

路由配置中明明设置了meta.title&#xff0c;但是页面标题仍然显示为"Vite App"&#xff1f;这是因为仅仅在路由配置中设置meta.title是不够的&#xff0c;还需要在路由守卫中动态设置页面标题。需要做以下几件事来正确设置页面标题&#xff1a;1.首先更新HTML文件的…

【机器学习】综合实训(二)

项目五 电影评分预测【教学内容】使用 MovieLens 数据集&#xff0c;训练一个模型预测用户对电影的评分。主要有以下几个知识点&#xff1a;&#xff08;1&#xff09;数据加载与探索性分析&#xff08;EDA&#xff09;。&#xff08;2&#xff09;处理稀疏数据&#xff08;如用…

STM32 UART + DMA + 空闲中断使用中的帧错误(FE)问题及解决方案

STM32 UART + DMA + IDLE中断使用中的帧错误(FE)问题及解决方案 在我调试STM32H7串口空闲中断DMA接受时遇到了一个bug,这个现象发生在系统刚上电时,有个串口由于帧错误FE挂起了中断,之后在HAL_UART_IRQHandler这个全局中断处理函数结束后,所有的中断使能标志位都被清除了,经过…

TDengine 选择函数 BOTTOM() 用户手册

BOTTOM() 函数用户手册 函数定义 BOTTOM(expr, k)功能说明 BOTTOM() 函数统计表/超级表中某列的值最小 k 个非 NULL 值。如果多条数据取值一样&#xff0c;全部取用又会超出 k 条限制时&#xff0c;系统会从相同值中随机选取符合要求的数量返回。 返回值 数据类型: 同应用…

西门子 S7-200 SMART PLC 实现星三角降压启动控制:原理、案例与完整程序

在工业控制场景中&#xff0c;中型异步电机直接启动时会产生远超额定电流的冲击电流&#xff08;通常为额定电流的 5-7 倍&#xff09;&#xff0c;不仅会影响电网稳定性&#xff0c;还可能对机械设备造成损伤。星三角&#xff08;Y-Δ&#xff09;降压启动是解决这一问题的经典…

【Android】View 的基础知识

【Android】View 的基础知识 1. 什么是 View&#xff1f; View 是 Android 中所有UI组件的基础类。它表示屏幕上的一个矩形区域&#xff0c;负责绘制内容和处理用户交互事件。所有的 UI 组件&#xff08;如按钮、文本框等&#xff09;都是 View 的子类&#xff0c;而 ViewGroup…

西门子 S7-200 SMART PLC 实现电机点动与连续运行综合控制

在工业生产中&#xff0c;电机控制并非单一模式&#xff1a;调试设备时需要 “按动即转、松开即停” 的点动功能&#xff0c;正常生产时则需要 “一键启动、持续运行” 的连续控制。本文以西门子 S7-200 SMART PLC 为载体&#xff0c;详细讲解电机点动控制原理&#xff0c;并设…

如何解决pip安装报错ModuleNotFoundError: No module named ‘sphinx-rtd-theme’问题

【Python系列Bug修复PyCharm控制台pip install报错】如何解决pip安装报错ModuleNotFoundError: No module named ‘sphinx-rtd-theme’问题 摘要 在使用 PyCharm 开发 Python 项目时&#xff0c;pip install 报错是常见痛点。特别是在构建文档或引入第三方库时&#xff0c;开…

HakcMyVM-Literal

目录信息搜集漏洞利用权限提升信息搜集 主机发现 ┌──(kali㉿kali)-[~] └─$ nmap -sn 192.168.21.0/24 Nmap scan report for 192.168.21.5端口扫描 ┌──(kali㉿kali)-[~] └─$ nmap -sS -sV -O -p- 192.168.21.5 Starting Nmap 7.95 ( https://nmap.org ) a…

0904 类的继承

Part 1.梳理思维导图一.继承中的特殊成员函数1.构造函数父类的构造函数会被继承到子类中&#xff0c;在构造的顺序中&#xff0c;是先构造父类&#xff0c;再构造子类#include <iostream>using namespace std;class Father { public:string name; protected:int *age; pr…

PDF教程|如何把想要的网页保存下来?

前段时间有个小伙伴咨询了小白&#xff1a;领导想要某个网页的整个页面&#xff0c;有没有比较好的方法把它保存下来&#xff1f; 在他找到小白之前&#xff0c;这种事情他已经接到好几次了&#xff0c;每次都是怎么解决的呢&#xff1f;其实很简单&#xff0c;就是打开Word&a…

【bash】命令查看当前目录下文件个数

要用 ls 查看当前目录下的文件个数&#xff0c;可以结合 wc -l 来统计行数&#xff1a; ls -1 | wc -l说明&#xff1a; ls -1&#xff1a;以一行一个文件的方式列出。wc -l&#xff1a;统计行数&#xff0c;也就是文件/目录的数量。 ⚠️ 需要注意&#xff1a; 这个方法会把文…

「日拱一码」081 机器学习——梯度增强特征选择GBFS

目录 什么是梯度增强特征选择&#xff08;GBFS&#xff09; 为什么 GBM 适合做特征选择 GBFS 的一般步骤 代码示例 什么是梯度增强特征选择&#xff08;GBFS&#xff09; GBFS 并非一个像 Lasso 或随机森林那样有严格标准定义的独立算法&#xff0c;而是一种基于梯度提升机…

解构汇编, 万物起源

汇编的诞生汇编全景图核心主干: CPU架构主要分支: 语法和工具共同的地貌: 核心概念延伸: 跨平台 & 跨架构跨平台跨架构总结以 GAS vs. NASM 为例NASM 不支持跨架构 ≠ 无法在ARM架构上的系统安装汇编的诞生 机器语言的困境 早期的程序员直接使用机器语言进行编程机器语言由…

广州旅游网站系统 - 纯静态旅游展示平台

&#x1f31f; 广州旅游网站系统 - 纯静态旅游展示平台观世界才有世界观 - 一个集景区展示、旅游攻略、文化传播于一体的精美旅游网站&#x1f4cb; 项目概述 这是一个专注于广州旅游文化的纯静态网站系统&#xff0c;采用现代化的前端技术栈&#xff0c;为游客提供全方位的广州…