近来,在为公司客户部署相关DNS系统服务,用于资源调度服务,但是客户出口缺少公网ip地址,不能方便的去管理这台服务器,开始想到使用teamviewer做中转,穿透内网,但是在Centos环境下,照teamviewer官方给出的手册尝试安装多次,未果,始终未能获取ID号,甚至最后都安装了图形gnome环境,尝试在图形环境下安装teamviewer,网络始终是notReady,最后,只能放弃使用teamviewer,在公司找了台有公网ip的机器,用ssh反向主动连接,也就是常说的端口转发。

    这种方式跟最早网上流行的反弹式远程控制工具原理类似,像灰鸽子,任我行,Pcshare等等,包括现在很多***使用的远程控制***程序都是这种主动连接反弹式***,“堡垒总是从内部突破容易的多”。

    回归正题,先来实操,最后上原理。


系统环境:

         公司主机:extrahost(代指主机名和ip,具有公网ip),用户名:root  ssh端口:2200

       客户服务器:Intrahost(代指主机名和ip,私网ip做了NAT),用户名:root  ssh端口:2211

        

ssh用到的参数:

        -N:不执行何指令

                -f:后台执行

                -R:建立反向 tunnel

在客户的系统中输入如下命令:

----------------------------------------------------------------------------------------------------------

 [root@Intrahost ]# ssh -NfR 2233:localhost:2211 root@extrahost -p 2200

输入密码即可

//port2233指绑定远程主机extrahost端口2233  

-------------------------------------------------------------------

 在公司管理设备查看端口2233是否在监听状态,netstat -ant,

 如果未成功监听,请检查管理设备防火墙 和sshd是否有相关访问控制

 在公司管理主机extrahost输入如下命令和密码,登陆到客户系统intrahost

--------------------------------------------------------------------

[root@extrahost]#ssh root@127.0.0.1 -p 2233 

//即可连接到客户的服务器上

------------------------------------------------------------------


问题

一.连接稳定问题

  由于是反向主动连接,在会话异常中断,无法由控制端发起连接,我们可以借助几个工具来帮我们保持会话。

  1.使用autossh工具  

    安装方法 autossh工具不在linux源中,需要从第三方源下载

     地址:http://pkgs.repoforge.org/autossh/ 安装包有32位和64位,下载根据操作系统去选择。

    使用方法 跟ssh类似,区别autossh需要不断去检测ssh连接状态,需要我们使用 -M参数,来指定autossh监听端口:

---------------------------------------------------------------------------------------

   [root@Intrahost]autossh -M 1100 -NfR 2233:localhost:2211 root@extrahost -p 2200

----------------------------------------------------------------------------------------

   2.使用nohup命令,截断挂起信号

    用法:Usage: nohup COMMAND [ARG]...   

            or:  nohup OPTION

    示例:

------------------------------------------------------------------------------------

[root@Intrahost]nohup ssh -NfR 2233:localhost:2211 root@extrahost -p 2200

来中断对ssh的挂起信号。

---------------------------------------------------------------------------

  3.建议大家使用nohup命令,这种方法可靠性很高,原因稍后阐述,现在我们来编写脚本使用crond定时任何计划来保持ssh会话,脚本内容如下。

 

#!/bin/bash 
 createTunnel() {  
/usr/bin/ssh -NfR 2233:localhost:2211 root@extrahost -p 2200
if [[ $? -eq 0 ]]; then    
echo Tunnel to jumpbox created successfully  
else    
echo An error occurred creating a tunnel to jumpbox. RC was $?  
fi
}
/bin/pidof ssh
if [[ $? -ne 0 ]]; then  
echo Creating new tunnel connection  
createTunnel
fi

  添加定时任务计划,重复执行脚本来判断通信隧道的建立

 -----------------------------------------------------

   命令:crontab -e

   */1 * * * * /root/ReverseSsh.sh > tunnel.log 2>&1

  别忘了将脚本赋予执行权限

  ----------------------------------------------------

    chmod u+x /root/ReverseSsh.sh

  -----------------------------------------------------

鄙人能看到和想到的维持会话的方法,就在这了,欢迎大家分享自己的创新方法。


二、安全性问题

    虽然我们坦然的建立了这条tunnel,可是大家忽略了一个东西,就是建立反向连接的tunnel时,我们需要输入对方设备的密码,假设我们的设备因为我们人品的关系,导致了重启,这时,无论再好的保持会话的工具和命令,都没办法替你输入密码,除非,公司的客户是你的好朋友或者至少是你信任的人,让他帮你输入密码,很不幸,事情往往超乎我们的想象。

    

   所以,我们需要建立一个脚本,来替我们输入密码,并且对脚本进行加密,来防止客户肆意窥探我们管理设备的密码。也有,拿密钥做认证来免密码登陆,不建议大家这么做,这样虽然方便管理,但同样意味着客户可以使用该设备随意进入我们的管理设备,这是我们不愿意发生的事情,虽然我们的客户很可爱而且善良和蔼可亲。

   

  脚本内容如下,我们需要借助自动化工具expect,至于expect是怎样的套件和工具,具体使用方法,大家可以去查资料学习,这个是我们自动化运维较常用的交互工具,建议大家掌握。

 except安装方法,建议使用yum安装:

