阿里云 VPS 搭建 ngrok

ngrok是一套反向代理、可以实现内网穿透的开源工具。
再直白一些,开发阶段,你家里的电脑上跑着一套web服务,想让好友帮你测试,但是又不想一遍一遍地把web服务发布到服务器上怎么办?用ngrok可以实现让别人从外网访问到你家里的电脑上的一个web服务

前期准备:

  1. 有相对固定的公网IP的服务器;
  2. 有域名。

按照以下步骤安装:

1.编译ngrok

1.1 首先装必要的工具

我购买的是阿里云香港 VPS ,系统是 Ubnuntu, 所以使用如下命令:

sudo apt-get install build-essential golang mercurial git

1.2 获取 ngrok 源码

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

1.3 生成证书

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

export NGROK_DOMAIN="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 和 Linux 的版本. 继续在原先的目录下:

#Linux平台64位系统
GOOS=linux GOARCH=amd64 make release-client
#Windows平台64位系统
GOOS=windows GOARCH=amd64 make release-client

编译选项解释:
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.mydomain.com:8080. 如果在 80 端口未作他用的情况下, 也可将 8080 端口改为 80, 这样更方便些. 而如果我们 VPS 的 80 端口被占用了, 但是我们还想用 80 端口作为服务端口, 那么可以使用 nginx 做一个 xxx.mydomain.com 的反向代理.

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

2.2 写客户端配置文件

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

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

2.3 映射 HTTP

假设子域名是test,则先添加泛解析 test (类型为 CNAME) 到 mydomain.com

之后打开 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://test.mydomain.com:8080 -> 127.0.0.1:80
Forwarding        https://test.mydomain.com:8080 -> 127.0.0.1:80
Web Interface     127.0.0.1:4040
# Conn            0
Avg Conn Time     0.00ms

打开浏览器, 分别在地址栏中输入 http://localhosthttp://test.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://mydomain.com:49805 -> 127.0.0.1:22
Web Interface     127.0.0.1:4040
# Conn            0
Avg Conn Time     0.00ms

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

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

3 优化

3.1 ngrok 服务器端后台运行

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

3.2 nginx代理

我vps的80端口已经被nginx用了, 所以ngrok无法再使用80端口, 只能用nginx, 那么直接反向代理走起~~.

在nginx的配置文件增加:

server {

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

}

3.3 客户端指定tcp端口

更改配置文件内容为:

#注意,tunnels下的名字随意命名
server_addr: "mydomain.com:4443"
trust_host_root_certs: false
tunnels:
    ssh:
        remote_port: 35219
        proto:
            tcp: 22
    vnc:
        remote_port: 5902
        proto:
            tcp: 5902
    dd:
        remote_port: 9208
        proto:
            tcp: 8888
    www_xly:
        subdomain: xly
        proto:
            http: 80

客户端启动命令改为:

#选择仅启动ssh和web服务
ngrok -config=ngrok.cfg start ssh www_xly

参考文章:
Debian 搭建ngrok 作者:suanite
ngrok指定tcp端口 作者:李悦