部署內網穿透神器 Ngrok 詳細教程
現在大部分寬帶都不分配固定 IP 了,當在外面想要連接家裏的智能管理,或者有項目想要臨時給客戶演示時,是十分不方便的,內網穿透工具就此誕生,現在比較流行的有 Ngrok 和 Frp,接下來我們將探討 Ngrok 的部署使用。
一、依賴
Ngrok 是一個 DDNS 服務,因此需要一個公有域名,而要實現外網訪問,也就意味着需要一個靜態 IP,既然寬帶不分配靜態 IP,那麼我們可以購買便宜的主機來實現。
注意,通過 Ngrok 連接的方式,如果 VPS 是選用國內的,雖然延遲好了,但網絡瓶頸也產生了,所以建議帶寬要大於 5Mbps。
二、部署
以 CentOS 7.0 x64 爲例:
1、安裝環境
2020/02/26 更新
Golang 下載地址參見:https://studygolang.com/dl
# 編譯環境
# yum -y install zlib-devel openssl-devel perl hg cpio expat-devel gettext-devel curl curl-devel perl-ExtUtils-MakeMaker hg wget gcc gcc-c++ mercurial
# GO 環境
# wget http://www.golangtc.com/static/go/1.9.2/go1.9.2.linux-amd64.tar.gz
# tar -zxvf go1.9.2.linux-amd64.tar.gz
# mv go /usr/local/
# ln -s /usr/local/go/bin/* /usr/bin/
# 驗證一下
# go env
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH=""
GORACE=""
GOROOT="/usr/lib/golang"
GOTOOLDIR="/usr/lib/golang/pkg/tool/linux_amd64"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build672964581=/tmp/go-build"
CXX="g++"
CGO_ENABLED="1"
# 安裝高版本 git(>1.8)
# yum remove git*
# wget http://mirrors.ustc.edu.cn/kernel.org/software/scm/git/git-2.9.5.tar.gz
# tar zxf git-2.9.5.tar.gz && cd git-2.9.5
# ./configure --prefix=/usr/local/git
# make && make install
# ln -s /usr/local/git/bin/* /usr/bin/
# 驗證一下
# git --version
git version 2.9.5
Ngrok 通過證書加密,可以自籤或者申請,因爲自籤會有不信任的問題,故建議申請正式證書,申請方法可參考:
- 獲取免費的 Let’s Encrypt 泛域名 SSL 證書
- 如何補全 SSL 證書鏈?(含申請免費泛域名 Alpha SSL 證書方法)
需要保存 4 個文件,CA 證書 ca.crt 、ROOT 簽發證書 root.crt 、域名證書 domain.com.crt 及私鑰 domain.com.key ,此處域名是指要做爲管理的域名,避免後續新增或更換需要重新部署,建議申請泛域名證書。
3、編譯 Ngrok
① 下載源碼
# git clone https://github.com/inconshreveable/ngrok.git
# export GOPATH=~/ngrok
② 替換證書
ca.crt -> ngrok/assets/client/tls/snakeoilca.crt
root.crt -> ngrok/assets/client/tls/ngrokroot.crt
domain.crt -> ngrok/assets/server/tls/snakeoil.crt
domain.key -> ngrok/assets/server/tls/snakeoil.key
注意 root.crt 不要跟 ca.crt 弄反了,否則在 Windows 客戶端正常連接,Linux 客戶端會出現 remote error: bad certificate
錯誤。
③ 編譯服務端
# cd ngrok/
# make release-server
④ 編譯客戶端
# Windows 平臺 64 位系統
# GOOS=windows GOARCH=amd64 make release-client
- 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 目錄下
4、使用方法
① 域名解析
在域名解析商處記錄 domain.com 至主機 IP,即運行 Ngrok 的 VPS,如果申請的證書是單域名證書,則解析單域名,泛域名則設置想要鏈接的域名。
② 啓動服務
服務端程序駐守爲 ngrok/bin/ngrokd,可以將其放入 $PATH 中:
# vim ~/.bash_profile
...
PATH=$PATH:$HOME/bin:/root/ngrok/bin
...
# source ~/.bash_profile
也可以直接創建鏈接:
# ln -s ~/ngrok/bin/* /usr/bin/
啓動服務端:
# nohup ngrokd -domain=domain.com -httpAddr=:5442 -httpsAddr=:5443 -tunnelAddr=:4443 > ~/ngrok/ngrok.log &
如果不用默認證書,也可以指定證書啓動:
# nohup ngrokd -tlsKey=~/server.key -tlsCrt=~/server.crt -domain=domain.com -httpAddr=:5442 -httpsAddr=:5443 -tunnelAddr=:4443 > ~/ngrok/ngrok.log &
其中,
-domain 爲服務域名,
-httpAddr 爲 http 服務默認端口地址,訪問形式爲 xxx.domain.com:5442,
-httpsAddr 爲 https 服務默認端口地址,
-tunnelAddr 是服務器用來跟客戶端通訊的長連接端口,
不要日誌的話刪除 > ~/ngrok/ngrok.log
即可。
查看端口監聽判斷是否啓動成功:
# lsof -i :4443
如果有啓用防火牆,記得開放端口:
# firewall-cmd --zone=public --add-port=5442/tcp --permanent # firewall-cmd --zone=public --add-port=5443/tcp --permanent # firewall-cmd --zone=public --add-port=4443/tcp --permanent # firewall-cmd --reload
③ 客戶端連接
客戶端有兩種啓動方式,一個是命令行直接啓動,一個是通過配置文件運行。
I、命令行啓動
新建文件 ngrok-config 保存服務器信息:
server_addr: tunel.domain.com:4443
trust_host_root_certs: true
注意,如果在上面證書配置中,如果沒有替換 CA 證書,那麼 trust_host_root_certs 應設爲 false,如果使用的是通配符證書,那麼 server_addr 域名隨便設,1.domain.com、ngrok.domain.com 都可以。
啓動 http 穿透
./ngrok -config=ngrok-config 80
啓動 ssh 穿透
./ngrok -config=ngrok-config --proto=tcp 22
要記錄日誌則添加 -log=log.log
即可
I、配置文件啓動
新建文件 ngrok-config 保存服務器及隧道信息
server_addr: tunel.domain.com:4443
trust_host_root_certs: true
tunnels:
web:
proto:
http: 80
subdomain: myapp
auth: "user:secretpassword"
webs:
proto:
https: 443
hostname: myapps.domain.com
crt: example.crt
key: example.key
ssh:
proto:
tcp: 22
remote_port: 5555
如果本地端口或者遠程端口不是標準的 80 443 端口,則應該在 hostname 後加上端口號。同樣的,可以監聽本地局域網內的其他主機,比如說:
ssh: proto: tcp: 192.168.1.3:22 remote_port: 5555
啓動命令:
./ngrok -config=ngrok-config start web ssh
ngrok (Ctrl+C to quit)
Tunnel Status online
Version 1.7/1.7
Forwarding http://myapp.domain.com:5442 -> 127.0.0.1:80
Forwarding tcp://tunel.domain.com:5555 -> 127.0.0.1:22
Web Interface 127.0.0.1:4040
# Conn 0
Avg Conn Time 0.00ms
如果屏幕顯示如上信息,表示隧道已經打通,我們就可以通過外網域名訪問到內網了,記得子域名也要在域名解析商處添加記錄,不然域名還是訪問不到。另外 Ngrok 也支持在配置中直接指定端口,記得主機要開放該端口。在本地訪問 http://127.0.0.1:4040 可以看到請求日誌詳情。
5、問題排查
① remote error: bad certificate
客戶端 ngrok.cfg 中 server_addr 後的值必須嚴格與服務端 -domain 以及證書中的域名相同,否則 Server 端就會出現此錯誤:
[04/15/18 18:55:46] [INFO] [tun:15dd7522] New connection from *.*.*.*:*
[04/15/18 18:55:46] [DEBG] [tun:15dd7522] Waiting to read message
[04/15/18 18:55:46] [WARN] [tun:15dd7522] Failed to read message: remote error: bad certificate
[04/15/18 18:55:46] [DEBG] [tun:15dd7522] Closing
也可以將配置文件中的 trust_host_root_certs
設爲 false
,另外再確認下 root.crt 有沒有跟 ca.crt 弄反了。
② make: bin/go-bindata: Command not found
安裝 go 環境時必須將 go/bin 目錄添加到 PATH,或者創建鏈接到系統 bin 目錄,比如:
# ln -s /root/go/bin/* /usr/bin/
其他出現 not found 提示也是類似的解決方法,比如
package code.google.com/p/log4go: exec: "hg": executable file not found in $PATH
是說找不到 hg 包,安裝一下即可:
# yum install hg -y
③ You may only specify one port to tunnel to on the command line, got 2:
出現這個問題大多是使用了官方給的配置模板,而 ngrok 1.x 舊版本(GitHub 最新版)對此配置支持有問題,開發者對 2.x 已不再開源,故只能調整配置文件(參照上面的配置),或者命令行直接啓動使用。
④ Error parsing configuration file *.conf: YAML error: line 5: found character that cannot start any token
主要存在於 Linux 系統下,原因是在寫啓動配置文件時,按下回車鍵後編輯器自動格式化了空格,導致 Ngrok 無法識別配置文件,解決方法就是將配置文件的空格刪掉,手動重新敲一遍。
參考文章:
1、《GitHub Wiki》
2、《搭建自己的ngrok服務》
3、《How to setup Ngrok with a self-signed SSL cert》
4、《Developer's guide to ngrok》
5、《內網穿透 ngrok 服務器和客戶端配置》
6、《ngrok - Documentation》
7、《CentOS7搭建ngrok服務器》