ngrokの代替 – FRPでセルフホストトンネリングを実現

最終更新日

ngrokと言えばhttp/httpsやTCP通信のフォワーディングが出来るサービスとして有名だが、不便だと感じたことはないだろうか。

私もこのngrokをMinecraftのサーバー用でTCP 25565の公開用で使うことがあるが、毎回公開ポートが変わったり、アドレスが変わったりで最近不便に感じている。

そこで、ngrokを自作できないか色々調べてみた。

Self-hosted ngrokを使う方法

まず初めに、Self-hosted ngrokと出会った。その名の通り自分でngrokをホストするというものだった。

それだけを聞くとSelf-hosted ngrokは最強に見えなくもないが、これはngrokの古いバージョンが使われているようで、下記の通りに公式からも実質的な非推奨を述べられていた。

この時点で、ngrokを流用する方法は途絶えてしまった

SSH -Rを使う方法

この方法は非常に有名だが、TCPプロトコルしか使用することが出来ないためあっさり却下。

FRPとの出会い

次に、FRP(Fast reverse proxy)に出会った。どうやらこれはNATやファイヤーウォールの背後にあるローカルサーバーをインターネット上に公開することが出来る高速なリバースプロキシらしい。

また、FRPはTCP, UDP, HTTP, HTTPS, TCPMUX, STCP, SUDPのプロトコルに対応しており、めちゃめちゃ幅広いことが分かった。

というわけで、これを使ってみることにした。

ホスト方法

身構えていたのだが、FRPは驚くことに超簡単だった。

まず初めに、公式GitHubのReleasesから自分の使っているOSに適したファイルをDLする。

私の場合はサーバー側にUbuntu、クライアント側にWindowsを使用していたので、frp_バージョン_linux_amd64.tar.gzfrp_バージョン_windows_amd64.zipをDLする。

まずはサーバー側から構築していく。DLから解凍までは以下のコマンドでできる。尚、このガイドではバージョン0.61.0を対象とする。

wget https://github.com/fatedier/frp/releases/download/v0.61.0/frp_0.61.0_linux_amd64.tar.gz
tar -zxvf frp_0.61.0_linux_amd64.tar.gz

次に、Ubuntu起動時にFRPSを自動起動するためのサービスを作る。(任意)

nano /etc/systemd/system/frps.service

[Unit]
Description=frps daemon
After=network.target
[Service]
Type=simple
ExecStart=/home/nomin/frp/frps -c /home/nomin/frp/frps.ini #この行は解凍したfrpsのパスを指定する。
Restart=always
RestartSec=20s
User=nobody
LimitNOFILE=infinity
[Install]
WantedBy=multi-user.target

FRPを解凍したパスに戻り、FRPSを下記のように設定する。

[common]
bind_port = 7000
token = #接続側と共有するトークン(パスワード)
dashboard_port = #ダッシュボードのポート番号(デフォルト7500)
dashboard_user = #Webダッシュポートのユーザー名
dashboard_pwd = #Webダッシュボードのパスワード
dashboard_addr = 0.0.0.0
allow_ports = #使用するポート番号 25565,19133,80など

注意点として、Minecraft統合版サーバーで使用するUDP 19132使用できなかった

Redditによるとこれは前からある問題のようで、おそらくFRPがデフォルトで特定のポートを使用していることが原因と見られる。

ufwなどでファイヤーウォールを設定している場合は、allowする必要がある。

sudo ufw allow 7000/tcp
sudo ufw allow 使用する全てのポート

これだけで導入は完了。サービスをEnableするだけで使用出来る。

sudo systemctl enable frps
sudo systemctl start frps

サーバー側の導入が完了したら、次にクライアント側の設定を行っていく。

今回はクライアント側としてWindowsを使用する。その為Windowsでのやり方となるが、基本的にどのOSでもやることは変わらない。

まずは先程DLしたWindows用のファイルを解凍する。

解凍後のディレクトリにあるfrpc.tomlファイルを開き、下記のように編集する。

transport.protocol = "tcp"
serverAddr = "サーバーのグローバルIP"
serverPort = 7000
auth.token = "サーバー側で設定したトークン(パスワード)"


#プロキシ設定↓
#以下の設定はMinecraftでの例。
[[proxies]]
name = "minecraft-tcp"
type = "tcp"
localIP = "127.0.0.1"
localPort = 25565
remotePort = 25565

[[proxies]]
name = "minecraft-udp"
type = "udp"
localIP = "127.0.0.1"
localPort = 19133
remotePort = 19133

これだけで接続する準備が完了する。

実際に接続するには、下記のようにクライアント側から先ほど設定したfrpc.tomlを指定してfrpc.exeを起動する。

frpc.exe -c frpc.toml

それっぽいログが出てきたら成功だ。

ダッシュボード

ダッシュボードを参照することで、より簡単に接続テストができる。

先ほど設定したサーバー側のダッシュボードにアクセスしてみる。

URLはhttp://サーバーIP:設定したポートとなる。

アクセスすると、ログイン画面が表示される。

これも先ほど設定したsrps.iniの情報を使用してログインする。

ログイン後、左のメニューからProxyを選択し、任意のプロトコルを選択することで、以下のようにプロキシのオンラインステータスを確認できる。

あとがき

今回は、ngrokの代替として注目されているFRPについて詳しく解説した。多くの開発者が「マンションのインターネット回線でポート開放ができない」「ISPがポート開放を制限している」といった課題に直面していると思う。

そんな中で、FRPは最高な選択肢となっている。サーバー側とクライアント側の設定が比較的シンプルなうえ、TCP、UDP、HTTP、HTTPSなど複数のプロトコルに対応しているのが特徴だ。また、独自のダッシュボードで接続状態を簡単に監視できる点も便利に感じる。

確かに、レイテンシーの面では直接的なポート開放に比べて若干の遅延が発生する可能性はあるが、多くの場合では実用上問題のないレベルだと考えている。

このガイドが、皆さんの一助となれば嬉しい。

Nomin(Sena)。日韓ハーフの高校生で、日本の学校に通いながら技術を磨いている。 アイデアの発想と同時にそれを実現することができるフルスタックエンジニアを目指している。 最近はFlutterを勉強している。得意分野は通信構造解析や実行効率化。

シェアする