自己搭建ngrok服务器实现树莓派内网穿透

目标

实现从公网访问位于家中的树莓派,包括ssh连接和http访问

准备

  1. VPS【有公网ip】:ubuntu14.04
  2. 树莓派【可连接internet】:raspbian jessy
  3. ngrok源码【点此下载】
  4. go 语言(ARM版 for 树莓派和AMD64版 for ubuntu)点此下载,需要扶梯子

VPS配置

我的VPS是腾讯的,安装了ubuntu14.04版本的go语言环境。
安装方式如下:
sudo apt-get install golang-1.6
注意在14.04版本需要上述命令,而在16.04的安装命令是:
sudo apt install golang
也可以在上面的下载地址中直接下载go语言,然后复制到你喜欢的路径下即可。
然后配置环境变量:
使用vim打开/etc/profile:
sudo vim /etc/profile
在最后加入:
export GOROOT=/usr/lib/go-1.6
export GOPATH=/home/ubuntu/ngrok
export PATH=$GOROOT/bin:$PATH

其中GOROOT的位置要只想go语言安装包中的/bin文件夹的上一级目录
GOPATH是开发目录,指向ngrok的源码目录即可
PATH中需要加入go语言安装包的/bin文件夹
配置完成,使用:
source /etc/profile
使配置生效。
可以采用 go env来查看是否go语言安装状态

树莓派配置

树莓派上无法通过包管理器直接安装go语言环境,需要下载源码,注意下载arm版本的。地址如上。
下载完成后解压缩,将go文件夹放到/usr/local/下。
配置环境变量和VPS下一致,只需要注意文件夹路径即可。

下载ngrok源码并编译运行

如上所述,ngrok的源码下载好后,我将其存放在我的本地电脑【ubuntu16.04】中。

首先需要配置证书:

$ cd ngrok
$ openssl genrsa -out rootCA.key 2048
$ openssl req -x509 -new -nodes -key rootCA.key -subj "/CN=yourdomain" -days 5000 -out rootCA.pem
$ openssl genrsa -out device.key 2048
$ openssl req -new -key device.key -subj "/CN=yourdomain" -out device.csr
$ openssl x509 -req -in device.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out device.crt -days 5000

注意上述代码中的yourdomain字段。这个域名必须和你的vps域名的根域名一致,使用时注意替换解释如下:
假设我的vps域名是myvps.com,假设我在这里把证书中的yourdomain替换为myvps.com,之后ngrok服务架设完成,我的树莓派上跑了一个nginx服务器,我需要把它穿透到外网,这个时候ngrok运行需要一个subdomain参数,假设我设置为rasp,那么最终我要访问我的树莓派上的web服务时,需要输入的域名就为rasp.myvps.com。
你也可以把这个yourdomain字段设置为ngrok.myvps.com用来区分,这样的话需要你在vps的域名解析中设置子域名的解析,否则无法使用。
上述命令执行完成后,在ngrok的目录下应该生成了6个新的文件。然后,我们需要执行:
cp rootCA.pem assets/client/tls/ngrokroot.crt
cp device.crt assets/server/tls/snakeoil.crt
cp device.key assets/server/tls/snakeoil.key

ok,证书的准备工作到此结束。

编译生成linux amd64 的ngrok服务端

最终这个服务端是要运行在vps上的,所以如果你不清楚本地编译的程序能否在vps上运行的话,最好直接在vps上编译。
我的vps是ubuntu14.04 amd64,本地环境是ubuntu16.04 amd64,所以我就直接在本地编译了。

cd ./ngrok
make release-server

编译过程中可能需要从http://gopkg.in/和github上下载一些所需的文件和包,由于国内的你懂的原因,可能访问速度不是很快,会出现域名解析失败或者连接超时等,我采用的方法时浏览器访问http://gopkg.in/,在需要下载github上代码的地方,如果下载不成功,可以自己手动根据命令行提示的地址自行下载,放到/src/github文件夹下即可。
最终编译完成的话,会在./ngrok/bin/文件夹下生成一个ngrokd可执行文件,使用scp命令将其复制到VPS上。
可以将ngrokd放置在 $GOROOT/bin下,这样可以直接运行。

运行ngrok服务端

在VPS上,运行:
ngrokd -domain="yourdomain" -httpAddr=":8081" -httpsAddr=":8082" -log ./ngrokd.log &
注意domain参数要和证书文件中的yourdomain一致,-log参数是记录日志文件,&时为了让ssh断开时ngrokd不退出。

编译树莓派上的ngrok客户端

将刚才用来编译ngrok服务端的ngrok源码文件夹全部复制到树莓派上:
cd ./ngrok
make release-client

编译完成后会在./ngrok/bin文件夹下看到ngrok可执行文件
将其复制到$GOROOT/bin文件夹下
在该文件夹下创建一个ngrok.cfg配置文件:
server_addr: "yourdomain:4443"
trust_host_root_certs: false

运行:
ngrok -log /usr/local/go/bin/ngrok.ssh.log -config /usr/local/go/bin/ngrok.cfg -proto tcp 22
ngrok -log /usr/local/go/bin/ngrok.log -subdomain rasp -config /usr/local/go/bin/ngrok.cfg 80
第一条命令是生成一个tcp连接,穿透到树莓派的22端口,实现ssh。
这样,会在客户端下看到VPS上的一个随机端口被分配,这个端口可以连接到树莓派上。
第二条命令是将rasp.yourdomain分配到树莓派上的80端口。可以在浏览器直接访问rasp.yourdomain:8081来访问树莓派上的web服务。

几个问题

  1. 使用ngrok的连接有个问题,一段时间后,访问树莓派上的web应用或者ssh连接,第一次都会很慢或者失败,但是第二次就很快了,目前没有看到如何解决。
  2. 如何让外网访问时的rasp.yourdomain:8081这样的地址中的端口号去掉?
    因为我的vps上的80端口是被占用了的,所以解决方案是使用nginx来反向代理,具体操作时编辑vps上的nginx配置文件/etc/nginx/sites-available/default:
    在其中加入这样一段:
    server {
    listen 80;
    server_name rasp.yourdomain;
    location / {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host:8081;
    proxy_set_header X-Nginx-Proxy true;
    proxy_set_header Connection "";
    proxy_pass http://127.0.0.1:8081;
    }
    }

    然后重启nginx服务,这样可以直接访问rasp.yourdomain来访问到树莓派。

  3. 我的证书文件下的域名和我的ngrok客户端运行时的配置文件中的域名一致,为什么服务器端的日志中还是出现bad certificate提示?
    这也是我遇到比较奇葩的一个问题,害得我重新下载了ngrok和go语言,重新编译了。最后我才知道,,原来我的树莓派下的时间不对,解决方法就是把vps和树莓派的时间设置为一致。

  4. 关于树莓派下使用nginx php5中,php显示空白页的问题。啥都不说了,看这个最新的解决方案,不要再被百度坑了,google大法好:http://aircheese.me/2016/typecho-lnmp-raspberry-pi3.html

猜你喜欢

转载自blog.csdn.net/LeeHDsniper/article/details/81188432