看到这篇文章的童鞋们,恭喜你们已经学会了自己解决问题,学会了自己思考,在我们遇到困难的时候,并没有放弃,而是坚持的去寻找我们自己的答案。,之前小锋也一直在使用免费的,但是免费的有时候很卡,卡的受不了,因此就想着自己搭建一个. 为了让童鞋们方便观看,小锋故意把xshell的文字效果调的更渲染一些,此处应该有掌声 那么我们来看看ngrok主要的用处
话不多说,先来谈谈我们为什么会用到ngrok,因为在日常生活中我们必须要用到80端口,比如微信公众号开发,就必须使用80端口.
本次搭建ngrok需要用到的文件包含go环境、git环境、ngrok文件。
下载地址:(若使用该文件,则可直接上传到linux服务器上,省事省心,若不使用,也可以通过wget等方式下载源码)
下载地址:
go环境的搭建(传送口)
git环境的搭建(传送口)
搭建好了go环境以及git环境了测试一下,这里git版本尽量高一些,最好都和我一致。
root@localhost:/# go version
go version go1.7 linux/amd64
root@localhost:/# git --version
git version 2.13.2
root@localhost:/#
然后再把ngrok文件夹上传到linux服务器上(我的目录是==/usr/local/ngrok==),你们的最好也是这样的。
好了,到这里环境基本上都搭建好了,接下来开始进入正题了
注意:
bw.xiaofeng.cn是一个base域名,也就是一个父域名,当我们用这个域名的时候,生成的域名是xx.bw.xiaofeng.cn,其中的xx是客户端,用户自定义的.(当然也可以随机产生)
还有这里命令的目录都是ngrok安装的所在目录(比如我的/usr/local/ngrok)
同时在这里也说一下为什么要自定义秘钥,(因为它收费,需要自己买)这里的秘钥是为了保证服务端和客户端连接的安全性,只有使用该秘钥产生的客服端才可以连接服务端,否则都白搭.
#为base域名bw.xiaofeng.cn生成证书
openssl genrsa -out rootCA.key 2048
openssl req -x509 -new -nodes -key rootCA.key -subj "/CN=bw.xiaofeng.cn" -days 5000 -out rootCA.pem
openssl genrsa -out device.key 2048
openssl req -new -key device.key -subj "/CN=bw.xiaofeng.cn" -out device.csr
openssl x509 -req -in device.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out device.crt -days 5000
上面的生成证书时间不长,很快我们就生成完了,
执行完上述命令,正常情况下,会多出device.crt、device.csr、device.key、rootCA.key、rootCA.pem、rootCA.srl六个文件,用它们来替换默认的证书文件即可。默认的证书文件在“./assets/client/tls”和“./assets/server/tls/”目录中
下面看一下生成完之后的截图
root@localhost:~# cd /usr/local/ngrok/
root@localhost:/usr/local/ngrok# ll
total 64
drwxr-xr-x. 4 root root 4096 May 24 15:55 assets
drwxr-xr-x. 4 root root 4096 May 24 17:05 bin
drwxr-xr-x. 2 root root 4096 May 24 15:55 contrib
-rw-r--r--. 1 root root 199 May 24 15:55 CONTRIBUTORS
-rw-r--r--. 1 root root 997 May 24 15:58 device.crt
-rw-r--r--. 1 root root 899 May 24 15:58 device.csr
-rw-r--r--. 1 root root 1679 May 24 15:58 device.key
drwxr-xr-x. 2 root root 4096 May 24 15:55 docs
-rw-r--r--. 1 root root 551 May 24 15:55 LICENSE
-rw-r--r--. 1 root root 1433 May 24 15:55 Makefile
drwxr-xr-x. 4 root root 4096 May 24 16:49 pkg
-rw-r--r--. 1 root root 2725 May 24 15:55 README.md
-rw-r--r--. 1 root root 1675 May 24 15:57 rootCA.key
-rw-r--r--. 1 root root 1115 May 24 15:58 rootCA.pem
-rw-r--r--. 1 root root 17 May 24 15:58 rootCA.srl
drwxr-xr-x. 5 root root 4096 May 24 16:05 src
root@localhost:/usr/local/ngrok#
然后我们再把ngrok自带的秘钥替换成我们刚刚生成的秘钥,
命令:
执行命令的目录就是ngrok的所在目录(比如我的/usr/local/ngrok)
cp rootCA.pem assets/client/tls/ngrokroot.crt
cp device.crt assets/server/tls/snakeoil.crt
cp device.key assets/server/tls/snakeoil.key
注意:
执行上面的命令时,每执行一行命令都会提示是否要覆盖该文件,这里必须要选择是,也就是在控制台上打 y,否则客户端是连接不上服务端的,显示秘钥证书错误.这里很多人都进坑了,所以着重说一下
因为我们的客户端的文件(ngrok)需要和服务端(ngrokd)一一对应,保证秘钥证书的正确性,因此这里的客户端和服务端都需要自己生成。
开始编译
elease-server是指生成linux服务端文件(ngrokd)
release-client是指生成linux客户端文件(ngrok)
这里是同时生成两个(执行目录ngrok的安装目录)
make release-server release-client
接下来它会使用到go命令和git命令,如果你这里环境没有安装好,则是报错的.这里编译的速度很慢,一般会根据计算机的执行速度以及网络的速度来看的,所以这里我们可以喝杯茶,慢慢的等会就好啦
下面是执行成功的过程:
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/...
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/...
github.com/inconshreveable/mousetrap (download)
github.com/rcrowley/go-metrics (download)
Fetching https://gopkg.in/inconshreveable/go-update.v0?go-get=1
Parsing meta tags from https://gopkg.in/inconshreveable/go-update.v0?go-get=1 (status code 200)
get "gopkg.in/inconshreveable/go-update.v0": found meta tag main.metaImport{Prefix:"gopkg.in/inconshreveable/go-update.v0", VCS:"git", RepoRoot:"https://gopkg.in/inconshreveable/go-update.v0"} at https://gopkg.in/inconshreveable/go-update.v0?go-get=1
gopkg.in/inconshreveable/go-update.v0 (download)
github.com/kardianos/osext (download)
github.com/kr/binarydist (download)
Fetching https://gopkg.in/inconshreveable/go-update.v0/check?go-get=1
Parsing meta tags from https://gopkg.in/inconshreveable/go-update.v0/check?go-get=1 (status code 200)
get "gopkg.in/inconshreveable/go-update.v0/check": found meta tag main.metaImport{Prefix:"gopkg.in/inconshreveable/go-update.v0", VCS:"git", RepoRoot:"https://gopkg.in/inconshreveable/go-update.v0"} at https://gopkg.in/inconshreveable/go-update.v0/check?go-get=1
get "gopkg.in/inconshreveable/go-update.v0/check": verifying non-authoritative meta tag
Fetching https://gopkg.in/inconshreveable/go-update.v0?go-get=1
Parsing meta tags from https://gopkg.in/inconshreveable/go-update.v0?go-get=1 (status code 200)
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)
github.com/inconshreveable/go-vhost (download)
github.com/alecthomas/log4go (download)
github.com/nsf/termbox-go (download)
github.com/mattn/go-runewidth (download)
github.com/gorilla/websocket (download)
go install -tags 'release' ngrok/main/ngrokd
如果你也执行到这一步了,首先要恭喜你.你已经成功了一大步了,接下来胜利在望了.
测试运行一下
接下来是运行服务端的代码
./bin/ngrokd 表示启动
-httpAddr:表示开放的端口号为80端口
-domain=“bw.xiaofeng.cn”,表示访问的域名是bw.xiaofeng.cn
当然这里我还可以配置其他的端口,比如默认的4443端口
root@localhost:/usr/local/ngrok# ./bin/ngrokd -domain="bw.xiaofeng.cn" -httpAddr=":80"
运行完上面的命令之后,会显示下面的命令,
这里会看到默认会启动4443端口,这里就和刚开始我们再防火墙配置暴露4443端口是对应的
[09:54:20 CST 2019/05/27] [INFO] (ngrok/log.(*PrefixLogger).Info:83) [registry] [tun] No affinity cache specified
[09:54:20 CST 2019/05/27] [INFO] (ngrok/log.(*PrefixLogger).Info:83) [metrics] Reporting every 30 seconds
[09:54:20 CST 2019/05/27] [INFO] (ngrok/log.Info:112) Listening for public http connections on [::]:80
[09:54:20 CST 2019/05/27] [INFO] (ngrok/log.Info:112) Listening for public https connections on [::]:443
[09:54:20 CST 2019/05/27] [INFO] (ngrok/log.Info:112) Listening for control and proxy connections on [::]:4443
启动后每隔一段时间会再屏幕上显示客服端的连接数(包含linux,windows等客户端),如图:
[09:54:50 CST 2019/05/27] [INFO] (ngrok/log.(*PrefixLogger).Info:83) [metrics] Reporting: {"bytesIn.count":0,"bytesOut.count":0,"connMeter.count":0,"connMeter.m1":0,"httpTunnelMeter.count":0,"linux":0,"osx":0,"other":0,"tcpTunnelMeter.count":0,"tunnelMeter.count":0,"tunnelMeter.m1":0,"windows":0}
[09:55:20 CST 2019/05/27] [INFO] (ngrok/log.(*PrefixLogger).Info:83) [metrics] Reporting: {"bytesIn.count":0,"bytesOut.count":0,"connMeter.count":0,"connMeter.m1":0,"httpTunnelMeter.count":0,"linux":0,"osx":0,"other":0,"tcpTunnelMeter.count":0,"tunnelMeter.count":0,"tunnelMeter.m1":0,"windows":0}
[09:55:50 CST 2019/05/27] [INFO] (ngrok/log.(*PrefixLogger).Info:83) [metrics] Reporting: {"bytesIn.count":0,"bytesOut.count":0,"connMeter.count":0,"connMeter.m1":0,"httpTunnelMeter.count":0,"linux":0,"osx":0,"other":0,"tcpTunnelMeter.count":0,"tunnelMeter.count":0,"tunnelMeter.m1":0,"windows":0}
[09:56:20 CST 2019/05/27] [INFO] (ngrok/log.(*PrefixLogger).Info:83) [metrics] Reporting: {"bytesIn.count":0,"bytesOut.count":0,"connMeter.count":0,"connMeter.m1":0,"httpTunnelMeter.count":0,"linux":0,"osx":0,"other":0,"tcpTunnelMeter.count":0,"tunnelMeter.count":0,"tunnelMeter.m1":0,"windows":0}
[09:56:50 CST 2019/05/27] [INFO] (ngrok/log.(*PrefixLogger).Info:83) [metrics] Reporting: {"bytesIn.count":0,"bytesOut.count":0,"connMeter.count":0,"connMeter.m1":0,"httpTunnelMeter.count":0,"linux":0,"osx":0,"other":0,"tcpTunnelMeter.count":0,"tunnelMeter.count":0,"tunnelMeter.m1":0,"windows":0}
[09:57:20 CST 2019/05/27] [INFO] (ngrok/log.(*PrefixLogger).Info:83) [metrics] Reporting: {"bytesIn.count":0,"bytesOut.count":0,"connMeter.count":0,"connMeter.m1":0,"httpTunnelMeter.count":0,"linux":0,"osx":0,"other":0,"tcpTunnelMeter.count":0,"tunnelMeter.count":0,"tunnelMeter.m1":0,"windows":0}
图片里所示,目前没有客户端连接.因此都是0.
crtl+C 取消运行
这里我们的启动都是在命令行中启动的,一旦我们关闭窗口,就会导致服务关闭,这我们是不能接受的,因此我们需要开启后台运行(开机自启),这里考虑篇幅问题,也另外开一个博客单独说,飞机票前往---------------------------------------后台运行(开机自启)
我们在刚刚编译的时候生成了linux的客户端(ngrok)和linux的服务端(ngrokd),我们只执行了linux的服务端,但是客户端并没有执行,其实linux的客户端和windows的客户端执行都差不多,因为我们在客户端用的比较多,因此这里主要先介绍windows的客户端连接.(如果大家对linux的客户端有兴趣,欢迎评论区留言,如果人多的话,我会继续发布新的帖子,详情关注 拉风的小锋).
之前我们生成了linux的客服端,但是呢,windows的我们并没有生成,所以我们首先先生成windows的版本(其中包含32位 64位,也有mac版本的)
windows平台生成:
#执行如下命令编译Windows 64位客户端
GOOS=windows GOARCH=amd64 make release-client
#以上GOARCH=amd64指的是编译为64位版本,如需32位改成GOARCH=386即可
mac平台生成:
#切换到ngrok目录
#mac平台下的64位环境
GOOS=darwin GOARCH=amd64 make release-client
生成完之后我们会再norok的bin目录下发现 windows_amd64(我生成的是64位的)
如图:
我们需要先把bin目录下的windows_amd64,拷贝到windows电脑上,
然后我们老样子,启动服务端(当前目录/usr/local/ngrok)
命令:
root@localhost:/usr/local/ngrok# ./bin/ngrokd -domain="bw.xiaofeng.cn" -httpAddr=":80"
这样我们服务端只要和上面测试时一样就不用管了,
画面切换到客户端(windows64位操作系统)
客户端配置文件
在ngrok.exe所在目录下建立文件ngrok.cfg,用记事本等文本编辑器写入以下内容并保存。
server_addr: "bw.xiaofeng.cn:4443"
trust_host_root_certs: false
建立一个log文件夹(方便查看log日志)
最后再建立一个批处理文件:start.bat,把下面的命令填入其中
-config=ngrok.cfg 读取配置文件
-log=log/ngrok.log 生成日志文件
-subdomain=xiaofeng 域名前缀,
80 当前客户端的端口为80端口
ngrok -config=ngrok.cfg -log=log/ngrok.log -subdomain=xiaofeng 80
以上的配置若执行成功,域名为:xiaofeng.bw.xiaofeng.cn
如图:
保存配置,然后我们双击start.bat文件.
看到这个我们是不是有一种欣喜若狂的感觉_.哈哈,我也是呢
然后我们看看服务端的截图
可以看到服务端接收到来自区域网192.168.100.200:53873的连接,然后连接成功.最后会显示总连接数是2个,windows2个.
如果大家对我的文章感兴趣的话,应该关注拉风的小锋,小锋会大量给大家发点干货福利等.
1、首先端口是否开放以及转发4443以及80端口
2、域名的二级域名和三级域名是否都转发到服务器的公网ip地址上
比如bw.xiaofeng.cn和*.bw.xiaofeng.cn都需要转发
3、证书生成后是否替换成功,证书生成时,域名填写是否正确?
4、启动服务端时的命令是否写错,导致域名错误
5、客户端启动后,如果没连接成功,不要着急。先查看log日志,查看是证书错误还是说是连接不上服务端。上面的错误一般都包含了,因此我们在搭建的时候一定要小心,一步错,步步错。小心使得万年船。
之前我一直以为搭建ngrok的服务端是为了解决80端口不能使用的问题,但是后来我才发现,你搭建ngrok的服务端的前提是必须要有公网ip,这一点小锋已经达到了,但是小锋的需求是用80端口,所以服务端ip的80端口也是要开放的,这一点小锋琢磨了好久,可是又有小伙伴说了,我就是因为没有80端口才想用ngrok的,你现在又说服务端必须开放80端口,这是什么意思呢,这个其实说的应该是客户端,当服务端开启80端口后,ngrok服务端监听80端口,当有访问的域名和你申请的域名一样的时候,ngrok服务端会将请求转发给保持长连接的客户端。然后就相当于访问客户端的网站。从而达到了内网共享的功能
这里nginx的安装就不说了,大家百度就行,也可以参考我的博客 ,在我的专栏里可以找到
nginx配置文件:
worker_processes 1;
pid /usr/local/nginx/pid/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name *.bw.xiaofeng88.cn;
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:88;
proxy_set_header X-Nginx-Proxy true;
proxy_set_header Connection "";
proxy_pass http://127.0.0.1:88;
}
#解决配置反向代理后js css文件无法加载问题
location ~ .*\.(js|css)$ {
proxy_pass http://127.0.0.1:88; #此处二级域名可以随意填写
proxy_set_header Host $host:88; # 这个是重点,$host 指的是与server_name相同的域名
}
}
}