在部署服务器的时候,经常会是这样一种情况:生产的服务器部署在一个安全的局域网环境中,不对外暴露端口的话,无法从外网访问到它。这时候,我们可以通过一台外网可访问的服务器做跳转,间接访问到服务器A。

ssh反向代理示意图
ssh反向代理示意图

  如上图,客户端C无法直接访问到服务器A,那么我们先在局域网内访问服务器A,在服务器A上建立与服务器B的反向代理通道。此时,客户端C可通过访问服务器B,再经由服务器B这个代理,访问到服务器

step1.设置免密码登录

  • 在内网服务器A上生产公钥和私钥,并把公钥内容拷到服务器B的~/.ssh/authorized_keys里
    1
    2
    3
    4
    $ ssh-keygen -t rsa
    ...(一直按Enter,最后在~/.ssh/下生成密钥)
    $ ssh-copy-id -i ~/.ssh/id_rsa.pub user@hostB
    把本机的公钥追到hostB的 ~/.ssh/authorized_keys 里

于是服务器 A上的用户就可以用ssh以用户B的身份无需密码登陆到服务器 B上了。如:

1
ssh -l userB serverB。

step2.用ssh建立反向链接

在内网服务器A上执行

1
$ ssh -NfR 1234:localhost:22 userB@123.123.123.123 -p 22

  上面命令中,-N表示不执行远程命令,-f表示后台运行,-R则针对后面的绑定参数进行端口映射。整体意思是:将本机(服务器A)的22与远程服务器的1234端口进行绑定,相当于远程端口映射(Remote Port Forwarding)。
  这时在服务器B上sshd会listen本地1234端口

1
2
3
4
$ ss -ant

State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 127.0.0.1:1234 *:*

客户端C通过如下步骤可访问到服务器A:

1.通过ssh连接到服务器B

1
$ ssh userB@服务器B地址

2.通过刚刚建立的反向通道,连接到服务器A

1
$ ssh localhost -p 1234

  搞定完上面的步骤,已经可以从外网连接到服务器A了,但是这种方式还存在问题,服务器A->服务器B的链路是不稳定的,随时可能会断开,这时候可以用autossh这个命令,它可以帮助监听链路的连接情况,断开时可帮我们自动重连。

1
autossh -M 5678 -NR 1234:localhost:22 userB@123.123.123.123 -p 22

  比之前的命令添加的一个-M 5678参数,负责通过5678端口监视连接状态,连接有问题时就会自动重连,去掉了一个-f参数,因为autossh本身就会在background运行
  最后,还有一种情况就是机器重启了,这时候需要将该命令加入到自启动命令列表里。有多种方式,这里采用在/etc/rc.local文件里追加内容,将以下内容加入到文件里即可

1
/usr/bin/sudo -u conwin /usr/bin/autossh -M 5678 -NR 1234:localhost:22 userB@123.123.123.123 -p 22