打造家里7*24小时在线的SSH代理

实现此功能,主要是为了充分压榨和利用家里的PT下载机,让家里的其他网络设备能够通过共享出来的socket5代理”平滑的”上网,你懂的……

我们都知道,SSH支持端口转发,能够把当前连接状态的SSH,共享为socket5代理,主要就是使用到ssh命令的-D参数。另外,在Linux/Unix平台下,一般运行SSH命令,是需要输入密码的,我们需要做一些设置,让SSH能够通过public key来验证,从而省去输入密码的繁琐步骤。如果你用的是windows平台,那就方便多了,推荐使用Tunnelier这个软件,不但可以保存SSH用户名和密码,还可以自动断线重连。使用此工具,你可以忽略掉此文了……

下面介绍一下Linux/Unix下通过public key验证SSH登录的步骤:

  • 需要在你的客户端机器生成public key,通过如下命令来实现:
    1
    ssh-keygen -t rsa

跟着提示,一步一步按回车,就可以生成一对key,包含private key和public key,然后,通过scp/SFTP/rsync/FTP 等等方式,把这个含有public key的文件: id_rsa.pub上传到你的SSH连接的服务端上去。

  • SSH连接到服务端,设置SSH验证的方式,把SSH配置文件中的下面两项的注释去掉,使其生效:
    1
    2
    PubkeyAuthentication yes
    AuthorizedKeysFile .ssh/authorized_keys

开启public key验证,并且指定了key存放的路径,比如,你如果用用户名user1登录SSH,就得把上面提到的public key file: id_rsa.pub 上传到服务器上的 /home/user1/.ssh/ 并改名叫做authorized_keys

步骤操作完成之后,重启一下sshd服务,然后客户端就可以通过public key来连接SSH了。

搞定上面的两步,我们可以编辑一个shell文件,比如叫做AutoSSH.sh,内容如下:

1
/usr/bin/ssh -p 24 -N -D 0.0.0.0:7070 [email protected] &

赋予脚本可执行权限,然后执行,你会发现SSH自动连接成功,并且会在本机监听7070端口,这就是一个socket5代理了,然后充分发挥你的智慧,该干嘛干嘛去,比如Firefox+AutoProxy,或者Chrome+Proxy SwitchySharp,等等…… 哥就不细说了……

这里需要注意的是,-D后的IP,必须是0.0.0.0,这样,这个socket5代理才能被家里局域网中的其他机器访问到,不然,默认只监听本机的127.0.0.0:7070,其他机器是访问不了的!

本文貌似要接近尾声了,不过,你用了一段时间后,会发现一个比较严肃的问题,这个SSH貌似一段时间连上能用,过了一段时间就自动断开了,你不得不一次又一次的手动运行这个脚本。

这是咋回事呢? 原来,SSH是默认有一个空闲时间的,当客户端没有操作处于一定的空闲时间,服务端就会主动断开SSH连接。

在SSH服务端的配置文件中,有两个参数,分别叫做:ClientAliveInterval 和 ClientAliveCountMax,这个就是用来控制最大闲置时间的。

ClientAliveInterval 数值是秒,比如你设置为300,就是5分钟.

ClientAliveCountMax 指如果发现客户端没有相应,则判断一次超时,这个参数设置允许超时的次数。比如:

ClientAliveInterval 300

ClientAliveCountMax 5;

则代表允许超时 1500秒 =25分钟

通过更改数值大小,能保证SSH连接最大闲置时间。不过感觉这样的方式还是不太靠谱,一旦网络遇到问题,或者其他原因导致SSH连接端口,你还是得手动去运行那个连接SSH的脚本。

既然这样,我们还是自己动手,丰衣足食一下,俺顺带用ruby写了个检测SSH连接是否断开,并且自从运行SSH连接脚本的简单程序:

#!/usr/local/rvm/bin/ruby

#AutoSSH.rb
#Written by Timothy 2012.11.19
#Run it with: ruby AutoSSH.rb &

lambda{

    PORT_NUM = "0.0.0.0:7070"
        GREP_STR = "netstat -anp|grep #{PORT_NUM}"
        SHELL_PATH = "/root/AutoSSH/AutoSSH.sh &"

        pipe = IO.popen(GREP_STR)
        result = pipe.gets

        if((result != nil)  && (result.include? PORT_NUM))
            return
        else
            p 'SSH is disconnected! Will reconnect it!'
                system SHELL_PATH
                end

}.call

这个程序的功能,就是检测0.0.0.0:7070 是否还在监听。你或许需要根据你的需求,配置一下AutoSSH.sh文件的路径,然后,把这个脚本加到系统的定时任务里面去,让它每一分钟执行并检测一次,若是遇到SSH连接端口,会立马重新连接SSH的。如果你机器没有配置ruby环境,可以google一下如何安装ruby。

大功告成,到此,你就有了一个7*24小时不断网的SSH代理,供家里其他的机器同时使用。

支持原创技术分享,据说打赏我的人,都找到了女朋友!