七叶笔记 » golang编程 » 老叔教你亲手搭建一个Ngrok内网穿透服务器

老叔教你亲手搭建一个Ngrok内网穿透服务器

最近公司需要开发公众号,在调试的时候就是个老大难问题,一般是需要内网穿透方式来让外网能够访问到本地的程序,提高我们的开发调试效率,一般大家会才用natapp、向日葵、ngrok等,这些都做得不错,但是你要用得好、用得舒心,还是得花钱,刚好我之前花了三百多块钱买了3年的云主机,所以就想着要不自己折腾一个ngrok吧,所以就有这个这篇文章

认识ngrok

这次我们需要用到ngrok这个东东,那么首先需要基本了解一下它是个啥?能干啥?ngrok是一款用Golang语言打造的开源的内网穿透软件,它可以帮助我们把内网的应用提供给外网用户访问。ngrok的开源地址是

搭建ngrok服务器

在搭建之前,我们需要准备两个东西:

  • 外网服务器
  • 域名 如果这两个没有的话,那就不好搞咯。这里我们先在服务器上安装好Golang的编译环境,由于我这边被墙了,所以就只有访问来下载了。
 
[root@VM_175_142_centos golang]# wget 
--2020-04-23 12:57:26--  
Resolving studygolang.com (studygolang.com)... 59.110.219.94
Connecting to studygolang.com (studygolang.com)|59.110.219.94|:443... connected.
HTTP request sent, awaiting response... 303 See Other
Location:  [following]
--2020-04-23 12:57:27--  
Resolving dl.google.com (dl.google.com)... 203.208.41.33, 203.208.41.41, 203.208.41.38, ...
Connecting to dl.google.com (dl.google.com)|203.208.41.33|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 123658438 (118M) [application/octet-stream]
Saving to: ‘go1.14.2.linux-amd64.tar.gz’

100%[====================================================================================================================================================================>] 123,658,438 9.72MB/s   in 13s

2020-04-23 12:57:41 (9.04 MB/s) - ‘go1.14.2.linux-amd64.tar.gz’ saved [123658438/123658438]

  

在go1.14.2.linux-amd64.tar.gz文件解压后会得到一个go文件,那么现在我们需要修改环境变量/etc/profile或者$HOME/.profile:

 export GOROOT=你的解压目录/go
export PATH=$PATH:$GOROOT/bin
  

再source /etc/profile让配置文件即刻生效,这时候就可以看到我们的go命令是可执行的

 [root@VM_175_142_centos go]# go version
go version go1.14.2 linux/amd64

  

现在,我们继续去github上下载ngrok源码

 [root@VM_175_142_centos ngrok]# wget 
--2020-04-23 13:09:37--  
Resolving github.com (github.com)... 13.250.177.223
Connecting to github.com (github.com)|13.250.177.223|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location:  [following]
--2020-04-23 13:09:38--  
Resolving codeload.github.com (codeload.github.com)... 54.251.140.56
Connecting to codeload.github.com (codeload.github.com)|54.251.140.56|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 200090 (195K) [application/zip]
Saving to: ‘master.zip’

100%[====================================================================================================================================================================>] 200,090      673KB/s   in 0.3s

2020-04-23 13:09:39 (673 KB/s) - ‘master.zip’ saved [200090/200090]

  

把master.zip解压出来

 [root@VM_175_142_centos ngrok]# unzip master.zip
