搭建自己的ngrok服务

在国内开发 微信公众号 、 企业号 以及做前端开发的朋友想必对 ngrok 都不陌生吧,就目前来看,ngrok可是最佳的在内网调试微信服务的tunnel工
具。记得今年春节前,ngrok.com提供的服务还一切正常呢,但春节后似乎就一切不正常了。ngrok.com无法访问,ngrok虽然能连上 ngrok.com提供的服务,但微信端因为无法访问ngrok.com,导致消息一直无法发送到我们的服务地址上,比如xxxx.ngrok.com。 这一切都表明,ngork被墙了。没有了ngrok tunnel,一切开始变得困难且没有效率起来。内网到外部主机部署和调试是一件慢的让人想骂街的事情。

ngrok不能少。ngrok以及其服务端ngrokd都是开源的,之前我也知道通过源码可以自搭建ngrok服务。请求搜索引擎后,发现国内有个朋友已经搭建了一个www.tunnel.mobi的ngrok公共服务,与ngrok.com类似,我也实验了一下。

编写一个ngrok.cfg,内容如下:

server_addr: "tunnel.mobi:44433" 
trust_host_root_certs: true

用ngrok最新客户端1.7版本执行如下命令:

$ngrok -subdomain tonybaiexample -config=ngrok.cfg 80

可以顺利建立一个tunnel,用于本机向外部提供"tonybaiexample.tunnel.mobi"服务。

Tunnel Status                 online 
Version                       1.7/1.7 
Forwarding                    http://tonybaiexample.tunnel.mobi -> 127.0.0.1:80 
Forwarding                    https://tonybaiexample.tunnel.mobi -> 127.0.0.1:80 
Web Interface                 127.0.0.1:4040 
# Conn                        0 
Avg Conn Time                 0.00ms

而且国内的ngrok服务显然要远远快于ngrok.com提供的服务,消息瞬间即达。

但这是在公网上直接访问的结果。放在公司内部,我看到的却是另外一个结果:

Tunnel Status                 reconnecting 
Version                       1.7/ 
Web Interface                 127.0.0.1:4040 
# Conn                        0 
Avg Conn Time                 0.00ms

我们无法从内网建立tunnel,意味着依旧不方便和低效,因为很多基础服务都在内网部署,内外网之间的交互十分不便。但内网连不上tunnel.mobi也是个事实,且无法知道原因,因为看不到server端的连接错误日志。

于是我决定自建一个ngrok服务。

一、准备工作

搭建ngrok服务需要在公网有一台vps,去年年末曾经在Amazon申请了一个体验主机EC2 ,有公网IP一个,这次就打算用这个主机作为ngrokd服务端。

需要一个自己的域名。已有域名的,可以建立一个子域名,用于关联ngrok服务,这样也不会干扰原先域名提供的服务。(不用域名的方式也许可以,但我没有试验过。)

搭建的参考资料主要来自下面三个:

1) ngrok的官方SELFHOST指南:https://github.com/inconshreveable/ngrok/blob/master/docs/SELFHOSTING.md

2) 国外一哥们的博客:http://www.svenbit.com/2014/09/run-ngrok-on-your-own-server/

3) "海运的博客"中的一篇文章:http://www.haiyun.me/archives/1012.html

二、实操步骤

我的AWS EC2实例安装的是UbuntuServer 14.04 x86_64,并安装了golang 1.4(go version go1.4 linux/amd64)。Golang是编译ngrokd和ngrok所必须的,建议直接从golang官方下载对应平台的二进制安装包(国内可以从 golangtc.com上下载,速度慢些罢了)。

1、下载ngrok源码

(GOPATH=~/goproj)

$ mkdir ~/goproj/src/github.com/inconshreveable

$ git clone https://github.com/inconshreveable/ngrok.git

$ export GOPATH=~/goproj/src/github.com/inconshreveable/ngrok

2、生成自签名证书

使用ngrok.com官方服务时,我们使用的是官方的SSL证书。自建ngrokd服务,我们需要生成自己的证书,并提供携带该证书的ngrok客户端。

证书生成过程需要一个 NGROK_BASE_DOMAIN 。 以ngrok官方随机生成的地址693c358d.ngrok.com为例,其NGROK_BASE_DOMAIN就是"ngrok.com",如果你要 提供服务的地址为"example.tunnel.tonybai.com",那NGROK_BASE_DOMAIN就应该 是"tunnel.tonybai.com"。

