Debian 搭建ngrok

1. 编译ngrok

网络上的教程大多是自己编译 git 和 go, 而且 go1.4 以上的版本还需要用 go1.4 来编译, 要先装gcc来编译 go1.4, 然后再用 go1.4 编译更新的版本.这就显得很坑了.
Debian8 软件源里的go版本是 1.3.3, git 版本 2.1.4, 这两个都不算太高. 我平时不会用到 go 语言, git 版本也不需要太高, 能支持 GitHub 就可以了. 所以就不自己编译, 不想瞎折腾, 能用上 ngrok 就可以了.

1.1 我的 VPS 系统是 Debian8, 首先装必要的工具:

sudo apt-get install build-essential golang mercurial git

ngrok 是用 go 语言写的, 所以 golang 是必须要装的. 安装 git 是为了从GitHub上下载 ngrok 的源码自己编译. mercurial 百度说是版本控制用的. 这是个坑, 之前没安装 mercurial 到了编译 golang 和 ngrok 时老是报错. 纠结了好几天都没有搞定, 后来上GitHub看开发者的readme才知道的.

1.2 获取 ngrok 源码:

cd /usr/local
git clone https://github.com/inconshreveable/ngrok.git
cd ngrok

1.3 生成证书

生成并替换源码里默认的证书. 注意域名修改为自己的.(之后编译出来的服务端客户端会基于这个证书来加密通讯, 保证安全性)

export NGROK_DOMAIN="ngrok.mydomain.com"

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 server.key 2048
openssl req -new -key server.key -subj "/CN=$NGROK_DOMAIN" -out server.csr
openssl x509 -req -in server.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out server.crt -days 5000

在软件源代码目录下面会生成一些证书文件, 我们需要把这些文件拷贝到指定位置

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

如果是在国内的服务器需要执行此步, 香港或者国外的服务器不需要

vim /usr/local/ngrok/src/ngrok/log/logger.go
log "github.com/keepeye/log4go"

1.4 开始编译服务端:

make release-server

1.5 编译客户端:

这里我们需要交叉编译, 使用不同的编译选项来选择编译以后生成的平台
这里我主要是生成了 windows, arm 和 Linux 的版本. 继续在原先的目录下:

GOOS=linux GOARCH=amd64 make release-client
GOOS=windows GOARCH=amd64 make release-client
GOOS=linux GOARCH=arm make release-client

不同平台使用不同的 GOOS 和 GOARCH, 前面的编译选项GOOS就是指编译出来的操作系统 (windows,linux,darwin) ; GOARCH是指对应的构架 (386,amd64,arm)

  • Linux 平台 32 位系统: GOOS=linux GOARCH=386

  • Linux 平台 64 位系统: GOOS=linux GOARCH=amd64

  • Windows 平台 32 位系统: GOOS=windows GOARCH=386

  • Windows 平台 64 位系统: GOOS=windows GOARCH=amd64

  • MAC 平台 32 位系统: GOOS=darwin GOARCH=386

  • MAC 平台 64 位系统: GOOS=darwin GOARCH=amd64

  • ARM 平台: GOOS=linux GOARCH=arm

如果一切正常, ngrok/bin 目录下应该有 ngrok, ngrokd 等文件. 其中ngrokd是服务端, ngrok是客户端.

通过前面的步骤, 就会在 bin 目录里面生成所有的客户端文件, 客户端平台是文件夹的名字. 客户端放在对应的目录下, 当前 Linux 平台客户端在bin目录. 然后我们就可以打个包, 把所有文件下载到自己的本机了.

2 运行并测试

2.1 启动服务器端 ngrokd

这个很简单, 首先执行VPS上的服务器端 ngrokd, 这里的 8080 指的是服务器启用 8080 端, 就是说内网穿透后的域名为 xxx.ngrok.mydomain.com:8080. 如果在 80 端口未作他用的情况下, 也可将 8080 端口改为 80, 这样更方便些. 而如果我们 VPS 的 80 端口被占用了, 但是我们还想用 80 端口作为服务端口, 那么可以使用 nginx 做一个 xxx.ngrok.mydomain.com 的反向代理.

#执行 ngrokd
/usr/local/ngrok/bin/ngrokd -domain="ngrok.mydomain.com" -httpAddr=":8080"

2.2 写客户端配置文件

在 ngrok.exe 所在目录下建立文件 ngrok.cfg, 用记事本等文本编辑器写入以下内容并保存.

#配置文件 ngrok.cfg 的内容
#
server_addr: "ngrok.mydomain.com:4443"
trust_host_root_certs: false

2.3 映射 HTTP

之后打开 Windows 服务器,这里以 80 端口为例。打开命令提示符,切到 ngrok.exe 所在目录,并执行以下命令。

# 启动 ngrok 客户端
# 注意:如果不加参数 -subdomain=test,将会随机自动分配子域名。
#
ngrok -config=ngrok.cfg -subdomain=test 80

正常情况下,客户端上会显示以下内容,表示成功连接到服务器端。

# 客户端ngrok正常执行显示的内容
ngrok                                            (Ctrl+C to quit)
 
Tunnel Status     online
Version           1.7/1.7
Forwarding        http://ngrok.dingdayu.com:8080 -> 127.0.0.1:80
Forwarding        https://ngrok.dingdayu.com:8080 -> 127.0.0.1:80
Web Interface     127.0.0.1:4040
# Conn            0
Avg Conn Time     0.00ms

打开浏览器, 分别在地址栏中输入 http://localhosthttp://test.tunnel.mydomain.com:8080, 如果后者正常显示并且和 http://localhost 显示的内容相同, 则证明我们已经成功了.

2.4 映射TCP

