yukuro’s blog

ぽえむ日記

無料で制限のないngrok的サービスを求めて

とあるハッカソンにてlocalhostで建てたサービスを外部に公開したいなぁという時があり、様々なサービスを試したのでメモ

ngrokの問題点

ngrokはコマンド一つでPublicなURLを得ることができるため、非常に便利ですが、今回使うにあたって以下のような問題にあたりました

stackoverflow.com

要約すると「過去1分間のコネクション数が多すぎるから20コネクション/分にしてね」というエラーなのですが、個人的には割とシビアな制限*1だな〜と思いました

ngrokのpricingを見ると

ngrok.com

FREEプランは40コネクション/分となっているので、ngrok全体への制限なのかなとも思ったりしましたが、最上位のプラン(Businessプラン)にしても制限はかかるっぽいので別のサービスを探すことにしました

localtunnel

localtunnel もngrokと同じ類のサービスですが、2年ほど前のIssueをみると

github.com

「セキュリティ的な迷惑行為が起きても、サーバーが落ちても、無制限」みたいなことを言っているためngrokの完全上位互換じゃん!とか思ったりしました

localtunnelの問題点

localtunnelはWebhookのテストを目的としているため、クソデカファイル(自分が試したときは60MBぐらい)を投げるとHTTP 413(Payload Too Large)を吐かれます

github.com

確かにテスト目的では良さそうなのですが、今回は画像を送り付けて何かするみたいなサービスを作っていたので、他のサービスを探すことにしました

最適解:frp

ここまでサービスの類を検討してきて、大体の場合に制限がかかっていたので自分でホスティングする方向で探しはじめました

frp は fast reverse proxyの略らしく、githubのstarの数が現時点で46.5k付いている人気なプロキシです

github.com

Readmeも丁寧かつ導入も楽そうなので、今回のハッカソンではこれを用いました

導入

frpの実行ファイルには2種類あり、Public IPが付与されるサーバー用のfrpsとクライアント用のfrpcです

githubReleaseに各種実行ファイルがあり、これに設定ファイル(frps.ini / frpc.ini)をつけて実行します

親切なことにsystemdで動かせるような*.serviceファイルも付属しており、これを/etc/systemd/systemとかにコピーするとsystemdで動かせるようになります

機能

  • frps.iniではクライアントとのSSHするポートのほかに、vhost_http_portとしてPublicに公開したいポートも選ぶことができる
  • *.inigroupをいじることでロードバランサーにもなる

やったこと

今回のハッカソンでは、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で指定したやつを指し示すようにする
  • ロードバランサーの設定であるgroupgroup_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:まぁ課金しろという話だとは思いますが