天天看點

ngrok服務實作内網穿透自建ngrok服務實作内網穿透實踐自建ngrok服務

自建ngrok服務實作内網穿透

名詞解釋

内網穿透,又叫NAT穿透,是計算機用語,翻譯過來就是你的電腦可以直接被你朋友通路。 通常我們的電腦是無法自己被通路的。因為我們的電腦缺少自己的獨立的ip位址。現在ip稀缺,電信營運商已經不會随便配置設定固定ip給個人。

通常實作内網穿透,是通過路由器上端口映射來實作的。但是路由器通常不是每個人都有權限可以通路和設定,而且可能存在多級路由器較為複雜的網絡結構。端口映射也無法實作。

這就需要ngrok來實作了。

原理

ngrok 建立一個隧道,将主機A的http請求 傳遞給 主機B,進而實作内網穿透。

ngrok分為client端(ngrok)和服務端(ngrokd),

ngrok服務實作内網穿透自建ngrok服務實作内網穿透實踐自建ngrok服務

實際使用中的部署如下:

ngrok服務實作内網穿透自建ngrok服務實作内網穿透實踐自建ngrok服務

圖中内網主機上安裝用戶端。

公網主機 安裝服務端。

client public 則代表 通路你電腦的使用者或者朋友。

實踐

現在都雲時代,各種服務都能找到提供商。内網穿透也是如此。ngrok服務端相當麻煩,如果你隻是簡單的穿透,又不是什麼敏感資訊,可以找到很多服務提供商。例如https://ngrok.com/

  • 下載下傳用戶端

    根據你的個人電腦系統下載下傳比對的用戶端。

    下載下傳位址: https://ngrok.com/download

  • 啟動
./ngrok http 4444

           
ngrok by @inconshreveable                                                                                                                                                                                                     (Ctrl+C to quit)

Session Status                online
Session Expires               7 hours, 59 minutes
Version                       2.2.8
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://ada02116.ngrok.io -> localhost:4444
Forwarding                    https://ada02116.ngrok.io -> localhost:4444

Connections                   ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00

           

如果此時通路 

http://ada02116.ngrok.io

 則等于通路了 

localhost:4444

自建ngrok服務

使用别人的服務,存在一些限制。例如不穩定、安全問題,費用昂貴等。是以可能需要自己搭建ngrok服務端。

自建服務需要具備的條件:

1、具備獨立ip的伺服器。例如阿裡雲、騰訊雲等。 我個人使用的阿裡雲ecs

2、需要域名。如果是國内則需要備案。我個人的域名是 xxxx.com

  • 配置域名

    增加2條A記錄,指向你的伺服器。這裡我配置的是 ngrok.xxxx.com 和 *.ngrok.xxxx.com

    ngrok服務實作内網穿透自建ngrok服務實作内網穿透實踐自建ngrok服務
    添加安全組。
  • 開放3個端口。這裡我選擇4443、4444、8081端口。

    其中4443是ngrok自身通信使用。

    4444 後面tcp端口轉發使用。

    8081 則是http請求轉發使用。預設是80 但是這裡80端口我配置設定給nginx了。

    截圖中少截圖了4444的配置。

    ngrok服務實作内網穿透自建ngrok服務實作内網穿透實踐自建ngrok服務
    編譯服務端。這裡采用docker鏡像來實作。
  • 登入伺服器,建立檔案夾 ngrok-server ,包含2個檔案

    檔案Dockerfile 内容如下

FROM golang:1.7.1-alpine
ADD build.sh /
RUN apk add --no-cache git make openssl
RUN git clone https://github.com/inconshreveable/ngrok.git --depth=1 /ngrok
RUN sed -i "109,109s/tcp/tcp4/g" /ngrok/src/ngrok/server/tunnel.go
RUN sed -i  "57,57s/tcp/tcp4/g" /ngrok/src/ngrok/conn/conn.go
RUN sh /build.sh
EXPOSE 8081
VOLUME [ "/ngrok" ]
CMD [ "/ngrok/bin/ngrokd"]
           

檔案build.sh内容如下

export NGROK_DOMAIN="ngrok.xxxx.com"
cd /ngrok/
openssl genrsa -out rootCA.key 2048
openssl 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
cp rootCA.pem assets/client/tls/ngrokroot.crt
cp device.crt assets/server/tls/snakeoil.crt
cp device.key assets/server/tls/snakeoil.key

