利用autossh和中间主机为内网主机建立稳定ssh 连接

通常会遇到一些内网主机没有独立IP 地址,隐藏在NAT 之后,用户无法直接建立ssh 连接。

这时候就需要一个中间人机器(具有独立IP)做为跳板,内网机器反向连接至中间机器。用户登陆时,首先连接至中间机器,再反向连接至内网主机。

其步骤如下:

  1. 在内网主机,运行 ssh -R 7777:localhost:22 qing@middleman
  2. 在中间主机,运行 ssh -p 7777 user@localhost

注意:步骤2的user 是内网主机user。

ssh -R 参数中7777 是远端映射的端口,连接该端口将建立起和内网22 号端口的链接;下面是man ssh 中关于-R 选项的说明

-R [bind_address:]port:host:hostport

-R [bind_address:]port:local_socket

-R remote_socket:host:hostport

-R remote_socket:local_socket

-R [bind_address:]port

Specifies that connections to the given TCP port or Unix socket on the remote (server) host are to be forwarded to the local side.

This works by allocating a socket to listen to either a TCP port or to a Unix socket on the remote side. Whenever a connection is made to this port or Unix socket, the connection is forwarded over the secure channel, and a connection is made from the local machine to either an explicit destination specified by host port hostport, or local_socket, or, if no explicit destination was specified, ssh will act as a SOCKS 4/5 proxy and forward connections to the destinations requested by the remote SOCKS client. Port forwardings can also be specified in the configuration file. Privileged ports can be forwarded only when logging in as root on the remote machine. IPv6 ad‐ dresses can be specified by enclosing the address in square brackets.

By default, TCP listening sockets on the server will be bound to the loopback interface only. This may be overridden by specifying a bind_address. An empty bind_address, or the address ‘*’, indicates that the remote socket should listen on all interfaces. Specifying a remote bind_address will only succeed if the server's GatewayPorts option is enabled (see sshd_config(5)).

If the port argument is ‘0’, the listen port will be dynamically allocated on the server and reported to the client at run time. When used together with -O forward the allocated port will be printed to the standard output.

但这样存在两个问题:1)ssh 连接超过固定时间会自动释放;2)每次连接中间机器都需要用户手动输入密码。

第一个问题通过autossh 解决

autossh 通过将ssh 命令包裹至一个循环中,并在ssh 命令断开时自动建立连接,这样就保证了即使内网机器无法访问,也会自动建立和中间主机的逆向连接。autossh 命令格式如下

autossh [autossh options] [ssh options]

即autossh 除了自身参数,其他参数直接用ssh 的即可。

第二个问题通过公钥免密码登录解决:1)内网主机执行ssh-keygen;2)ssh-copy-id -i ~/.ssh/id_rsa.pub user@middleman_machine

结合起autossh 和免密码登录,autossh 命令如下:

autossh -o "PasswordAuthentication=no" -o "PubkeyAuthentication=yes" -i ~/.ssh/id_rsa -R 7777:localhost:22 user@middleman

将该命令添加至开机启动模块中实现开机启动。