Files
vps/init/00-password.sh

488 lines
15 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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 "$@"