ngrok 應用在.net core 實作
===
###### tags: `課程教案`
## ngrok online
## 說明
### 自建ngrok服務支援https訪問
:::info
前言
:::
最近從事第三方平臺代小程式實現業務開發,很多業務互動請求需要https,本地除錯開發實現不了,不可能把部署到生產伺服器除錯,那又很不方便。我參考網上很多教程,很多不完整,不繫統。我於是整理出完整教程當備用。
:::info
專業術語
:::
內網穿透,又叫NAT穿透,是計算機用語,翻譯過來就是 你的電腦可以直接被你朋友訪問。 通常我們的電腦是無法自己被訪問的。因為我們的電腦缺少自己的獨立的ip地址。現在ip稀缺,電信運營商已經不會隨便分配固定ip給個人。
通常實現內網穿透,是通過路由器上埠對映來實現的。但是路由器通常不是每個人都有許可權可以訪問和設定,而且可能存在多級路由器較為複雜的網路結構。埠對映也無法實現。這就需要ngrok來實現了。
:::info
原理
:::
ngrok 建立一個隧道,將主機A的http請求 傳遞給 主機B,從而實現內網穿透。
ngrok分為client端(ngrok)和服務端(ngrokd),

實際使用中的部署如下:

圖中內網主機上安裝客戶端。
公網主機 安裝服務端。
client public 則代表 訪問你電腦的使用者或者朋友。
現在都雲時代,各種服務都能找到提供商。內網穿透也是如此。ngrok服務端相當麻煩,如果你只是簡單的穿透,又不是什麼敏感資訊,可以找到很多 服務提供商。例如 https://ngrok.com/
下載客戶端根據你的個人電腦系統下載匹配的客戶端。下載地址: https://ngrok.com/download

