Ngrok 搭建指南

文章转载至 Luozm’s Blog

ngrok是一个反向代理,它能够让你本地的web服务或tcp服务通过公共的端口和外部建立一个安全的通道,使得外网可以访问本地的计算机服务。ngrok1.x开源,ngrok2.x不开源。

ngrok

Ngrok的主要用途有以下几种:

  • 内网穿透,可代替vpn
  • 将无外网IP的desktop映射到公网
  • 临时搭建网络并分配二级域名
  • 微信二次开发的本地调试

自己搭建ngrok服务需要一台外网服务器,一个域名(如果只用来内网穿透好像也可以不要?)。本文中使用的服务器系统为Ubuntu 16.04。

有域名之后,需要配置DNS的Host Records,将准备分配给ngrok服务器的域名解析到公网服务器IP地址,如下图所示:

A_Records

泛解析还不太了解,后面补上

ngrok是基于go语言开发的,因此需要先安装go:

sudo apt-get install golang

输入go version来验证安装:

go versiongo version go1.6.2 linux/amd64

设置go环境变量(好像可以不用?):

此外还要使用git,一般ubuntu系统都会自带。

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

使用ngrok.com官方服务时,我们使用的是官方的SSL证书。自己建立ngrok服务,需要我们生成自己的证书,并提供携带该证书的ngrok客户端。首先指定域名:

export NGROK_DOMAIN="ngrok.test.website"

生成证书:

openssl genrsa -out rootCA.key 2048openssl req -x509 -new -nodes -key rootCA.key -subj "/CN=$NGROK_DOMAIN" -days 5000 -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 5000

我们在编译可执行文件之前,需要把生成的证书分别替换到 assets/client/tls和assets/server/tls中,这两个目录分别存放着ngrok和ngrokd的默认证书。

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

有没有release的区别是,包含release的编译结果会把assets目录下的内容包括进去,从而可以独立执行。如果你今后还要更换证书,建议编译不包含release的版本。。首先编译ngrok服务端(ngrokd),默认为Linux版本:

make clean
make release-server

编译过程需要等待一会,因为需要通过git安装相关依赖包。如果提示没有权限,使用sudo命令来安装。

在编译客户端的时候需要指明对应的操作系统和构架:

  • 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

例如编译树莓派 ARM 位的客户端:

export GOOS=linux
export GOARCH=arm
make release-client

生成的文件放在/bin对应的文件夹中,如windows 64位的为:windows_amd64,默认版本的文件就在根目录下。

编译后生成两个文件分别为服务端(ngrokd)和客户端(ngrok)。切换到对应的文件夹,运行服务端:

./ngrokd -domain="$NGROK_DOMAIN" -httpAddr=":801" -httpsAddr=":802"

参数-domain表示服务器域名,请改成你自己的域名;-httpAddr表示默认监听的HTTP端口,-httpsAddr表示默认监听的HTTPS端口,因为我用不到所以都设置成空字符串”“来关闭监听,如果需要打开的话记得格式是:12345(冒号+端口号)这样的;-tunnelAddr表示服务器监听客户端连接的隧道端口号,格式和前面一样;-log表示日志文件位置;还有个-log-level用来控制日志记录的事件级别,选项有DEBUG、INFO、WARNING、ERROR。

如果编译的是不带release的版本,还可以通过-tlsCrt-tlsKey选项来指定证书文件的位置。

出现类似以下内容,则说明我们的服务器端ngrokd正常运行了:

[16:41:56 CST 2017/04/20] [INFO] (ngrok/log.(*PrefixLogger).Info:83) [registry] [tun] No affinity cache specified
[16:41:56 CST 2017/04/20] [INFO] (ngrok/log.(*PrefixLogger).Info:83) [metrics] Reporting every 30 seconds
[16:41:57 CST 2017/04/20] [INFO] (ngrok/log.Info:112) Listening for public http connections on [::]:80
[16:41:57 CST 2017/04/20] [INFO] (ngrok/log.Info:112) Listening for public https connections on [::]:443
[16:41:57 CST 2017/04/20] [INFO] (ngrok/log.Info:112) Listening for control and proxy connections on [::]:4443
[16:41:57 CST 2017/04/20] [INFO] (ngrok/log.(*PrefixLogger).Info:83) [tun:627acc92] New connection from 42.53.196.242:9386
[16:41:57 CST 2017/04/20] [DEBG] (ngrok/log.(*PrefixLogger).Debug:79) [tun:627acc92] Waiting to read message
[16:41:57 CST 2017/04/20] [DEBG] (ngrok/log.(*PrefixLogger).Debug:79) [tun:627acc92] Reading message with length: 159

如果需要后台运行可以使用screennohup,详情自行搜索。

附1:将ngrokd 添加到系统服务(CentOS)

新建系统服务文件ngrokd.service

sudo vim /usr/lib/systemd/system/ngrokd.service

[Unit]
Description=Share local port(s) with ngrok
After=syslog.target network.target

[Service]
PrivateTmp=true
Type=simple
Restart=always
RestartSec=1min
StandardOutput=null
StandardError=null
ExecStart=/usr/local/ngrok/bin/ngrokd -tlsKey=/usr/local/ngrok/assets/server/tls/snakeoil.key -tlsCrt=/usr/local/ngrok/assets/server/tls/snakeoil.crt -domain=xxx网址 -httpAddr=:8081 -httpsAddr=:443 -tunnelAddr=:8083 %i
ExecStop=/usr/bin/killall ngrok

[Install]
WantedBy=multi-user.target

保存并设置为默认启动服务

systemctl enable ngrok.service //加入开机启动
systemctl daemon-reload //重新载入 systemd,扫描新的或有变动的单元

将之前编译好的客户端文件拷贝到需要使用服务的设备上。

在ngrok同路径下建立配置文件ngrok.yml

server_addr: “ngrok.test.website:4443"
trust_host_root_certs: falsetunnels:
    ssh:
    remote_port: 6666
    proto:
      tcp: 22

server_addr端口默认4443,可通过ngrokd服务端启动修改端口。在tunnels里配置隧道信息,具体可见「翻译」ngrok 1.X 配置文档。注意httphttps隧道可设置subdomainauth,而tcp里只能设置remote_port

还可以转发其他IP的端口,方法就是在proto下的tcp(或http、https)后的端口号写成IP地址:端口号的格式(中间是英文冒号)。如:tcp: 192.168.11.1:80

现在运行客户端:

./ngrok -config=ngrok.yml start ssh

回车后,看到这样一个界面,说明启动成功:

Online

如果显示reconnecting说明连接有错,在运行时加入-log=stdout来进行debug。可能有以下几方面原因:

  1. 可能是服务器端口未开放,在服务器上使用sudo iptables --list查看当前规则
  2. 查看是否网络问题,ping到对应的地址检查
  3. 可能是编译的时候证书没有覆盖或者版本不对,重新编译试试

以下是我搭建服务器时参考的一些资料:

Related post

Comment

There are no comment yet.