ngrokのドメイン名を固定した時の「Bad Request」エラーを回避する


普通にngrokを起動すると、http://28f1ac85.ngrok.ioのように、ngrok.ioの前に毎回違った文字列が割り当てられます。それだと少し使いづらいので、下記の記事を参考にngrokのプランをBasic以上に上げて、ドメイン名を固定しました。

ngrokで常に同じアドレスを使う方法 - Qiita
とても分かりやすかったです


ところが、ドメインを固定した時のみ何故か「Bad Request」エラーが出てるようになりました。
もちろん、ローカルのWebサーバーは起動しています。

結局、原因は単純だったのですが、かなりハマってしまいました。
(同じ症状の人がいないので、もしかしたらMacだけかも?)

症状

サブドメインを登録後、サイトの指示に従い、ターミナルから ngrok を起動します。

./ngrok http -subdomain=testtest 8080

正常に動いているっぽい。

ngrok by @inconshreveable                                                                                    

Session Status               online
Account                      fukusin (Plan: Pro)
Version                       2.3.35
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwardinghttp://testtest.ngrok.io -> http://localhost:8080
Forwarding                    https://testtest.ngrok.io -> http://localhost:8080

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

ところが、ローカルのWebサーバーを起動し、ブラウザでhttp://testtest.ngrok.ioにアクセスすると、ターミナルにエラーが出ます。

HTTP Requests
-------------
GET  /favicon.ico              400 Bad Request
GET  /                         400 Bad Request

もちろん、ローカルのWebサーバーにもリクエストが届いていません。

原因

80番ポートで接続して、エラーの詳細を確認します。

Failed to complete tunnel connection
The connection to http://testtest.ngrok.io was successfully tunneled to your ngrok client, but the client failed to establish a connection to the local address localhost:80.

Make sure that a web service is running on localhost:80 and that it is a valid address.

The error encountered was: dial tcp [::1]:80: connect: connection refused

Failed to complete tunnel connection ???

正常にポート指定ができていないようで、http://testtest.ngrok.io -> http://localhost:80間のトンネルコネクションに失敗していました。

ngrok の仕様なのか Mac環境の問題なのかは不明ですが、対策をしていきます。

対策

ドメインと localhost どちらも同じポートを指定して起動すると良さそうです。

ドメインの場合 ./ngrok http -subdomain=testtest 8080
localhost の場合 ./ngrok http -host-header=localhost 8080

ところが、この2つのコマンドは同時に使えません。

そこで、先ほどの記事を参考にngrok.ymlを使って起動します。
ngrok.ymlを使うとオプションをまとめられるので、毎回の起動が楽になります。

ngrok.yml
authtoken: <トークン文字列>
region: us
tunnels:
  process1:
    proto: http
    addr: 8080
    host_header: localhost 8080
    subdomain: testtest

Macの場合、[ユーザー]/.ngrok2/ngrok.ymlに保存されています。
localhostのポートも指定したいので、記事のコードに host_header: localhost 8080を追加しています。

保存して、ターミナルから起動します。

./ngrok start process1
ngrok by @inconshreveable

Session Status                online
Account                       fukusin (Plan: Pro)
Version                       2.3.35
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://testtest.ngrok.io -> http://localhost:8080
Forwarding                    https://testtest.ngrok.io -> http://localhost:8080

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

起動画面はエラーが出た時と同じ内容ですが、ブラウザでhttp://testtest.ngrok.ioにアクセスすると、今回は正常にWebサーバーに繋がります。

HTTP Requests
-------------
POST /                         200 OK

無事、Webサーバーでもリクエストが受け取れました。


最終的に起動コマンドを ./ngrok start process1に変えるだけで、「Bad Request」エラーを回避できるようになりました。
参考になれば。