:::info
啟動
:::
> 如果 http://localhosts:4040 -> 代理成 https://xx.xxx.ngrok.com/
```
ngrok http 4040
```
> 如果 https://xx.xxx.ngrok.com/ -> https://xx.maxaiot.ngrok.com/ 要付錢 20US/Month = 20*30*12 = 7200元/年
### Linux Client 版安裝程式
```
cd ~/
wget https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-linux-amd64.tgz
tar -C /usr/lib -xzf ngrok-v3-stable-linux-amd64.tgz
/usr/lib/ngrok config add-authtoken 2Dylrflb3y4PQxlIYNOiWodujZf_ua5E63cRYsTaXMDtJU1r
```
## Ngrok Server 建置
:::warning
以下失敗文件參考就好
:::
實ngrok 可以自己架說, 但我架了半天, 失敗。
github 說的了, github 上面是ngrok 1.x 不在維護有很多bug , 難怪建不起來,唉..跟openalpr opensource 一樣狀況。
:::info
說明
:::
從外部要訪問內網部署的服務。大概步驟也比較簡單(6步):
1. LXC(TWS,GCP...提供Public IP 並可以設定services port的雲端簡稱) 。
2. dns server 將domain 指到此LXC(Public IP);
3. LXC ngrok原始碼(ngrokd 服務)
4. 生成證書;
5. 編譯生成主機服務(最終生成二進位制檔案ngrokd,啟動跑在LXC主機上);
6. 編譯生成客戶端服務(最終生成二進位制檔案ngrok,要從LXC主機複製到內網真正提供服務的主機上,並啟動)。ngrok伺服器,實現內網穿透的本質,就是部署在公網端的ngrokd服務和部署在客戶端的ngrok服務相互通訊轉發指令和資料。 我的公網伺服器端和客戶端都是Ubuntu系統,以下有公網IP域名的稱為服務端,內網稱為客戶端。
### 安裝 ngrok V2
apt install gccgo-go
wget https://storage.googleapis.com/golang/go1.8.linux-amd64.tar.gz
tar -C /usr/lib -zxvf go1.8.linux-amd64.tar.gz
rm go1.8.linux-amd64.tar.gz
sudo vi /etc/profile
sudo echo export GOROOT=/usr/lib/go >> /etc/profile
sudo echo export GOPATH=$GOROOT/bin >> /etc/profile
sudo echo export PATH=$PATH:$GOPATH >> /etc/profile
source /etc/profile
sudo apt install snapd -y
sudo snap install ngrok
wget htps://coding.net/u/sfantree/p/self_use_OSS/git/raw/master/source/ngrok.tar.gz
tar -C /usr/lib -zxvf ngrok.tar.gz
cd ngrok
### 參數說明
* **GOROOT** GoLang 程式的路徑
* **GOPATH** GoLang 應用程式的路徑
### 安裝 ngrok V1 沒成功
```
echo ---------------------------------安裝環境應用程式
cd ~/
sudo apt-get update && sudo apt-get upgrade -y
sudo apt-get install openssh-server ssh openssl git curl mercurial make binutils bison gcc build-essential -y
echo ---------------------------------安裝 golang
sudo add-apt-repository ppa:longsleep/golang-backports
sudo apt update -y
sudo apt install golang-go -y
wget -c https://go.dev/dl/go1.19.linux-amd64.tar.gz
rm -rf /usr/lib/go
tar -C /usr/lib -xzf go1.19.linux-amd64.tar.gz
rm go1.19.linux-amd64.tar.gz
echo export GOROOT=/usr/lib/go >>~/.bashrc
echo export GOPATH=/usr/lib/go/bin >>~/.bashrc
echo export PATH=$GOPATH:$PATH >>~/.bashrc
echo 記得將ngrok.maxaiot.com 改成計劃要用的domain哦
echo export NGROK_DOMAIN="ngrok.maxaiot.com" >>~/.bashrc
source ~/.bashrc
cd /usr/lib/go/src
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 ./make.bash
cp /usr/lib/go/bin/go /usr/bin
sudo sed -i "s/RANDFILE/#RANDFILE/g" /etc/ssl/openssl.cnf
```
要重開ssl 目前只有重開機才行, 沒找到法
```
echo --------------------------------安裝ngrok
cd /usr/lib
git clone https://github.com/inconshreveable/ngrok.git
cd ngrok
echo --------------------------------生成證書:
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 server.key 2048
openssl req -new -key server.key -subj "/CN=$NGROK_DOMAIN" -out server.csr
openssl x509 -req -in server.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out server.crt -days 5000
cp rootCA.pem assets/client/tls/ngrokroot.crt
cp server.crt assets/server/tls/snakeoil.crt
cp server.key assets/server/tls/snakeoil.key
GOOS=linux GOARCH=amd64 make release-server release-client
```
### 移除golang
### Error1
```
GOOS="" GOARCH="" go get github.com/jteeuwen/go-bindata/go-bindata
../go1.4/src/sync/pool.go:8:2: C source files not allowed when not using cgo or SWIG: atomic_amd64x.c defs.c float.c heapdump.c lfstack.c malloc.c mcache.c mcentral.c mem_linux.c mfixalloc.c mgc0.c mheap.c msize.c os_linux.c panic.c parfor.c proc.c runtime.c signal.c signal_amd64x.c signal_unix.c stack.c string.c sys_x86.c vdso_linux_amd64.c
Makefile:22: recipe for target 'bin/go-bindata' failed
make: *** [bin/go-bindata] Error 1
```
#### 問題1:server.pem 沒有完成
go-bindata被安装到了$GOBIN下了,go编译器找不到了。修正方法是将$GOBIN/go-bindata拷贝到当前ngrok/bin下。
cp /home/ubuntu/.bin/go14/bin/go-bindata ./bin
cp /usr/lib/ngrok/src/github.com/jteeuwen/go-bindata /usr/lib/ngrok/bin
### go build 環境變數怎麼設定
在執行 go build . 的時候,會讀取讀 GO 的環境變數 GOOS 和 GOARCH 來決定要產生什麼樣平台的執行檔案。 如下圖所示,我執行 go env 來查看環境變數, 可以看到 GOARCH=amd64,GOOS=windows,這表示我執行 go build . 的時候會產生 windows 64位元 作業系統的執行檔案。
>go env

