SSH服务加固脚本
此脚本实现了ssh修改到指定端口 并添加指定的IP白名单
#!/bin/bash
# SSH安全加固配置脚本
# 文件名: secure_ssh.sh
# 版本: 2.0
# 描述: 用户友好的SSH安全配置脚本
set -e
# 定义颜色代码
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# 定义符号
CHECKMARK="${GREEN}✓${NC}"
WARNING="${YELLOW}⚠${NC}"
ERROR="${RED}✗${NC}"
INFO="${BLUE}ℹ${NC}"
QUESTION="${CYAN}?${NC}"
STEP="${MAGENTA}▶${NC}"
# 函数:打印带颜色的消息
print_info() {
echo -e "${INFO} $1"
}
print_success() {
echo -e "${CHECKMARK} ${GREEN}$1${NC}"
}
print_warning() {
echo -e "${WARNING} ${YELLOW}$1${NC}"
}
print_error() {
echo -e "${ERROR} ${RED}$1${NC}"
}
print_step() {
echo -e "\n${STEP} ${CYAN}$1${NC}"
}
print_question() {
echo -e "${QUESTION} ${CYAN}$1${NC}"
}
# 函数:打印横幅
print_banner() {
clear
echo -e "${BLUE}====================================================${NC}"
echo -e "${GREEN} SSH安全配置助手 v1.0${NC}"
echo -e "${BLUE}====================================================${NC}"
echo -e "${YELLOW}这个脚本将帮助您:${NC}"
echo -e "1. 修改SSH默认端口(22 → 22222)"
echo -e "2. 禁止root用户远程登录"
echo -e "3. 配置IP白名单"
echo -e "4. 设置默认拒绝所有连接"
echo -e "${BLUE}====================================================${NC}\n"
}
# 函数:检查是否为root用户
check_root() {
if [ "$EUID" -ne 0 ]; then
print_error "此脚本需要以root权限运行"
echo -e "请使用以下命令之一:"
echo -e " ${GREEN}sudo -E bash $0${NC}"
echo -e "\n或者以root用户登录后再运行此脚本。"
exit 1
fi
print_success "权限检查通过"
}
# 函数:检查系统信息
check_system() {
print_step "检查系统信息..."
# 检测发行版
if [ -f /etc/os-release ]; then
. /etc/os-release
OS_NAME=$NAME
OS_VERSION=$VERSION_ID
else
OS_NAME=$(uname -s)
OS_VERSION=$(uname -r)
fi
echo -e "${GREEN}操作系统:${NC} $OS_NAME"
echo -e "${GREEN}版本:${NC} $OS_VERSION"
# 检查SSH服务
if systemctl is-active sshd &> /dev/null; then
SSH_SERVICE="sshd"
print_success "SSH服务: 运行中 (sshd)"
elif systemctl is-active ssh &> /dev/null; then
SSH_SERVICE="ssh"
print_success "SSH服务: 运行中 (ssh)"
else
print_warning "SSH服务未运行"
SSH_SERVICE="unknown"
fi
# 检查当前SSH端口
CURRENT_PORT=$(grep -E "^Port\s+[0-9]+" /etc/ssh/sshd_config 2>/dev/null | awk '{print $2}' | head -1)
if [ -z "$CURRENT_PORT" ]; then
CURRENT_PORT="22 (默认)"
fi
echo -e "${GREEN}当前SSH端口:${NC} $CURRENT_PORT"
# 检查root登录设置
ROOT_LOGIN=$(grep -E "^PermitRootLogin\s+" /etc/ssh/sshd_config 2>/dev/null | tail -1 | awk '{print $2}')
if [ -z "$ROOT_LOGIN" ]; then
ROOT_LOGIN="yes (默认)"
fi
echo -e "${GREEN}Root远程登录:${NC} $ROOT_LOGIN"
}
# 函数:检查当前用户和连接
check_current_connection() {
print_step "检查当前连接状态..."
if [ -z "$CURRENT_IP" ]; then
# 获取当前用户名
CURRENT_USER=$(whoami)
# 使用w命令获取登录信息
W_INFO=$(w -h 2>/dev/null | grep "^$CURRENT_USER" | head -1)
if [ -n "$W_INFO" ]; then
CURRENT_IP=$(echo "$W_INFO" | awk '{print $3}')
if [ -n "$CURRENT_IP" ] && [ "$CURRENT_IP" != "-" ] && [ "$CURRENT_IP" != ":0" ]; then
echo -e "${GREEN}通过w命令检测到连接:${NC}"
echo -e "${GREEN}用户:${NC} $CURRENT_USER"
echo -e "${GREEN}来源:${NC} $CURRENT_IP"
echo -e "${GREEN}检测方式: w命令${NC}"
fi
fi
fi
}
# 函数:检查可用用户
check_available_users() {
print_step "检查系统用户..."
# 获取非root用户列表
NON_ROOT_USERS=$(awk -F: '($3 >= 1000) && ($1 != "nobody") && ($1 != "systemd-*") { print $1 }' /etc/passwd | sort)
if [ -z "$NON_ROOT_USERS" ]; then
print_error "系统中没有发现可用的非root用户!"
echo -e "\n${YELLOW}⚠ 严重警告:${NC}"
echo -e "禁止root远程登录后,您将无法通过SSH连接服务器。"
echo -e "\n${GREEN}建议操作:${NC}"
echo -e "1. 创建一个新用户: ${BLUE}adduser 用户名${NC}"
echo -e "2. 设置密码: ${BLUE}passwd 用户名${NC}"
echo -e "3. 给予sudo权限:"
echo -e " Ubuntu/Debian: ${BLUE}usermod -aG sudo 用户名${NC}"
echo -e " CentOS/RHEL: ${BLUE}usermod -aG wheel 用户名${NC}"
echo -e "\n${CYAN}您希望:${NC}"
echo -e "1) 继续配置(不推荐)"
echo -e "2) 退出脚本,先创建用户"
while true; do
read -p "请选择 (1/2): " USER_CHOICE
case $USER_CHOICE in
1)
print_warning "您选择了继续配置,请确保您有其他登录方式!"
return 1
;;
2)
print_info "正在退出脚本,请先创建用户后再运行。"
exit 1
;;
*)
print_error "无效选择,请输入1或2"
;;
esac
done
else
echo -e "${GREEN}可用的非root用户:${NC}"
echo -e "----------------------------------------"
printf "%-15s %-20s\n" "用户名" "用户组"
echo -e "----------------------------------------"
for user in $NON_ROOT_USERS; do
groups=$(id -Gn $user 2>/dev/null | tr ' ' ',')
printf "%-15s %-20s\n" "$user" "$groups"
done
echo -e "----------------------------------------"
print_success "有可用的非root用户"
echo -e "\n${YELLOW}请确保您知道至少一个用户的密码!${NC}"
if [ -n "$SSH_CONNECTION" ] && [ "$CURRENT_USER" != "root" ]; then
print_success "您当前以 '$CURRENT_USER' 连接,配置后可以使用此用户登录。"
fi
fi
}
# 函数:创建备份
create_backup() {
print_step "创建配置备份..."
BACKUP_DIR="/root/ssh_backup_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$BACKUP_DIR"
# 备份关键文件
cp /etc/ssh/sshd_config "$BACKUP_DIR/sshd_config"
[ -f /etc/hosts.allow ] && cp /etc/hosts.allow "$BACKUP_DIR/hosts.allow"
[ -f /etc/hosts.deny ] && cp /etc/hosts.deny "$BACKUP_DIR/hosts.deny"
# 保存当前系统信息
echo "备份时间: $(date)" > "$BACKUP_DIR/backup_info.txt"
echo "操作系统: $OS_NAME $OS_VERSION" >> "$BACKUP_DIR/backup_info.txt"
echo "当前SSH端口: $CURRENT_PORT" >> "$BACKUP_DIR/backup_info.txt"
echo "Root登录状态: $ROOT_LOGIN" >> "$BACKUP_DIR/backup_info.txt"
print_success "备份已创建到: $BACKUP_DIR"
echo -e " 备份包含:"
echo -e " - sshd_config"
[ -f /etc/hosts.allow ] && echo -e " - hosts.allow"
[ -f /etc/hosts.deny ] && echo -e " - hosts.deny"
echo -e " - 系统信息"
BACKUP_LOCATION="$BACKUP_DIR"
}
# 函数:修改SSH端口
configure_ssh_port() {
print_step "配置SSH端口..."
NEW_PORT="22222"
# 检查端口是否被占用
if netstat -tuln 2>/dev/null | grep -q ":$NEW_PORT\b"; then
print_error "端口 $NEW_PORT 已被占用!"
echo -e "占用情况:"
netstat -tulpn 2>/dev/null | grep ":$NEW_PORT\b" || echo "未知进程"
while true; do
read -p "请输入新的SSH端口号 (1024-65535): " NEW_PORT
# 验证端口号
if ! [[ "$NEW_PORT" =~ ^[0-9]+$ ]] || [ "$NEW_PORT" -lt 1024 ] || [ "$NEW_PORT" -gt 65535 ]; then
print_error "端口号必须是1024-65535之间的数字"
continue
fi
if netstat -tuln 2>/dev/null | grep -q ":$NEW_PORT\b"; then
print_error "端口 $NEW_PORT 仍被占用,请选择其他端口"
else
print_success "端口 $NEW_PORT 可用"
break
fi
done
else
print_success "端口 $NEW_PORT 可用"
fi
echo -e "\n${YELLOW}当前配置:${NC}"
echo -e " 旧端口: $CURRENT_PORT"
echo -e " 新端口: $NEW_PORT"
# 确认修改
print_question "确认将SSH端口从 $CURRENT_PORT 改为 $NEW_PORT ?(y/n)"
read -p "> " CONFIRM_PORT
if [[ $CONFIRM_PORT =~ ^[Yy]$ ]]; then
# 备份原始配置
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup.$(date +%Y%m%d_%H%M%S)
# 注释掉已有的Port配置
sed -i 's/^Port/#Port/' /etc/ssh/sshd_config
# 添加新端口配置
echo "# SSH端口修改于 $(date)" >> /etc/ssh/sshd_config
echo "Port $NEW_PORT" >> /etc/ssh/sshd_config
print_success "SSH端口已改为 $NEW_PORT"
SSH_NEW_PORT=$NEW_PORT
else
print_info "已跳过端口修改"
SSH_NEW_PORT=$CURRENT_PORT
fi
}
# 函数:配置root登录
configure_root_login() {
print_step "配置root远程登录..."
echo -e "${YELLOW}安全建议:${NC}"
echo -e " 禁止root远程登录是重要的安全措施。"
echo -e " 即使root密码很强,也应使用普通用户登录后su或sudo。"
if [ "$CURRENT_USER" = "root" ]; then
print_warning "您当前以root用户连接!"
echo -e " 配置后,新的root登录将被拒绝,但当前连接不会断开。"
fi
print_question "是否禁止root用户远程登录?(y/n)"
read -p "> " CONFIRM_ROOT
if [[ $CONFIRM_ROOT =~ ^[Yy]$ ]]; then
# 备份原始配置
if ! grep -q "^# Backup for root login" /etc/ssh/sshd_config; then
echo "# Backup for root login - Original: $(grep -i 'permitrootlogin' /etc/ssh/sshd_config 2>/dev/null || echo 'PermitRootLogin yes')" >> /etc/ssh/sshd_config
fi
# 修改配置
sed -i 's/^#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sed -i 's/^PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
if ! grep -q "^PermitRootLogin no" /etc/ssh/sshd_config; then
echo "PermitRootLogin no" >> /etc/ssh/sshd_config
fi
print_success "已禁止root远程登录"
ROOT_STATUS="禁止"
else
print_info "保持root远程登录允许"
ROOT_STATUS="允许"
fi
}
# 函数:配置IP白名单
configure_ip_whitelist() {
print_step "配置IP白名单..."
echo -e "${YELLOW}什么是IP白名单?${NC}"
echo -e " 只允许指定IP地址连接SSH,其他所有IP都会被拒绝。"
echo -e " 这提供了额外的安全层。"
print_question "是否配置IP白名单?(y/n)"
read -p "> " CONFIGURE_IPS
if [[ $CONFIGURE_IPS =~ ^[Yy]$ ]]; then
# 清空hosts.allow中的旧SSH规则
if [ -f /etc/hosts.allow ]; then
grep -v "^sshd:" /etc/hosts.allow > /tmp/hosts.allow.tmp
mv /tmp/hosts.allow.tmp /etc/hosts.allow
fi
IP_LIST=""
echo -e "\n${GREEN}请输入允许访问的IP地址:${NC}"
echo -e " 格式示例:"
echo -e " 单个IP: 192.168.1.100"
echo -e " IP段: 192.168.1.0/24"
echo -e " 多个IP: 192.168.1.100,192.168.1.101"
echo -e " 网段: 192.168.1."
echo -e "\n${YELLOW}提示:${NC} 直接按回车结束输入"
echo -e "----------------------------------------"
COUNTER=1
while true; do
read -p "IP地址 #$COUNTER (回车结束): " IP
if [ -z "$IP" ]; then
if [ $COUNTER -eq 1 ]; then
print_info "未添加任何IP地址"
else
print_success "IP白名单配置完成"
fi
break
fi
# 添加IP到白名单
echo "sshd: $IP" >> /etc/hosts.allow
IP_LIST="$IP_LIST\n $COUNTER. $IP"
echo -e " ${GREEN}✓${NC} 已添加: $IP"
((COUNTER++))
done
if [ -n "$IP_LIST" ]; then
WHITELIST_ENABLED="是"
else
WHITELIST_ENABLED="否"
fi
else
print_info "跳过IP白名单配置"
WHITELIST_ENABLED="否"
fi
# 自动添加当前连接IP(如果用户以非root连接)
if [ -n "$CURRENT_IP" ] && [ "$CURRENT_USER" != "root" ] && [ "$WHITELIST_ENABLED" = "是" ]; then
if ! grep -q "sshd:.*$CURRENT_IP" /etc/hosts.allow 2>/dev/null; then
echo -e "\n${YELLOW}注意:${NC} 当前连接IP $CURRENT_IP 不在白名单中"
print_question "是否将当前IP ($CURRENT_IP) 添加到白名单?(y/n)"
read -p "> " ADD_CURRENT_IP
if [[ $ADD_CURRENT_IP =~ ^[Yy]$ ]]; then
echo "sshd: $CURRENT_IP" >> /etc/hosts.allow
print_success "已添加当前IP到白名单"
IP_LIST="$IP_LIST\n $COUNTER. $CURRENT_IP (当前连接)"
fi
fi
fi
}
# 函数:配置默认拒绝规则
configure_default_deny() {
print_step "配置默认拒绝规则..."
echo -e "${YELLOW}默认拒绝规则:${NC}"
echo -e " 在/etc/hosts.deny中添加'all:all'规则"
echo -e " 这将拒绝所有未在hosts.allow中明确允许的连接"
if [ -f /etc/hosts.deny ]; then
if grep -q "^all:all" /etc/hosts.deny; then
print_info "已存在'all:all'规则"
DENY_RULE_EXISTS="是"
else
# 移除旧的all:all规则(如果有其他格式)
grep -v "^all:all" /etc/hosts.deny > /tmp/hosts.deny.tmp
mv /tmp/hosts.deny.tmp /etc/hosts.deny
# 添加新规则
echo "# 默认拒绝所有连接 - 添加于 $(date)" >> /etc/hosts.deny
echo "all:all" >> /etc/hosts.deny
print_success "已添加默认拒绝规则"
DENY_RULE_EXISTS="是"
fi
else
echo "# SSH安全配置 - 创建于 $(date)" > /etc/hosts.deny
echo "all:all" >> /etc/hosts.deny
print_success "已创建hosts.deny并添加拒绝规则"
DENY_RULE_EXISTS="是"
fi
}
# 函数:重启SSH服务
restart_ssh_service() {
print_step "重启SSH服务..."
# 测试配置文件语法
echo -n "检查SSH配置文件语法... "
if sshd -t 2>/dev/null; then
print_success "语法正确"
else
print_error "配置文件语法错误"
echo -e "\n${YELLOW}错误详情:${NC}"
sshd -t 2>&1 || true
echo -e "\n${RED}请修复错误后重试${NC}"
exit 1
fi
# 重启服务
echo -n "重启SSH服务... "
if systemctl restart sshd 2>/dev/null || systemctl restart ssh 2>/dev/null || service sshd restart 2>/dev/null || service ssh restart 2>/dev/null; then
print_success "SSH服务重启成功"
# 检查服务状态
sleep 2
if systemctl is-active sshd &> /dev/null || systemctl is-active ssh &> /dev/null; then
print_success "SSH服务正在运行"
else
print_warning "SSH服务状态未知,请手动检查"
fi
else
print_error "SSH服务重启失败"
echo -e "\n${YELLOW}请手动检查SSH服务状态${NC}"
fi
}
# 函数:生成恢复脚本
create_restore_script() {
print_step "生成恢复脚本..."
RESTORE_SCRIPT="$BACKUP_LOCATION/restore_ssh_config.sh"
cat > "$RESTORE_SCRIPT" << EOF
#!/bin/bash
# SSH配置恢复脚本
# 生成时间: $(date)
# 使用此脚本可以恢复SSH原始配置
echo "=== SSH配置恢复 ==="
echo "此脚本将恢复SSH配置到修改前的状态"
# 检查是否为root
if [ "\$EUID" -ne 0 ]; then
echo "错误:需要root权限运行此脚本"
echo "请使用: sudo bash \$0"
exit 1
fi
# 恢复配置文件
echo "恢复sshd_config..."
cp "$BACKUP_LOCATION/sshd_config" /etc/ssh/sshd_config
if [ -f "$BACKUP_LOCATION/hosts.allow" ]; then
echo "恢复hosts.allow..."
cp "$BACKUP_LOCATION/hosts.allow" /etc/hosts.allow
else
echo "清空hosts.allow..."
> /etc/hosts.allow
fi
if [ -f "$BACKUP_LOCATION/hosts.deny" ]; then
echo "恢复hosts.deny..."
cp "$BACKUP_LOCATION/hosts.deny" /etc/hosts.deny
else
echo "清空hosts.deny..."
> /etc/hosts.deny
fi
# 重启SSH服务
echo "重启SSH服务..."
if systemctl restart sshd 2>/dev/null || systemctl restart ssh 2>/dev/null || service sshd restart 2>/dev/null || service ssh restart 2>/dev/null; then
echo "✓ SSH服务已重启"
else
echo "⚠ SSH服务重启失败,请手动检查"
fi
echo ""
echo "=== 恢复完成 ==="
echo "SSH配置已恢复到备份时的状态"
echo "原端口: $CURRENT_PORT"
echo "Root登录: $ROOT_LOGIN"
echo ""
echo "现在可以使用原来的配置连接SSH"
EOF
chmod +x "$RESTORE_SCRIPT"
print_success "恢复脚本已创建: $RESTORE_SCRIPT"
}
# 函数:显示配置摘要
show_summary() {
print_step "配置摘要"
echo -e "${BLUE}====================================================${NC}"
echo -e "${GREEN} SSH安全配置完成${NC}"
echo -e "${BLUE}====================================================${NC}"
echo -e ""
echo -e "${CYAN}配置详情:${NC}"
echo -e "----------------------------------------"
printf "%-25s %s\n" "SSH端口:" "${SSH_NEW_PORT:-$CURRENT_PORT}"
printf "%-25s %s\n" "Root远程登录:" "${ROOT_STATUS:-$ROOT_LOGIN}"
printf "%-25s %s\n" "IP白名单:" "${WHITELIST_ENABLED:-否}"
printf "%-25s %s\n" "默认拒绝规则:" "${DENY_RULE_EXISTS:-是}"
echo -e "----------------------------------------"
if [ "$WHITELIST_ENABLED" = "是" ] && [ -n "$IP_LIST" ]; then
echo -e "\n${CYAN}允许的IP地址:${NC}"
echo -e "----------------------------------------"
echo -e "$IP_LIST" | sed '/^$/d'
echo -e "----------------------------------------"
fi
echo -e "\n${CYAN}备份和恢复:${NC}"
echo -e "----------------------------------------"
echo -e "备份目录: $BACKUP_LOCATION"
echo -e "恢复脚本: $BACKUP_LOCATION/restore_ssh_config.sh"
echo -e "----------------------------------------"
echo -e "\n${YELLOW}重要提示:${NC}"
echo -e "1. 请立即测试新配置:"
echo -e " ${GREEN}ssh -p ${SSH_NEW_PORT:-22222} 用户名@服务器IP${NC}"
echo -e ""
echo -e "2. 如果连接失败:"
echo -e " - 检查防火墙是否开放端口 ${SSH_NEW_PORT:-22222}"
echo -e " - 确保使用正确的用户名和密码"
echo -e " - 如果启用了IP白名单,确保您的IP在列表中"
echo -e ""
echo -e "3. 紧急恢复:"
echo -e " ${GREEN}bash $BACKUP_LOCATION/restore_ssh_config.sh${NC}"
echo -e " 或者手动复制备份文件:"
echo -e " ${GREEN}cp $BACKUP_LOCATION/sshd_config /etc/ssh/sshd_config${NC}"
echo -e " ${GREEN}systemctl restart sshd${NC}"
echo -e "\n${GREEN}配置已完成!当前SSH连接不会断开。${NC}"
echo -e "${BLUE}====================================================${NC}"
}
# 函数:显示完成动画
show_completion() {
echo -e "\n"
for i in {1..3}; do
echo -ne "${GREEN}配置完成${NC} .\r"
sleep 0.3
echo -ne "${GREEN}配置完成${NC} ..\r"
sleep 0.3
echo -ne "${GREEN}配置完成${NC} ...\r"
sleep 0.3
done
echo -e "${GREEN}✓ SSH安全配置已完成!${NC}"
}
# 主函数
main() {
# 显示横幅
print_banner
# 欢迎信息
echo -e "${CYAN}欢迎使用SSH安全配置助手${NC}"
echo -e "此脚本将引导您完成SSH安全配置。"
echo -e "在继续之前,请确保您有其他方式访问服务器。"
echo -e ""
# 等待用户确认
print_question "按回车键继续,或按Ctrl+C取消..."
read
# 检查root权限
check_root
# 检查系统信息
check_system
# 检查当前连接
check_current_connection
# 检查可用用户
check_available_users
# 等待确认继续
echo -e "\n${YELLOW}即将开始配置,请确认:${NC}"
echo -e "1. 您有可用的非root用户和密码"
echo -e "2. 您有其他方式访问服务器(如控制台)"
echo -e "3. 您了解配置变更的影响"
print_question "是否继续配置?(y/n)"
read -p "> " CONFIRM_START
if [[ ! $CONFIRM_START =~ ^[Yy]$ ]]; then
print_info "已取消配置"
exit 0
fi
# 创建备份
create_backup
# 配置SSH端口
configure_ssh_port
# 配置root登录
configure_root_login
# 配置IP白名单
configure_ip_whitelist
# 配置默认拒绝规则
configure_default_deny
# 重启SSH服务
restart_ssh_service
# 生成恢复脚本
create_restore_script
# 显示完成动画
show_completion
# 显示配置摘要
show_summary
# 最终提示
echo -e "\n${GREEN}感谢使用SSH安全配置助手!${NC}"
echo -e "脚本执行完成于: $(date)"
}
# 异常处理
trap 'echo -e "\n${RED}脚本被中断${NC}"; exit 1' INT TERM
# 运行主函数
main "$@"

浙公网安备 33010602011771号