ngrok source

https://github.com/inconshreveable/ngrok

Pre-required

  • Ubuntu server with public IP (EC2)
  • A public Domain
  • nginx
  • docker, docker-compose

Add record set to your domain

在網域管理底下添加2個A紀錄到你的Domain

  • ngrok.scottchayaa.com
  • *.ngrok.scottchayaa.com

Run ngrok-server on docker

1
2
3
~$ mkdir ngrok-server
~$ cd ngrok-server
~$ vi docker-compose.yml

docker-compose.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
version: '3'

services:
  ngrok-server:
    image: hteen/ngrok
    ports:
      - "8880:80"
      - "8443:443"
      - "4443:4443"
    volumes:
      - "./data:/myfiles"
    environment:
      - DOMAIN=ngrok.scottchayaa.com # your subdomain
    command: ["/bin/sh", "/server.sh"]
    restart: always
  • 因為 80, 443 比較常使用,所以我們改使用別的port來當作http和https
  • 之後會透過 nginx 反向代理來指向 local ngrok 的 http 和 https
  • 4443 port是 ngrok server 與 client 溝通的 port

    1
    2
    
    # 啟動 ngrok-server
    ~$ docker-compose up -d
  • 啟動後,build.sh會產生./data 的產物

  • 私有金鑰 base.*, device.* (不重要)

  • /bin : 裡面是 ngrok-clinet的執行程序,且有windows和linux版本 (重要)

/bin 這個因為compile比較久,會比較慢出現

若要重build /data,只要砍掉/data後,重新執行docker-compose即可

nginx 反向代理配置

/etc/nginx/conf.d/ngrok-proxy.conf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
server {
    listen 80;
    server_name ngrok.scottchayaa.com *.ngrok.scottchayaa.com;
    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://127.0.0.1:8880;
    }

    location /.well-known/acme-challenge/ {
        root /var/www/letsencrypt/;
        log_not_found off;
    }
}

/etc/nginx/conf.d/ngrok-proxy-ssl.conf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 第一組
server {
    listen 443 ssl;
    server_name test1.ngrok.scottchayaa.com;

    ssl_certificate /etc/nginx/ssl/test1.ngrok.scottchayaa.com.crt;
    ssl_certificate_key /etc/nginx/ssl/test1.ngrok.scottchayaa.com.key;

    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://127.0.0.1:8880;
   }
}

# 第二組
server {
    listen 443 ssl;
    server_name test2.ngrok.scottchayaa.com;

    ssl_certificate /etc/nginx/ssl/test2.ngrok.scottchayaa.com.crt;
    ssl_certificate_key /etc/nginx/ssl/test2.ngrok.scottchayaa.com.key;
    
    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://127.0.0.1:8880;
   }
}

取得letsencrypt憑證

1
2
3
4
5
6
7
8
~$ docker run --rm -v ~/letsencrypt:/etc/letsencrypt \
-v /var/www/letsencrypt:/html -ti \
certbot/certbot certonly \
--email example@gmail.com \
--agree-tos \
--webroot \
-w /html \
-d *.ngrok.scottchayaa.com # test1.ngrok.scottchayaa.com, test2.ngrok.scottchayaa.com ...

取得憑證後,將 fullchain1.pem, privkey1.pem 拷貝到 /etc/nginx/ssl 底下 然後重啟nginx service

1
sudo service nginx restart

Run ngrok-client on localhost

  • 從你一開始編譯的 ~/ngrok-server/data/bin 裡面下載所需的 ngrok client 版本
  • 配置 ngrok.cfg 設定檔

    1
    2
    
    server_addr: "ngrok.scottchayaa.com:4443"
    trust_host_root_certs: false
  • 啟動 ngrok

    1
    2
    3
    4
    
    ./ngrok -config=ngrok.cfg -subdomain=test1 3000
    ./ngrok -config=ngrok.cfg -subdomain=test2 3000
        
    # 可以指定兩組 https

可以寫個nodejs http server,port指定3000

執行成功則會顯示

確認憑證是否完整合法

Summary

之前在還沒有使用 ngrok 時
測試 webhook 功能會受限於在測試環境(因為主機有對外)

有了自己的ngrok server後
由於在本機,所以開發和測試上會快速許多
不用 git push 後在那邊等自動部署到測試環境
然後發現有個地方寫錯等等還要重新 commit…等
繁瑣流程會降低開發效率(速度)

本機程式開發最好就是開發與測試環境是可以一致的
頂多就config配置不同

不過,這以上都還是需要依賴網路
最理想的狀況是連網路這個依賴都拔除
這時候就要靠單元測試
以後有機會再來寫單元測試如何應用在專案上的單元

後記

後來有次在使用 ngrok 上傳檔案時遇到 413 Request Entity Too Large 的錯誤
這是你 server 上 nginx 發生的限制錯誤(當時還以為是本機打通的 nginx sevice)
查了一下,主要是要修改 /etc/nginx/nginx.conf 就好
把 upload max size 限制拉到 20M 左右即可(自行控制)

1
client_max_body_size 20M;
1
2
# 重啟 nginx 
sudo service nginx restart

Reference