Holesailを試してみた – サーバーレスでP2Pトンネリングを構築する

社内のローカル環境で動かしているWebアプリを、外部のメンバーに少しだけ見せたい。そんな場面で最近Holesailという面白いツールを見つけました。中央サーバーを介さない完全P2P型のトンネリングツールで、しかもオープンソースかつ無料です。今回は実際にインストールから動作確認まで一通り触ってみたので、その記録を残しておきます。

Holesailとは

公式の説明では「The future of peer-to-peer networking」とされていますが、要するにTCP/UDPの両方に対応したP2P型のトンネリング兼リバースプロキシです。一般的なトンネリングサービスとの最大の違いは、データが中継サーバーを一切経由しないという点にあります。

特徴を整理するとこうなります。

  • 中央サーバーを使わない完全P2P接続
  • libsodiumによるエンドツーエンド暗号化
  • アカウント登録もログインも不要
  • ポートフォワーディングや動的DNSの設定が不要
  • 接続確立まで1秒以下、レイテンシオーバーヘッドは5ms未満
  • メモリ使用量は50MB未満と軽量
  • 帯域制限なし

ngrokのような既存サービスは便利ですが、無料プランだと帯域制限があったり、URLが毎回変わったり、そもそもトラフィックが事業者のサーバーを通る点が気になる場面もあります。Holesailはそのあたりの懸念を構造的に解決しているのが面白いところです。

動作環境

公式によると以下のプラットフォームに対応しています。

  • Windows 10 / 11
  • macOS 12以降(Intel / Apple Silicon両対応)
  • Ubuntu 22.04
  • Alpine 3.13
  • iOS 14以降
  • Android 10以降

今回はmacOS(Apple Silicon)の環境で試しています。

インストール

最も手軽なのはnpm経由でのグローバルインストールです。Node.jsが入っていれば一行で済みます。

npm install -g holesail

ネイティブバイナリも公式のDownloadページから入手可能で、Node.jsを入れたくない環境でも動かせます。Dockerイメージも提供されているので、コンテナ環境への組み込みも難しくないはずです。

インストール後、バージョン確認とヘルプを見ておきます。

holesail --help

サーバーとして公開する

ここでは、ローカルの3000番ポートで動いている開発用Webサーバーを共有してみます。Holesailを「サーバーモード」で起動すると、そのポートを外部に公開する役割になります。

holesail --live 3000

実行すると、コンソールに hs://s000... という形式の接続キーが表示されます。s で始まるのはセキュアモード(暗号化あり)を意味していて、hs://0000... だと非セキュアモードです。共有相手にはこのキー文字列だけを渡せば良いので、URL管理の煩わしさがありません。

クライアントから接続する

別のマシン、もしくは別のターミナルから、先ほど発行されたキーを使って接続します。

holesail hs://s000abcdef...

接続が確立されると、ローカルのポート(デフォルトでは同じ3000番)にトラフィックがマッピングされ、ブラウザから http://localhost:3000 にアクセスするとリモート側のサービスがそのまま見えます。体感としては「VPNを張ったような感覚」に近く、それでいて設定の煩雑さはありません。

SSHトンネルとして使う

個人的に一番嬉しかったのがこの使い方です。普段はリモート作業のためにVPSやクラウドVMを踏み台にしていましたが、HolesailならSSHのポート(22番)をP2Pで直接共有できます。

サーバー側(接続を受ける側):

holesail --live 22

クライアント側:

holesail hs://s000xxxxxx --port 2222
ssh user@localhost -p 2222

これでファイアウォール越しの自宅マシンにも、グローバルIPなしでSSH接続できます。出先のカフェから自宅のラボ環境を触る、といった用途にぴったりです。

プログラムから利用する

CLIだけでなく、Node.jsのモジュールとしてもAPIが提供されています。アプリケーションに組み込む使い方ですね。

const Holesail = require('holesail')

// サーバー側
const server = new Holesail({ server: true, secure: true })
await server.ready()
console.log(server.info())

// クライアント側
const client = new Holesail({ client: true, key: 'hs://s000abcdef...' })
await client.ready()

.ready().pause().resume().info().close() といったメソッドが用意されていて、起動・停止の制御もシンプルです。CIや自動化スクリプトに組み込むのも難しくなさそうです。

使ってみての所感

数日触ってみての率直な感想ですが、まず「すぐ動く」という点が想像以上に効きました。ngrokのようにアカウントを作る必要がなく、コマンド一発で接続キーが生まれる体験は気持ちが良いです。

レイテンシも実測で十分許容範囲でした。HTTPでのページ表示やSSHのキー入力でラグを感じることはほぼありません。逆に大規模なファイル転送ではP2Pの素直さが効いて、中継型サービスより速いと感じる場面もありました。

一方で、現状の課題として感じたのは以下の点です。

  • 接続キーがそこそこ長く、口頭やチャットで共有するときはコピペ前提になる
  • NAT越えに失敗するネットワーク環境(厳しめのCGNAT配下など)では接続が確立しないことがある
  • 永続化された固定キーの運用は自前で管理する必要がある

とはいえ、無料・オープンソースでこの体験ならば文句のつけようがありません。ローカル開発の共有、自宅ラボへのリモートアクセス、出先からのSSH、Minecraftのような小規模ゲームのLANプレイなど、用途を選ばず汎用的に使えるツールという印象です。

まとめ

Holesailは「サーバーを介さない」というシンプルな思想を、実用に耐えるレベルで形にしているプロジェクトです。インストールはnpmコマンド一行、利用も holesail --live <port> から始められる手軽さで、それでいてE2E暗号化までカバーしています。

これまでngrokやcloudflaredを使っていた場面の半分くらいは、Holesailで置き換えられそうな気がしています。少なくとも個人開発や社内のクイックな共有では、選択肢に入れて損はないツールです。気になった方はぜひ npm i -g holesail から試してみてください。

参考リンク

  • 公式サイト: https://holesail.io/
  • 機能紹介: https://holesail.io/features
  • ダウンロード: https://holesail.io/download

コメント

タイトルとURLをコピーしました