我们这里以NGROK_BASE_DOMAIN="tunnel.tonybai.com"为例,生成证书的命令如下:

$ cd ~/goproj/src/github.com/inconshreveable/ngrok

$ openssl genrsa -out rootCA.key 2048

$ openssl req -x509 -new -nodes -key rootCA.key -subj "/CN=

tunnel.tonybai.com 

" -days 5000 -out rootCA.pem

$ openssl genrsa -out device.key 2048

$ openssl req -new -key device.key -subj "/CN=

tunnel.tonybai.com 

" -out device.csr

$ openssl x509 -req -in device.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out device.crt -days 5000

执行完以上命令,在ngrok目录下就会新生成6个文件:

-rw-rw-r– 1 ubuntu ubuntu 1001 Mar 14 02:22 device.crt 
-rw-rw-r– 1 ubuntu ubuntu  903 Mar 14 02:22 device.csr 
-rw-rw-r– 1 ubuntu ubuntu 1679 Mar 14 02:22 device.key 
-rw-rw-r– 1 ubuntu ubuntu 1679 Mar 14 02:21 rootCA.key 
-rw-rw-r– 1 ubuntu ubuntu 1119 Mar 14 02:21 rootCA.pem 
-rw-rw-r– 1 ubuntu ubuntu   17 Mar 14 02:22 rootCA.srl

ngrok通过bindata将ngrok源码目录下的assets目录(资源文件)打包到可执行文件(ngrokd和ngrok)中 去,assets/client/tls和assets/server/tls下分别存放着用于ngrok和ngrokd的默认证书文件,我们需要将它们替换成我们自己生成的:(因此这一步务必放在编译可执行文件之前)

cp rootCA.pem assets/client/tls/ngrokroot.crt 
cp device.crt assets/server/tls/snakeoil.crt 
cp device.key assets/server/tls/snakeoil.key

3、编译ngrokd和ngrok

在ngrok目录下执行如下命令,编译ngrokd:

$ make release-server

不过在我的AWS上,出现如下错误:

GOOS="" GOARCH="" go get github.com/jteeuwen/go-bindata/go-bindata 
bin/go-bindata -nomemcopy -pkg=assets -tags=release \ 
-debug=false \ 
-o=src/ngrok/client/assets/assets_release.go \ 
assets/client/… 
make: bin/go-bindata: Command not found 
make: *** [client-assets] Error 127

go-bindata被安装到了$GOBIN下了,go编译器找不到了。修正方法是将$GOBIN/go-bindata拷贝到当前ngrok/bin下。

$ cp /home/ubuntu/.bin/go14/bin/go-bindata ./bin

再次执行make release-server。

~/goproj/src/github.com/inconshreveable/ngrok$ make release-server 
bin/go-bindata -nomemcopy -pkg=assets -tags=release \ 
-debug=false \ 
-o=src/ngrok/client/assets/assets_release.go \ 
assets/client/… 
bin/go-bindata -nomemcopy -pkg=assets -tags=release \ 
-debug=false \ 
-o=src/ngrok/server/assets/assets_release.go \ 
assets/server/… 
go get -tags 'release' -d -v ngrok/… 
code.google.com/p/log4go (download) 
go: missing Mercurial command. See http://golang.org/s/gogetcmd 
package code.google.com/p/log4go: exec: "hg": executable file not found in $PATH 
github.com/gorilla/websocket (download) 
github.com/inconshreveable/go-update (download) 
github.com/kardianos/osext (download) 
github.com/kr/binarydist (download) 
github.com/inconshreveable/go-vhost (download) 
github.com/inconshreveable/mousetrap (download) 
github.com/nsf/termbox-go (download) 
github.com/mattn/go-runewidth (download) 
github.com/rcrowley/go-metrics (download) 
Fetching https://gopkg.in/yaml.v1?go-get=1 
Parsing meta tags from https://gopkg.in/yaml.v1?go-get=1 (status code 200) 
get "gopkg.in/yaml.v1": found meta tag main.metaImport{Prefix:"gopkg.in/yaml.v1", VCS:"git", RepoRoot: "https://gopkg.in/yaml.v1" } at https://gopkg.in/yaml.v1?go-get=1 
gopkg.in/yaml.v1 (download) 
make: *** [deps] Error 1