Archive:  master.zip
a8e7fa486348f391f4bdf241344d798297f953bc
   creating: ngrok-master/
  inflating: ngrok-master/.gitignore
  inflating: ngrok-master/.travis.yml
  inflating: ngrok-master/CONTRIBUTORS
  inflating: ngrok-master/LICENSE
  inflating: ngrok-master/Makefile
  inflating: ngrok-master/README.md
   creating: ngrok-master/assets/
   creating: ngrok-master/assets/client/
  inflating: ngrok-master/assets/client/page.html
   creating: ngrok-master/assets/client/static/
   creating: ngrok-master/assets/client/static/css/
  inflating: ngrok-master/assets/client/static/css/bootstrap.min.css
  inflating: ngrok-master/assets/client/static/css/highlight.min.css
   creating: ngrok-master/assets/client/static/img/
  inflating: ngrok-master/assets/client/static/img/glyphicons-halflings.png
   creating: ngrok-master/assets/client/static/js/
  inflating: ngrok-master/assets/client/static/js/angular-sanitize.min.js
  inflating: ngrok-master/assets/client/static/js/angular.js
  inflating: ngrok-master/assets/client/static/js/base64.js
  inflating: ngrok-master/assets/client/static/js/highlight.min.js
  inflating: ngrok-master/assets/client/static/js/jquery-1.9.1.min.js
  inflating: ngrok-master/assets/client/static/js/jquery.timeago.js
  inflating: ngrok-master/assets/client/static/js/ngrok.js
  inflating: ngrok-master/assets/client/static/js/vkbeautify.js
   creating: ngrok-master/assets/client/tls/
  inflating: ngrok-master/assets/client/tls/ngrokroot.crt
  inflating: ngrok-master/assets/client/tls/snakeoilca.crt
   creating: ngrok-master/assets/server/
   creating: ngrok-master/assets/server/tls/
  inflating: ngrok-master/assets/server/tls/snakeoil.crt
  inflating: ngrok-master/assets/server/tls/snakeoil.key
   creating: ngrok-master/contrib/
  inflating: ngrok-master/contrib/com.ngrok.client.plist
   creating: ngrok-master/docs/
  inflating: ngrok-master/docs/CHANGELOG.md
  inflating: ngrok-master/docs/DEVELOPMENT.md
  inflating: ngrok-master/docs/SELFHOSTING.md
   creating: ngrok-master/src/
   creating: ngrok-master/src/ngrok/
   creating: ngrok-master/src/ngrok/cache/
  inflating: ngrok-master/src/ngrok/cache/lru.go
   creating: ngrok-master/src/ngrok/client/
  inflating: ngrok-master/src/ngrok/client/cli.go
  inflating: ngrok-master/src/ngrok/client/config.go
  inflating: ngrok-master/src/ngrok/client/controller.go
  inflating: ngrok-master/src/ngrok/client/debug.go
  inflating: ngrok-master/src/ngrok/client/main.go
  inflating: ngrok-master/src/ngrok/client/metrics.go
  inflating: ngrok-master/src/ngrok/client/model.go
   creating: ngrok-master/src/ngrok/client/mvc/
  inflating: ngrok-master/src/ngrok/client/mvc/controller.go
  inflating: ngrok-master/src/ngrok/client/mvc/model.go
  inflating: ngrok-master/src/ngrok/client/mvc/state.go
 extracting: ngrok-master/src/ngrok/client/mvc/view.go
  inflating: ngrok-master/src/ngrok/client/release.go
  inflating: ngrok-master/src/ngrok/client/tls.go
  inflating: ngrok-master/src/ngrok/client/update_debug.go
  inflating: ngrok-master/src/ngrok/client/update_release.go
   creating: ngrok-master/src/ngrok/client/views/
   creating: ngrok-master/src/ngrok/client/views/term/
  inflating: ngrok-master/src/ngrok/client/views/term/area.go
  inflating: ngrok-master/src/ngrok/client/views/term/http.go
  inflating: ngrok-master/src/ngrok/client/views/term/view.go
   creating: ngrok-master/src/ngrok/client/views/web/
  inflating: ngrok-master/src/ngrok/client/views/web/http.go
  inflating: ngrok-master/src/ngrok/client/views/web/view.go
   creating: ngrok-master/src/ngrok/conn/
  inflating: ngrok-master/src/ngrok/conn/conn.go
  inflating: ngrok-master/src/ngrok/conn/tee.go
   creating: ngrok-master/src/ngrok/log/
  inflating: ngrok-master/src/ngrok/log/logger.go
   creating: ngrok-master/src/ngrok/main/
   creating: ngrok-master/src/ngrok/main/ngrok/
  inflating: ngrok-master/src/ngrok/main/ngrok/ngrok.go
   creating: ngrok-master/src/ngrok/main/ngrokd/
  inflating: ngrok-master/src/ngrok/main/ngrokd/ngrokd.go
   creating: ngrok-master/src/ngrok/msg/
  inflating: ngrok-master/src/ngrok/msg/conn.go
  inflating: ngrok-master/src/ngrok/msg/msg.go
  inflating: ngrok-master/src/ngrok/msg/pack.go
   creating: ngrok-master/src/ngrok/proto/
  inflating: ngrok-master/src/ngrok/proto/http.go
  inflating: ngrok-master/src/ngrok/proto/interface.go
  inflating: ngrok-master/src/ngrok/proto/tcp.go
   creating: ngrok-master/src/ngrok/server/
  inflating: ngrok-master/src/ngrok/server/cli.go
  inflating: ngrok-master/src/ngrok/server/control.go
  inflating: ngrok-master/src/ngrok/server/http.go
  inflating: ngrok-master/src/ngrok/server/main.go
  inflating: ngrok-master/src/ngrok/server/metrics.go
  inflating: ngrok-master/src/ngrok/server/registry.go
  inflating: ngrok-master/src/ngrok/server/tls.go
  inflating: ngrok-master/src/ngrok/server/tunnel.go
   creating: ngrok-master/src/ngrok/util/
  inflating: ngrok-master/src/ngrok/util/broadcast.go
  inflating: ngrok-master/src/ngrok/util/errors.go
  inflating: ngrok-master/src/ngrok/util/id.go
  inflating: ngrok-master/src/ngrok/util/ring.go
  inflating: ngrok-master/src/ngrok/util/shutdown.go
   creating: ngrok-master/src/ngrok/version/
  inflating: ngrok-master/src/ngrok/version/version.go

  

