用于快速创建一个受限的 SSH 跳板机(Jump Host)用户。

支持参数化运行。直接指定用户名,或者不带参数运行进入交互模式。

方式 A: 交互式

sudo bash setup_jump_user.sh

方式 B: 参数化

sudo bash setup_jump_user.sh my_jump_user

脚本说明

  • 权限限制:用户被设置为禁止交互式登录(No TTY),仅允许端口转发(TCP Forwarding)。
  • 安全认证:强制使用密钥对验证,禁用密码登录。
  • 自动配置:自动修改 /etc/ssh/sshd_config 并重启服务。
  • SELinux 修复、权限加固 以及 本地使用指南。
  • 只显示IPv4地址。

安全特性说明

  • PermitTTY no: 禁止分配终端,用户尝试正常登录会直接被拒绝或提示提示语。
  • AllowTcpForwarding yes: 允许该用户进行隧道转发(跳板核心功能)。
  • ForceCommand: 强制执行特定的回显,进一步防止尝试绕过 shell 限制。
  • Ed25519: 使用现代、高性能且更安全的加密算法生成密钥。

关于 SSHD 参数要求,Debian 13 (Trixie) 默认配置已经非常接近需求,但为了确保脚本 100% 成功,你的主机配置需要满足以下几点:

1. SSHD 主机环境要求

  • PubkeyAuthentication yes:必须开启(Debian 默认开启)。
  • AllowTcpForwarding yes:全局不能显式设为 no(脚本会在 Match 块中为该用户单独开启)。
  • StrictModes yes:这是 SSH 的“洁癖”模式,脚本已经通过 chmod 700 和 chown 逻辑完美适配。
  • Match 块位置:SSH 要求 Match 指令必须放在 /etc/ssh/sshd_config 的 文件末尾。脚本使用 >> 追加模式,符合此规则。

集成了参数化支持、IPv4 强制获取、权限加固以及测试成功的 ProxyCommand 输出。

#!/bin/bash

# --- 权限检查 ---
if [ "$EUID" -ne 0 ]; then
  echo "❌ Error: 请使用 sudo 运行此脚本。"
  exit 1
fi

# --- 1. 参数化支持 ---
# 优先级:命令行参数 $1 > 环境变量 $JUMP_USER > 交互输入
USER_NAME=${1:-$JUMP_USER}
if [ -z "$USER_NAME" ]; then
    read -p "请输入要创建的跳板机用户名: " USER_NAME
fi

# --- 2. 检查用户冲突 ---
if id "$USER_NAME" &>/dev/null; then
    echo "⚠️  用户 $USER_NAME 已存在,脚本将仅尝试更新其配置。"
else
    if ! grep -q "/usr/sbin/nologin" /etc/shells; then
        echo "/usr/sbin/nologin" >> /etc/shells
    fi
    useradd -m -s /usr/sbin/nologin "$USER_NAME"
    echo "✅ 用户 $USER_NAME 创建成功。"
fi

USER_HOME=$(eval echo "~$USER_NAME")

# --- 3. 生成 Ed25519 密钥对 ---
KEY_DIR="/tmp/ssh_gen_$USER_NAME"
mkdir -p "$KEY_DIR"
ssh-keygen -t ed25519 -f "$KEY_DIR/id_ed25519" -N "" -C "jump-only-key" > /dev/null

# --- 4. 权限与所有权 (针对 Debian 13 优化) ---
# 确保父目录路径安全
chown root:root /home
chmod 755 /home

# 用户目录与 SSH 配置
mkdir -p "$USER_HOME/.ssh"
cp "$KEY_DIR/id_ed25519.pub" "$USER_HOME/.ssh/authorized_keys"

chown "$USER_NAME:$USER_NAME" "$USER_HOME"
chmod 700 "$USER_HOME"
chown -R "$USER_NAME:$USER_NAME" "$USER_HOME/.ssh"
chmod 700 "$USER_HOME/.ssh"
chmod 600 "$USER_HOME/.ssh/authorized_keys"

# --- 5. 修改 SSHD 配置 (原子清理与追加) ---
SSHD_CONF="/etc/ssh/sshd_config"
# 清理可能存在的旧 Match 块
sed -i "/# --- Jump User: $USER_NAME ---/,/# --- End $USER_NAME ---/d" "$SSHD_CONF"

