ngrok服务端客户端编译

编译分两块:

  1. 服务端
  2. 配套客户端

客户端是需要和服务端匹配的,在编译的时候是要指定域名证书的,所以不用担心别人用其他的客户端去连你的服务端。

编译准备

  1. 一个vps,阿里云或者其他,linux系统即可,这里我推荐debian或ubuntu.
  2. 一个域名,将域名泛解析到你的服务器上。
  3. 为服务器安装git和go

我就直接在我的博客服务器上编译了,我准备使用ngrok.ekan001.com作为动态域名的根,记得泛解析。

首先我们需要在服务器上安装go环境,我建议下载最新版的go包,直接解压到服务器(也可以直接apt-get install

/usr/local/go即可,然后将/usr/local/go/bin/*复制到/usr/bin/

go的下载地址:http://www.golangtc.com/download 下载和你服务器系统对应的版本即可,这里我是linux 64位的,就选择下载go1.4.2.linux-amd64.tar.gz即可。

接着,下载ngrok源码:

cd /usr/local/src/
git clone https://github.com/inconshreveable/ngrok.git
export GOPATH=/usr/local/src/ngrok/
export NGROK_DOMAIN="ngrok.ekan001.com"
cd ngrok

(我是下好ngrok_master放到/home/lym/goproj/src目录下的

然后cd ~/goproj/src/ngrok_master

开始编译

  1. 首先为根域名生成证书

    openssl genrsa -out rootCA.key 2048
    openssl req -x509 -new -nodes -key rootCA.key -subj "/CN=$NGROK_DOMAIN" -days 5000 -out rootCA.pem
    openssl genrsa -out device.key 2048
    openssl req -new -key device.key -subj "/CN=$NGROK_DOMAIN" -out device.csr
    openssl x509 -req -in device.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out device.crt -days 5000
    cp rootCA.pem assets/client/tls/ngrokroot.crt
    cp device.crt assets/server/tls/snakeoil.crt 
    cp device.key assets/server/tls/snakeoil.key
    
  2. 编译服务端

服务端比较容易,先指定一下我的环境变量,然后再make:

    GOOS=linux GOARCH=amd64
    #如果是32位系统,这里 GOARCH=386

然后make

    make release-server

按理讲,应该就可以编译成功了,但是我发现,编译的时候很多依赖包是需要自动下载的,有一个包log4go是在 code.google 上的,我们天朝服务器是无法访问google的,大家懂,所以我这里是这么处理的:修改源码,将该包改为 github 上的地址:

找到/usr/local/src/ngrok/src/ngrok/log/logger.go,第五行import中的 log 包,改为:log "github.com/keepeye/log4go"

然后重新make release-server

接下来可能还会遇到一个问题,编译时在go get gopkg.in/yaml.v1步骤时候卡住,这是因为git版本太低,请将服务器git版本升级到1.7.9.5以上。

或许:

install hg(sudo apt-get install mercurial)

编译成功后,应该可以在/usr/local/src/ngrok/bin下生成了一个ngrokd可执行文件,这就是我们的服务端了,现在启动服务端试试:

bin/ngrokd -domain="$NGROK_DOMAIN" -httpAddr=":8000"

如果没有报错的话,会出现以下输出:

[10:05:48 CST 2015/04/17] [INFO] (ngrok/log.(*PrefixLogger).Info:83) [registry] [tun] No affinity cache specified
[10:05:48 CST 2015/04/17] [INFO] (ngrok/log.(*PrefixLogger).Info:83) [metrics] Reporting every 30 seconds
[10:05:48 CST 2015/04/17] [INFO] (ngrok/log.Info:112) Listening for public http connections on [::]:8000
[10:05:48 CST 2015/04/17] [INFO] (ngrok/log.Info:112) Listening for public https connections on [::]:443
[10:05:48 CST 2015/04/17] [INFO] (ngrok/log.Info:112) Listening for control and proxy connections on [::]:4443

现在先ctrl+c退出,我们还需要编译客户端呢。

  1. 编译客户端

我的本机系统是 mac osx ,64位,对应的 GOOS 和 GOARCH 是这样的:

GOOS=darwin GOARCH=amd64

然后我直接编译:

make release-client

编译是成功了,但是我发现编译出来的东西是bin/ngrok,它还是linux平台的包,我mac上无法执行。原因是我们没有为go生成交叉编译环境,需要补充下面的一个步骤:

前文说到,我们的 go 安装在/usr/local/go,现在我们执行下面的命令:

cd /usr/local/go/src
GOOS=darwin GOARCH=amd64 ./make.bash

然后回去ngrok目录,接着编译:

cd -
GOOS=darwin GOARCH=amd64 make release-client

完了以后可以在/usr/local/src/ngrok/bin/darwin_amd64/下发现ngrok文件,将它拷贝到我的mac上。

如果是windows下的客户端,是这样的:

cd /usr/local/go/src
GOOS=windows GOARCH=amd64 ./make.bash
cd -
GOOS=windows GOARCH=amd64 make release-client
#同理,这里的amd64是64位系统,32位改成386
#应该会在 bin/windows_amd64 目录下生成ngrok客户端程序

到这里,编译就完成了,现在让我们把应用跑起来:

按之前的方式启动服务端ngrokd,有以下提示:

Listening for public http connections on [::]:8000
Listening for control and proxy connections on [::]:4443

记住这两个端口 8000 和 4443 。

现在我们来到自己电脑上,准备启动客户端。在启动之前,我们需要为客户端编写一个配置文件 ngrok.cfg :

server_addr: "ngrok.ekan001.com:4443"
trust_host_root_certs: false

注意,配置文件中用的是4443端口。

然后启动客户端,假设我们要分配一个域名test.ngrok.ekan001.com执行以下命令:

./ngrok -config=./ngrok.cfg -subdomain=test 80
如果是用来做ss转发的话加上 -proto=tcp

解释一下参数:

-config 就是上面配置文件ngrok.cfg的路径
-subdomain 就是需要分配域名的前缀部分
80 就是本机websever的端口,比如apache监听的端口,一会ngrok会将请求映射到该端口上。

如果没错误,应该会出现以下的输出:

Tunnel Status                 online
Version                       1.7/1.7
Forwarding                    http://test.ngrok.ekan001.com:8000 -> 127.0.0.1:80
Forwarding                    https://test.ngrok.ekan001.com:8000 -> 127.0.0.1:80
Web Interface                 127.0.0.1:4040
# Conn                        0
Avg Conn Time                 0.00ms

现在,访问test.ngrok.ekan001.com:8000,ngrok服务端就会讲请求转发到我们本地客户端,再由客户端转发给我们的webserver 80端口。所以,我们只需要配置apache或nginx,添加虚拟主机,绑定域名test.ngrok.ekan001.com即可。

事情还没有结束!

我们前面提到,微信开发中的api地址,是不认80以外的端口的,所以如果我们将test.ngrok.ekan001.com:8000作为接口域名,得到的只能是 非法地址 或 配置失败 这个提示。

为什么在启动服务端的时候,端口不指定为80呢?就像下面:

bin/ngrokd -domain="$NGROK_DOMAIN" -httpAddr=":80"

很遗憾,因为这台vps不是只用来做ngrok服务的,我博客还在上面呢,80端口已经被nginx占用了。

那怎么办?

不得不提nginx是个牛逼的软件,我们可以在nginx中配置一个server,就绑定test.ngrok.ekan001.com域名,然后将所有请求转发到后端:8000端口上,这就是反向代理。我发一下自己的nginx配置:

#ngrok.ekan001.com.conf
upstream nodejs {
    server 127.0.0.1:8000;
    keepalive 64;
}

server {
    listen 80;
    server_name *.ngrok.ekan001.com;
    access_log /home/wwwlogs/ngrok.ekan001.log;
    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:8000;
        proxy_set_header X-Nginx-Proxy true;
        proxy_set_header Connection "";
        proxy_pass      http://nodejs;

    }

}

总结:

生命在于折腾,enjoy it!

参考:

[1] http://www.haiyun.me/archives/1012.html
[2] http://blog.csdn.net/savechina/article/details/5612399
[3] http://www.golangtc.com/download

转载请注明出处:自行编译ngrok服务端客户端,替代花生壳,跨平台

你可能感兴趣的:(杂)