# 强烈建议使用 frp 进行内网穿透!(适用于生产环境)
# 原文(不适合生产环境,仅临时开发)
# 起源
校内显卡服务器在实验室内网,考虑到便携性与安全性的博弈,使用一台中转服务器实现鉴权。
# 实现
请使用 autossh 实现自动重连:
autossh -M 0 -o ServerAliveInterval=10 -o ServerAliveCountMax=5 -l joytion -p 0123 -gNTR xxxx:localhost:4567 66.66.66.66 |
否则正常长时间使用 ssh 会超时报错。后面涉及到 ssh 的部分都需要更改。
# 内网 ssh 挂载到公网端口
ssh -lpub -p0123 -qngfNTR xxxx:localhost:4567 66.66.66.66 -o ServerAliveInterval=10 |
- 66.66.66.66 为公网 ip
- xxxx 为公网端口
- 0123 为 66.66.66.66 已有的 ssh 端口,一般服务器默认是 22
- 4567 为内网 ssh 端口
# 设备通过公网端口库连接内网
# 公网设置允许 ssh 转发
vim /etc/ssh/sshd_config
找到对应行修改
AllowTcpForwarding yes
GatewayPorts yes
ps: 我内网也设置了转发配置,不知道是否必要,懒得测试了
# 公网服务器配置
- 方式一(弃用):完全实现 ssh 正常登录的环境严格限制,但是能被 ssh 后接命令可以绕过限制
- 方式二(最佳):强制使用 ForceCommand,忽略 ssh 后接命令,实现完全控制
方式一(弃用)
通过在 /etc/profile.d 创建脚本
- 不足:通过 ssh 后接命令可以绕过限制
本文参考:https://blog.csdn.net/Victor2code/article/details/112437728
另一个可能有用的参考:https://blog.csdn.net/xujiamin0022016/article/details/88979420
我的代码:
#!/bin/bash | |
# 确认当前环境是否提供交互式登录和是否通过 SSH 连接 | |
m=$(whoami) | |
if [[ -n $SSH_CONNECTION || $- == *i* ]]; then | |
if [[ "${m}" == "pub" ]]; then | |
# 告知用户特殊身份 | |
echo -e "\e[01;33m** 您是特殊用户 'pub',将启用定制的SSH登录模式 **\e[00m" | |
# 创建必要的目录和快捷方式 | |
mkdir -p $HOME/bin | |
rm -f $HOME/bin/* | |
ln -s /usr/bin/ssh $HOME/bin/ | |
# 创建限制性的 bash 环境设置文件 | |
cat > $HOME/.newbash_profile <<EOF | |
export HISTFILESIZE=500000000 | |
export HISTSIZE=99999999 | |
export HISTTIMEFORMAT="%Y/%m/%d_%H:%M:%S :" | |
export PATH=$HOME/bin | |
export NAME=joytion | |
EOF | |
echo "export PATH=$HOME/bin" > $HOME/.bashrc | |
# 重设 PATH 变量,防止继承任何其他 PATH | |
export PATH="$HOME/bin" | |
source $HOME/.bashrc | |
# 捕获用户输入并尝试 SSH 连接 | |
read -p "请输入您要SSH登录的用户名: " ssh_user | |
clean_username=$(echo "$ssh_user" | sed 's/[^a-zA-Z0-9_-]//g') | |
echo "正在尝试使用 SSH 通过 $clean_username 登录内网..." | |
/usr/bin/ssh -p xxxx "$clean_username"@localhost | |
# SSH 连接后强制退出,防止用户进一步使用 shell | |
echo "exit 0" >> $HOME/.bashrc | |
source $HOME/.bashrc | |
chown ${m}:${m} $HOME/.bashrc | |
chown ${m}:${m} $HOME/.newbash_profile | |
exec bash --restricted --noprofile --rcfile $HOME/.newbash_profile | |
else | |
echo "欢迎,${m},您不需要进入定制SSH登录模式。" | |
fi | |
else | |
echo "本脚本仅限于SSH会话中使用。" | |
fi |
方式二(最终方案)
- 强制使用 ForceCommand
vim /etc/ssh/sshd_config
进行编辑- 追加:
Match user pub
ForceCommand /home/pub/ssh_for_pub.sh
- 创建并执行脚本
#!/bin/bash | |
while true; do | |
# 提示用户确认,并提供默认选项 | |
read -e -p "此操作将会删除用户及其所有配置([y]/n): " -i "y" confirm | |
# 标准化输入为小写 | |
confirm=${confirm,,} # 将输入转换为小写 | |
# 检查用户输入是否为 'yes' 或 'no' | |
if [[ "$confirm" == "y" ]]; then | |
echo "继续操作。" | |
break # 退出循环,继续执行后续代码 | |
elif [[ "$confirm" == "n" ]]; then | |
echo "操作已取消。" | |
exit 0 | |
else | |
echo "无效输入,请输入y或n。" | |
fi | |
done | |
# 删除现有用户(如果存在),并忽略不存在的错误 | |
userdel -f -r pub 2>/dev/null | |
# 添加新用户 | |
useradd -m pub || { echo "无法创建用户 'pub'"; exit 1; } | |
# 随机生成长密码并设置 | |
new_password=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 64) # 生成 64 位随机密码 | |
echo "pub:$new_password" | chpasswd || { echo "设置密码失败"; exit 1; } | |
echo "为用户pub设置的新密码是:$new_password" # 显示密码 | |
# 尝试从文件读取 SSH 公钥 | |
if [ -f "LAN-ssh_pub" ]; then | |
ssh_pub_key=$(<LAN-ssh_pub) | |
echo "从文件读取SSH公钥成功。" | |
else | |
read -p "请输入LAN的ssh公钥:" ssh_pub_key | |
fi | |
# 创建.ssh 目录并设置公钥 | |
mkdir -p /home/pub/.ssh || { echo "无法创建SSH目录"; exit 1; } | |
echo "$ssh_pub_key" > /home/pub/.ssh/authorized_keys || { echo "无法写入公钥"; exit 1; } | |
chown -R pub:pub /home/pub/.ssh | |
# 创建和设置 ssh 登录脚本 | |
cat > /home/pub/ssh_for_pub.sh << 'EOF' | |
#!/bin/bash | |
m=$(whoami) | |
if [[ -n $SSH_CONNECTION || $- == *i* ]]; then | |
# 显示版权和开发者信息 | |
printf "\e[1;34m本脚本由 @joytion 开发。\e[0m\n" | |
printf "\e[1;34m版权所有 © 2024 Joytion. 保留所有权利。\e[0m\n" | |
echo -e "\e[01;33m** 您是特殊用户 'pub',将启用定制的SSH登录模式 **\e[0m" | |
# 请求用户输入SSH登录的用户名,并检查是否通过Ctrl+D中断 | |
read -p "请输入自己在内网的用户名: " ssh_user | |
if [[ $? -ne 0 ]]; then | |
echo -e "\e[1;31m输入中断,操作已取消。\e[0m" | |
exit 1 | |
fi | |
# 使用正则表达式清洗和验证用户名 | |
if [[ ! "$ssh_user" =~ ^[a-zA-Z0-9_-]{1,32}$ ]]; then | |
echo -e "\e[1;31m无效的用户名。请使用1到32个字母、数字、下划线或破折号。\e[0m" | |
exit 1 | |
fi | |
# 通知用户即将尝试的操作 | |
echo -e "\e[1;32m正在尝试使用 SSH 通过 ${ssh_user} 登录内网...\e[0m" | |
# 执行SSH命令,并检查是否成功 | |
ssh -p xxxx "${ssh_user}"@localhost | |
if [[ $? -ne 0 ]]; then | |
echo -e "\e[1;31mSSH 登录失败或被中断。\e[0m" | |
exit 1 | |
fi | |
else | |
echo -e "\e[1;31m本脚本仅限于SSH会话中使用。\e[0m" | |
fi | |
exit 0 | |
EOF | |
chmod +x /home/pub/ssh_for_pub.sh || { echo "无法设置脚本权限"; exit 1; } | |
chown pub:pub /home/pub/ssh_for_pub.sh || { echo "无法设置脚本所有权"; exit 1; } | |
echo "pub用户创建成功!" |
执行脚本即可
# 连接
任意能访问公网的设备中输入:
ssh pub@66.66.66.66 -p 0123 |
即可进入脚本连接