背景:

本人所处的校内网络与外网网络经由一道防火墙。导致很多校内服务在外网无法访问(教务处信息,知网信息,校内服务器集群等)。传统的回校方法是借用实验室老师的VPN账户回校,但做开发用占时长,在一定程度影响了老师的回校(不能一号两用)。于是打算另寻他路,研究新的回校方法。在咨询过师兄后,师兄给出使用ngrok实现,在各种baidu了解后,恰巧手头上有一台云服务器,一个域名。于是便有了今天的《搭建ngrok服务器实现内网穿透》

实验环境:

  1. 公网云服务器一台

  2. 域名一个

  3. 云服务器操作系统:Ubuntu16.04LTS

实验概要:

  • 在域名提供商给出的接口上设置域名解析(可以是泛解析)

  • 安装Golang环境

  • 生成私钥以配置私人Ngrokd

  • 生成ngrok-server ngrok-client

  • 写ngrok-client配置文件

  • 在需要进行穿透内网的主机上设置开机启动

实验步骤:

  • 在域名提供商给的接口设置解析。(本次实验使用的是企鹅云。设置如图。(偷懒,直接添加了一条泛解析))

  • 登录云服务器。(本次实验使用的云服务器操作系统是Ubuntu16.04LTS,故直接使用putty登录)

  • 配置环境前准备:(安装gcc git)

sudo apt-get update -y
sudo apt-get install gcc
sudo apt-get install git
  • 配置golang环境

sudo apt-get install golang
  • 下载ngrok源码

cd /usr/local/src
git clone https://github.com/inconshreveable/ngrok.git
  • 生成私钥证书

cd ngrok
openssl genrsa -out rootCA.key 2048
openssl req -x509 -new -nodes -key rootCA.key -subj "/CN=你的域名" -days 5000 -out rootCA.pem
openssl genrsa -out device.key 2048
openssl req -new -key device.key -subj "/CN=你的域名" -out device.csr
openssl x509 -req -in device.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out device.crt -days 5000
  • 将生成的证书替换原ngrok的证书

yes|cp rootCA.pem assets/client/tls/ngrokroot.crt
yes|cp device.crt assets/server/tls/snakeoil.crt
yes|cp device.key assets/server/tls/snakeoil.key
  • 编译生成ngrokd(服务端)

# 交叉编译,客户端同。
# GOOS:linux windows darwin (Mac os)
# GOARCH: 386 amd64 arm(树莓派)
sudo GOOS=linux GOARCH=386 make release-server
  • 在云服务器上开启Ngrokd服务端进行监听:

  • ./bin/ngrokd -tlsKey="assets/server/tls/snakeoil.key" -tlsCrt="assets/server/tls/snakeoil.crt" -domain="你的域名"  -httpAddr=":80" -httpsAddr=":443" -tunnelAddr=":4443"
    # httpAddr httpsAddr分别用来转发http https端口,默认为80 443
    # tunnelAddr 是用来监听隧道中客户端请求的端口

  • 打开您刚刚配置的域名,看看是否出现Tunnel not found的字样。出现则成功完成服务端配置

  • 编译生成ngrok客户端

# 此处事例的是为树莓派Raspbian操作系统生成的客户端,不同的客户端编译方法不同。参照生成服务端的交叉编译即可。
# 编译成功后,ngrok程序生成在./bin/文件夹中
sudo GOOS=linux GOARCH=arm make release-client
  • 配置ngrok客户端文件(ngrok.cfg):

server_addr: "你的域名:4443"
trust_host_root_certs: false
tunnels:
    ssh:
        remote_port: 22000  #远程的端口(占用服务器的端口)
        proto:
            tcp: 22   #可以设置内网其他主机端口转发。如"192.168.1.2:80"
    http:
        subdomain: mysubdomain  #若不设置,会随机分配域名
        proto:
            http: 80
    vnc:
        remote_port: 59000
        proto:
            tcp: 5900
#使用时把#后内容删除
  • 配置完成后,使用命令开启反向代理隧道即可

cd NGROK目录(自行改动)
./ngrok -config=ngrok.cfg start http vnc ssh  #linux下
ngrok.exe -config=ngrok.cfg start http vnc ssh #Windows下
  • 出现如下界面即为成功

  • 设置脚本开机自启动(略)

实验中遇到的问题及解决思路(Q&A)

  • 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安装目录的bin目录下找到go-bindata,将他移动到ngrok/bin下 (没有bin,可新建一个) 

  • package code.google.com/p/log4go: Get https://code.google.com/p/log4go/source/checkout?repo=: dial tcp 216.58.197.110:443: i/o timeout
  • 解决方法:在 ngrok/src/ngrok/log 目录下找到 logger.go 文件,修改其中第4或5行的:
                log "code.google.com/p/log4go”为
                log "github.com/keepeye/log4go"  

  • GOOS="" GOARCH="" go get github.com/jteeuwen/go-bindata/go-bindata
             # github.com/jteeuwen/go-bindata
                src/github.com/jteeuwen/go-bindata/toc.go:47: function ends without a return statement
                make: *** [bin/go-bindata] Error 2
  • 解决方法

参考文献

作者 WellLee

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注