又出错!提示找不到hg,原来是aws上没有安装hg。install hg后(sudo apt-get install mercurial),再编译。

$ make release-server 
bin/go-bindata -nomemcopy -pkg=assets -tags=release \ 
-debug=false \ 
-o=src/ngrok/client/assets/assets_release.go \ 
assets/client/… 
bin/go-bindata -nomemcopy -pkg=assets -tags=release \ 
-debug=false \ 
-o=src/ngrok/server/assets/assets_release.go \ 
assets/server/… 
go get -tags 'release' -d -v ngrok/… 
code.google.com/p/log4go (download) 
go install -tags 'release' ngrok/main/ngrokd

同样编译ngrok:

$ make release-client 
bin/go-bindata -nomemcopy -pkg=assets -tags=release \ 
-debug=false \ 
-o=src/ngrok/client/assets/assets_release.go \ 
assets/client/… 
bin/go-bindata -nomemcopy -pkg=assets -tags=release \ 
-debug=false \ 
-o=src/ngrok/server/assets/assets_release.go \ 
assets/server/… 
go get -tags 'release' -d -v ngrok/… 
go install -tags 'release' ngrok/main/ngrok

AWS上ngrokd和ngrok被安装到了$GOBIN下。

三、调试

1、 启动ngrokd

$ ngrokd -domain="tunnel.tonybai.com" -httpAddr=":8080" -httpsAddr=":8081"

[03/14/15 04:47:24] [INFO] [registry] [tun] No affinity cache specified

[03/14/15 04:47:24] [INFO] [metrics] Reporting every 30 seconds

[03/14/15 04:47:24] [INFO] Listening for public http connections on [::]:8080

[03/14/15 04:47:24] [INFO] Listening for public https connections on [::]:8081

… …

2、公网连接ngrokd

将生成的ngrok下载到自己的电脑上。

创建一个配置文件ngrok.cfg,内容如下:

server_addr: "tunnel.tonybai.com:4443" 
trust_host_root_certs: false

执行ngrok:

$ ngrok -subdomain example -config=ngrok.cfg 80

Tunnel Status                 reconnecting 
Version                       1.7/ 
Web Interface                 127.0.0.1:4040 
# Conn                        0 
Avg Conn Time                 0.00ms

连接失败。此刻我的电脑是在公网上。查看ngrokd的日志,没有发现连接到达Server端。试着在本地ping tunnel.tonybai.com这个地址,发现地址不通。难道是DNS设置的问题。之前我只是设置了"*.tunnel.tonybai.com"的A地址,并未设置"tunnel.tonybai.com"。于是到DNS管理页面,添加了"tunnel.tonybai.com"的A记录。

待DNS记录刷新OK后,再次启动ngrok:

Tunnel Status online 
Version 1.7/1.7 
Forwarding http://epower.tunnel.tonybai.com:8080 -> 127.0.0.1:80 
Forwarding https://epower.tunnel.tonybai.com:8080 -> 127.0.0.1:80 
Web Interface 127.0.0.1:4040 
# Conn 0 
Avg Conn Time 0.00ms

这回连接成功了!

3、内网连接ngrokd

将ngrok拷贝到内网的一台PC上,这台PC设置了公司的代理。

按照同样的步骤启动ngrok:

$ ngrok -subdomain example -config=ngrok.cfg 80

Tunnel Status                 reconnecting 
Version                       1.7/ 
Web Interface                 127.0.0.1:4040 
# Conn                        0 
Avg Conn Time                 0.00ms

不巧,怎么又失败了!从Server端来看,还是没有收到客户端的连接,显然是连接没有打通公司内网。从我自己的squid代理服务器来看,似乎只有443端口的请求被公司代理服务器允许通过,4443则无法出去。

1426301143.558 9294 10.10.126.101 TCP_MISS/000 366772 CONNECT api.equinox.io:443 – DEFAULT_PARENT/proxy.xxx.com -   通过了 
1426301144.441 27 10.10.126.101 TCP_MISS/000 1185 CONNECT tunnel.tonybai.com:4443 – DEFAULT_PARENT/proxy.xxx.com -  似乎没有通过

只能修改server监听端口了。将-tunnelAddr由4443改为443(注意AWS上需要修改防火墙的端口规则,这个是实时生效的,无需重启实例):