# 这里以SSH连接Linux时的22端口为例
./ngrok -proto=tcp 22

映射成功的话,会显示如下内容:

# 客户端ngrok正常执行显示的内容
ngrok                                           (Ctrl+C to quit)
 
Tunnel Status     online
Version           1.7/1.7
Forwarding        tcp://ngrok.dingdayu.com:49805 -> 127.0.0.1:22
Web Interface     127.0.0.1:4040
# Conn            0
Avg Conn Time     0.00ms

现在, 在 putty 等 ssh 工具中即可连接 tunnel.mydomain.com. 切记端口是号 49805, 是随机分配的一个端口号, 而不是默认的 22 端口了.

Windows 的远程桌面可以将其映射到 3389 端口来实现. 同理, 如果要做 MySQL 的远程连接, 只需映射 3306 端口即可. FTP可映射21端口.

3. 定制个人信息

通过以上操作, 我们的 ngrok 服务器就已经成功搭建了, 客户端也成功的跑了起来. 但是, 如果我们想要对 ngrok 进行一些定制和优化, 可以参考这些后续定制及优化的方法.

3.1 修改客户端 ngrok 默认服务地址

客户端每次还需要加载配置文件, 这样显得有些麻烦. 能不能像官方服务那样直接执行命令 ngrok 80 就能使用呢? 我们只需要在编译客户端之前, 稍作修改即可. 同样, 如果需要指定域名可以执行命令 ngrok -subdomain=test 80 来运行客户端.

# 修改默认服务地址
vim ./src/ngrok/client/model.go
# 找到第23行,将
defaultServerAddr = "ngrokd.ngrok.com:443"
# 修改为defaultServerAddr = "ngrok.dingdayu.com:4443" 即可

3.2 修改客户端 ngrok 左上角蓝色文字 logo

运行客户端后, 我们会发现在客户端左上角会有一个蓝色字体的 “ngrok” 字样的文字 logo, 如果觉得不太喜欢, 或者想修改一下的话, 可以在编译客户端之前, 作如下修改.

# 修改客户端蓝色文字logo
Vim ./src/ngrok/client/views/term/view.go

找到第 100 行, 将

v.APrintf(termbox.ColorBlue|termbox.AttrBold, 0, 0, "ngrok")

修改为

v.APrintf(termbox.ColorBlue|termbox.AttrBold, 0, 0, "your logo")

3.3 修改客户端帮助信息

ngrok 客户端默认的帮助信息很少, 我们可以在编译客户端之前, 自己定制帮助内容.

# 修改客户端默认帮助信息
vim ./src/ngrok/client/client/cli.go

找到第 14 行, 修改const usage2 string的值即可.

4. 后续优化

4.1 ngrok 服务器端开机启动运行

4.1.1 在 ngrok 安装目录下创建启动脚本 start.sh

/usr/local/ngrok/bin/ngrokd -domain="ngrok.mydomain.com" -httpAddr=":8080" -httpsAddr=":443"

后台运行

nohup /usr/local/ngrok/bin/ngrokd  -domain="ngrok.mydomain.com" -log="ngrok.log" -httpAddr=":8080" &

更改脚本文件权限

chmod 755 start.sh

4.1.2 编写 ngrok 开机启动脚本

新建脚本文件

 vim /etc/init.d/ngrok

编辑脚本内容

#!/bin/sh
### BEGIN INIT INFO
# Provides:          ngrok
# Required-Start:    
# Required-Stop:     
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start or stop the ngrok Proxy.
### END INIT INFO

ngrok_path=/usr/local/ngrok
case "$1" in
        start)
                echo "start ngrok service.."
                sh ${ngrok_path}/start.sh
                ;;
        *)
        exit 1
        ;;
esac

更改文件权限

cd /etc/init.d
chmod 755 ngrok

4.1.3 注册开机启动

cd /etc/init.d
update-rc.d ngrok defaults 90

此处有坑,用putty时不会报错. 但是我在linuxmint下用ssh时会出现perl报错的情况. 这是linuxmint上的语言环境用的是utf-8_zh,但是vps用的是utf-8_en. 我懒得修改系统的语言, 所以建议用putty远程.

4.2 nginx代理

我vps的80端口已经被nginx用了, 所以ngrok无法再使用80端口, 只能用nginx, 那么直接反向代理走起~~.
安装nginx: apt-get install nginx
/etc/nginx/conf.d 目录下创建一个新的配置文件ngrok_proxy.conf, 输入:

server {
        server_name     *.ngrok.mydomain.com;
        listen 80;
        keepalive_timeout 70;
        proxy_set_header "Host" $host:8080;
        location / {
                proxy_pass_header Server;
                proxy_redirect off;
                proxy_pass http://127.0.0.1:8080;
        }
        access_log off;
        log_not_found off;
}

检测语法是否有错:
nginx -t -c /etc/nginx/nginx.conf
然后重启nginx就可以了: nginx -s reload
之前对语法检测的对象理解有误. 要检测现有的修改过的Nginx配置是否有错误, 不是单单检测那个修改过的扩展的 .conf 文件, 而是不管任何时候, 始终都是去检测主文件 /etc/nginx/nginx.conf, 只有这样, 才能顺利的在对应的模块加载扩展的.conf文件. 具体可以看参考文章.

参考文章:

  1. Ngrok搭建服务器
  2. 搭建 ngrok 服务实现内网穿透
  3. 搭建ngrok服务器及跨平台客户端内网穿透的使用
  4. ngrok 服务器端开机启动运行
  5. ubuntu安装ngrok并使用nginx代理
  6. Nginx 错误[emerg] “server” directive is not allowed here的可能情况

推荐阅读更多精彩内容