适用场景:异地远程连接完全隔离的内网服务器及 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 连接使用

  1. 打开 VS Code。
  2. 安装插件 Remote - SSH
  3. 点击左侧“远程资源管理器”。
  4. 右键点击 dev-hostdev-docker -> “Connect in Current Window”。
  5. VS Code 会自动穿过公网,跳进隧道,连接到你的内网环境。

6. 安全性检查清单

为了保证这套系统坚不可摧,请务必检查以下安全项:

  1. 公网防火墙 (Security Group)
    • 阿里云安全组仅需放行 22 端口(公网 SSH)。
    • 严禁放行 50022、50023 等映射端口(因为它们绑定的是 127.0.0.1,放行了也没用,反而混淆视听)。
  2. 公网用户权限
    • 确认 /home/tunnel_user/.ssh 目录权限为 700
    • 确认 /home/tunnel_user/.ssh/authorized_keys 权限为 600
    • 确认所有者为 tunnel_user
  3. 内网 SSH 安全
    • 建议在内网服务器 /etc/ssh/sshd_config 中设置 PasswordAuthentication no(禁止密码登录),仅允许密钥登录,防止隧道被攻破后遭到爆破。

7. 故障排查速查表

现象可能原因检查命令
autossh 服务启动失败密钥路径错误或权限不足journalctl -u autossh-host -f
VS Code 连接超时公网服务器 GatewayPorts 未开公网执行 cat /etc/ssh/sshd_config
提示 Permission deniedtunnel_user 目录权限错误公网执行 ls -la /home/tunnel_user/.ssh
连接时提示 Host key verification failed主机指纹变更本地执行 ssh-keygen -R [127.0.0.1]:50022
隧道频繁断开阿里云防火墙切断了空闲连接检查 autossh -o ServerAliveInterval 参数