make release-server
GOOS=linux GOARCH=386 make release-client
GOOS=linux GOARCH=amd64 make release-client
GOOS=windows GOARCH=386 make release-client
GOOS=windows GOARCH=amd64 make release-client
GOOS=darwin GOARCH=386 make release-client
GOOS=darwin GOARCH=amd64 make release-client
GOOS=linux GOARCH=arm make release-client
           

需要修改的地方是

export NGROK_DOMAIN="ngrok.xxxx.com"

修改為你自己的域名。

  • 建構鏡像。

    運作

docker build -t ngrok .
           

注意 最後一個 

.

 别少了。

  • 啟動容器

    運作

docker run -it  -p 8081:8081 -p 4443:4443 -p 4444:4444  -d ngrok /ngrok/bin/ngrokd -domain="ngrok.xxxx.com" -httpAddr=":8081"
           

注意修改這裡的ngrok.xxxx.com為你自己的域名。

到這裡ngrok服務端已經完成。

  • 下載下傳用戶端。

    進入上面啟動的容器,下載下傳對應的用戶端。

    例如容器id 

    c71b99a242fa

    運作 docker inspect c71 可以檢視這個容器的具體資訊。
    ngrok服務實作内網穿透自建ngrok服務實作内網穿透實踐自建ngrok服務
    進入圖中劃線的目錄下,再進入Bin下。
ngrok服務實作内網穿透自建ngrok服務實作内網穿透實踐自建ngrok服務

這裡就是用戶端。對應的不同系統的版本。

我個人電腦是mac,64位系統 ,需要選擇 darwin_amd64檔案夾下載下傳。

386代表是 32系統。amd64表示 64位。

linux和window無需多言。

下載下傳指令可以通過很多方式。例如ftp或者scp指令。

我選擇的是scp指令。

scp -P 你的服務端端口 -r  root@你的服務端ip位址:/var/lib/docker/volumes/6e5383924c5caf1b1b61250f31aa002308dcb371ebd9a7efad2419e20107a362/_data/bin/darwin_amd64/ngrok  ./ngrok
           

這裡要注意下權限,如果你不是用root,可能沒法子拷貝。

  • 配置用戶端

    建立配置檔案 config.yml,其中内容如下

server_addr: "ngrok.xxxx.com:4443"
trust_host_root_certs: false
tunnels:
  webapp:
   proto:
     http: 8081
   subdomain: test
  tcp12345:
    remote_port: 4444
    proto:
      tcp: 12345
           

注意修改ngrok.xxxx.com為自己的域名。

這裡配置了2個隧道。一個http的請求,一個tcp轉發。

  • 啟動用戶端
./ngrok  -config=config.yml start-all
           
ngrok服務實作内網穿透自建ngrok服務實作内網穿透實踐自建ngrok服務

在浏覽器通路 上圖中位址即可看到本地内容。

ngrok服務實作内網穿透自建ngrok服務實作内網穿透實踐自建ngrok服務

增加tcp的轉發截圖。

ngrok服務實作内網穿透自建ngrok服務實作内網穿透實踐自建ngrok服務

測試下12345端口的功能。

  • 監聽12345端口。

    執行

nc -l 12345
           
  • 在其他電腦或者本地執行
nc ngrok.xxxx.com 4444
           

這樣就可以了。輸入和輸出都會顯示。

如圖

ngrok服務實作内網穿透自建ngrok服務實作内網穿透實踐自建ngrok服務

最後

docker真得降低了很多問題的難度。

補充

微信公衆号和小程式的開發中,需要http和https。 這裡的請求都攜帶了端口,不符合要求。

由于我的伺服器 80和443都配置設定給了nginx容器,是以這裡無法測試。

下面是本人沒測試的方案,主要是替換證書。

  • 啟動容器的時候指定證書路徑,映射80和443端口
docker run -it  -p 80:80 -p 443:443 -p 4443:4443   -d ngrok /ngrok/bin/ngrokd -domain="ngrok.xxxx.com" -tlsKey="/ngrok/assets/server/tls/snakeoil.key" -tlsCrt="/ngrok/assets/server/tls/snakeoil.crt"
           

這裡使用是自建證書,是不被浏覽器認可的。建議去申請免費證書。

然後将證書 挂載到鏡像,再啟動服務端。

已知的問題

因為ngrok會預設監聽IPv6端口,考慮到國内的網絡環境,我們需要修改一下代碼,否則将無法使用。主要修改兩個地方,一個是src/ngrok/server/tunnel.go的109行net.ListenTCP後面的"tcp"改成"tcp4",另一處是src/ngrok/conn/conn.go的57行的net.Listen後的"tcp"同樣改成"tcp4"。

繼續閱讀