$ sudo ngrokd -domain="tunnel.tonybai.com" -httpAddr=":8080" -httpsAddr=":8081" -tunnelAddr=":443"

[03/14/15 04:47:24] [INFO] [registry] [tun] No affinity cache specified

[03/14/15 04:47:24] [INFO] [metrics] Reporting every 30 seconds

[03/14/15 04:47:24] [INFO] Listening for public http connections on [::]:8080

[03/14/15 04:47:24] [INFO] Listening for public https connections on [::]:8081

… …

将ngrok.cfg中的地址改为443:

server_addr: "tunnel.tonybai.com:443"

再次执行ngrok客户端:

Tunnel Status                 online 
Version                       1.7/1.7 
Forwarding                    http://epower.tunnel.tonybai.com:8080 -> 127.0.0.1:80 
Forwarding                    https://epower.tunnel.tonybai.com:8080 -> 127.0.0.1:80 
Web Interface                 127.0.0.1:4040 
# Conn                        0 
Avg Conn Time                 0.00ms

这回成功连上了。

4、80端口

是否大功告成了呢?我们看看ngrok的结果,总感觉哪里不对呢?噢,转发的地址怎么是8080端口呢?为何不是80?微信公众号/企业号可只是支持80端口啊!

我们还需要修改一下Server端的参数,将-httpAddr从8080改为80。

$ sudo ngrokd -domain="tunnel.tonybai.com" -httpAddr=":80" -httpsAddr=":8081" -tunnelAddr=":443"

这回再用ngrok连接一下:

Tunnel Status                 online

Version                       1.7/1.7

Forwarding                    http://epower.tunnel.tonybai.com -> 127.0.0.1:80

Forwarding                    https://epower.tunnel.tonybai.com -> 127.0.0.1:80

Web Interface                 127.0.0.1:4040

# Conn                        0

Avg Conn Time                 0.00ms

这回与我们的需求匹配上了。

5、测试

在内网的PC上建立一个简单的http server 程序:hello

//hello.go 
package main

import "net/http"

func main() { 
http.HandleFunc("/", hello) 
http.ListenAndServe(":80", nil) 
}

func hello(w http.ResponseWriter, r *http.Request) { 
w.Write([]byte("hello!")) 
}

$ go build -o hello hello.go 
$ sudo ./hello

通过公网浏览器访问一下“http://epower.tunnel.tonybai.com”这个地址,如果你看到浏览器返回"hello!"字样,那么你的ngrokd服务就搭建成功了!

四、注意事项

客户端ngrok.cfg中server_addr后的值必须严格与-domain以及证书中的NGROK_BASE_DOMAIN相同,否则Server端就会出现如下错误日志:

[03/13/15 09:55:46] [INFO] [tun:15dd7522] New connection from 54.149.100.42:38252 
[03/13/15 09:55:46] [DEBG] [tun:15dd7522] Waiting to read message 
[03/13/15 09:55:46] [WARN] [tun:15dd7522] Failed to read message: remote error: bad certificate 
[03/13/15 09:55:46] [DEBG] [tun:15dd7522] Closing

时间: 2024-09-16 21:56:09

搭建自己的ngrok服务的相关文章

Moving to Docker(二)搭建一个私有registry服务

本文讲的是Moving to Docker(二)搭建一个私有registry服务,[编者的话]本文是<Moving to Docker>系列的第二篇,这个系列的文章讲述了创业公司如何把基础服务迁移到Docker上,以及迁移过程中的经验教训.本文主要介绍了如何安装.测试和使用私有registry服务,其中也包含了从DigitalOcean选VPS和注册Amazon S3服务. 这是迁移到Docker系列的第二篇,整个系列都是介绍我们公司是如何把基础设施从PaaS迁移到Docker的. 第一篇:介

vpn-我在国外的一台机器亚马逊AWS EC2上搭建了 一个VPN服务,用国内的网络去访问,显示超时。

问题描述 我在国外的一台机器亚马逊AWS EC2上搭建了 一个VPN服务,用国内的网络去访问,显示超时. 日志如图所示 解决方案 这种服务,早就被墙了,没有做混淆的服务,基本连一天都用不了 解决方案二: 请教大神,也就是说企图用这种方式进行翻墙是不可行的啦? 解决方案三: http://www.fj.xinhuanet.com/2015-01/28/c_1114164074.htm

Win7下如何搭建IIS 7.0服务_win服务器