进入到ngrok源码解压目录,并创建一个ssl目录,用于存放自定义证书

 mkdir ssl&& cd ssl
export NGROK_DOMAIN="ngrok.52fx.biz"
openssl genrsa -out rootCA.key 2048
openssl req -x509 -new -nodes -key rootCA.key -subj "/CN=$NGROK_DOMAIN" -days 8888 -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 8888

  

执行完上面的命令后,会得到这些文件:

 [root@VM_175_142_centos ssl]# tree
.
|-- device.crt
|-- device.csr
|-- device.key
|-- rootCA.key
|-- rootCA.pem
`-- rootCA.srl

  

我们现在把这个文件复制到ngrok对应的目录并覆盖原文件

 [root@VM_175_142_centos ssl]# cp rootCA.pem ../assets/client/tls/ngrokroot.crt
cp: overwrite ‘../assets/client/tls/ngrokroot.crt’? y
[root@VM_175_142_centos ssl]# cp device.crt ../assets/server/tls/snakeoil.crt
cp: overwrite ‘../assets/server/tls/snakeoil.crt’? y
[root@VM_175_142_centos ssl]# cp device.key ../assets/server/tls/snakeoil.key
cp: overwrite ‘../assets/server/tls/snakeoil.key’? y

  

现在我们就来开始编译ngrok

 <!--linux服务端/客户端-->
GOOS=linux GOARCH=386 make release-server (32位)
GOOS=linux GOARCH=amd64 make release-server(64位)

GOOS=linux GOARCH=386 make release-client (32位)
GOOS=linux GOARCH=amd64 make release-client(64位)

<!--Mac OS服务端/客户端-->
GOOS=darwin GOARCH=386 make release-server
GOOS=darwin GOARCH=amd64 make release-server

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


<!--windows服务端/客户端-->
GOOS=windows GOARCH=386 make release-server
GOOS=windows GOARCH=amd64 make release-server

GOOS=windows GOARCH=386 make release-client
GOOS=windows GOARCH=amd64 make release-client
  

,我们先编译一个linux运行的服务端

 [root@VM_175_142_centos ngrok-master]# export GOOS=linux
[root@VM_175_142_centos ngrok-master]# export GOARCH=amd64
[root@VM_175_142_centos ngrok-master]# 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/...
github.com/rcrowley/go-metrics (download)
get "gopkg.in/inconshreveable/go-update.v0": found meta tag get.metaImport{Prefix:"gopkg.in/inconshreveable/go-update.v0", VCS:"git", RepoRoot:"#34;} at //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)
get "gopkg.in/inconshreveable/go-update.v0/check": found meta tag get.metaImport{Prefix:"gopkg.in/inconshreveable/go-update.v0", VCS:"git", RepoRoot:"#34;} at //gopkg.in/inconshreveable/go-update.v0/check?go-get=1
get "gopkg.in/inconshreveable/go-update.v0/check": verifying non-authoritative meta tag
get "gopkg.in/yaml.v1": found meta tag get.metaImport{Prefix:"gopkg.in/yaml.v1", VCS:"git", RepoRoot:"#34;} at //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

  

第一次执行命令时会下载包,所以会比较花时间,可以通过在环境变量中加入GOPROXY值为的方式来添加代理。我继续编译一个windows 64的客户端

 [root@VM_175_142_centos ngrok-master]# export GOOS=windows
[root@VM_175_142_centos ngrok-master]# export GOARCH=amd64
[root@VM_175_142_centos ngrok-master]# 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

  

现在,我们可以在bin目录下看到这些文件

 [root@VM_175_142_centos bin]# tree
.
|-- go-bindata
|-- ngrokd
`-- windows_amd64
    `-- ngrok.exe

  

先把服务端运行起来,默认情况下ngrok是占用的80和443端口,我们可以自行配置

 [root@VM_175_142_centos bin]# ./ngrokd -domain="ngrok.52fx.biz" -httpAddr=":8888" -httpsAddr=":8433"
[14:08:59 CST 2020/04/23] [INFO] (ngrok/log.(*PrefixLogger).Info:83) [registry] [tun] No affinity cache specified
[14:08:59 CST 2020/04/23] [INFO] (ngrok/log.Info:112) Listening for public http connections on [::]:8888
[14:08:59 CST 2020/04/23] [INFO] (ngrok/log.Info:112) Listening for public https connections on [::]:8433
[14:08:59 CST 2020/04/23] [INFO] (ngrok/log.Info:112) Listening for control and proxy connections on [::]:4443
[14:08:59 CST 2020/04/23] [INFO] (ngrok/log.(*PrefixLogger).Info:83) [metrics] Reporting every 30 seconds

  

现在,我们新建一个客户端配置文件ngrok.cfg

 <!--配置服务端连接地址,也就是基础域名。端口则与服务端-tunnelAddr配置相同-->
server_addr: "ngrok.52fx.biz:4443"  
trust_host_root_certs: false
  

现在就可以在客户端运行代理了,ngrok -config=ngrok.cfg -subdomain 域名 端口 ,如ngrok -config=ngrok.cfg -subdomain weixin 8080 执行完成之后会看到这样的界面

这里我们还需要配置域名,切记,需要配置两条

  • ngrok.52fx.biz-> xxx.xx.xxx.xxx(外网IP)
  • *.ngrok.52fx.biz-> xxx.xx.xxx.xxx(外网IP) 该记录为泛解析,就是这样的域名都会解析到指定的ip然后再转发 现在我们来访问一下看是否正常 ok,就是这么回事。但是呢,我们这里的端口是8888,每次访问还得在域名后面加端口,真的是太不优雅了,所以得想办法处理。因为我之前的80端口被nginx给占用了,所以,我们这里再来转发一次吧。
 server {
        listen       80;
        server_name  *.ngrok.52fx.biz;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
             proxy_set_header X-Real-IP $remote_addr;
                        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                        proxy_set_header X-Nginx-Proxy true;
                        proxy_set_header Connection "";
                        proxy_pass       #这里的weixin可以改为任意名称,因为是泛解析
        }
        
          location ~ .*\.(js|css)$ {            
             proxy_pass       #这里的weixin可以改为任意名称,因为是泛解析

         }

      
    }
  

这样看起来是不是更友好一些了呢?如果你的ngrok是监听的80端口,大可不必这样麻烦。

相关文章