1. 通过日志排查

通过 cat /var/log/secure 可以来获取登录失败的原因。实际中可以通过以下命令实时监控:

tail -n 0 -f /var/log/secure

1.1 具体例子

[root@VM-16-33-centos ~]# sudo tail -f /var/log/secure
Jul  3 15:51:50 VM-16-33-centos sshd[7449]: Connection closed by 44.220.132.166
Jul  3 15:52:58 VM-16-33-centos sshd[7304]: Received signal 15; terminating.
Jul  3 15:52:58 VM-16-33-centos sshd[7840]: Server listening on 0.0.0.0 port 22.
Jul  3 15:53:01 VM-16-33-centos sshd[7868]: User root from 113.108.77.60 not allowed because not listed in AllowUsers
Jul  3 15:53:01 VM-16-33-centos sshd[7869]: input_userauth_request: invalid user root
Jul  3 15:53:01 VM-16-33-centos sshd[7869]: userauth_pubkey: unsupported public key algorithm: ssh-ed25519
Jul  3 15:53:03 VM-16-33-centos sshd[7868]: error: Could not get shadow information for NOUSER
Jul  3 15:53:03 VM-16-33-centos sshd[7868]: Failed password for invalid user root from 113.108.77.60 port 33401 ssh2
Jul  3 15:53:05 VM-16-33-centos sshd[7868]: Failed password for invalid user root from 113.108.77.60 port 33401 ssh2
Jul  3 15:53:43 VM-16-33-centos sudo:     root : TTY=pts/0 ; PWD=/root ; USER=root ; COMMAND=/usr/bin/tail -f /var/log/secure

日志分析

/var/log/secure 日志中,我们可以看到以下关键信息:

Jul  3 15:53:01 VM-16-33-centos sshd[7868]: User root from 113.108.77.60 not allowed because not listed in AllowUsers

这行日志表明,root 用户的 SSH 登录被拒绝,因为它没有被列在 AllowUsers 配置中。具体来说,SSH 服务的配置文件中设置了 AllowUsers 参数,限制了哪些用户可以通过 SSH 登录。由于 root 不在 AllowUsers 列表中,尝试从 113.108.77.60 地址登录时,系统拒绝了该请求。

解决方法

  1. 修改 sshd_config 文件,允许 root 用户登录

    /etc/ssh/sshd_config 文件中,找到并修改 AllowUsers 设置,确保 root 用户被允许登录。比如:

    AllowUsers root <other_usernames>
    

    如果没有 AllowUsers 设置,你可以添加它。确保没有其他限制,允许 root 登录。

  2. 重启 SSH 服务

    修改 sshd_config 文件后,记得重启 SSH 服务以使更改生效:

    sudo systemctl restart sshd
    

来实时获取对应的内容,并将结果扔给大模型,就可以很好的排查出问题。

2. PermitRootLogin

参数 PermitRootLogin 设置为 no 或者 prohibit-password 都会导致无法登录 SSH。

对应的 /var/log/secure 的报错如下:

PermitRootLogin yes  # 允许root用户登录
Jul  3 16:07:10 VM-16-33-centos sshd[13295]: Failed password for root from 113.108.77.60 port 27180 ssh2

3. UsePAM

/etc/ssh/sshd_config 中,参数 UsePAM no 表示禁用PAM认证,也就是SSH认证将完全依赖于 sshd_config 的配置文件。

UsePAM no

4. AllowUsers(DenyUsers)

AllowUsers 参数控制哪些用户可以通过SSH登录,可以指定多名用户:

AllowUsers root tester

也可以指定特定IP地址的用户:

AllowUsers root@47.107.126.252

5. AllowGroups(DenyGroups)

AllowGroups 参数控制哪些用户组可以通过SSH登录,可以指定多个用户组:

AllowGroups root tester

也可以指定特定IP地址的用户组:

AllowGroups root@47.107.126.252

6. 权限优先级说明

AllowUsers 的设置会优先于 DenyGroups

在这种情况下 test 用户依旧可以登录,但是 test 用户组下的非 test 用户无法登录:

AllowUsers test
DenyGroups test

7. 一键配置脚本(当无法通过ssh登录时)

#!/bin/bash

# SSH安全配置脚本
# 作者: SSH配置助手
# 版本: 1.0
# 用途: 自动配置SSH服务器安全设置

set -euo pipefail  # 严格模式

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 配置变量
SSH_CONFIG="/etc/ssh/sshd_config"
BACKUP_DIR="/etc/ssh/backup"
LOG_FILE="/var/log/ssh_config.log"
TIMESTAMP=$(date '+%Y%m%d_%H%M%S')

# 日志函数
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}

# 打印带颜色的消息
print_message() {
    local color=$1
    local message=$2
    echo -e "${color}${message}${NC}"
}

# 检查是否为root用户
check_root() {
    if [[ $EUID -ne 0 ]]; then
        print_message "$RED" "错误: 此脚本需要root权限运行"
        exit 1
    fi
}

