Shell脚本如何防止暴力破解SSH

wen 实用脚本 2

本文目录导读:

Shell脚本如何防止暴力破解SSH

  1. 使用fail2ban(推荐,但非纯Shell)
  2. 纯Shell脚本实现IP白名单
  3. 基于失败次数自动封禁
  4. 增强版:动态防火墙脚本
  5. SSH配置加固(最基础)
  6. 完整的防护脚本
  7. 使用建议

防止SSH暴力破解是服务器安全的重要一环,Shell脚本可以实现多种防护机制,以下是一些常见且有效的方法:

使用fail2ban(推荐,但非纯Shell)

虽然不是纯Shell,但这是最成熟的方法:

# 安装fail2ban
apt-get install fail2ban  # Debian/Ubuntu
yum install fail2ban      # CentOS/RHEL
# 配置SSH防护
cat > /etc/fail2ban/jail.local << 'EOF'
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
findtime = 600
EOF
systemctl restart fail2ban

纯Shell脚本实现IP白名单

#!/bin/bash
# IP白名单防护脚本
ALLOWED_IPS=("192.168.1.0/24" "10.0.0.0/8")
AUTH_LOG="/var/log/auth.log"
BAN_DURATION=3600  # 封禁时长(秒)
ban_ip() {
    local ip=$1
    echo "封禁IP: $ip"
    # 使用iptables封禁
    iptables -A INPUT -s $ip -j DROP
    # 定时解封
    (sleep $BAN_DURATION && iptables -D INPUT -s $ip -j DROP) &
}
# 监控日志
tail -f $AUTH_LOG | while read line; do
    if echo "$line" | grep -q "Failed password"; then
        ip=$(echo "$line" | grep -oP 'from \K(\d+\.\d+\.\d+\.\d+)')
        # 检查是否在白名单
        in_whitelist=false
        for allowed in "${ALLOWED_IPS[@]}"; do
            if [[ $ip =~ $allowed ]]; then
                in_whitelist=true
                break
            fi
        done
        if [ "$in_whitelist" = false ]; then
            ban_ip $ip
        fi
    fi
done

基于失败次数自动封禁

#!/bin/bash
# 失败次数阈值
MAX_ATTEMPTS=5
CHECK_INTERVAL=300  # 检查间隔(秒)
BAN_DURATION=3600
# 临时文件存储失败记录
FAIL_LOG="/tmp/ssh_failed_ips.txt"
check_and_ban() {
    while IFS= read -r line; do
        ip=$line
        attempts=$(grep -c "$ip" /var/log/auth.log | tail -n 100)
        if [ "$attempts" -ge "$MAX_ATTEMPTS" ]; then
            echo "IP $ip 超过失败次数,执行封禁"
            iptables -A INPUT -s $ip -j DROP
            echo "$ip" >> /tmp/banned_ips.txt
            # 定时解封
            (sleep $BAN_DURATION && 
             iptables -D INPUT -s $ip -j DROP &&
             sed -i "/$ip/d" /tmp/banned_ips.txt) &
        fi
    done < <(grep -oP 'Failed password for .* from \K(\d+\.\d+\.\d+\.\d+)' /var/log/auth.log | sort -u)
}
# 主循环
while true; do
    check_and_ban
    sleep $CHECK_INTERVAL
done

增强版:动态防火墙脚本

#!/bin/bash
# 配置
MAX_ATTEMPTS=3
BAN_TIME=3600
WHITELIST=(192.168.1.100 10.0.0.50)
LOG_FILE="/var/log/auth.log"
BAN_LOG="/var/log/ssh_ban.log"
# 获取需要监控的IP列表
get_offending_ips() {
    # 分析30分钟内的失败登录
    grep "Failed password" $LOG_FILE | \
    awk '{print $(NF-3)}' | \
    sort | uniq -c | \
    awk -v max="$MAX_ATTEMPTS" '$1 >= max {print $2}'
}
# 白名单过滤
is_whitelisted() {
    local ip=$1
    for whitelist_ip in "${WHITELIST[@]}"; do
        if [ "$ip" = "$whitelist_ip" ]; then
            return 0
        fi
    done
    return 1
}
# 封禁IP
ban_ip() {
    local ip=$1
    if ! iptables -C INPUT -s $ip -j DROP 2>/dev/null; then
        iptables -A INPUT -s $ip -j DROP
        echo "$(date) - 封禁IP: $ip" >> $BAN_LOG
        # 异步解封
        (sleep $BAN_TIME && 
         iptables -D INPUT -s $ip -j DROP && 
         echo "$(date) - 解封IP: $ip" >> $BAN_LOG)&
    fi
}
# 主逻辑
main() {
    local offending_ips=$(get_offending_ips)
    for ip in $offending_ips; do
        if ! is_whitelisted $ip; then
            ban_ip $ip
        fi
    done
}
# 设置定时执行
while true; do
    main
    sleep 300  # 每5分钟检查一次
done

SSH配置加固(最基础)

