Skip to content

内网穿透利器 ngrok 部署配置指南 ​

ngrok 是使用 go 语言开发的反向代理服务,可以在公共的端点和本地内网的 Web 服务之间建立一个安全通道,实现内网穿透功能。 虽然 ngrok 2.x 的版本已经闭源,但 ngrok 1.x 还是开源的,版本停留在了1.7不再开发和维护,但它作为个人平时开发和调试的内网穿透工具偶尔使用还是够用的。之前小白的 ngrok 部署在个人的一台 AWS EC2 主机上已有好几年,最近这台 EC2 释放掉了,小白需要在新的主机上部署 ngrok 服务,正好借着这个机会整理一下 ngrok 的部署和配置过程。

1.前提条件 ​

  1. 一台 Linux 云主机(这里是 CentOS 7),并要求具有固定公网 IP 暴露这台云主机指定端口的能力
  2. 有一个域名解析到这个公网 IP,如ngrok.frognew.com和*.ngrok.frognew.com解析到这个公网 IP

2. 编译 ngrok 服务端 ngrokd 和客户端 ngrok ​

首先需要从 ngrok 1.x 的源码编译 ngrok 的服务端 ngrokd 和客户端 ngrok 程序。ngrok 使用 golang 开发,这里先在这台新的云主机上安装 Go 语言。 这台云主机是 CentOS 7,这里直接使用 yum 安装 golang:

fallback
yum install golang

yum 安装完成的 go,会自动创建/usr/bin/go 到安装目录的软链接,所以这里不再配置环境变量。

接下来使用 git clone ngrok 1.x 的源码:

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

因为这里 ngrok 服务的域名是ngrok.frognew.com,接下来为这个域名生成 ngrok 服务端和客户端的证书:

gdscript3
export NGROK_DOMAIN=ngrok.frognew.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

使用生成的证书替换 ngrok 源码中的证书:

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

编译 ngrok 的服务端 ngrokd:

gdscript3
export GOPATH=/usr/local/ngrok
export GOOS=linux
export GOARCH=amd64
make release-server

按需编译 ngrok 的客户端 ngrok,小白这里是 Mac 所以只编译 Mac OS 系统的客户端:

fallback
GOOS=darwin GOARCH=amd64 make release-client

关于 golang 的交叉编译,通过GOOS指定对应操作系统,darwin对应 Mac OS,windows对应 Windows,linux对应 Linux.

3. 配置启动服务端 ngrokd ​

接下来配置启动服务端 ngrokd,创建一个非特权用户 ngrok 作为服务端的运行用户:

fallback
useradd ngrok

编写 ngrokd 的 Systemd 配置文件/etc/systemd/system/ngrokd.service:

fallback
[Unit]
Description=ngrok server
After=network.target
[Service]
Type=simple
User=ngrok
ExecStart=/usr/local/ngrok/bin/ngrokd --domain=ngrok.frognew.com --tunnelAddr=:14443  --httpAddr=:8081 --httpsAddr=
Restart=on-failure
[Install]
WantedBy=multi-user.target

ngrokd 包含了下面的启动参数:

  • --domain ngrok 的域名,也是前面生成证书时用到的那个域名
  • --httpAddr http 协议端口,默认为 80,这里修改为 8081,
  • --httpsAddr https 协议端口 默认为 443,这里修改空表示不监听和使用 https 端口
  • --tunnelAddr 通道端口 默认 4443,这里修改为 14443

注: 关于 http 协议只启用了 http,是因为这里并不会通过公网 IP 直接暴露 8081 这个端口,而在 ngrokd 前面会部署一个 nginx 暴露 80 和 443,nginx 通过 443 做 TLS Termination,所以--httpsAddr就不再需要了。

启动 ngrokd:

fallback
systemctl enable ngrokd
systemctl start ngrokd

netstat -nltp | grep ngrokd
tcp6       0      0 :::14443                :::*                    LISTEN      8485/ngrokd
tcp6       0      0 :::8081                 :::*                    LISTEN      8485/ngrokd

4.nginx 配置 ​

接下来配置 nginx 反向代理 ngrokd 的 http 服务:

fallback
server {
    listen 80;
    server_name *.ngrok.frognew.com;
    rewrite ^(.*)$  https://$host$1 permanent;
}


server {
    listen       443 ssl;
    server_name  *.ngrok.frognew.com;
    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:8081;
    proxy_set_header X-Nginx-Proxy true;
    proxy_set_header Connection "";

    ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
    ssl_certificate /etc/letsencrypt/live/frognew.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/frognew.com/privkey.pem;
    location / {
       # proxy_intercept_errors on;
       # error_page 404 /404.html;
       proxy_pass http://127.0.0.1:8081;
    }

}

5.ngrok 客户端配置 ​

使用 python3 在本地快速启动一个 http 服务用于测试:

fallback
python3 -m http.server 8080

下面将使用 ngrok 将这个 http 服务暴露到公网,将前面编译的 ngrok 客户端ngork可执行文件下载到本地。 编写 ngrok 的客户端配置文件 ngrok.yml:

yml
server_addr: ngrok.frognew.com:14443
trust_host_root_certs: false
tunnels:
  py-http-demo:
    proto:
      http: 8080

启动 ngrok 客户端:

fallback
./ngrok -config ngrok.yml start py-http-demo

Tunnel Status                 online
Version                       1.7/1.7
Forwarding                    http://py-http-demo.ngrok.frognew.com:8081 -> 127.0.0.1:8080
Web Interface                 127.0.0.1:4040
# Conn                        0
Avg Conn Time                 0.00ms

使用http://py-http-demo.ngrok.frognew.com即可从公网访问前面使用 python 启动的用于测试的 http 服务。

China SmallGu Blog