LoginSignup
2

More than 3 years have passed since last update.

posted at

updated at

自分用ngrokを構築する(self hosted ngrok)

きっかけ

Raspberry piに構築した、Node-redとMQTTへ、外部からアクセスさせたい。
よくあるhttp/httpsだけではなくMQTTプロトコルが使用するTCPポート指定してのトンネリングが行えること。
証明書を使ったサーバー認証を行うため、固定IPで独自ドメイン取得前提。

自宅がマンションタイプの2重ルーターなのでそれを超えられること。

方針検討:

ngrok:有料:TCPポートの開放に対応しているサービス。
試しにsshをTCPトンネルさせてみると、下記の通り。

$ ngrok tcp 22
ngrok by @inconshreveable                                       (Ctrl+C to quit)

Tunnel Status                 online
Version                       2.0.19/2.0.19
Web Interface                 http://127.0.0.1:4040
Forwarding                    tcp://0.tcp.ngrok.io:36198 -> localhost:22

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

ドキュメントによると、無料のアカウントでは、

<ランダムな数字1桁>.tcp.ngrok.io:<ランダムなポート番号>

これでは証明書が保証できるURLとしては接続できない。
有料だと、
image.png

年間99ドルで"2 reserved TCP sddress"とあるが、これも、ポート番号が固定できるだけ。

serveo:無料:まったくアクセスできず使えなかった。

独自ドメインが必要なので自分でサーバーを構築できるものを探してみた。

Softether
VPSなどのパブリック固定IPのサーバーへvpnserverをインストール、それに向かってRaspberry pi側からvpnbridge、もしくはvpnclientで接続するのが基本構成だが、どうやってもうまくいかなかった。Raspberry pi側をマルチNIC(Ether+Wifi)にすればうまくいったかもしれない。

localtunnel
ドキュメントをざっと読んで、インストールしてみたが、httpsしか設定できないのでボツ。

ngrok
旧バージョン(1.7)のngrokがサーバー・クライアント両方ともソースが公開されている。
"DO NOT RUN THIS VERSION OF NGROK (1.X) IN PRODUCTION."と記載されており注意が必要だが、商用版の"ngrok.io"部分を独自ドメインにして使えそう。
これを試してみる。

サーバーの検討

固定IPを使えるVPSサービスを検討。スペックは最低レベル。
WEBARENA VPSクラウド
月額360円で1コア、SSD20GB、メモリ1GBと申し分なく愛用できるサービスだが、
2019年11月現在、残念ながら在庫なし。

Conoha VPS
月額630円で1コア、SSD20GB、メモリ512MB,やむなくこちらを選択する。

ドメインの取得

すでにアカウントを持っているバリュードメイン
年間99円の(初年度だけ)ドメインを購入し、下記1~5を参考にし設定。
VALUE-DOMAIN で取得したドメインをConohaで使ってみる

構成

サーバー:Conoha VPS CentOS7
クライアント:Raspberry pi Zero WH Raspbian buster

セットアップ

基本的にサーバー、クライアント側両方ともにGoのセットアップを行う。
下記を参考にGoのセットアップ。
Linux(CentOS, Ubuntu)にGo言語の開発環境を構築する
あまりGoが新しいとエラーになるので、Go1.7をインストールする。

下記を実行する。

git clone https://github.com/inconshreveable/ngrok.git
cd ngrok
#raspbianは下記
GOOS=linux GOARCH=arm make release-client
#CentOS7は下記
GOOS=linux GOARCH=amd64 make release-server

上記でngrok/bin/内にバイナリができる。

自己認証局、サーバー証明書の作成

OpenSSL ECDSAでの自己認証局作成を参考にルートCA,中間CAを作成。

証明書を作成:
サーバー証明書の秘密鍵とCSRを作成

openssl req -new -config openssl.cnf -newkey ec:<(openssl ecparam -name prime256v1) -keyout server.key -out server.csr

サーバー証明書を中間CAで署名

openssl ca -config openssl.cnf -extensions svr_cert -keyfile icacert.key -cert icacert.pem -in server.csr -out server.crt -days 3650

openssl.cnfの主な変更点

[ svr_cert ]
subjectAltName= @alt_names

[ alt_names ]
#SAN対策
DNS.1 = <取得したドメイン>
DNS.2 = *.<所得したドメイン>

証明書チェーンの作成

サーバー証明書として組み込むため、
サーバー証明書+中間CA証明書+自己認証局CA証明書をくっつける。

SSLCertificateChainFile Deprecation Warning on Apache 2.4.8+


./bundle.sh server.crt > server.chain
./bundle.sh icacert.pem >> server.chain
./bundle.sh cacert.pem >> server.chain

サーバー、クライアントへの自己認証局CA証明書の組み込み

下記を参考に信頼されたルート証明書として作成した自己認証局CA証明書を組み込む。
独自のルートCA証明書を追加する方法(Ubuntu, CentOS 7)

ngrokクライアントのCA証明書の入れ替え

クライアント側のngrokroot.crtを、自己認証局CA証明書に入れ替えて
再度GOOS= linux GOARCH=arm make release-clientを実施する。

サーバー、クライアントの実行。

サーバー側

bin/ngrokd -tlsKey=server.key -tlsCrt=server.chain -domain=<取得したドメイン>

クライアント側
設定ファイルを書いて実行する。

vi .ngrok


server_addr: <所得したドメイン>:4443
trust_host_root_certs: false
tunnels:
  mqtt:
    proto:
      tcp: 8883
    remote_port: 8883
  node-red:
    proto:
      https: 1880
    subdomain: nodered


#実行
bin/ngrok -config=.ngrok start-all

実行確認

クライアント側の状態

ngrok                                                           (Ctrl+C to quit)

Tunnel Status                 online
Version                       1.7/1.7
Forwarding                    https://nodered.<取得したドメイン> -> 127.0.0.1:1880
Forwarding                    tcp://<取得したドメイン>:8883 -> 127.0.0.1:8883
Web Interface                 127.0.0.1:4040
# Conn                        106
Avg Conn Time                 436138.60ms



HTTP Requests
-------------

GET /icons/node-red/rpi.svg   304 Not Modified
GET /icons/node-red/file.svg  304 Not Modified
GET /icons/node-red/file-in.s 304 Not Modified
GET /icons/node-red/watch.svg 304 Not Modified
GET /icons/node-red/parser-ya 304 Not Modified
GET /icons/node-red/file-out. 304 Not Modified
GET /icons/node-red/parser-xm 304 Not Modified
GET /icons/node-red/parser-js 304 Not Modified
GET /icons/node-red/parser-ht 304 Not Modified

問題なくTCP接続が確認できた。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
2