----------------------------------------------

        yum -y install expect*

----------------------------------------------

#!/bin/sh
# description:The script file for keepalive ssh session
# Founder broadband interconnection.DE created by John.zhang
# update 20151104

passwd=********

expect -c "
/usr/bin/ssh -NfR 2233:localhost:2211 root@extrahost -p 2200
set timeout 5
expect \"password:\"
send \"${passwd}\r\"
expect eof
"

    脚本内容功能实现简单,大家可以尽情发挥,然后我们对该脚本文件进行加密,较常用的有三四种,我们这里推荐大家使用SHC工具,方便安全容易。


  详细的安装方法大家去网上检索,这里简单飘过,我们只说使用方法。

     下载地址:wget http://www.datsi.fi.upm.es/~frosal/sources/shc-3.8.9b.tgz

   

    下载后,我们进行解包,

    tar -xvf shc-3.8.9b.tgz

    

  这个包下到的不是源代码,是预编译好的文件,直接安装即可make install

   

    使用示例:[root@Intrahost]#shc -r -f ~/ReverseSsh_pass.sh

    

    运行后会生成两个文件,ReverseSsh_pass.x 和 ReverseSsh_pass.x.c.   其中sReverseSsh_pass.x是加密后的可执行的二进制程序;用./ReverseSsh_pass.x即可运行,ReverseSsh_pass.x.c是生成ReverseSsh_pass.x的原文件,建议大家拷贝到自己电脑,从服务器上删除。并且对该程序添加执行权限,添加到开机启动。

                [root@Intrahost]# vi /etc/rc3.d/S99local

    在该文件下边写入我们加密脚本后的程序 /root/ReverseSsh_pass.x,用于开机自启动。注意这里是命令行方式,注意启动级别。


三、原理阐述,大神可忽略。

 1.SSH reverse tunnel

        wKioL1cQWc-QCNF_AABIUFxMF48574.png

    如图,为ssh服务的正向和反向两种会话连接示意图,正常情况下(正向),我们由客户端发起会话请求到服务端,使用ssh协议为我们建立起一条连接通讯,我们可以将这条连接看做是条隧道(tunnel),这样我就可以使用终端工具来远程管理我们的服务器,注意,这里我们并不是真正意思上打开了终端,而是我们在网络层上,通过建立起来的隧道来连接到终端,所以我们把像使用putty,Securecrt这类工具,建立起连接呈现的终端也叫仿真终端。

    

    既然我们建立起这样一条隧道,那必然每条隧道都有相同的端点,起始端和结束端,而这两端的端点正是我们的客户端和服务端,不同的是,正向连接是声明要连接的对端ip和端口,而反向连接则是由服务端声明可以连接到本机的对端ip和通讯端口。

    

    这里提醒大家的是,正向连接和反向连接,建立起隧道的方向是一致的,都是由客户端作为起始端创建的通讯隧道,所谓的正向连接和反向连接取决于服务端在建立隧道的行为,正向连接,是被动接受来自客户端的请求,建立连接;而反向连接则是由服务端主动请求连接,但创建会话连接的起始端始终是客户端。

     同样,弄懂原理后,那么像Telnet,FTP,甚至是我们用来连接windows桌面的RDP,也可以实现反向连接,大家可以在网上搜搜具体方法。

 

    2.nohup

    

    刚才我们提到了nohup这个命令,这个理解其实很容易,从字面不难理解禁止挂断,官方手册解释也很简单,ignoring hangup signals,忽略挂断信号,个人认为把它解释为截断挂断信号,更好点,nohup实现原理像一个守护进程,但它工作的机制是信号量级的,当我们所运行的进程在异常中断,或者超时的时候,会产生中断信号,来结束该进程,节约资源开销,nohup原理就是当收到来自针对该进程的中断信号时,会阻止该信号的发送,从而保持进程的运行不会因为异常情况而中断。

    使用这个命令的优势很明显,autossh保持会话的工作原理基本和我们编写的脚本类似,而nohup工作机制直接是信号量级的,不需要通过执行另外的程序产生信号结果反馈,linux的信号机制起源于Unix系统,信号量由软件产生,进程之间的通讯均由信号完成,所以nohup执行效率和稳定性相比autossh很高,或者说两个没有可比性,因为它们实现的方式不一样。


     就写到这吧,路漫漫上下而求索,希望大家能提出更好的方法,最后附上相关组件和工具。