|
@@ -1,65 +1,176 @@
|
|
|
#!/bin/bash
|
|
#!/bin/bash
|
|
|
|
|
+set -euo pipefail
|
|
|
|
|
|
|
|
-# SSH服务配置脚本
|
|
|
|
|
-# 用于设置和启动SSH服务
|
|
|
|
|
|
|
+# ============================================
|
|
|
|
|
+# SSH 服务配置脚本
|
|
|
|
|
+# 用于 安装、配置 和 启动 SSH 服务
|
|
|
|
|
+# 用法: bash setup-ssh.sh
|
|
|
|
|
+# 环境变量: SSH_ROOT_PASSWORD(默认 root)
|
|
|
|
|
+# ============================================
|
|
|
|
|
|
|
|
-echo "开始配置SSH服务..."
|
|
|
|
|
|
|
+log_info() { echo "[INFO] $*"; }
|
|
|
|
|
+log_warn() { echo "[WARN] $*" >&2; }
|
|
|
|
|
+log_error() { echo "[ERROR] $*" >&2; }
|
|
|
|
|
|
|
|
-# 安装 SSH 服务
|
|
|
|
|
-apt-get update && apt-get install -y openssh-server
|
|
|
|
|
|
|
+log_info "开始配置 SSH 服务..."
|
|
|
|
|
|
|
|
-# 创建sshd用户(如果不存在)
|
|
|
|
|
|
|
+# -------------------------------------------
|
|
|
|
|
+# 环境变量:SSH_ROOT_PASSWORD 可覆盖默认密码
|
|
|
|
|
+# -------------------------------------------
|
|
|
|
|
+ROOT_PASSWORD="${SSH_ROOT_PASSWORD:-root}"
|
|
|
|
|
+
|
|
|
|
|
+# -------------------------------------------
|
|
|
|
|
+# 安装 SSH 服务(仅在未安装时执行)
|
|
|
|
|
+# -------------------------------------------
|
|
|
|
|
+if ! command -v sshd &>/dev/null; then
|
|
|
|
|
+ log_info "openssh-server 未安装,开始安装..."
|
|
|
|
|
+ export DEBIAN_FRONTEND=noninteractive
|
|
|
|
|
+ if ! apt-get update -qq 2>/dev/null; then
|
|
|
|
|
+ log_warn "apt-get update 失败,尝试离线安装..."
|
|
|
|
|
+ fi
|
|
|
|
|
+ if ! apt-get install -y -qq openssh-server; then
|
|
|
|
|
+ log_error "openssh-server 安装失败,请检查网络或镜像源"
|
|
|
|
|
+ exit 1
|
|
|
|
|
+ fi
|
|
|
|
|
+ log_info "openssh-server 安装完成"
|
|
|
|
|
+else
|
|
|
|
|
+ log_info "openssh-server 已安装,跳过"
|
|
|
|
|
+fi
|
|
|
|
|
+
|
|
|
|
|
+# -------------------------------------------
|
|
|
|
|
+# 创建 sshd 用户(如果不存在)
|
|
|
|
|
+# -------------------------------------------
|
|
|
if ! id "sshd" &>/dev/null; then
|
|
if ! id "sshd" &>/dev/null; then
|
|
|
useradd -r -s /bin/false -d /var/run/sshd -c "SSH privilege separation" sshd
|
|
useradd -r -s /bin/false -d /var/run/sshd -c "SSH privilege separation" sshd
|
|
|
- echo "已创建sshd用户"
|
|
|
|
|
|
|
+ log_info "已创建 sshd 用户"
|
|
|
fi
|
|
fi
|
|
|
|
|
|
|
|
-# 创建并设置正确的目录权限
|
|
|
|
|
-mkdir -p /var/run/sshd
|
|
|
|
|
-chown root:root /var/run/sshd
|
|
|
|
|
-chmod 755 /var/run/sshd
|
|
|
|
|
-
|
|
|
|
|
-# 创建/run/sshd目录(系统运行时目录)
|
|
|
|
|
-mkdir -p /run/sshd
|
|
|
|
|
-chown root:root /run/sshd
|
|
|
|
|
-chmod 755 /run/sshd
|
|
|
|
|
|
|
+# -------------------------------------------
|
|
|
|
|
+# 创建并设置运行时目录权限
|
|
|
|
|
+# /var/run -> /run (符号链接),只创建一次即可
|
|
|
|
|
+# -------------------------------------------
|
|
|
|
|
+SSHD_RUN_DIR="/run/sshd"
|
|
|
|
|
+mkdir -p "${SSHD_RUN_DIR}"
|
|
|
|
|
+chown root:root "${SSHD_RUN_DIR}"
|
|
|
|
|
+chmod 755 "${SSHD_RUN_DIR}"
|
|
|
|
|
|
|
|
-# 生成SSH主机密钥(如果不存在)
|
|
|
|
|
|
|
+# -------------------------------------------
|
|
|
|
|
+# 生成 SSH 主机密钥(如果不存在)
|
|
|
|
|
+# 注意:在容器环境中,如需跨重启持久化,
|
|
|
|
|
+# 请将 /etc/ssh 挂载为持久化卷
|
|
|
|
|
+# -------------------------------------------
|
|
|
if [ ! -f /etc/ssh/ssh_host_rsa_key ]; then
|
|
if [ ! -f /etc/ssh/ssh_host_rsa_key ]; then
|
|
|
ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key -N ""
|
|
ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key -N ""
|
|
|
- echo "已生成RSA主机密钥"
|
|
|
|
|
|
|
+ chmod 600 /etc/ssh/ssh_host_rsa_key
|
|
|
|
|
+ log_info "已生成 RSA 主机密钥"
|
|
|
fi
|
|
fi
|
|
|
if [ ! -f /etc/ssh/ssh_host_ecdsa_key ]; then
|
|
if [ ! -f /etc/ssh/ssh_host_ecdsa_key ]; then
|
|
|
ssh-keygen -t ecdsa -b 521 -f /etc/ssh/ssh_host_ecdsa_key -N ""
|
|
ssh-keygen -t ecdsa -b 521 -f /etc/ssh/ssh_host_ecdsa_key -N ""
|
|
|
- echo "已生成ECDSA主机密钥"
|
|
|
|
|
|
|
+ chmod 600 /etc/ssh/ssh_host_ecdsa_key
|
|
|
|
|
+ log_info "已生成 ECDSA 主机密钥"
|
|
|
fi
|
|
fi
|
|
|
if [ ! -f /etc/ssh/ssh_host_ed25519_key ]; then
|
|
if [ ! -f /etc/ssh/ssh_host_ed25519_key ]; then
|
|
|
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ""
|
|
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ""
|
|
|
- echo "已生成Ed25519主机密钥"
|
|
|
|
|
|
|
+ chmod 600 /etc/ssh/ssh_host_ed25519_key
|
|
|
|
|
+ log_info "已生成 Ed25519 主机密钥"
|
|
|
fi
|
|
fi
|
|
|
|
|
|
|
|
|
|
+# -------------------------------------------
|
|
|
# 设置 root 用户密码
|
|
# 设置 root 用户密码
|
|
|
-passwd -u root && echo 'root:root' | chpasswd
|
|
|
|
|
|
|
+# -------------------------------------------
|
|
|
|
|
+passwd -u root 2>/dev/null || true
|
|
|
|
|
+echo "root:${ROOT_PASSWORD}" | chpasswd
|
|
|
|
|
+log_info "root 密码已设置"
|
|
|
|
|
|
|
|
-# 配置SSH服务
|
|
|
|
|
-# 允许 root 用户通过 SSH 登录
|
|
|
|
|
-sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
|
|
|
|
|
-# 允许密码认证
|
|
|
|
|
-sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config
|
|
|
|
|
|
|
+# -------------------------------------------
|
|
|
|
|
+# 配置 SSH 服务——允许 root 登录 + 密码认证
|
|
|
|
|
+# 兼顾注释和未注释两种状态
|
|
|
|
|
+# -------------------------------------------
|
|
|
|
|
+sed -i 's/^#*PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config
|
|
|
|
|
+sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config
|
|
|
|
|
|
|
|
-# 重启 SSH 服务
|
|
|
|
|
-service ssh start
|
|
|
|
|
|
|
+# 检查 /etc/ssh/sshd_config.d/*.conf 中是否有覆盖配置
|
|
|
|
|
+OVERRIDE_FILES=$(grep -rls "PermitRootLogin no\|PasswordAuthentication no" /etc/ssh/sshd_config.d/ 2>/dev/null || true)
|
|
|
|
|
+if [ -n "${OVERRIDE_FILES}" ]; then
|
|
|
|
|
+ log_warn "以下文件可能覆盖主配置,请手动检查:"
|
|
|
|
|
+ for f in ${OVERRIDE_FILES}; do
|
|
|
|
|
+ echo " ${f}"
|
|
|
|
|
+ done
|
|
|
|
|
+fi
|
|
|
|
|
+
|
|
|
|
|
+# -------------------------------------------
|
|
|
|
|
+# 清理 ~/.ssh/config 中重复的 Host localhost 条目
|
|
|
|
|
+# 避免端口被意外覆盖
|
|
|
|
|
+# -------------------------------------------
|
|
|
|
|
+SSH_CONFIG="${HOME}/.ssh/config"
|
|
|
|
|
+if [ -f "${SSH_CONFIG}" ]; then
|
|
|
|
|
+ HOST_COUNT=$(grep -c "^Host localhost$" "${SSH_CONFIG}" 2>/dev/null || true)
|
|
|
|
|
+ if [ "${HOST_COUNT}" -gt 1 ]; then
|
|
|
|
|
+ log_warn "~/.ssh/config 中发现 ${HOST_COUNT} 个重复的 Host localhost 条目,保留最后一个"
|
|
|
|
|
+ # 用 awk 按块拆分(每块含 Host 行 + 后续缩进行),保留每个块的 Host 名
|
|
|
|
|
+ # 只保留最后一个 Host localhost 块,其他同名块跳过
|
|
|
|
|
+ awk '
|
|
|
|
|
+ BEGIN { idx = 0 }
|
|
|
|
|
+ /^Host / {
|
|
|
|
|
+ idx++
|
|
|
|
|
+ name[idx] = \$0
|
|
|
|
|
+ content[idx] = ""
|
|
|
|
|
+ next
|
|
|
|
|
+ }
|
|
|
|
|
+ {
|
|
|
|
|
+ content[idx] = content[idx] \$0 "\n"
|
|
|
|
|
+ }
|
|
|
|
|
+ END {
|
|
|
|
|
+ for (i = 1; i <= idx; i++) {
|
|
|
|
|
+ if (name[i] == "Host localhost") {
|
|
|
|
|
+ is_last = 0
|
|
|
|
|
+ for (j = i + 1; j <= idx; j++) {
|
|
|
|
|
+ if (name[j] == "Host localhost") is_last = 1
|
|
|
|
|
+ }
|
|
|
|
|
+ if (is_last) continue
|
|
|
|
|
+ }
|
|
|
|
|
+ print name[i]
|
|
|
|
|
+ if (content[i] != "") printf "%s", content[i]
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ ' "${SSH_CONFIG}" > "${SSH_CONFIG}.tmp" && mv "${SSH_CONFIG}.tmp" "${SSH_CONFIG}"
|
|
|
|
|
+ chmod 600 "${SSH_CONFIG}"
|
|
|
|
|
+ log_info "已清理重复的 Host localhost 条目"
|
|
|
|
|
+ fi
|
|
|
|
|
+fi
|
|
|
|
|
+
|
|
|
|
|
+# -------------------------------------------
|
|
|
|
|
+# 重启 / 启动 SSH 服务
|
|
|
|
|
+# -------------------------------------------
|
|
|
|
|
+if service ssh status &>/dev/null; then
|
|
|
|
|
+ service ssh restart
|
|
|
|
|
+ log_info "SSH 服务已重启"
|
|
|
|
|
+else
|
|
|
|
|
+ service ssh start
|
|
|
|
|
+ log_info "SSH 服务已启动"
|
|
|
|
|
+fi
|
|
|
|
|
|
|
|
-# 检查SSH服务状态
|
|
|
|
|
|
|
+# -------------------------------------------
|
|
|
|
|
+# 最终状态检查
|
|
|
|
|
+# -------------------------------------------
|
|
|
|
|
+sleep 1
|
|
|
if service ssh status >/dev/null 2>&1; then
|
|
if service ssh status >/dev/null 2>&1; then
|
|
|
- echo "SSH服务启动成功"
|
|
|
|
|
- echo "SSH连接信息:"
|
|
|
|
|
- echo " 用户名: root"
|
|
|
|
|
- echo " 密码: root"
|
|
|
|
|
- echo " 端口: 22"
|
|
|
|
|
|
|
+ log_info "SSH 服务运行正常"
|
|
|
|
|
+ echo ""
|
|
|
|
|
+ echo " SSH 连接信息:"
|
|
|
|
|
+ echo " 地址: localhost"
|
|
|
|
|
+ echo " 端口: 22"
|
|
|
|
|
+ echo " 用户: root"
|
|
|
|
|
+ echo " 密码: ${ROOT_PASSWORD}"
|
|
|
|
|
+ echo ""
|
|
|
|
|
+ echo " 提示: 可通过环境变量 SSH_ROOT_PASSWORD 自定义密码"
|
|
|
|
|
+ echo " 例: SSH_ROOT_PASSWORD=mysecret bash setup-ssh.sh"
|
|
|
|
|
+ echo ""
|
|
|
else
|
|
else
|
|
|
- echo "警告:SSH服务启动失败"
|
|
|
|
|
|
|
+ echo ""
|
|
|
|
|
+ log_error "SSH 服务启动失败"
|
|
|
|
|
+ service ssh status 2>&1 || true
|
|
|
exit 1
|
|
exit 1
|
|
|
fi
|
|
fi
|
|
|
|
|
|
|
|
-echo "SSH服务配置完成"
|
|
|
|
|
|
|
+log_info "SSH 服务配置完成"
|