架設自己的 Localtunnel server

Merik Chen
13 min readMay 29, 2018

--

也許你有聽過 ngrok 或者正在使用它開發著你的產品。

但如果你需要一個以上的產品需要同時使用 ngrok 做開發,那就得付錢…

今天介紹的是這個

Localtunnel

Localtunnel allows you to easily share a web service on your local development machine without messing with DNS and firewall settings.

它能夠將你的本機伺服器代理至網路上,讓全世界都能夠直接訪問你的本機伺服器 (中文好難…)

偏偏事情就是沒有那麼順利… Localtunnel 預設所提供的 localtunnel.me 伺服器遠遠遠在美國,ping 值隨便就是 2~300 ms 來回根本就不堪設想 (;´༎ຶД༎ຶ`)

剛好看到人家有開源 localtunnel server (以下各種簡稱 lt server),好奇心很重的我立馬有那種:我也來架設一個好了的心態。

我想,流程是這樣的:

買 Domain → 設定 DNS → 等待生效 → 設定 Wildcard SSL → Testing → DONE.

開 VM → 設定 VM → 裝 Localtunnel → 設定 nginx ↗
by 愛亂花錢的我 ❤️

今天準備了 tunneling.live 這個 Domain 是在 GoDaddy 買的,VM 是在 Vultr 5 美一個月,Wildcard SSL 用 Let’s Encrypt 提供的。根本物美價廉啊!!

網域的設定

首先我在 GoDaddy 的網域後台設定了 lt, *.lt 的 subdomain.

原本以為 wildcard subdomain 不會有太多業者提供設定,沒想到查一下還有蠻多有提供的。

機器的設定

等待 DNS 生效的同時,我在 Vultr 開了一個 東京 $5/mo 的機器。使用了我熟悉的 Ubuntu 18.04 版本。

安裝系統套件

根據官方的指示,將各種套件源加入 apt 的 source 裡面

Node.js

curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -

Nginx

curl -sL http://nginx.org/keys/nginx_signing.key | apt-key add -vim /etc/apt/sources.listAdd these two lines behind:
deb http://nginx.org/packages/ubuntu/ bionic nginx
deb-src http://nginx.org/packages/ubuntu/ bionic nginx

在安裝 certbot 之前,請先將 node.js, nginx 安裝好

apt update
apt install -y build-essential nodejs nodejs-legacy nginx git

Certbot

git clone 一份 certbot 的源碼:

git clone https://github.com/certbot/certbot

接著切換到 certbot 的資料夾下,執行:

/certbot# ./certbot-auto certonly --manual -d *.lt.tunneling.live -d lt.tunneling.live --agree-tos --manual-public-ip-logging-ok --preferred-challenges dns-01 --server https://acme-v02.api.letsencrypt.org/directory--------------------------------------------------------------------
Please deploy a DNS TXT record under the name
_acme-challenge.lt.tunneling.live with the following value:

qqiR_lsa2AjMfoVR16mH4UDbOxy_E02l0K1CNyz1RdI

Before continuing, verify the record is deployed.
--------------------------------------------------------------------
Press Enter to Continue
--------------------------------------------------------------------
Please deploy a DNS TXT record under the name
_acme-challenge.lt.tunneling.live with the following value:

qqiR_lsa2AjMfoVR16mH4UDbOxy_E02l0K1CNyz1RdI

Before continuing, verify the record is deployed.
--------------------------------------------------------------------
Press Enter to Continue

TIP: 這邊要注意一下,新增 TXT 的時候,是新增兩次而非修改第一次的值。

TIP: 在按下確認前,可以先用 SuperTool 測試 TXT 是否已經確實生效。

之後,確認出現下方的訊息就表示已經完成認證並取得有效 SSL 了

Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/example.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/example.com/privkey.pem
Your cert will expire on 2018-06-11. To obtain a new or tweaked
version of this certificate in the future, simply run certbot-auto
again. To non-interactively renew *all* of your certificates, run
"certbot-auto renew"
- If you like Certbot, please consider supporting our work by:

Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le

Localtunnel Server 安裝與設定

安裝的部分

git clone git://github.com/defunctzombie/localtunnel-server.git
cd localtunnel-server
npm install

這樣就準備好 server 主體與相依套件的部分了!

設定的部分

我讓 lt server 跑在 1069 port (笑)

cd localtunnel-server
node -r esm bin/server --secure true --domain lt.tunneling.live --port 1069
localtunnel server listening on port: 1069 +0ms

localtunnel server 設定好了 (誒)

Nginx reverse proxy with SSL support configuration

原本我是打算想要自己嘗試些這份 nginx config 檔,在幾番嘗試之後一直沒有很好的成效… 在反覆找了幾次可能的方法裡面,最終讓我在 Readme 下方找到原作者提供可用的 config 檔(是我眼殘)

我將原作者所提供的檔案再加上一些 SSL 的優化,最終產出以下 config:

proxy_http_version 1.1;map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream lt-server {
server 127.0.0.1:1069;
}
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;

listen 443 default_server ssl http2;
listen [::]:443 default_server ssl http2 ipv6only=on;
server_name .lt.tunneling.live;

ssl on;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
ssl_certificate /etc/letsencrypt/live/lt.tunneling.live/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/lt.tunneling.live/privkey.pem;
ssl_ciphers EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:EDH+aRSA:HIGH:!aNULL:!eNULL:!LOW:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!SEED:!DSS:!CAMELLIA;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_dhparam /etc/nginx/ssl/dhp-2048.pem;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/lt.tunneling.live/fullchain.pem;
location / {
proxy_pass http://lt-server/;
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;
proxy_set_header X-Forwarded-Proto http;
proxy_set_header X-NginX-Proxy true;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_redirect off;
}
}

這組 config 檔所測出來的 SSL 分數為 A+

功能測試

完成 lt server 與 nginx 的設定之後,現在就來測試看看是否能正常代理吧!

首先開啟 lt server

Server 端

在我的電腦上,使用 lt client 指定連接我的伺服器,代理 8080 port 並使用 enterprise 這個代號 (若沒有指定,系統會隨機產生一個

Client 端

現在,我們能在 https://enterprise.lt.tunneling.live/ 上面存取我們本機的伺服器了~

使用 webpack dev server 當作示範

TIP: webpack dev server 會認 host 所以一開始建立的時候只會顯示 Invalid HOST Header 這幾個字,必須將 *.lt.tunneling.live 網域利用 devServer.allowedHosts 的選項加入認可清單內。

For example:

"scripts": {    "dev": "webpack-dev-server --inline --progress --allowed-hosts .lt.tunneling.live --config build/webpack.dev.conf.js",    "start": "npm run dev",    "lint": "eslint --ext .js,.vue src",    "build": "node build/build.js"},

黑,沒錯我就認真的架出來惹。
我也不打算有任何隱瞞,歡迎有需要的迷眾也能夠使用。

lt \
-h https://lt.tunneling.live \
-p 你的本地 port \
--subdomain 想要的subdomain (可選,系統中只能有唯一值)
your url is: https://moody-snake-32.lt.tunneling.live

每個月只有 1T 的流量… 用完就只能等下個月了 ಠ_ಠ

後記

拿來開發 frontend or bot 也方便許多,也很適合在 demo 的場合上使用!

與 ngrok 相比,最大的差別是無法代理 TCP 的部分,不過這一段我也少用,對我的衝擊也比較小就是惹。

附錄

在 nginx config 裡面有使用了 ssl_dhparam 來提高安全性,這邊附上產生 dhparam.pem 的語法

dhparam.pem

openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048

--

--