弄了好长时间,终于把IIS及PHP的服务器搭建好了,下面我讲讲我自己的搭建过程. 分两步:搭建IIS 7,搭建php. 首先介绍一下在Windows 7 下怎么搭建IIS 7.0服务. 1.单击开始菜单-->控制面板-->程序和功能-->左侧"打开或关闭Windows功能".如下图: 2.选择Internet信息服务,选择需要的功能.单击确定按钮,等待系统配置.如图所示: 3.重新进入控制面板-->管理工具-->Internet信息服务(IIS)管理器.如

搭建spring cloud微服务架构

在搭建环境之前,首先根据公司的业务定义微服务架构的代码结构,因为考虑到不同行业,不同领域,不同业务,我这边针对于所有行业做通用的架构模式. 项目整个架构使用maven来构建的,使用maven不仅仅是jar包的管控,重要的是要抓住maven的一个核心作用,那就是将整个项目按照模块化的方式进行划分,业务与业务之间解耦,然后将模块化的业务再进行服务化或者组件化,这样可以进行任意的项目或者平台的业务移植. 最后还要考虑到服务的细粒度拆分,比如:一个登录的模块,我们可以将所有跟登录有关系的业务进行服务化(

node.js连接mongoDB数据库 快速搭建自己的web服务_node.js

一.写在前面   人人都想成为全栈码农,作为一个web前端开发人员,通往全栈的简洁之路,貌似就是node.js了.前段时间学习了node.js,来谈谈新手如何快速的搭建自己的web服务,开启全栈之路. 二.安装node.js   接触过后端开发的人都知道,首先要安装服务.作为新手,肯定是选择最简单的可视化安装了(傻瓜式下一步,其它的方式等熟悉相关操作后自然就会了的),通过官网http://nodejs.org/dist/v0.6.1/node-v0.6.1.msi 下载电脑适配的安装包(这个是w

mac 搭建 内网微信服务 ngrok

首先使用对是 ngrok的服务,不过这个服务器是放在国外不能访问了,国内的网友发布了一个部署在国内的服务器 搭建步骤: 1,下载工具 下载地址:http://www.qydev.com 2,得到两个文件 一个ngrok可执行文件 一个ngrok.cnf配置文件 3,拷贝文件这2个文件到一个独立的目录 我在本机事拷贝到了/user/local 目录 打开mac的终端 输入sudo -i 切换到root用户的权限 Last login: Sat Oct 24 11:28:19 on ttys000

Linux下搭建与部署samba服务

Samba的概述: 首先我们在学习samba的时候会有很多的人为什么要学习samba服务器呢?samba是连接两大操作系统平台之间的纽带,由于samba的出现方便了Linux和Windows下的互相通信.可以实现资源的共享以及文件的拷贝等一些强大的功能.当然我们也可以把samba服务器加入到域中. Samb的环境: Samba服务器可以实现文件的打印共享,身份验证和权限设置:名称解析,以及浏览服务. Samba的工作原理: Samba服务器在Linux系统之上实现SMB/CIFS协议,即可以在L

创企如何搭建强壮的SaaS服务

注:创业公司不仅要满足用户的需求,更要让自己的产品安全可靠,亡羊补牢不如未雨绸缪,这正是风控系统需要做的.本文为岂安科技带来的分享,作者为bigsec安全业务研发负责人王笑天,主导公司安全业务和Redq系统的研发工作.擅长python编程,分布式系统的研发和运维.以下为文章原文: 在本文开始之前先贴一份2015年11月的统计数据: 11月,实物电商交易量达到人民币1.0万亿(人民币,下同),同比增长38.3%. 服务业电商交易量达到630亿,同比增长41.3%. 11月总电商交易量达到1.07万

利用阿里云的VPC+ECS+负载均衡搭建安全的WEB服务

        随着云计算时代的到来,各公有云平台都提供了各种丰富的产品供消费者使用,商品也达到了"琳琅满目"的程度了.以阿里云为例,它就提供了10多种分类.五六十种具体的服务产品.那么,中小企业在搭建WEB服务时,利用公有云的哪些产品就能快速.便捷.低成本地搭建出高安全.高可用的.可伸缩的服务呢?我就自身经验,给出如下的实践过程,供有同类需求的业内人士参考.         打开阿里云的首页,鼠标放到"产品"这个菜单上,默认出来的子菜单的第一个,就是"弹