# 创建备份目录
create_backup_dir() {
    if [[ ! -d "$BACKUP_DIR" ]]; then
        mkdir -p "$BACKUP_DIR"
        print_message "$GREEN" "已创建备份目录: $BACKUP_DIR"
    fi
}

# 备份当前SSH配置
backup_ssh_config() {
    local backup_file="${BACKUP_DIR}/sshd_config_${TIMESTAMP}"
    
    if [[ -f "$SSH_CONFIG" ]]; then
        cp "$SSH_CONFIG" "$backup_file"
        print_message "$GREEN" "已备份SSH配置到: $backup_file"
        log "备份SSH配置: $backup_file"
        return 0
    else
        print_message "$RED" "错误: SSH配置文件不存在: $SSH_CONFIG"
        return 1
    fi
}

# 应用SSH配置
apply_ssh_config() {
    print_message "$BLUE" "正在应用SSH配置..."
    
    cat > "$SSH_CONFIG" << 'EOF'
# SSH服务器配置文件
# 由SSH配置脚本自动生成

# ==================== 基础配置 ====================
Port 22
Protocol 2

# ==================== 认证配置 ====================
# 允许root登录(谨慎使用)
PermitRootLogin yes

# 禁用空密码
PermitEmptyPasswords no

# 启用密码认证
PasswordAuthentication yes

# 启用公钥认证
PubkeyAuthentication yes

# ==================== PAM配置 ====================
# 禁用PAM认证
UsePAM no

# ==================== 用户和组控制 ====================
# 允许特定用户登录
AllowUsers root

# 允许特定用户组登录
AllowGroups root

# ==================== 安全增强配置 ====================
# 最大认证尝试次数
MaxAuthTries 3

# 最大会话数
MaxSessions 10

# 登录宽限时间
LoginGraceTime 60

# 客户端存活检测
ClientAliveInterval 300
ClientAliveCountMax 3

# ==================== 其他安全设置 ====================
# 禁用DNS反向解析(提高连接速度)
UseDNS no

# 禁用GSSAPI认证(提高连接速度)
GSSAPIAuthentication no

# 启用严格模式
StrictModes yes

# 设置日志级别
LogLevel INFO

# 禁用用户环境处理
PermitUserEnvironment no

# 压缩延迟
Compression delayed
EOF

    print_message "$GREEN" "SSH配置已应用"
    log "SSH配置已更新"
}

# 验证SSH配置
validate_ssh_config() {
    print_message "$BLUE" "正在验证SSH配置..."
    
    if sshd -t -f "$SSH_CONFIG" 2>/dev/null; then
        print_message "$GREEN" "SSH配置验证通过"
        log "SSH配置验证成功"
        return 0
    else
        print_message "$RED" "SSH配置验证失败"
        sshd -t -f "$SSH_CONFIG"
        log "SSH配置验证失败"
        return 1
    fi
}

# 重启SSH服务
restart_ssh_service() {
    print_message "$BLUE" "正在重启SSH服务..."
    
    # 检测系统类型并重启服务
    if command -v systemctl >/dev/null 2>&1; then
        if systemctl restart sshd; then
            print_message "$GREEN" "SSH服务重启成功 (systemctl)"
            log "SSH服务重启成功"
            return 0
        else
            print_message "$RED" "SSH服务重启失败"
            return 1
        fi
    elif command -v service >/dev/null 2>&1; then
        if service sshd restart; then
            print_message "$GREEN" "SSH服务重启成功 (service)"
            log "SSH服务重启成功"
            return 0
        else
            print_message "$RED" "SSH服务重启失败"
            return 1
        fi
    else
        print_message "$RED" "无法找到适当的服务管理命令"
        return 1
    fi
}

# 检查SSH服务状态
check_ssh_status() {
    print_message "$BLUE" "检查SSH服务状态..."
    
    if command -v systemctl >/dev/null 2>&1; then
        systemctl status sshd --no-pager -l
    elif command -v service >/dev/null 2>&1; then
        service sshd status
    fi
    
    # 检查端口监听
    if netstat -tlnp 2>/dev/null | grep -q ":22 "; then
        print_message "$GREEN" "SSH服务正在监听端口22"
    else
        print_message "$YELLOW" "警告: SSH服务可能未正确监听端口22"
    fi
}

# 显示配置摘要
show_config_summary() {
    print_message "$BLUE" "==================== 配置摘要 ===================="
    echo "端口: 22"
    echo "Root登录: 允许"
    echo "密码认证: 启用"
    echo "公钥认证: 启用"
    echo "PAM认证: 禁用"
    echo "允许用户: root"
    echo "允许用户组: root"
    echo "最大尝试次数: 3"
    echo "最大会话数: 10"
    echo "客户端存活检测: 300秒"
    print_message "$BLUE" "=================================================="
}

# 安全提示
show_security_warnings() {
    print_message "$YELLOW" "==================== 安全提示 ===================="
    print_message "$YELLOW" "1. 已禁用PAM认证,请确保其他安全措施到位"
    print_message "$YELLOW" "2. 允许root登录存在安全风险,建议使用普通用户+sudo"
    print_message "$YELLOW" "3. 建议配置防火墙限制SSH访问来源"
    print_message "$YELLOW" "4. 定期检查SSH登录日志: /var/log/secure"
    print_message "$YELLOW" "5. 考虑使用非标准端口提高安全性"
    print_message "$YELLOW" "=================================================="
}

