ngrokの魔法を解き直す ── 仕組みを理解し、Goで自作してみる

ngrokがlocalhostを世界に出している仕組みを、NAT越え・muxado多重化・エッジ処理の三層モデルで解き明かし、Goで200行のクローンを段階的に育てながら理解するシリーズ。

ngrokの魔法を解き直す ── 仕組みを理解し、Goで自作してみる

このシリーズが解決すること

ngrok http 3000 と打つだけで、家の Wi-Fi に繋がった自分のラップトップが、いきなり全世界からアクセスできる HTTPS の URL を持つ。便利だが、裏で何が起きているのか説明できる人は意外と少ない

  • 「ファイアウォール内のサーバーが、なぜ外部からのリクエストを受けられるのか不思議」
  • 「Cloudflare Tunnel や Tailscale Funnel との違いを技術的に説明できない」
  • 「自分で似たものを作れる気がしない」

このシリーズは、その「魔法に見える」状態を終わりにするためのものです。

読み終えるとできるようになること

  • ngrok の裏側で起きている通信を、永続コントロールコネクション + 多重化されたデータコネクション + TLS 終端付きエッジルーター の三層モデルで説明できる
  • 自分で 200 行程度の HTTP リバーストンネル を Go で書ける
  • Cloudflare Tunnel・frp・bore・Tailscale Funnel などを「設計の選択肢」として比較評価できる
  • NAT の非対称性が「リバーストンネルが成立する根拠」になっていることを RFC レベルで説明できる

このシリーズの対象

項目内容
対象読者ngrok を実務で使ったことがある Web / バックエンド開発者
前提知識TCP/TLS の基本、HTTP/1.1 の基本、Go の基本構文
難易度★★★☆☆(中級)
読了時間本編 約 2.5 時間 / 付録含め 約 3.5 時間
対象バージョンngrok agent config v3、golang.ngrok.com/muxado/v2 v2.0.1、Go 1.23+
構成本編 9 章 + 付録 2 本

シリーズ構成

スパイラル型で組み立てています。毎章コードが少しずつ育ち、第 6 章までに本物の ngrok に近い「型付き多重化トンネル」が手元に完成する設計です。

タイトル何をするか
1プロローグ:ngrok http 3000 の魔法を、自分の手で解き直すシリーズの読み方とゴールを共有
2NAT の非対称性を解剖するなぜ localhost が世界に出ないのか、conntrack と RFC の話
380 行の Go で ssh -R を再発明する最も素朴なリバーストンネルを動かす
41 本の TCP に複数の会話を流すmuxado でストリーム多重化を導入
5ホスト名で振り分けるHTTP ルーティングと x-forwarded-*
6コントロールとデータを分けるTypedStreamSession で型付け多重化
7本物の ngrok と答え合わせするGSLB・Traffic Policy・Agent Endpoint
8同じ問題を違う設計で解くCloudflare Tunnel・frp・bore・Tailscale Funnel との比較表
9エピローグ:トンネリングの未来を展望するMCP/AI Gateway 時代のトンネルと参考文献
付録 ATLS 終端と SNI ルーティングを実装する本編で省いた TLS 周辺
付録 B同じトンネルを yamux と HTTP/2 で書き直すmuxado との設計対比

読み方ガイド

  • 「使ったことはあるが中身は知らない」読者 は、第 1 章から順に読むのがおすすめです。3 章以降は前章のコードを増築していくため、飛ばすとコンテキストが切れます
  • プロトコル設計に興味がある読者 は、第 2 章・第 4 章・第 6 章・付録 B が中心的な読み所です
  • 競合プロダクトとの比較が知りたい読者 は、第 8 章だけ単独で読んでも価値があります

参考にしたソース

主要な一次情報は最終章(第 9 章)でまとめて掲載します。本シリーズは公式ドキュメント・公式リポジトリ・関連 RFC を一次情報として参照し、必要に応じて創業者 Alan Shreve のポッドキャストや公式ブログから直接引用しています。


それでは、第 1 章から始めましょう。

目次

  1. プロローグ:`ngrok http 3000` の魔法を、自分の手で解き直す シリーズの読み方とゴールを共有する導入章。「魔法を解く旅」の地図を渡す。
  2. NAT の非対称性を解剖する —— なぜ localhost は世界に出ないのか conntrack の非対称性と関連 RFC を解剖し、リバーストンネルが成立する理論的根拠を押さえる。
  3. 80 行の Go で `ssh -R` を再発明する NAT を内側から裏返す最小実装。agent → server の outbound 1 本だけで、外部リクエストを localhost に届ける 80 行の Go コードを書く。
  4. 1 本の TCP に複数の会話を流す —— muxado でストリーム多重化を導入する ch03 の素朴な実装が抱える「TCP 1 本=同時 1 リクエスト」の制約を、muxado による論理ストリーム多重化で解消する。HTTP/2 のフレーム層を削ぎ落とした 4 種類のフレームと、`net.Listener` を実装する Session の妙を体感する。
  5. ホスト名で振り分ける —— HTTP ルーティングと `x-forwarded-*` を実装する 公開 URL のホスト名から agent を引き、`x-forwarded-*` を付けて upstream に流す「エッジの正体」を 40 行で再現する。
  6. コントロールとデータを分ける —— `TypedStreamSession` で型付け多重化する muxado.TypedStreamSession でストリームに型 ID を付け、コントロールチャネルとデータチャネルを分離する。本物の ngrok と同じプロトコル系統まで自作版を引き上げる。
  7. 本物の ngrok と答え合わせする —— GSLB・Traffic Policy・Agent Endpoint 自作 mintunnel と本物の ngrok を並べ、省略した要素・別実装の要素・偶然一致した要素を答え合わせする。
  8. 同じ問題を違う設計で解く —— 競合トンネリングプロダクトを比較する localhost を世界に出す同じ問題を、6 プロダクトがどう違う設計で解いているかを 3 つの設計軸で比較する。
  9. エピローグ:トンネリングの未来を展望する シリーズで得た知識でプロローグの 3 つの問いに答え、MCP / AI Gateway / Zero Trust / QUIC への発展を展望する締めくくり。
  10. 付録 A:TLS 終端と SNI ルーティングを実装する 本編で HTTP に絞った mintunnel に、エッジでの TLS 終端・SNI ベースのルーティング・autocert による Let's Encrypt 自動発行を後付けする付録。
  11. 付録 B:同じトンネルを yamux と HTTP/2 で書き直す ch06 までで書いた muxado 版 mintunnel を、hashicorp/yamux 版と golang.org/x/net/http2 版に書き換えて並べる。3 つのライブラリの API・フレーム数・HTTP semantics の有無を実コードで対比し、ngrok がなぜ muxado を選んだのかを「書いてみて」体感する付録。