#!/bin/bash
# SSH配置加固脚本
SSHD_CONFIG="/etc/ssh/sshd_config"
# 备份原配置
cp $SSHD_CONFIG ${SSHD_CONFIG}.bak
# 应用安全配置
cat >> $SSHD_CONFIG << 'EOF'
# 限制登录尝试
MaxAuthTries 3
MaxSessions 2
# 禁止root直接登录
PermitRootLogin no
# 使用密钥登录(推荐)
PasswordAuthentication no
PubkeyAuthentication yes
# 限制登录用户
AllowUsers your_username
DenyUsers root
# 限制IP
ListenAddress 192.168.1.0/24
# 超时设置
ClientAliveInterval 300
ClientAliveCountMax 2
EOF
# 重启SSH服务
systemctl restart sshd

完整的防护脚本

#!/bin/bash
# ==================== 配置 ====================
SSH_PORT=22
MAX_ATTEMPTS=5
BAN_TIME=86400  # 24小时
CHECK_INTERVAL=60
LOG_FILE="/var/log/auth.log"
BANNED_FILE="/tmp/ssh_banned_ips.txt"
WHITELIST_FILE="/etc/ssh_whitelist.txt"
# ==============================================
# 初始化
init() {
    # 创建必要文件
    [ ! -f $BANNED_FILE ] && touch $BANNED_FILE
    [ ! -f $WHITELIST_FILE ] && touch $WHITELIST_FILE
    # 加载白名单
    mapfile -t WHITELIST < $WHITELIST_FILE 2>/dev/null
}
# 日志记录
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> /var/log/ssh_protect.log
}
# 检查IP是否已封禁
is_banned() {
    grep -q "$1" $BANNED_FILE
}
# 检查IP是否在白名单
in_whitelist() {
    local ip=$1
    for wl_ip in "${WHITELIST[@]}"; do
        [ "$ip" = "$wl_ip" ] && return 0
    done
    return 1
}
# 封禁IP
ban_ip() {
    local ip=$1
    local reason="$2"
    if ! is_banned "$ip" && ! in_whitelist "$ip"; then
        # 使用iptables封禁
        iptables -A INPUT -p tcp --dport $SSH_PORT -s $ip -j DROP
        echo "$ip" >> $BANNED_FILE
        log "封禁IP: $ip - 原因: $reason"
        # 定时解封
        (sleep $BAN_TIME && 
         iptables -D INPUT -p tcp --dport $SSH_PORT -s $ip -j DROP 2>/dev/null &&
         sed -i "/^$ip$/d" $BANNED_FILE &&
         log "解封IP: $ip") &
    fi
}
# 分析日志并封禁
analyze_and_ban() {
    # 获取最近失败的登录IP及其次数
    local failed_ips=$(grep "Failed password" $LOG_FILE | \
                       grep -oP 'from \K(\d+\.\d+\.\d+\.\d+)')
    # 统计每个IP的失败次数
    echo "$failed_ips" | sort | uniq -c | \
    while read count ip; do
        count=$(echo $count | tr -d ' ')
        if [ "$count" -ge "$MAX_ATTEMPTS" ]; then
            ban_ip "$ip" "失败登录${count}次"
        fi
    done
}
# 监控实时日志
monitor_realtime() {
    tail -f $LOG_FILE | while read line; do
        if echo "$line" | grep -q "Failed password"; then
            ip=$(echo "$line" | grep -oP 'from \K(\d+\.\d+\.\d+\.\d+)')
            # 检查短时间内是否再次失败
            local recent_fails=$(grep "$ip" $LOG_FILE | grep "Failed password" | \
                               awk -v date="$(date -d '5 minutes ago' '+%b %d %H:%M')" \
                               '$0 > date' | wc -l)
            if [ "$recent_fails" -ge "$MAX_ATTEMPTS" ]; then
                ban_ip "$ip" "5分钟内失败${recent_fails}次"
            fi
        fi
    done
}
# 清理过期封禁
cleanup() {
    while IFS= read -r ip; do
        if [ -n "$ip" ]; then
            # 检查iptables规则是否还在
            if iptables -C INPUT -p tcp --dport $SSH_PORT -s $ip -j DROP 2>/dev/null; then
                # 检查是否超时(这里简化处理,实际应用中需要记录封禁时间)
                log "清理检查IP: $ip"
            fi
        fi
    done < $BANNED_FILE
}
# 主函数
main() {
    init
    log "SSH防暴力破解脚本启动"
    # 启动定时检查和实时监控
    while true; do
        analyze_and_ban
        cleanup
        sleep $CHECK_INTERVAL
    done &
    # 实时监控
    monitor_realtime
}
# 执行
main

使用建议

  1. 先测试:在非生产环境测试脚本
  2. 保留备用通道:不要在测试完成前完全禁止密码登录
  3. 结合多种方法:脚本+ fail2ban + 安全配置
  4. 监控和日志:定期检查封禁日志
  5. 定期更新白名单:确保合法用户不被误封

这些脚本可以根据实际需求调整参数,建议先在测试环境验证,确保不会误封合法用户。

抱歉,评论功能暂时关闭!