背景
家里淘汰了一臺筆記本,windows系統(tǒng)裝起來很卡,于是裝了個linux系統(tǒng)。這臺筆記本有2G內存,奔騰雙核處理器,配置比我在阿里云上買的ECS高多了,于是想著給它利用起來。研究了一下,發(fā)現(xiàn)ngrok內網穿透能實現(xiàn)這個功能,剛好我也有外網服務器和域名,那就直接開干。
安裝gcc、git和go語言
yum install gcc -y
yum install git -y
yum install golang -y
源碼編譯
下載源碼
此處從git下載,選擇的是tutumcloud修改過的源碼,解決了部分包無法獲取的問題。也可以在window下下載zip包,然后再上傳至服務器,解壓即可。
git clone https://github.com/tutumcloud/ngrok.git ngrok
生成自簽名證書
我們采用自己的服務器自建ngrokd服務,需要生成自己的自簽名證書,并用該證書編譯一個ngrok客戶端。
生成證書需要配置一個環(huán)境變量NGROK_BASE_DOMAIN,直接在命令行里定義即可,這個域名是一個基礎域名,后面ngrok提供http服務的時候,可以在這個域名前面再加前綴。以ngrok.com的官方服務為例,它提供的服務地址為xxx.ngrok.com,那么它這個NGROK_BASE_DOMAIN變量就為,“ngrok.com”。此處,我用自己的二級域名“ngrok.shawnan.xyz”,后續(xù)提供http服務時,域名為“xxx.ngrok.shawnan.xyz”。
生成簽名的代碼如下,在ngrok目錄執(zhí)行。
cd ngrok
NGROK_DOMAIN="ngrok.shawnan.xyz"
openssl genrsa -out base.key 2048
openssl req -new -x509 -nodes -key base.key -days 10000 -subj "/CN=$NGROK_DOMAIN" -out base.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 base.pem -CAkey base.key -CAcreateserial -days 10000 -out server.crt
替換證書
生成完成后需要替換證書,就在當前目錄把編譯要用到的證書替換掉。
cp base.pem assets/client/tls/ngrokroot.crt
編譯
編譯,編譯一個服務端和一個客戶端,如果是在window下使用,就編譯windows的客戶端。
make release-server release-client
// 編譯windows客戶端
GOOS=windows GOARCH=amd64 make release-client
編譯后會在bin目錄下生成ngrokd和ngrok文件,ngrokd和ngrok文件分別是ngrok的服務端程序和linux平臺下的客戶端程序。如果編譯了windows客戶端,則會生成一個ngrok.exe,是windows下的客戶端程序。
到此處編譯工作就完成了,下面開始啟動服務。
啟動服務
準備工作
準備工作之一就是首先要確定幾個端口,分別是ngrok用來轉發(fā)http、https服務的端口,還有轉發(fā)ssh、ftp等服務的端口,此處我用到了3個,分別是http的8088、https的8443、ssh的8022。此處要記得在linux的防火墻開啟這幾個端口,如果是云服務器,則要配置相應的規(guī)則,否則外網的設備如何也連不進你部署的ngrokd服務。
我們可以在windows下采用telnet命令測試服務器的端口是否已經打開:
telnet xx.xx.xxx.xx 222
// 如果返回類似“SSH-2.0-OpenSSH_7.4”的結果,則222端口就打開了,如果一直是connecting,則該端口就沒打開
此處假設端口已經可用了,下面開始啟動ngrok服務。
啟動ngrokd服務
通過命令行啟動ngrokd服務很簡單,只需要配置幾個參數(shù)即可,httpAddr、httpsAddr分別是ngrok用來轉發(fā)http、https服務的端口,可以自由配置,domain就是你的外網域名。ngrokd 還會開一個4443 端口用來跟客戶端通訊,這個端口也可通過 -tunnelAddr=”:xxx” 指定。
./bin/ngrokd -tlsKey=server.key -tlsCrt=server.crt -domain="ngrok.shawnan.xyz" -httpAddr=":8088" -httpsAddr=":8443"
nginx映射
服務端啟動完畢之后,還要配置nginx代理。在服務器上面的nginx的配置文件里面增加如下一段:
server {
listen 80;
server_name ngrok.shawnan.xyz *.ngrok.shawnan.xyz;
location / {
proxy_pass http://127.0.0.1:8088;
proxy_redirect off;
proxy_set_header Host $http_host:8088;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Nginx-Proxy true;
proxy_set_header Connection "";
proxy_connect_timeout 90;
proxy_send_timeout 120;
proxy_read_timeout 120;
}
}
此處就把ngrok.shawnan.xyz和*.ngrok.shawnan.xyz上的請求都轉發(fā)到了8088上,實現(xiàn)客戶端可以通過xxx.ngrok.shawnan.xyz域名訪問。
啟動客戶端
http服務
linux在ngrok文件(windows在ngrok.exe)的同級目錄新建配置文件,ngrok.config,輸入以下內容(域名改成自己的):
server_addr: "ngrok.shawnan.xyz:4443"
trust_host_root_certs: false
然后利用以下命令啟動:
ngrok -config=ngrok.config -subdomain=local 8080
Tunnel Status online
Version 1.7/1.7
Forwarding http://local.ngrok.shawnan.xyz:8888 -> 127.0.0.1:8080
Forwarding https://local.ngrok.shawnan.xyz:8888 -> 127.0.0.1:8080
Web Interface 127.0.0.1:4040
# Conn 0
Avg Conn Time 0.00ms
啟動后如果正常連接,Tunnel Status會顯示online,這樣就把local.ngrok.shawnan.xyz映射到了你本地的8080端口。
如果連接不上會顯示connecting,超時之后還會顯示reconnecting。
tcp服務
除了http服務,ngrok還可以對tcp服務進行轉發(fā),這樣我們就可以通過轉發(fā)22端口利用SSH把局域網內的linux服務器共享到局域網外面去遠程連接了。
比如把本機的22端口轉發(fā)到外網,還是使用剛才的配置文件,使用如下命令:
ngrok -config=ngrok.config -proto=tcp 22
如果配置文件里面沒有配置端口,ngrok會隨機選擇一個端口進行tcp轉發(fā)。比如將本地的22端口轉發(fā)到了ngrok.shawnan.xyz的34538。
Tunnel Status online
Version 1.7/1.7
Forwarding tcp://ngrok.shawnan.xyz:34538 -> 127.0.0.1:22
Web Interface 127.0.0.1:4040
# Conn 0
Avg Conn Time 0.00ms
此時就可以使用域名和端口遠程連接局域網內的linux機器了。
ssh xxx@ngrok.shawnan.xyz -p 34358
完善配置文件
前面ngrok隨機選擇了一個端口對22端口進行轉發(fā),很不方便,每次還需要先看一下端口才能遠程ssh連接。此處如果想自定義tcp轉發(fā)的端口,則需要完善ngrok的配置文件,通過完善配置文件,可以大大簡化運行命令。配置文件前面兩行不變,仍舊是配置服務器地址和禁用TLS加密協(xié)議的證書信任。下面配置管道,可以同時配置多種管道,比如ssh、http、https等。
server_addr: ngrok.moonwalker.me:4443
trust_host_root_certs: false
tunnels:
ssh:
remote_port: 1122
proto:
tcp: 22
ftp:
remote_port: 20
proto:
tcp: 20
ftp2:
remote_port: 21
proto:
tcp: 21
http:
subdomain: www
proto:
http: 80
https: 443
配置完成后,可以直接啟動指定的管道或者啟動全部管道。
./ngrok -config ngrok.cfg start ssh
./ngrok -config ngrok.cfg start-all
配置成為服務并設置自啟動
服務端和客戶端都配置完了,但是我們不想每次都輸入這么長的命令,那么就可以借助systemctl來將我們的服務配置成為系統(tǒng)服務并設置自動啟動。此處以Centos7為例,CentOS7的服務systemctl腳本存放在:/usr/lib/systemd/system,在此文件夾下建立ngrok.service文件,內容如下:
[Unit]
Description=ngrok
After=network.target
[Service]
ExecStart=/usr/local/ngrok/bin/ngrokd -tlsKey=/usr/local/ngrok/server.key -tlsCrt=/usr/local/ngrok/server.crt -domain=ngrok.shawnan.xyz -httpAddr=:8088 -httpsAddr=:8443
[Install]
WantedBy=multi-user.target
[Unit]部分主要是對這個服務的說明,內容包括Description和After,Description用于描述服務,After用于描述服務類別。[Service]部分是服務具體運行參數(shù)的設置,此處ExecStart即為服務啟動的命令,[Install]部分是服務安裝的相關設置,可設置為多用戶的。
配置完畢后,使用如下命令分別啟動服務,停止服務,查看狀態(tài)。
systemctl start ngrok.service // 啟動
systemctl stop ngrok.service // 停止
systemctl status ngrok.service // 查看狀態(tài)
使用enable指令可以配置該服務為開機自啟動,這條命令實際上是創(chuàng)建了一個該文件的軟連接到/etc/systemd/system/multi-user.target.wants/ngrok.service。放在/etc/systemd/system下的service都是會開機自啟動的,但是比較規(guī)范的做法是放到/usr/lib/systemd/system,然后再使用systemctl enable設置開機啟動。
systemctl enable ngrok.service
至此,借助ngrok,家里的筆記本也可以作為服務器對外提供服務了。