#!/bin/bash # 用法: # 启用安全模式: ./00-password.sh enable # 关闭安全模式: ./00-password.sh disable # 查看状态: ./00-password.sh status # # curl -sS -O https://gitea.tohub.top/Share/vps/raw/branch/main/init/00-password.sh && chmod +x 00-password.sh set -e # 遇到错误立即退出 # 颜色输出 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # 日志函数 log_info() { echo -e "${GREEN}[INFO]${NC} $1" } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } log_status() { echo -e "${BLUE}[STATUS]${NC} $1" } # 用户设置 NEW_SSH_PORT="4399" # 根据需求修改端口 DEFAULT_SSH_PORT="22" BACKUP_DIR="/root/ssh_backup_$(date +%Y%m%d_%H%M%S)" PERSISTENT_BACKUP_DIR="/root/ssh_config_backup" # 检查是否为root用户 if [ "$EUID" -ne 0 ]; then log_error "请使用 root 用户运行此脚本" exit 1 fi # 显示使用帮助 show_usage() { echo "用法: $0 {enable|disable|status}" echo "" echo "命令:" echo " enable - 启用 SSH 安全模式(禁用密码登录,使用密钥认证)" echo " disable - 关闭 SSH 安全模式(恢复密码登录)" echo " status - 查看当前 SSH 配置状态" echo "" echo "示例:" echo " $0 enable # 启用安全模式" echo " $0 disable # 关闭安全模式" echo " $0 status # 查看状态" exit 1 } # 获取当前SSH配置状态 get_ssh_config_value() { local key=$1 local config_file="/etc/ssh/sshd_config" # 获取配置值(忽略注释行) grep "^${key}" "$config_file" 2>/dev/null | awk '{print $2}' | head -n1 } # 检查当前状态 check_current_status() { local port=$(get_ssh_config_value "Port") local password_auth=$(get_ssh_config_value "PasswordAuthentication") local pubkey_auth=$(get_ssh_config_value "PubkeyAuthentication") local permit_root=$(get_ssh_config_value "PermitRootLogin") # 默认值 port=${port:-22} password_auth=${password_auth:-yes} pubkey_auth=${pubkey_auth:-yes} permit_root=${permit_root:-yes} echo "当前 SSH 配置状态:" echo "----------------------------------------" echo " SSH 端口: $port" echo " 密码认证: $password_auth" echo " 公钥认证: $pubkey_auth" echo " Root登录: $permit_root" echo "----------------------------------------" # 判断是否为安全模式 if [[ "$password_auth" == "no" ]] && [[ "$pubkey_auth" == "yes" ]]; then log_status "当前处于【安全模式】- 密码登录已禁用" return 0 # 安全模式 else log_status "当前处于【普通模式】- 密码登录已启用" return 1 # 普通模式 fi } # 显示状态 show_status() { log_info "正在检查 SSH 配置状态..." echo "" check_current_status # 检查是否有备份 if [ -d "$PERSISTENT_BACKUP_DIR" ] && [ -f "$PERSISTENT_BACKUP_DIR/sshd_config.original" ]; then echo "" log_info "找到配置备份: $PERSISTENT_BACKUP_DIR" fi } # 创建持久化备份 create_persistent_backup() { if [ ! -d "$PERSISTENT_BACKUP_DIR" ]; then mkdir -p "$PERSISTENT_BACKUP_DIR" cp /etc/ssh/sshd_config "$PERSISTENT_BACKUP_DIR/sshd_config.original" log_info "已创建原始配置备份: $PERSISTENT_BACKUP_DIR/sshd_config.original" else log_info "使用现有配置备份: $PERSISTENT_BACKUP_DIR" fi } # 1. 检查公钥是否存在 check_ssh_keys() { log_info "检查 SSH 公钥..." if [ ! -f ~/.ssh/authorized_keys ] || [ ! -s ~/.ssh/authorized_keys ]; then log_error "未找到 SSH 公钥文件或文件为空!" log_error "路径: ~/.ssh/authorized_keys" echo "" log_warn "如果继续,您将无法通过 SSH 登录服务器!" read -p "是否要继续?(输入 YES 继续): " confirm if [ "$confirm" != "YES" ]; then log_info "操作已取消" exit 0 fi else log_info "找到 SSH 公钥,密钥数量: $(grep -c "^ssh-" ~/.ssh/authorized_keys || echo 0)" echo "密钥内容预览:" head -n 2 ~/.ssh/authorized_keys fi } # 2. 检查端口是否被占用 check_port() { local port=$1 log_info "检查端口 $port 是否可用..." if ss -tlnp 2>/dev/null | grep -q ":$port " || netstat -tlnp 2>/dev/null | grep -q ":$port "; then # 检查是否是SSH服务占用 if ss -tlnp 2>/dev/null | grep ":$port " | grep -q "sshd" || netstat -tlnp 2>/dev/null | grep ":$port " | grep -q "sshd"; then log_info "端口 $port 已被 SSH 服务占用(正常)" else log_error "端口 $port 已被其他服务占用!" ss -tlnp 2>/dev/null | grep ":$port " || netstat -tlnp 2>/dev/null | grep ":$port " exit 1 fi else log_info "端口 $port 可用" fi } # 3. 修改SSH配置 modify_ssh_config() { local mode=$1 # enable 或 disable log_info "开始配置 SSH..." # 创建临时备份目录 mkdir -p "$BACKUP_DIR" # 备份原始配置 cp /etc/ssh/sshd_config "$BACKUP_DIR/sshd_config.bak" log_info "已备份 SSH 配置到: $BACKUP_DIR/sshd_config.bak" # 创建新配置 cp /etc/ssh/sshd_config /etc/ssh/sshd_config.tmp if [ "$mode" == "enable" ]; then log_info "配置安全模式..." # 1. 禁止 root 密码登录,但允许密钥登录 if grep -q "^PermitRootLogin" /etc/ssh/sshd_config.tmp; then sed -i 's/^PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config.tmp else sed -i 's/^#PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config.tmp fi # 2. 禁用密码认证 if grep -q "^PasswordAuthentication" /etc/ssh/sshd_config.tmp; then sed -i 's/^PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config.tmp else sed -i 's/^#PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config.tmp fi # 3. 启用公钥认证 if grep -q "^PubkeyAuthentication" /etc/ssh/sshd_config.tmp; then sed -i 's/^PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config.tmp else sed -i 's/^#PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config.tmp fi # 4. 修改端口 if grep -q "^Port " /etc/ssh/sshd_config.tmp; then sed -i "s/^Port [0-9]\+/Port $NEW_SSH_PORT/" /etc/ssh/sshd_config.tmp else sed -i "s/^#Port 22/Port $NEW_SSH_PORT/" /etc/ssh/sshd_config.tmp fi # 5. 额外的安全加固 # 禁用空密码 if grep -q "^PermitEmptyPasswords" /etc/ssh/sshd_config.tmp; then sed -i 's/^PermitEmptyPasswords.*/PermitEmptyPasswords no/' /etc/ssh/sshd_config.tmp else sed -i 's/^#PermitEmptyPasswords.*/PermitEmptyPasswords no/' /etc/ssh/sshd_config.tmp fi # 禁用质询响应认证 if grep -q "^ChallengeResponseAuthentication" /etc/ssh/sshd_config.tmp; then sed -i 's/^ChallengeResponseAuthentication.*/ChallengeResponseAuthentication no/' /etc/ssh/sshd_config.tmp fi elif [ "$mode" == "disable" ]; then log_info "配置普通模式(允许密码登录)..." # 如果有原始备份,直接恢复 if [ -f "$PERSISTENT_BACKUP_DIR/sshd_config.original" ]; then log_info "从原始备份恢复配置..." cp "$PERSISTENT_BACKUP_DIR/sshd_config.original" /etc/ssh/sshd_config.tmp else # 手动修改为允许密码登录 log_info "手动修改配置..." # 1. 允许 root 密码登录 if grep -q "^PermitRootLogin" /etc/ssh/sshd_config.tmp; then sed -i 's/^PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config.tmp else sed -i 's/^#PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config.tmp fi # 2. 启用密码认证 if grep -q "^PasswordAuthentication" /etc/ssh/sshd_config.tmp; then sed -i 's/^PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config.tmp else sed -i 's/^#PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config.tmp fi # 3. 启用公钥认证(保持) if grep -q "^PubkeyAuthentication" /etc/ssh/sshd_config.tmp; then sed -i 's/^PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config.tmp else sed -i 's/^#PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config.tmp fi # 4. 恢复默认端口 if grep -q "^Port " /etc/ssh/sshd_config.tmp; then sed -i "s/^Port [0-9]\+/Port $DEFAULT_SSH_PORT/" /etc/ssh/sshd_config.tmp fi fi fi # 验证配置文件语法 log_info "验证 SSH 配置文件语法..." if sshd -t -f /etc/ssh/sshd_config.tmp; then log_info "SSH 配置文件语法正确" mv /etc/ssh/sshd_config.tmp /etc/ssh/sshd_config else log_error "SSH 配置文件语法错误!" rm /etc/ssh/sshd_config.tmp exit 1 fi } # 4. 重启 SSH 服务(兼容多种系统) restart_ssh() { log_info "重启 SSH 服务..." # 保持当前连接 log_warn "注意: SSH 服务将重启,但当前连接会保持" if command -v systemctl &> /dev/null; then systemctl restart sshd || systemctl restart ssh log_info "SSH 服务已通过 systemctl 重启" elif command -v service &> /dev/null; then service sshd restart || service ssh restart log_info "SSH 服务已通过 service 重启" else /etc/init.d/sshd restart || /etc/init.d/ssh restart log_info "SSH 服务已通过 init.d 重启" fi } # 5. 配置防火墙(启用模式) configure_firewall_enable() { log_info "配置防火墙..." # 检查系统并安装 UFW if ! command -v ufw &> /dev/null; then log_info "安装 UFW 防火墙..." apt-get update -y && apt-get install -y ufw fi # 备份当前防火墙规则 mkdir -p "$BACKUP_DIR" ufw status numbered > "$BACKUP_DIR/ufw_rules.bak" 2>/dev/null || true # 配置防火墙规则 log_info "设置防火墙规则..." # 先允许新端口,避免锁死 ufw allow $NEW_SSH_PORT/tcp comment "SSH" # 询问是否允许其他常用端口 read -p "是否允许 HTTP (80) 和 HTTPS (443) 端口? (y/n): " allow_web if [[ $allow_web =~ ^[Yy]$ ]]; then ufw allow 80/tcp comment "HTTP" ufw allow 443/tcp comment "HTTPS" log_info "已允许 HTTP 和 HTTPS 端口" fi # 启用防火墙 ufw --force enable log_info "防火墙状态:" ufw status verbose } # 6. 配置防火墙(禁用模式) configure_firewall_disable() { log_info "恢复防火墙配置..." if ! command -v ufw &> /dev/null; then log_info "未安装 UFW,跳过防火墙配置" return fi # 允许默认SSH端口 ufw allow $DEFAULT_SSH_PORT/tcp comment "SSH" log_info "已允许默认 SSH 端口 $DEFAULT_SSH_PORT" # 询问是否删除自定义端口规则 read -p "是否删除自定义 SSH 端口 $NEW_SSH_PORT 的防火墙规则? (y/n): " remove_port if [[ $remove_port =~ ^[Yy]$ ]]; then ufw delete allow $NEW_SSH_PORT/tcp 2>/dev/null || true log_info "已删除端口 $NEW_SSH_PORT 的防火墙规则" fi ufw status verbose } # 启用安全模式 enable_security() { log_info "=== 启用 SSH 安全模式 ===" echo "" # 检查当前状态 if check_current_status > /dev/null 2>&1; then log_warn "SSH 已经处于安全模式" read -p "是否要重新配置? (y/n): " reconfig if [[ ! $reconfig =~ ^[Yy]$ ]]; then log_info "操作已取消" exit 0 fi fi # 显示当前配置 log_info "当前 SSH 配置:" echo " - 当前端口: $(get_ssh_config_value "Port" || echo "22 (默认)")" echo " - 将修改为: $NEW_SSH_PORT" echo "" # 确认执行 read -p "是否继续执行? (y/n): " confirm if [[ ! $confirm =~ ^[Yy]$ ]]; then log_info "操作已取消" exit 0 fi # 创建持久化备份 create_persistent_backup # 执行配置 check_ssh_keys check_port "$NEW_SSH_PORT" modify_ssh_config "enable" restart_ssh configure_firewall_enable # 显示完成信息 echo "" echo "========================================" log_info "SSH 安全模式已启用!" echo "========================================" echo "" echo "修改后的配置:" echo " - SSH 端口: $NEW_SSH_PORT" echo " - 密码登录: 已禁用" echo " - 密钥登录: 已启用" echo " - Root 密码登录: 已禁用" echo "" echo "备份信息:" echo " - 临时备份: $BACKUP_DIR" echo " - 永久备份: $PERSISTENT_BACKUP_DIR" echo "" echo "重要提示:" echo " 1. 请勿关闭当前 SSH 连接" echo " 2. 在新终端测试登录: ssh -p $NEW_SSH_PORT root@your_server_ip" echo " 3. 确认新连接成功后再关闭此窗口" echo " 4. 如需恢复,运行: $0 disable" echo "" echo "========================================" } # 关闭安全模式 disable_security() { log_info "=== 关闭 SSH 安全模式 ===" echo "" # 检查当前状态 if ! check_current_status > /dev/null 2>&1; then log_warn "SSH 已经处于普通模式" read -p "是否要重新配置? (y/n): " reconfig if [[ ! $reconfig =~ ^[Yy]$ ]]; then log_info "操作已取消" exit 0 fi fi # 警告 log_warn "警告: 此操作将允许密码登录,安全性会降低!" read -p "确认要关闭安全模式吗? (输入 YES 继续): " confirm if [ "$confirm" != "YES" ]; then log_info "操作已取消" exit 0 fi # 执行配置 check_port "$DEFAULT_SSH_PORT" modify_ssh_config "disable" restart_ssh configure_firewall_disable # 显示完成信息 echo "" echo "========================================" log_info "SSH 安全模式已关闭!" echo "========================================" echo "" echo "修改后的配置:" echo " - SSH 端口: $DEFAULT_SSH_PORT" echo " - 密码登录: 已启用" echo " - 密钥登录: 已启用" echo "" echo "重要提示:" echo " 1. 请勿关闭当前 SSH 连接" echo " 2. 在新终端测试登录: ssh -p $DEFAULT_SSH_PORT root@your_server_ip" echo " 3. 确认新连接成功后再关闭此窗口" echo " 4. 如需重新启用安全模式,运行: $0 enable" echo "" echo "========================================" } # 主流程 main() { local action=${1:-} case "$action" in enable) enable_security ;; disable) disable_security ;; status) show_status ;; *) show_usage ;; esac } # 执行主函数 main "$@"