# 回滚功能
rollback_config() {
    local latest_backup=$(ls -t "${BACKUP_DIR}"/sshd_config_* 2>/dev/null | head -n1)
    
    if [[ -n "$latest_backup" ]]; then
        print_message "$YELLOW" "找到备份文件: $latest_backup"
        read -p "是否要回滚到此配置? (y/N): " -n 1 -r
        echo
        
        if [[ $REPLY =~ ^[Yy]$ ]]; then
            cp "$latest_backup" "$SSH_CONFIG"
            if validate_ssh_config && restart_ssh_service; then
                print_message "$GREEN" "配置已成功回滚"
                log "配置回滚成功: $latest_backup"
            else
                print_message "$RED" "回滚失败"
                return 1
            fi
        fi
    else
        print_message "$RED" "未找到备份文件"
        return 1
    fi
}

# 测试SSH连接
test_ssh_connection() {
    print_message "$BLUE" "测试SSH连接..."
    
    # 获取本机IP
    local local_ip=$(hostname -I | awk '{print $1}')
    
    print_message "$YELLOW" "请在另一个终端测试SSH连接:"
    print_message "$YELLOW" "ssh root@${local_ip}"
    print_message "$YELLOW" "ssh root@localhost"
    
    read -p "测试完成后按Enter继续..."
}

# 主菜单
show_menu() {
    clear
    print_message "$BLUE" "==================== SSH配置管理脚本 ===================="
    echo "1. 应用SSH配置"
    echo "2. 验证当前配置"
    echo "3. 重启SSH服务"
    echo "4. 查看服务状态"
    echo "5. 显示配置摘要"
    echo "6. 回滚配置"
    echo "7. 测试SSH连接"
    echo "8. 查看备份文件"
    echo "9. 退出"
    print_message "$BLUE" "=========================================================="
}

# 查看备份文件
show_backups() {
    print_message "$BLUE" "备份文件列表:"
    if ls "${BACKUP_DIR}"/sshd_config_* 2>/dev/null; then
        echo
        print_message "$BLUE" "选择要查看的备份文件编号,或按Enter返回:"
        select backup in "${BACKUP_DIR}"/sshd_config_*; do
            if [[ -n "$backup" ]]; then
                print_message "$GREEN" "查看备份文件: $backup"
                echo "----------------------------------------"
                cat "$backup"
                echo "----------------------------------------"
                read -p "按Enter继续..."
            fi
            break
        done
    else
        print_message "$YELLOW" "未找到备份文件"
    fi
}

# 主程序
main() {
    # 检查权限
    check_root
    
    # 创建日志文件
    touch "$LOG_FILE"
    log "SSH配置脚本启动"
    
    # 创建备份目录
    create_backup_dir
    
    # 如果提供了参数,直接执行
    if [[ $# -gt 0 ]]; then
        case "$1" in
            "apply")
                backup_ssh_config
                apply_ssh_config
                validate_ssh_config && restart_ssh_service
                show_config_summary
                show_security_warnings
                ;;
            "rollback")
                rollback_config
                ;;
            "validate")
                validate_ssh_config
                ;;
            *)
                echo "用法: $0 [apply|rollback|validate]"
                exit 1
                ;;
        esac
        exit 0
    fi
    
    # 交互式菜单
    while true; do
        show_menu
        read -p "请选择操作 (1-9): " choice
        
        case "$choice" in
            1)
                print_message "$YELLOW" "警告: 此操作将覆盖当前SSH配置"
                read -p "是否继续? (y/N): " -n 1 -r
                echo
                if [[ $REPLY =~ ^[Yy]$ ]]; then
                    backup_ssh_config
                    apply_ssh_config
                    if validate_ssh_config; then
                        restart_ssh_service
                        show_config_summary
                        show_security_warnings
                    else
                        print_message "$RED" "配置验证失败,请检查配置"
                    fi
                fi
                read -p "按Enter继续..."
                ;;
            2)
                validate_ssh_config
                read -p "按Enter继续..."
                ;;
            3)
                restart_ssh_service
                read -p "按Enter继续..."
                ;;
            4)
                check_ssh_status
                read -p "按Enter继续..."
                ;;
            5)
                show_config_summary
                read -p "按Enter继续..."
                ;;
            6)
                rollback_config
                read -p "按Enter继续..."
                ;;
            7)
                test_ssh_connection
                ;;
            8)
                show_backups
                read -p "按Enter继续..."
                ;;
            9)
                print_message "$GREEN" "退出脚本"
                log "SSH配置脚本退出"
                exit 0
                ;;
            *)
                print_message "$RED" "无效选择,请重试"
                read -p "按Enter继续..."
                ;;
        esac
    done
}

# 信号处理
trap 'print_message "$RED" "\n脚本被中断"; exit 1' INT TERM

# 启动主程序
main "$@"
Logo

一站式 AI 云服务平台

更多推荐