無料で制限のないngrok的サービスを求めて
とあるハッカソンにてlocalhostで建てたサービスを外部に公開したいなぁという時があり、様々なサービスを試したのでメモ
ngrokの問題点
ngrokはコマンド一つでPublicなURLを得ることができるため、非常に便利ですが、今回使うにあたって以下のような問題にあたりました
要約すると「過去1分間のコネクション数が多すぎるから20コネクション/分にしてね」というエラーなのですが、個人的には割とシビアな制限*1だな〜と思いました
ngrokのpricingを見ると
FREEプランは40コネクション/分となっているので、ngrok全体への制限なのかなとも思ったりしましたが、最上位のプラン(Businessプラン)にしても制限はかかるっぽいので別のサービスを探すことにしました
localtunnel
localtunnel もngrokと同じ類のサービスですが、2年ほど前のIssueをみると
「セキュリティ的な迷惑行為が起きても、サーバーが落ちても、無制限」みたいなことを言っているためngrokの完全上位互換じゃん!とか思ったりしました
localtunnelの問題点
localtunnelはWebhookのテストを目的としているため、クソデカファイル(自分が試したときは60MBぐらい)を投げるとHTTP 413(Payload Too Large)
を吐かれます
確かにテスト目的では良さそうなのですが、今回は画像を送り付けて何かするみたいなサービスを作っていたので、他のサービスを探すことにしました
最適解:frp
ここまでサービスの類を検討してきて、大体の場合に制限がかかっていたので自分でホスティングする方向で探しはじめました
frp は fast reverse proxyの略らしく、githubのstarの数が現時点で46.5k付いている人気なプロキシです
Readmeも丁寧かつ導入も楽そうなので、今回のハッカソンではこれを用いました
導入
frpの実行ファイルには2種類あり、Public IPが付与されるサーバー用のfrps
とクライアント用のfrpc
です
githubのReleaseに各種実行ファイルがあり、これに設定ファイル(frps.ini
/ frpc.ini
)をつけて実行します
親切なことにsystemd
で動かせるような*.service
ファイルも付属しており、これを/etc/systemd/system
とかにコピーするとsystemd
で動かせるようになります
機能
frps.ini
ではクライアントとのSSHするポートのほかに、vhost_http_port
としてPublicに公開したいポートも選ぶことができる*.ini
のgroup
をいじることでロードバランサーにもなる
やったこと
今回のハッカソンでは、Public IPが付与されるAzure上のVMの無料枠(B1s)をfrp server、本番環境をfrp clientとしてセルフホストなngrok的なやつを構築しました
また、本番環境だけでなくメンバー宅PCもfrp clientに指定して、もし本番環境が落ちたらメンバー宅PCに切り替えるみたいなこともできるようにしました
以下に使用した*.ini
を示します
frps.ini
[common] token = XXXXXX bind_port = 8080 vhost_http_port = 80 vhost_https_port = 443
frpc.ini
[common] token = XXXXXX server_addr = XX.XX.XX server_port = 8080 [web1] type = http local_ip = 127.0.0.1 local_port = 5000 custom_domains = www.example.com group = XXX group_key = XXXXX
token
を指定しないとタダ乗りされる恐れがあるので、推測されにくいやつを指定するcustom_domains
で指定したドメインのAレコード(or CNAME)をserver_addr
で指定したやつを指し示すようにする- ロードバランサーの設定である
group
とgroup_key
はクライアント間で共通にする
今回は導入における手間を最小限にしたかったのでtype=http
にしました
vhost_http_port
に80番を指定すると(自分の環境では) Permission denied
で弾かれたのですが、sudo
をつけると実行できました
よって、systemd
で動かす際にはfrps.service
を
[Unit] Description=Frp Server Service After=network.target [Service] Type=simple User=root Restart=on-failure RestartSec=5s ExecStart=/usr/bin/frps -c /etc/frp/frps.ini [Install] WantedBy=multi-user.target
のようにUser=nobody
からUser=root
に書き換えました
まとめ
frp自体はHTTPS等他のプロトコルにも対応しているようなので、ハッカソン以外にも自分専用のngrok的サービスとして使うのも良さげだなと思いました
特に学生はAzure for StudentでB1s枠が実質無料で使えるため、おすすめです
*1:まぁ課金しろという話だとは思いますが