cat >> "$SSHD_CONF" << EOF

# --- Jump User: $USER_NAME ---
Match User $USER_NAME
    AllowTcpForwarding yes
    X11Forwarding no
    PermitTTY no
    GatewayPorts no
    AuthenticationMethods publickey
# --- End $USER_NAME ---
EOF

# 重启服务应用更改
systemctl restart sshd

# --- 6. 获取 IPv4 网络信息 ---
# 强制使用 IPv4 获取公网 IP
EXT_IP=$(curl -4 -s --max-time 5 ifconfig.me || curl -4 -s --max-time 5 api.ipify.org || echo "YOUR_SERVER_IP")
SSH_PORT=$(grep -E "^Port " /etc/ssh/sshd_config | awk '{print $2}' | head -n1)
SSH_PORT=${SSH_PORT:-22}
PRIVATE_KEY=$(cat "$KEY_DIR/id_ed25519")

# --- 7. 生成输出结果 ---
clear
cat << EOF
====================================================
🎯 跳板机用户 $USER_NAME 配置成功!
====================================================
用户名: $USER_NAME
公网 IPv4: $EXT_IP
SSH 端口: $SSH_PORT
----------------------------------------------------
👉 步骤 1:全选并复制下方命令到你的 Mac/Local 终端执行
(这会自动在本地保存私钥并设置权限):

cat << 'KEYEOF' > ~/${USER_NAME}_key
$PRIVATE_KEY
KEYEOF
chmod 600 ~/${USER_NAME}_key

----------------------------------------------------
👉 步骤 2:使用 ProxyCommand 方案一键跳转 (Copy-Paste):

ssh -o "ProxyCommand=ssh -i ~/${USER_NAME}_key -p $SSH_PORT -o IdentitiesOnly=yes -W %h:%p $USER_NAME@$EXT_IP" [目标用户]@[目标IP]

----------------------------------------------------
✅ 提示:该用户已受限,仅能作为 SSH 跳转隧道使用。
====================================================
EOF

# 清理临时文件
rm -rf "$KEY_DIR"

  • PermitTTY no: 禁止分配终端,用户尝试正常登录会直接被拒绝或提示提示语。
  • AllowTcpForwarding yes: 允许该用户进行隧道转发(跳板核心功能)。
  • ForceCommand: 强制执行特定的回显,进一步防止尝试绕过 shell 限制。
  • Ed25519: 使用现代、高性能且更安全的加密算法生成密钥。

为什么这个版本更稳定?

  • 私钥保存自动化:我使用了 cat << 'KEYEOF'。由于加了单引号 'KEYEOF',Bash 会禁用变量替换,确保生成的私钥内容原封不动,不会因为私钥里的特殊符号(如果有的话)导致转义错误。
  • SSHD 安全:AuthenticationMethods publickey 强制该用户只能走证书,即使你以后不小心给这个用户设了密码,密码登录也无效。

连接测试:

复制整段脚本的输出,类似这样

cat << 'KEYEOF' > ~/me_key
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW----私钥---略
-----END OPENSSH PRIVATE KEY-----
KEYEOF
chmod 600 ~/me_key

根据步骤2,修改下末尾的 [目标用户]@[目标IP] 或者输入你配置在.ssh/config里的主机名代替。


👉 步骤 2:使用 ProxyCommand 方案一键跳转 (Copy-Paste):
ssh -o "ProxyCommand=ssh -i ~/me_key -p 7021 -o IdentitiesOnly=yes -W %h:%p me@--jumper的IP" [目标用户]@[目标IP]

由于脚本设置了 PermitTTY no,该用户无法直接登录获取命令行。它的正确用途是作为 SOCKS 代理 或 端口转发:

动态转发 (SOCKS5):
ssh -i private_key_file -D 1080 -N -p 22 username@server_ip

作为 ProxyJump 节点:
在你的本地 ~/.ssh/config 中配置:


Host jump-server
    HostName server_ip
    User username
    Port 你的ssh端口 默认22可忽略这行
    IdentityFile ~/path/to/private_key
    IdentitiesOnly yes

Host internal-server
    HostName 连接目标的IP
    ...其他设置略
    ProxyJump jump-server