使用autossh实现反向SSH隧道

有时候内网服务器在防火墙后,只能通过NAT访问外网,但不能在外网SSH登录到这个服务器。

解决办法是:

  • 创建SSH反向隧道:
    • 需要一台跳板服务器,这台服务器的SSH服务可通过公网直接访问
    • 通过内网服务器执行SSH命令登录跳板服务器并形成反向隧道
  • 使用SSH反向隧道:
    • 在外网,SSH登录到跳板服务器
    • 在跳板服务器,执行比如ssh -p10022 localhost,这里10022是反向隧道在跳板机的端口

这种做法有一个问题,就是这个后台运行的SSH反向隧道,可能会失效,或者在内网服务器重启后不再有效。

解决办法是使用autossh,自动后台执行ssh命令。

具体做法是:

  • 安装autossh
  • 设置免密码在内网服务器登录跳板服务器,因为脚本执行不能通过交互方式输入密码了
  • 通过systemd服务脚本,让autossh自动后台执行

安装autossh

在ubuntu server执行命令:

1
sudo apt-get install autossh

设置免密码登录

设置从内网服务器到跳板服务器的免密码登录。

可参照Initial Server Setup with Ubuntu 16.04

基本是两步:

  • 在内网服务器上创建key
  • 使用ssh-copy-id将key传到跳板服务器上

创建autossh脚本

创建文件~/autossh.service:

1
2
3
4
5
6
7
8
9
10
11
12
13
[Unit]
Description=AutoSSH service for a reverse tunnel from some.example.com to localhost
After=network-online.target

[Service]
User=marshal
Environment="AUTOSSH_GATETIME=0"
ExecStart=/usr/bin/autossh -M 0 -N -T -q -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -R 10022:localhost:22 tom@apple.com
Restart=always
RestartSec=60

[Install]
WantedBy=multi-user.target

其中:

  • 10022是指定的在跳板服务器上的隧道的端口号(自定义,可以是别的),即如想在跳板机上: ssh -p10022 localhost连接到隧道的端口
  • `tom@apple.com`,tom,指代跳板服务器的用户名,apple.com,指代跳板服务器域名

部署autossh脚本

转移文件:

1
sudo mv ~/autossh.service /etc/systemd/system/

重新加载:

1
sudo systemctl daemon-reload

设置让autossh可用:

1
sudo systemctl enable autossh.service

启动autossh服务:

1
sudo systemctl start autossh.service

查看是否有问题,查看autossh服务的状态:

1
sudo systemctl status autossh.service

如果autossh启动失败,可看到退出的日志。

使用反向SSH隧道

首先,要ssh登录到跳板服务器上。

然后,在跳板服务器执行:

1
ssh -p10022 localhosr