### Error2 : golang有問題
>go env 不會出現資訊
```
GOOS="" GOARCH="" go get github.com/jteeuwen/go-bindata/go-bindata
/bin/sh: 1: go: not found
Makefile:22: recipe for target 'bin/go-bindata' failed
make: *** [bin/go-bindata] Error 127
```
### Error3 : 使用 1.11.4 版本的 golang 然後就可以了
>如果编译报以下错,安装最新的go和配置GOPATH
```
package github.com/rivo/uniseg: found packages uniseg (doc.go) and main (gen_breaktest.go) in /usr/lib/ngrok/src/github.com/rivo/uniseg
github.com/gorilla/websocket (download)
Makefile:8: recipe for target 'deps' failed
make: *** [deps] Error 1
```
## 接下來就可以編譯了:
GOOS=Windows GOARCH=amd64 make release-server release-client
編譯完成之後這只是linux的版本,如果要在windows下使用,需要交叉編譯:
> cd /root/.gvm/gos/go1.4/src
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 ./make.bash
> 編譯windows版本的ngrok
> cd ~/ngrok
GOOS=windows GOARCH=amd64 make release-server release-client
cd /usr/local/
git clone https://github.com/inconshreveable/ngrok.git
export GOPATH=/usr/local/ngrok/
export NGROK_DOMAIN="ngrok.maxaiot.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 server.key 2048
openssl req -new -key server.key -subj "/CN=$NGROK_DOMAIN" -out server.csr
openssl x509 -req -in server.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out server.crt -days 5000
cp rootCA.pem assets/client/tls/ngrokroot.crt
cp server.crt assets/server/tls/snakeoil.crt
cp server.key assets/server/tls/snakeoil.key
vi /usr/local/ngrok/src/ngrok/log/logger.go
curl -s -S -L https://gist.github.com/bradw2k/e776d26df44f59adfe44#file-install-go1-4-amd64-sh > install-go1-4-amd64.sh
## 更改ngrok 域名
```
export GOPATH=/usr/local/ngrok
export NGROK_DOMAIN="ngrok.maxaito.com"
```
## 域名生成証書
```
openssl genrsa -out rootCA.key 2048
openssl req x-x509 -new -key rootCA.key -subj "/CN=#NGROK_DOMAIN"
openssl grenrsa -out server.kye 2048
opoenssl req -new -key server.key -sub "/CN=$NGROK_DOMAIN" -out server.csr
openssl x509 -req in server.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out server.crt -days 5000
```
## 複制cert到指定位置
```
cp rootCA.pem assets/client/tls/ngrokroot.crt
cp server.crt assets/server/tls/snakeoil.crt
cp server.key assets/server/tls/snkeoil.key
```
## 編譯
```
make release-server release client
GOOS=windows GOARCH=amd64 make release-client
```
## 運用行Server
```
./ngrokd -tlskey="../assets/server/tls/snakeoil.key" -tlsCrt="assets/server/tls/snakeoil.key" -tlsCrt="../assets/server/tls/sankeoil.crt" -domain="ngrok.maxaiot.com"
```
## 運行用戶端
```
server_addr: "ngrok.maxaiot.com"
trust_host_root_certs:false
ngrok -subdoman ngrok.maxaiot.com -config=ngrok.cfg port
```
## golang 手動安裝 1.7.4 比較舊的版本
```
wget -c https://storage.googleapis.com/golang/go1.7.4.linux-amd64.tar.gz
tar -C /usr/local -zxvf go1.7.4.linux-amd64.tar.gz
```
### golang 1.4
```
wget -c https://go.dev/dl/go1.4.linux-amd64.tar.gz && tar -C /usr/lib -zxvf go1.4.linux-amd64.tar.gz && rm go1.4.linux-amd64.tar.gz
cd /usr/lib
mv go go1.4
echo export GOROOT=/usr/lib/go1.4 >>~/.bashrc
echo export GOPATH=$HOME/go >>~/.bashrc
echo export PATH=$GOPATH/bin:$GOROOT/bin:$PATH >>~/.bashrc
source ~/.bashrc
cd /usr/lib/go1.4/src
```
### golang 1.10.2 安裝
```
sudo add-apt-repository ppa:longsleep/golang-backports
sudo apt update -y
sudo apt install golang-go -y
```