SSH反向连接及Autossh

参考文章

http://www.freeoa.net/osuport/netmanage/autossh-useage-refer_2831.html

接触Linux恐怕对SSH再熟悉不过了,还有scp,sftp各种方便的功能,一般的使用都需要ip:port(如果不是默认22的话),但有些情况比较特殊,就是想连接一台内网主机(比如公司内网,当然你肯定做不了Port Forwarding,除非你想在公司防火墙上拆个洞)。

稍懂一点网络的童鞋会明白,Internet上去主动连接一台内网是不可能的,一般的解决方案分两种,一种是端口映射(Port Forwarding),将内网主机的某个端口Open出防火墙,相当于两个外网主机通信;另一种是内网主机主动连接到外网主机,又被称作反向连接(Reverse Connection),这样NAT路由/防火墙就会在内网主机和外网主机之间建立映射,自然可以相互通信了。但是,这种映射是NAT路由自动维持的,不会持续下去,如果连接断开或者网络不稳定都会导致通信失败,这时内网主机需要再次主动连接到外网主机,建立连接。

实例:

 

 

公司要建立反向连接,之前没有接触过,所以安装autossh的时候有点小心,但在公司实验的时候总是出现问题,总结下问题

 autossh反向隧道本质上还是ssh连接,现在目标是A服务器通过ssh秘钥登录B服务器,免密码连接。建立测试A----ssh连------>B,成功

A远程设备服务器地址:192.168.1.111

B本地服务器地址:192.168.1.112

 现建立反向隧道,先安装autossh,写脚本

#!/bin/bash
/usr/local/bin/autossh -M15678 -NfR 1234:localhost:22 root@www.xxxxx.com -p4321

  将B服务器的4321端口映射到22接入端口,默认为22端口。

  1234为A服务器的映射端口,在公司连接远程内网A的方式为192.168.1.112:1234

  若重启后,不能远程连接A,可以在B服务器上netstat -lnpt | grep 1234,确定B服务器端没有被进程占用,若占用kill掉进程,然后就能远程连接A了

主要原因还是因为autossh连接不稳定造成的

总结概括就是A、B都要kill掉ssh相关进程,A远程设备服务器ps -ef | grep ssh

B服务器 

 

 

autossh -M 5678 -CqTfnN -D 192.168.0.2:7070  freeoa@remote-host

参数解释:
-M为autossh参数, -CqTfnN -D 为ssh参数

-M 5678 : 负责通过5678端口监视连接状态,连接有问题时就会自动重连
-C  :启动数据压缩传输
-q  :安静模式运行,忽略提示和错误
-T  :不占用shell
-f  :后台运行
-n  :配合 -f 参数使用
-N  :不执行远程命令,专为端口转发度身打造
-D 192.168.0.2:7070  :指定一个本地机器 “动态的“ 应用程序端口转发,如果不加IP地址,默认只监听127.0.0.1

 

1、实际操作

A要控制B

A主机:外网,ip:123.123.123.123,sshd端口:2221

B主机:内网,sshd端口:2223

无论是外网主机A,还是内网主机B都需要跑ssh daemon

1.1.首先在B上执行

ssh -NfR 1234:localhost:2223 user1@123.123.123.123 -p2221

这句话的意思是将A主机的1234端口和B主机的2223端口绑定,相当于远程端口映射(Remote Port Forwarding)。

这里每次需要输入A主机user1的登陆密码,后面会讲到解决办法

1.2.这时在A主机上sshd会listen本地1234端口

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

1.3.像平时一样连接到A主机的1234端口就可以控制内网B主机了

$ ssh localhost -p1234

 

2.一开始提到,这种反向连接(Reverse Connection)不稳定,可能随时断开,需要内网主机B再次向外网A发起连接,这时需要个“朋友”帮你在内网B主机执行这条命令。它就是Autossh。

在此之前还要解决之前的一个问题,那就是每次内网主机B连接外网主机A时都需要输入密码,这个问题ssh本身是提供另外一种验证方式——通过密钥验证用户身份,实现自动登录。

 

2.1.在内网B主机上生产公钥和私钥

$ ssh-keygen
...(一直按Enter,最后在~/.ssh/下生成密钥)
$ ls ~/.ssh/
id_rsa id_rsa.pub known_hosts

 

2.2.复制B主机上生成的id_rsa.pub公钥到外网A主机上,并将内容加入到~/.ssh/authorized_keys中

$ cat id_rsa.pub >> ~/.ssh/authorized_keys

试下,内网B主机连接外网A主机,就不再输入密码验证了

补充:今天了解到ssh-copy-id这个命令,上面这个操作就变的简单了

$ ssh-copy-id user1@123.123.123.123

 

2.3.再来看看Autossh的用法

$ autossh -M 5678 -NR 1234:localhost:2223 user1@123.123.123.123 -p2221

  /usr/local/bin/autossh -M15678 -NfR 20191:localhost:22 root@www.xxxxx.com.cn -p8022

比之前的命令添加的一个-M 5678参数,负责通过5678端口监视连接状态,连接有问题时就会自动重连,去掉了一个-f参数,因为autossh本身就会在background运行。

 

3.终极方案:当重启内网B主机,谁来自动Autossh呢,加入daemon吧

以daemon方式执行,相当于root去执行autossh, ssh,这时刚才普通用户目录下的.ssh/authorized_keys文件会不起效。有两种办法解决,一种是用autossh的参数指定.ssh路径;另外一种是以普通用户身份执行daemon,下面是第二种方式。

/bin/su -c '/usr/bin/autossh -M 5678 -NR 1234:localhost:2223 user1@123.123.123.123 -p2221' - user1

autossh还有很多参数,用来设置重连间隔等等。

将上面命令放入下面各启动方式中,根据自己系统自己配置:

SysV:/etc/inid.d/autossh

Upstart: /etc/init/autossh.conf

systemd: /usr/lib/systemd/system/autossh.service

posted @ 2017-03-27 23:43  陈浩然201  阅读(2631)  评论(0编辑  收藏  举报