SSH Tunnel解决无公网IP 80被封等问题

有了一个CB3,一个树莓派B,外加一堆功耗很小的电脑,扔那扔着可惜,爬虫的话,一个就够了
于是想折腾怎么把这些“废品”给利用起来。
其实,用3322.org或者花生壳之类的DDNS都可以,因为我现在用的还是电信的宽带,除了80端口被封,还是可以拿到动态的公网IP的,但是呢,心里总是感觉不爽,凭啥非要再输入个端口号呢。而且放web服务这种事,最好还是别那么张扬。大环境下,指不定哪天就被查水表了。
从网上找到以下几种解决方案:

一、新花生壳/Nat123
看上去很美好,但是新花生壳的免费版帐号每天11点抢,正好是我比较忙的时间段,而且这种营销方式我很是不喜,最最主要的是这俩货都不支持Linux、Mac的客户端,只有Windows,除了玩游戏的一台台式机(而且功耗还很高),一个公司的笔记本以外,我就没有windows了,而且很明显,这两个都不能保证24小时开机,所以 Pass
其实,花生壳现在有一个叫花生棒的东西,内置了一个免费的新花生壳内网版,但是以为一个卖200+的玩意,居然只能映射2个端口,每个月还就1G的流量,我只能说:我勒个去,在我的概念里,那个小硬件其实就是一个嵌入式Linux,采用下面说的方案三来实现的。

二、树莓派VPN拨入VPS,通过VPS上的Nginx将“内网”中的树莓派做端口转发
这个方案的可行性倒是不错,但是看看可怜的树莓派,512Mb内存,还得跑服务,还得跑VPN客户端,而且最主要的,电信大概1-2天会重置一次网络,网络会间断一段时间,那么VPN的监控与重播又是一个麻烦事。

三、使用SSH Tunnel来建立本机/局域网与VPS的隧道,从而完成端口映射
具体的实施步骤如下:
1、先在VPS上打开openssh服务器的GatewayPorts支持

vi /etc/ssh/sshd_config

注意是sshd_config哦,在尾部添加:

GatewayPorts yes

保存,退出后,重启openssh服务器

2、在树莓派上:

ssh -fNR 0.0.0.0:80:localhost:8080 root@xxx.xxx.xxx -p 2112

上述的含义为:以root用户ssh连接到xxx.xxx.xxx,其中xxx.xxx.xxx的ssh端口为2112,然后建立一个隧道把localhost的8080端口绑定到xxx.xxx.xxx的80端口,xxx.xxx.xxx的监听IP为0.0.0.0,即所有地址。

下面是V友给的原文解释:

ssh的-R A.A.A.A:XXXX:B.B.B.B:YYYY 意思是: 在远程机器打开监听A.A.A.A:XXXX端口,该端口管道到本机,以本机的身份链接B.B.B.B:YYYY,而建立的管道。
还有个-L是类似的: -L A.A.A.A:XXXX:B.B.B.B:YYYY 意思是:在本机打开监听A.A.A.A:XXXX端口,该端口管道到远程机,以远程机的身份链接B.B.B.B:YYYY,而建立的管道。

这样访问http://xxx.xxx.xxx就可以访问到树莓派8080端口上的应用啦

3.监控脚本(非aotussh)
在树莓派上安装screen和expect
将下面的脚本保存为autossh.sh,打开screen,然后执行:authssh.sh

#!/bin/sh

if [ "$1x" != "connectx" ]; then

    if [ -z $1 ]; then
        echo "Usage: $0 [username@]host[:port]" 2>&1
        exit 0
    fi

    echo -n "Password: "

    stty -echo; read pass; stty echo; echo ""

    expect -- << EOF
        spawn $0 connect $1

        while 1 {
            expect {
                "password:" {
                    send "$pass\r"
                }
                "yes/no" {
                    send "yes\r"
                }
                "Permission denied" {
                    puts "Password error."
                    break
                }
            }
        }
EOF
else
    shift
    port=`echo $1 | perl -nle 'print /\:(\d+)$/ ? $1 : "22"'`
    while [ 1 ]
        do ssh -p $port -CN -D 0.0.0.0:80 $1 target "while nc -zv localhost 80; do sleep 20; done"
        sleep 20
    done
fi

4.监控断线(使用autossh)
请参考 http://yuanxiao.sinaapp.com/pages/122/132/377/article_index.html
使用命令:autossh -M 7890 -NR 0.0.0.0:8080:localhost:8080 root@xxx.xxx.xxx -p 2112
可以看到,多了一个M参数,该参数是指使用本地的7890端口来监听SSH连接是否正常
以daemon方式执行,相当于root去执行autossh, ssh,这时刚才普通用户目录下的.ssh/authorized_keys文件会不起效。有两种办法解决,一种是用autossh的参数指定.ssh路径;另外一种是以普通用户身份执行daemon,下面是第二种方式。

/bin/su -c '/usr/bin/autossh -M 7890 -NR 0.0.0.0:8080:localhost:8080 root@xxx.xxx.xxx -p 2112 -f' - tan9le

注意:如果需要远程服务器直接监听0.0.0.0地址的话,需要将 远程 服务器的ssh服务配置文件(如/etc/sshd_config)中修改GatewayPorts no为GatewayPorts yes来打开它,否则远程服务器将只能够监听127.0.0.1
将上面命令放入下面各启动方式中,根据自己系统自己配置:

SysV:/etc/inid.d/autossh
Upstart: /etc/init/autossh.conf
systemd: /usr/lib/systemd/system/autossh.service

标签: ssh, ssh tunnel, 内网, nat, autossh