relay: Add multi-user login support (#258)
* relay: add multi-user login support * relay: Fix close handling, connect username
This commit is contained in:
parent
ce06762dce
commit
c395f0b05b
3 changed files with 38 additions and 5 deletions
|
|
@ -170,7 +170,7 @@ For documentation on the protocol, and packets/fields see the [the protocol doc]
|
||||||
|
|
||||||
### Proxy docs
|
### Proxy docs
|
||||||
|
|
||||||
You can create a proxy ("Relay") to create a machine-in-the-middle (MITM) connection to a server. You can observe and intercept packets as they go through. The Relay is a server+client combo with some special packet handling and forwarding that takes care of the authentication and encryption on the server side. You'll be asked to login if `offline` is not specified once you connect.
|
You can create a proxy ("Relay") to create a machine-in-the-middle (MITM) connection to a server. You can observe and intercept packets as they go through. The Relay is a server+client combo with some special packet handling and forwarding that takes care of the authentication and encryption on the server side. Clients will be asked to login if `offline` is not specified on connection.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const { Relay } = require('bedrock-protocol')
|
const { Relay } = require('bedrock-protocol')
|
||||||
|
|
|
||||||
12
index.d.ts
vendored
12
index.d.ts
vendored
|
|
@ -131,6 +131,10 @@ declare module "bedrock-protocol" {
|
||||||
* Close the connection. Already called by disconnect. Call this to manually close RakNet connection.
|
* Close the connection. Already called by disconnect. Call this to manually close RakNet connection.
|
||||||
*/
|
*/
|
||||||
close()
|
close()
|
||||||
|
|
||||||
|
on(event: 'login', cb: () => void)
|
||||||
|
on(event: 'join', cb: () => void)
|
||||||
|
on(event: 'close', cb: (reason: string) => void)
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Server extends EventEmitter {
|
export class Server extends EventEmitter {
|
||||||
|
|
@ -161,6 +165,14 @@ declare module "bedrock-protocol" {
|
||||||
}
|
}
|
||||||
// Whether to enable chunk caching (default: false)
|
// Whether to enable chunk caching (default: false)
|
||||||
enableChunkCaching?: boolean
|
enableChunkCaching?: boolean
|
||||||
|
|
||||||
|
// Only allow one client to connect at a time (default: false)
|
||||||
|
forceSinge: boolean
|
||||||
|
|
||||||
|
// Dispatched when a new client has logged in, and we need authentication
|
||||||
|
// tokens to join the backend server. Cached after the first login.
|
||||||
|
// If this is not specified, the client will be disconnected with a login prompt.
|
||||||
|
onMsaCode(data, client)
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Relay extends Server {
|
export class Relay extends Server {
|
||||||
|
|
|
||||||
29
src/relay.js
29
src/relay.js
|
|
@ -159,7 +159,7 @@ class Relay extends Server {
|
||||||
constructor (options) {
|
constructor (options) {
|
||||||
super(options)
|
super(options)
|
||||||
this.RelayPlayer = options.relayPlayer || RelayPlayer
|
this.RelayPlayer = options.relayPlayer || RelayPlayer
|
||||||
this.forceSingle = true
|
this.forceSingle = options.forceSingle
|
||||||
this.upstreams = new Map()
|
this.upstreams = new Map()
|
||||||
this.conLog = debug
|
this.conLog = debug
|
||||||
this.enableChunkCaching = options.enableChunkCaching
|
this.enableChunkCaching = options.enableChunkCaching
|
||||||
|
|
@ -175,12 +175,18 @@ class Relay extends Server {
|
||||||
const options = {
|
const options = {
|
||||||
authTitle: this.options.authTitle,
|
authTitle: this.options.authTitle,
|
||||||
offline: this.options.destination.offline ?? this.options.offline,
|
offline: this.options.destination.offline ?? this.options.offline,
|
||||||
username: this.options.offline ? ds.profile.name : null,
|
username: this.options.offline ? ds.profile.name : ds.profile.xuid,
|
||||||
version: this.options.version,
|
version: this.options.version,
|
||||||
realms: this.options.destination.realms,
|
realms: this.options.destination.realms,
|
||||||
host: this.options.destination.host,
|
host: this.options.destination.host,
|
||||||
port: this.options.destination.port,
|
port: this.options.destination.port,
|
||||||
onMsaCode: this.options.onMsaCode,
|
onMsaCode: (code) => {
|
||||||
|
if (this.options.onMsaCode) {
|
||||||
|
this.options.onMsaCode(code, ds)
|
||||||
|
} else {
|
||||||
|
ds.disconnect("It's your first time joining. Please sign in and reconnect to join this server:\n\n" + code.message)
|
||||||
|
}
|
||||||
|
},
|
||||||
profilesFolder: this.options.profilesFolder,
|
profilesFolder: this.options.profilesFolder,
|
||||||
backend: this.options.backend,
|
backend: this.options.backend,
|
||||||
autoInitPlayer: false
|
autoInitPlayer: false
|
||||||
|
|
@ -213,6 +219,16 @@ class Relay extends Server {
|
||||||
|
|
||||||
this.emit('join', /* client connected to proxy */ ds, /* backend server */ client)
|
this.emit('join', /* client connected to proxy */ ds, /* backend server */ client)
|
||||||
})
|
})
|
||||||
|
client.on('error', (err) => {
|
||||||
|
ds.disconnect('Server error: ' + err.message)
|
||||||
|
debug(clientAddr, 'was disconnected because of error', err)
|
||||||
|
this.upstreams.delete(clientAddr.hash)
|
||||||
|
})
|
||||||
|
client.on('close', (reason) => {
|
||||||
|
ds.disconnect('Backend server closed connection')
|
||||||
|
this.upstreams.delete(clientAddr.hash)
|
||||||
|
})
|
||||||
|
|
||||||
this.upstreams.set(clientAddr.hash, client)
|
this.upstreams.set(clientAddr.hash, client)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -225,7 +241,7 @@ class Relay extends Server {
|
||||||
this.conLog('closed upstream connection', clientAddr)
|
this.conLog('closed upstream connection', clientAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when a new player connects to our proxy server. Once the player has authenticted,
|
// Called when a new player connects to our proxy server. Once the player has authenticated,
|
||||||
// we can open an upstream connection to the backend server.
|
// we can open an upstream connection to the backend server.
|
||||||
onOpenConnection = (conn) => {
|
onOpenConnection = (conn) => {
|
||||||
if (this.forceSingle && this.clientCount > 0) {
|
if (this.forceSingle && this.clientCount > 0) {
|
||||||
|
|
@ -240,6 +256,11 @@ class Relay extends Server {
|
||||||
player.on('login', () => {
|
player.on('login', () => {
|
||||||
this.openUpstreamConnection(player, conn.address)
|
this.openUpstreamConnection(player, conn.address)
|
||||||
})
|
})
|
||||||
|
player.on('close', (reason) => {
|
||||||
|
this.conLog('player disconnected', conn.address, reason)
|
||||||
|
this.clientCount--
|
||||||
|
delete this.clients[conn.address]
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue