适用场景:异地远程连接完全隔离的内网服务器及 Docker 容器进行开发。
1. 方案核心概念
1.1 什么是 SSH 反向隧道?
通常,外网无法直接访问内网设备(因为内网设备没有公网 IP)。反向隧道的原理是:让内网设备(主动方)去连接公网服务器(被动方),并在两者之间建立一条加密通道。公网服务器就像一个中转站,我们将请求发送给公网服务器,它通过这条现成的通道将请求“反向”转发给内网设备。
1.2 为什么选择这个架构?
- 低成本:无需购买昂贵的商业内网穿透服务,仅需一台普通的云服务器。
- 高安全 (ProxyJump):本方案采用
ProxyJump模式。公网服务器不再对外开放任何业务端口(如旧方案的 8022),端口仅监听在本地回环地址 (127.0.0.1)。黑客扫描公网 IP 无法发现任何入口,只有通过 SSH 验证后的用户才能“跳”进隧道。 - 稳定性 (Autossh):原生 SSH 连接容易因网络波动断开,
autossh是一个监控程序,能自动检测连接状态并在断线时毫秒级重连,实现无人值守。
2. 公网服务器配置
目标:创建一个权限受限的专用账户,用于接收内网的连接请求,防止 Root 权限泄露。
2.1 创建隧道专用用户
不要使用 root 建立隧道。登录公网服务器(root),执行以下命令:
# 1. 创建用户 tunnel_user,并创建家目录
useradd -m -s /bin/bash tunnel_user
# 2. 切换到该用户,创建 ssh 目录
su - tunnel_user
mkdir ~/.ssh
chmod 700 ~/.ssh
touch ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
2.2 安全配置 SSHD
编辑公网服务器的 SSH 配置文件,启用网关功能(虽然我们绑定 127.0.0.1,但此选项仍需开启以允许转发)。
# 切回 root 权限
exit
sudo vim /etc/ssh/sshd_config
确保以下配置存在:
GatewayPorts yes
AllowTcpForwarding yes
重启 SSH 服务:
sudo systemctl restart sshd
3. 内网服务器配置 (部署 Autossh)
目标:配置内网服务器主动连接公网,并注册为系统服务实现开机自启。
3.1 准备工作:免密登录配置
在内网服务器上,将用户的公钥复制到公网服务器的 tunnel_user 中。
# 在内网服务器上执行 (假设当前用户是 tkk)
# 如果没有密钥,先生成:ssh-keygen -t rsa
# 将公钥发送到公网服务器 (需要输入公网 tunnel_user 的密码,或者手动复制内容)
# ssh-copy-id tunnel_user@<公网IP>
验证:尝试 ssh tunnel_user@<公网IP>,如果不需要密码直接登录,即成功。
3.2 安装 Autossh
sudo apt update
sudo apt install autossh
3.3 编写 Systemd 服务文件 (宿主机)
创建服务文件,使隧道常驻后台。
sudo vim /etc/systemd/system/autossh-host.service
配置内容 (核心修改点:绑定 127.0.0.1):
[Unit]
Description=AutoSSH Tunnel for Host (Secure Loopback)
After=network-online.target
[Service]
# 内网服务器的实际操作用户
User=tkk
# 启动命令核心参数解析:
# -M 0: 关闭 autossh 自带的监控端口(使用 SSH 原生心跳)
# -N: 不执行远程命令
# -R 127.0.0.1:50022:localhost:22
# -> 127.0.0.1: 强制公网服务器只在本地监听,禁止外网直接连
# -> 50022: 公网服务器上的映射端口 (宿主机入口)
# -> localhost:22: 流量转发到内网本机的 22 端口
ExecStart=/usr/bin/autossh -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -N -R 127.0.0.1:50022:localhost:22 tunnel_user@<公网IP> -i /home/tkk/.ssh/id_rsa
# 失败重启策略
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
3.4 启动并验证服务
# 重载配置
sudo systemctl daemon-reload
# 启动服务
sudo systemctl start autossh-host
# 设置开机自启
sudo systemctl enable autossh-host
# 查看状态
sudo systemctl status autossh-host
若状态为 active (running),则隧道建立成功。
4. Docker 容器的远程开发配置
目标:让 Docker 容器也能像独立服务器一样被远程连接。
4.1 容器内准备 (Dockerfile 或 手动)
确保你的开发容器安装了 openssh-server 并运行中。
# 进入容器安装
apt-get update && apt-get install -y openssh-server
mkdir /var/run/sshd
# 设置 root 密码或者配置密钥 (推荐密钥)
4.2 为 Docker 配置独立的 Autossh 服务
无需在容器内跑 Autossh,直接在内网宿主机上跑第二个 Autossh 服务,指向容器映射到宿主机的端口。
假设:Docker 容器的 22 端口映射到了宿主机的 22334 端口。
创建新文件 /etc/systemd/system/autossh-docker-dev.service:
[Unit]
Description=AutoSSH Tunnel for Docker Dev
After=network-online.target
[Service]
User=tkk
# 核心区别:将流量转发到 localhost:22334 (容器映射端口)
# 公网映射端口改为 50023 (避免冲突)
ExecStart=/usr/bin/autossh -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -N -R 127.0.0.1:50023:localhost:22334 tunnel_user@<公网IP> -i /home/tkk/.ssh/id_rsa
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
启动该服务:sudo systemctl enable --now autossh-docker-dev
5. 本地开发环境配置 (VS Code)
目标:配置 VS Code 实现一键无感连接,就像连接本地虚拟机一样。
5.1 客户端 SSH 配置
在你的笔记本(Windows/Mac)上,打开 SSH 配置文件 ~/.ssh/config。
# ------------------------------
# 1. 跳板机配置 (公网服务器)
# ------------------------------
Host aliyun-jump
HostName <公网IP>
User root # 你平时管理云服务器的账号
Port 22 # 云服务器 SSH 端口
IdentityFile ~/.ssh/id_rsa_laptop # 笔记本连云服务器的私钥
# ------------------------------
# 2. 内网宿主机 (目标 1)
# ------------------------------
Host dev-host
HostName 127.0.0.1 # 必须填 127.0.0.1
User tkk # 内网服务器用户名
Port 50022 # 对应 autossh-host 服务映射的端口
ProxyJump aliyun-jump # 核心:通过跳板机跳转
IdentityFile ~/.ssh/id_rsa_laptop
# ------------------------------
# 3. Docker 开发环境 (目标 2)
# ------------------------------
Host dev-docker
HostName 127.0.0.1
User root # 容器内的用户名
Port 50023 # 对应 autossh-docker 服务映射的端口
ProxyJump aliyun-jump
IdentityFile ~/.ssh/id_rsa_laptop
5.2 连接使用
- 打开 VS Code。
- 安装插件 Remote - SSH。
- 点击左侧“远程资源管理器”。
- 右键点击
dev-host或dev-docker-> “Connect in Current Window”。 - VS Code 会自动穿过公网,跳进隧道,连接到你的内网环境。
6. 安全性检查清单
为了保证这套系统坚不可摧,请务必检查以下安全项:
- 公网防火墙 (Security Group):
- 阿里云安全组仅需放行 22 端口(公网 SSH)。
- 严禁放行 50022、50023 等映射端口(因为它们绑定的是 127.0.0.1,放行了也没用,反而混淆视听)。
- 公网用户权限:
- 确认
/home/tunnel_user/.ssh目录权限为700。 - 确认
/home/tunnel_user/.ssh/authorized_keys权限为600。 - 确认所有者为
tunnel_user。
- 确认
- 内网 SSH 安全:
- 建议在内网服务器
/etc/ssh/sshd_config中设置PasswordAuthentication no(禁止密码登录),仅允许密钥登录,防止隧道被攻破后遭到爆破。
- 建议在内网服务器
7. 故障排查速查表
| 现象 | 可能原因 | 检查命令 |
|---|---|---|
| autossh 服务启动失败 | 密钥路径错误或权限不足 | journalctl -u autossh-host -f |
| VS Code 连接超时 | 公网服务器 GatewayPorts 未开 | 公网执行 cat /etc/ssh/sshd_config |
| 提示 Permission denied | tunnel_user 目录权限错误 | 公网执行 ls -la /home/tunnel_user/.ssh |
| 连接时提示 Host key verification failed | 主机指纹变更 | 本地执行 ssh-keygen -R [127.0.0.1]:50022 |
| 隧道频繁断开 | 阿里云防火墙切断了空闲连接 | 检查 autossh -o ServerAliveInterval 参数 |