Relay(プロキシ)
Relay は「サーバー + クライアント」の組み合わせで、中間者(MITM)接続 を実現するクラスです。クライアントと宛先サーバーの間に割り込み、通過するパケットを観測・改変・遮断できます。認証や暗号化の処理は Relay が面倒を見ます。
最小のサンプル
js
const { Relay } = require('bedrock-protocol')
const relay = new Relay({
version: '1.21.50',
host: '0.0.0.0', // クライアントの受け口
port: 19132,
destination: { // 転送先サーバー
host: '127.0.0.1',
port: 19131
}
})
relay.listen() // 待ち受け開始
relay.on('connect', player => {
console.log('新しい接続:', player.connection.address)
// サーバー → クライアント方向のパケットを観測・改変
player.on('clientbound', ({ name, params }, des) => {
if (name === 'disconnect') {
params.message = 'Intercepted' // キックメッセージを書き換え
}
})
// クライアント → サーバー方向のパケットを観測・改変・遮断
player.on('serverbound', ({ name, params }, des) => {
if (name === 'text') {
params.message += `, on ${new Date().toLocaleString()}` // チャットに時刻を追記
}
if (name === 'command_request' && params.command === '/test') {
des.canceled = true // パケットを握りつぶす(転送しない)
}
})
})使い方の要点
パケットの流れ
クライアント ⇄ [Relay サーバー] ⇄ [Relay 上流クライアント] ⇄ 宛先サーバー
│
clientbound / serverbound イベントで傍受| イベント | 対象 |
|---|---|
clientbound | 宛先サーバーから クライアントへ向かう パケット |
serverbound | クライアントから 宛先サーバーへ向かう パケット |
ハンドラは (packet, des) を受け取ります。
packet.name… パケット名(例:'text')packet.params… パケット本体(ここを書き換えると改変される)des.canceled = true… そのパケットの転送をキャンセル
送信
| 操作 | コード |
|---|---|
| クライアントへ送る | player.queue(name, params) |
| 宛先サーバーへ送る | player.upstream.queue(name, params) |
主なオプション
| オプション | 説明 |
|---|---|
destination.host / port | 転送先サーバー(必須) |
destination.offline | 上流接続で認証をスキップするか |
offline | 接続してきたクライアントの認証をスキップ(false 指定時はログイン要求) |
version | 動作させるバージョン |
logging | パケットログの出力 |
enableChunkCaching | チャンクキャッシュを有効化(デフォルト false) |
forceSingle | 同時接続を 1 クライアントに制限(デフォルト false) |
omitParseErrors | パースエラー時に切断せずパケットを破棄(デフォルト false) |
onMsaCode | 上流参加用の認証トークンが必要になったときに呼ばれるコールバック。未指定の場合、クライアントはログインプロンプト付きで切断されます |
認証について
offline を指定しない場合、Relay に接続してきたクライアントに対してログイン(Xbox Live 認証)を求めます。上流サーバーがオンラインモードの場合、その認証情報がそのまま転送に使われます。
上級者向けの拡張ポイント(コードから)
src/relay.js を読むと、ドキュメント外のカスタマイズポイントが見つかります。
| オプション / 機能 | 説明 |
|---|---|
relayPlayer | 独自の RelayPlayer 派生クラスを注入できる(new Relay({ relayPlayer: MyPlayer }))。パケット中継ロジックを丸ごと差し替え可能 |
noLoginForward(Client 側フラグ) | 下流クライアントの skinData を上流ログインに転送しない |
'join' イベント | Relay 自体が (下流 Player, 上流 Client) の 2 引数付きで発火する。両側を直接操作したい場合に便利 |
| 双方向キュー | 上流 / 下流のどちらかが未接続でも、到着したパケットは自動でキューイングされ、接続後にフラッシュされる |
client_cache_status 強制制御 | チャンクキャッシュ要求は enableChunkCaching の値で常に上書きされる |
js
relay.on('join', (downstream, upstream) => {
// downstream: Relay に接続した Player
// upstream: バックエンドに接続済みの Client
})Realm を経由する Relay
destination.realms を指定すると、宛先として Realm を使えます。実装例はリポジトリの examples/realmRelay.js を参照してください。