GoにおけるYggdrasilネットワーキング
概要
このスキルを使用して、Yggdrasil エンドツーエンド暗号化IPv6メッシュに接続し、サービスを提供するGoプログラムを構築します。クライアント、HTTP/TCP/UDPサーバー、SOCKS5プロキシ、ポートフォワーダー、ディスカバリメタデータを公開するノードなどに対応。ノードはgVisor netstack上のユーザースペースで動作します。TUNデバイス不要、root不要、外部 yggdrasil デーモン不要、 yggstack バイナリも不要。標準Goインターフェース(net.Conn、net.Listener、net.PacketConn、http.Transport)でYggdrasil経由のダイヤルとリスンを行います。
組み込みライブラリは github.com/voluminor/ratatoskr です。ratatoskr.New でノードを作成し、すべてをそのGo APIで駆動します。パッケージのスコープと安定性は以下にまとめられています。
制約のあるメッシュ向け設計
Yggdrasilはエンドツーエンド暗号化オーバーレイメッシュであり、データセンターファブリックではありません。リンクは高レイテンシ、低帯域幅、損失が多く、断続的です。今到達可能なピアが1秒後にはいなくなり、トラフィックは多くのホップを経由する可能性があります。すべてのYggdrasilソリューションを、弱く不安定な接続向けに構築してください。これはオプションの装飾ではなく、ここで正しいコードのデフォルトの形状です。
- 無制限にしない。 すべてのダイヤルとリクエストに期限を設定(
context.WithTimeout)。制限付きリトライ、制限付きキュー。無限待機は禁止。 - 並行性を制限する。 処理中の作業を制限:SOCKS
MaxConnections、フォワードSetMaxUDPSessions、http.Transport.MaxConnsPerHost/MaxIdleConnsPerHost、独自のワーカープール。どちらもデフォルトは無制限 — 実際の制限を設定すること。 - 大きな転送はチャンク分割し、検証し、再開可能にする。 大きなファイルを一度に移動しない。小さなチャンク(例:HTTP
Range)に分割し、各チャンクを検証(サイズ/チェックサム)し、再開可能にすることで、リンク切断時に全体ではなく1チャンクのみが失われるようにする。 - べき乗バックオフ+ジッターで冪等にリトライする。 処理中切断を想定。処理を再開可能/冪等にすること。指数バックオフ+ジッター。試行回数に上限を設定。
- ペイロードを小さく保つ。 おしゃべりなプロトコルやポーリングを避け、圧縮し、コンパクトなエンコーディングを使用。NodeInfo/シジルは16KB制限を十分下回るように保つ。
- バッファをリンクに合わせる。 パケットバッファには
node.MTU()を使用(ユーザースペースMTUは動的で、最小1280)。 - 劣化し、叩かない。 失敗時はバックオフして部分結果を返す。ピアを積極的にリトライしたり、メッシュをフラッドさせたりしない。
「net/http で大きなファイルを提供する」や「1つの巨大なリクエスト/レスポンス」という単純なアプローチは誤った形状です。正しい形状は、制限付き、チャンク化、再開可能、フォールトトレラントがデフォルトです。制約のあるメッシュ転送パターンについては references/integrations.md を参照。
信頼できる情報源
アクティブなモジュールが信頼できる情報源です。メモリ、古いREADMEテキスト、このスキルではありません。バージョン固有のガイダンスを書く前に、プロジェクトが実際に依存しているものを確認してください:
go list -m github.com/voluminor/ratatoskr # 選択されたバージョン
go doc github.com/voluminor/ratatoskr # コンパイルされたルートAPI
go doc github.com/voluminor/ratatoskr/mod/peermgr ConfigObj
選択されたバージョンの実際のソースを読むには、パスを推測する代わりにモジュールキャッシュから解決します:
go list -m -f '{{.Dir}}' github.com/voluminor/ratatoskr
READMEテキストから最小Goバージョンを固定しないでください。go.mod ディレクティブより遅れる可能性があります。選択されたRatatoskrバージョンのアクティブな go.mod を読んでください。
デフォルトワークフロー
- アプリケーションの形状を特定する:組み込みノード、HTTPクライアント/サーバー、生のTCP/UDP、SOCKS5、ポートフォワーディング、ピア管理、またはNodeInfo/シジル。
- アプリケーションにはルートパッケージ
github.com/voluminor/ratatoskrを使用する。mod/coreにはcore.Interfaceコントラクトを通じてのみアクセスし、低レベルパッケージが本当に必要としない限り*core.Obj/UnsafeCore()を避ける。 context.Contextを所有し、それをratatoskr.ConfigObj.Ctxとして渡し、かつ 正常起動後にdefer node.Close()を行う。両方が必要。- ピアは厳密に1箇所で設定する:
- 静的Yggdrasilピア:
cfg.Config.Peers - Ratatoskrピアマネージャー:
ratatoskr.ConfigObj.Peers(その場合cfg.Config.Peersは空のままにする。さもないとNewはErrPeersConflictを返す)。
- 静的Yggdrasilピア:
- アウトバウンドTCP/UDPには
node.DialContext、Yggdrasil内のサービスにはnode.Listen/node.ListenPacketを使用する。 - URLやホスト-ポート文字列ではIPv6アドレスを角括弧で囲む:
http://[200:abcd::1]:8080、決してhttp://200:abcd::1:8080としない。 - リンクを弱いものとして扱う:すべての呼び出しに期限を設定し、並行性を制限し、大きな転送はチャンク/検証/再開可能にする(「制約のあるメッシュ向け設計」参照)。
- 実際のプロジェクトにコードを生成する際は、ビルドできると仮定するのではなく、コンパイルチェックまたは焦点を絞ったテストを追加する。
モジュールスコープと安定性
Yggdrasilアドレスはノードキーから派生するため、ネットワーク表面は小さく安定しています。ライブラリが完成済みとして扱う部分を優先し、残りは明示的にフラグを立てて、その上に構築しないようにします。
| パッケージ | ステータス | 使用経路 |
|---|---|---|
ルート ratatoskr | 安定、プライマリAPI | New、EnableSOCKS、Ask/AskAddr、Snapshot、Close |
mod/core | 安定コントラクト | ノードに埋め込まれた core.Interface メソッド |
mod/peermgr | 安定 | ratatoskr.ConfigObj.Peers |
mod/socks | 安定 | node.EnableSOCKS(直接インスタンス化しない) |
mod/resolver | 安定 | EnableSOCKS により自動作成。直接使用は高度 |
mod/forward | 安定 | forward.New → Add* → Start |
mod/sigils(+ info、services、public、inet) | 安定 | ratatoskr.ConfigObj.Sigils |
mod/ninfo | 安定 | node.Ask / node.AskAddr |
mod/probe | 高度/不安定 — UnsafeCore() が必要、APIは変更可能性あり | トポロジ/経路トレースが明示的に必要な場合のみ |
mod/settings | 作業中 - スキーマ未確定 | 避ける;代わりに yggdrasil-go/src/config を直接使用 |
cmd/* | サンプルアプリ、インポート可能なライブラリAPIではない | パターンとして読み、インポートしない |
ルート vs サブモジュール: デフォルトでは ratatoskr.New を使用(コア + SOCKS + ピアマネージャー + ninfo + シジルを1つの Close で管理)。最小表面(生のダイヤル/リスン)には mod/core に降りて core.New を使用するか、カスタムトランスポートやテストのために core.Interface の周りにサブモジュールを構成する。各サブモジュール(peermgr/socks/forward/resolver/ninfo)は core.Interface を取ります。詳細は references/overview.md を参照。
システムシジル — ここで先に公開する
NodeInfoは、ノードが自分自身をネットワークに説明する方法です。4つの組み込み(「システム」)シジルはすべてのノードで自動的に解析されるため、そこに配置したデータは他の参加者に認識されます。カスタムシジルを発明する前にこれらを活用してください。ratatoskr.ConfigObj.Sigils を介して渡します。それぞれを小さく保ってください — これらは1つの16KB NodeInfo予算を共有します。
| シジル | ここに含めるもの | 使用理由 |
|---|---|---|
info | ノードのアイデンティティ:名前、タイプ、場所、連絡先、説明 | 他のノードにあなたのノードが誰/何かを知らせる。 |
services | Yggdrasil内で公開するポート。name → port | ポートスキャンなしでのサービスディスカバリ。 |
public | ネットワーク別にグループ化された公開ピアリングURI | 他のノードが直接ピアリングできるようにする。 |
inet | 実際のアドレス(ドメイン/IP) | Yggdrasilノードをクリアネットアイデンティティにマッピング。 |
発見可能で標準的なデータをこれらに配置し、ネットワーク全体が読めるようにします。これらの4つでカバーされないデータに対してのみカスタムシジルを定義してください。そして、あなたのコードを実行しているピアだけがそれを解析することを忘れないでください。コンストラクタは検証とエラー返却を行います。ratatoskr.New の前にエラーを処理してください。詳細、正確な制限、型付きアクセス、カスタムシジル作成:references/nodeinfo-sigils.md および references/custom-sigils.md。
リファレンスマップ
現在のタスクに必要なファイルのみを読んでください:
- 組み込みノードの基本、Ratatoskr vs yggstack、アーキテクチャ、スコープ:references/overview.md
ratatoskr.New、ConfigObj、ライフサイクル、スレッドセーフティ、ルートメソッド、エラー、スナップショット:references/root-api.md- TCP、UDP、
DialContext、Listen、ListenPacket、HTTPクライアント/サーバー、マルチキャスト/管理、テストシーム:references/networking.md - 静的ピア、ピアマネージャー、SOCKS5、リゾルバ、ポートフォワーディング:references/peers-socks-forwarding.md
- NodeInfo、
Ask/AskAddr、正確な制限付き組み込みシジル:references/nodeinfo-sigils.md - 型付きアクセスと独自シジルの作成/配線(生の
map[string]anyは不使用):references/custom-sigils.md - クライアント/サーバーテンプレートとフレームワーク統合(net/http、fasthttp、gRPC、gnetブリッジ):references/integrations.md
- 高度/作業中領域(probe、settings)とCLI/サンプルアプリパターン:references/advanced-and-examples.md
- 適用可能なアプリケーションレシピ:references/recipes.md
よくある間違い
| 間違い | 修正 |
|---|---|
| 組み込みアプリのために外部Yggdrasilデーモンを起動する | ratatoskr.New を使用。ユーザースペースgVisor netstackを実行する。 |
ライブラリ統合に yggstack を推奨する | yggstack はエンドユーザーバイナリ。Go API制御にはRatatoskrを使用。 |
cfg.Config.Peers と ConfigObj.Peers の両方を設定する | 静的ピアまたはピアマネージャーのどちらかを選択。両方は不可 → ErrPeersConflict。 |
Ctx を渡すが Close をスキップする(またはその逆) | 両方を行う:キャンセルはシャットダウンをトリガーし、Close はリソースを解放する。 |
| IPv6角括弧なしでURLを構築する | fmt.Sprintf("http://[%s]:%d", ip, port) を使用。 |
基本的なクエリに ninfo.New を作成する | node.Ask / node.AskAddr を使用。ルートオブジェクトはすでにninfoを構築する。 |
| 実行時にシジルを動的に組み立てたり登録したりする | シジルは厳密にコード内で組み立てられる。重複や上書きキーはデフォルトのマージではなくハードエラー。ConfigObj.Sigils を介して公開。自分のキーは res.Node.Extra から読み取る。 |
デフォルトで UnsafeCore() / mod/probe / mod/settings に手を伸ばす | ルートAPIに留まる。これらは高度または作業中。 |
| READMEからGoバージョンをハードコーディングする | 選択されたモジュールバージョンのアクティブな go.mod を読む。 |
検証
SKILL.md をナビゲーションレイヤーとして保持し、重いAPI詳細は references/ に配置する。公開前に evals/evals.json のシナリオに対して変更をフォワードテストする。