velocity player forwarding
This commit is contained in:
parent
7a12dfb51d
commit
700bf95a5d
72
Cargo.lock
generated
72
Cargo.lock
generated
@ -29,6 +29,15 @@ version = "1.5.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47"
|
||||||
|
dependencies = [
|
||||||
|
"shlex",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
@ -78,6 +87,17 @@ dependencies = [
|
|||||||
"miniz_oxide",
|
"miniz_oxide",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.15.1"
|
version = "0.15.1"
|
||||||
@ -141,9 +161,11 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
|||||||
name = "meexprox"
|
name = "meexprox"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"bytebuffer",
|
||||||
"ignore-result",
|
"ignore-result",
|
||||||
"log",
|
"log",
|
||||||
"random-string",
|
"random-string",
|
||||||
|
"ring",
|
||||||
"rust_mc_proto",
|
"rust_mc_proto",
|
||||||
"serde_yml",
|
"serde_yml",
|
||||||
"simplelog",
|
"simplelog",
|
||||||
@ -213,6 +235,21 @@ dependencies = [
|
|||||||
"fastrand",
|
"fastrand",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ring"
|
||||||
|
version = "0.17.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"cfg-if",
|
||||||
|
"getrandom",
|
||||||
|
"libc",
|
||||||
|
"spin",
|
||||||
|
"untrusted",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rust_mc_proto"
|
name = "rust_mc_proto"
|
||||||
version = "0.1.16"
|
version = "0.1.16"
|
||||||
@ -264,6 +301,12 @@ dependencies = [
|
|||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "shlex"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "simplelog"
|
name = "simplelog"
|
||||||
version = "0.12.2"
|
version = "0.12.2"
|
||||||
@ -275,6 +318,12 @@ dependencies = [
|
|||||||
"time",
|
"time",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spin"
|
||||||
|
version = "0.9.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.87"
|
version = "2.0.87"
|
||||||
@ -334,6 +383,12 @@ version = "1.0.13"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
|
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "untrusted"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "1.11.0"
|
version = "1.11.0"
|
||||||
@ -346,13 +401,28 @@ version = "0.9.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-util"
|
name = "winapi-util"
|
||||||
version = "0.1.9"
|
version = "0.1.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys",
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -10,4 +10,6 @@ uuid = "1.11.0"
|
|||||||
log = "0.4.22"
|
log = "0.4.22"
|
||||||
simplelog = "0.12.2"
|
simplelog = "0.12.2"
|
||||||
ignore-result = "0.2.0"
|
ignore-result = "0.2.0"
|
||||||
random-string = "1.1.0"
|
random-string = "1.1.0"
|
||||||
|
ring = "0.17.8"
|
||||||
|
bytebuffer = "2.3.0"
|
@ -30,5 +30,5 @@ incoming_forwarding: # player forwarding for incoming connections
|
|||||||
# player forwarding types:
|
# player forwarding types:
|
||||||
# - velocity (or "modern" in Velocity config) (secret is required)
|
# - velocity (or "modern" in Velocity config) (secret is required)
|
||||||
# - bungeecord (or "legacy" in Velocity config) (secret is optional)
|
# - bungeecord (or "legacy" in Velocity config) (secret is optional)
|
||||||
# - meexprox (best) (secret is required)
|
# - meexprox (open-source protocol) (secret is required)
|
||||||
# - none (enabled: false)
|
# - none (enabled: false)
|
@ -1,11 +1,13 @@
|
|||||||
use std::{net::{SocketAddr, TcpStream}, sync::{Arc, Mutex}, thread};
|
use std::{net::{SocketAddr, TcpStream}, sync::{Arc, Mutex}, thread};
|
||||||
|
|
||||||
|
use bytebuffer::ByteBuffer;
|
||||||
use ignore_result::Ignore;
|
use ignore_result::Ignore;
|
||||||
use log::debug;
|
use log::info;
|
||||||
|
use ring::hmac;
|
||||||
use rust_mc_proto::{DataBufferReader, DataBufferWriter, MCConnTcp, Packet, ProtocolError};
|
use rust_mc_proto::{DataBufferReader, DataBufferWriter, MCConnTcp, Packet, ProtocolError};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::{config::{ProxyConfig, ServerInfo}, error::{AsProxyResult, ProxyError}};
|
use super::{config::{PlayerForwarding, ProxyConfig, ServerInfo}, error::{AsProxyResult, ProxyError}};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct LoginInfo {
|
pub struct LoginInfo {
|
||||||
@ -74,6 +76,7 @@ pub struct Player {
|
|||||||
|
|
||||||
impl Player {
|
impl Player {
|
||||||
pub fn read(
|
pub fn read(
|
||||||
|
_config: &ProxyConfig,
|
||||||
protocol_version: u16,
|
protocol_version: u16,
|
||||||
server_address: String,
|
server_address: String,
|
||||||
server_port: u16,
|
server_port: u16,
|
||||||
@ -98,7 +101,7 @@ impl Player {
|
|||||||
login_info: None,
|
login_info: None,
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
uuid,
|
uuid,
|
||||||
server: Some(server),
|
server: Some(server.clone()),
|
||||||
protocol_version
|
protocol_version
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -128,6 +131,47 @@ impl Player {
|
|||||||
player.set_server_compression(compression);
|
player.set_server_compression(compression);
|
||||||
player.set_client_compression(compression);
|
player.set_client_compression(compression);
|
||||||
}
|
}
|
||||||
|
0x04 => { // login plugin request
|
||||||
|
let message_id = packet.read_isize_varint().as_proxy()?;
|
||||||
|
let channel = packet.read_string().as_proxy()?;
|
||||||
|
|
||||||
|
if channel == "velocity:player_info" {
|
||||||
|
if let PlayerForwarding::Velocity(secret) = &server.player_forwarding {
|
||||||
|
let version: u8 = if packet.buffer().len() - packet.buffer().get_rpos() == 1 {
|
||||||
|
packet.read_byte().as_proxy()?
|
||||||
|
} else {
|
||||||
|
1
|
||||||
|
};
|
||||||
|
|
||||||
|
let response = Packet::build(0x02, |p| {
|
||||||
|
p.write_isize_varint(message_id)?;
|
||||||
|
p.write_boolean(true)?;
|
||||||
|
|
||||||
|
let mut buf = ByteBuffer::new();
|
||||||
|
DataBufferWriter::write_u8_varint(&mut buf, version)?;
|
||||||
|
DataBufferWriter::write_string(&mut buf, &addr.to_string())?;
|
||||||
|
DataBufferWriter::write_uuid(&mut buf, &uuid)?;
|
||||||
|
DataBufferWriter::write_string(&mut buf, &name)?;
|
||||||
|
DataBufferWriter::write_u8_varint(&mut buf, 0)?; // properties // maybe fix later
|
||||||
|
let buf = buf.as_bytes();
|
||||||
|
|
||||||
|
let key = hmac::Key::new(hmac::HMAC_SHA256, secret.as_bytes());
|
||||||
|
let sig = hmac::sign(&key, &buf);
|
||||||
|
|
||||||
|
p.write_bytes(sig.as_ref())?;
|
||||||
|
p.write_bytes(buf.as_ref())?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}).as_proxy()?;
|
||||||
|
|
||||||
|
player.write_server_packet(&response)?;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
player.write_client_packet(&packet)?;
|
||||||
|
player.write_server_packet(&player.read_client_packet()?)?;
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(ProxyError::LoginPacket);
|
return Err(ProxyError::LoginPacket);
|
||||||
},
|
},
|
||||||
@ -144,8 +188,6 @@ impl Player {
|
|||||||
verify_token
|
verify_token
|
||||||
});
|
});
|
||||||
|
|
||||||
debug!("player connected");
|
|
||||||
|
|
||||||
player.client_recv_loop();
|
player.client_recv_loop();
|
||||||
player.server_recv_loop();
|
player.server_recv_loop();
|
||||||
|
|
||||||
@ -155,40 +197,58 @@ impl Player {
|
|||||||
pub fn client_recv_loop(&self) {
|
pub fn client_recv_loop(&self) {
|
||||||
let mut client: rust_mc_proto::MinecraftConnection<TcpStream> = self.client_conn.clone().lock().unwrap().try_clone().unwrap();
|
let mut client: rust_mc_proto::MinecraftConnection<TcpStream> = self.client_conn.clone().lock().unwrap().try_clone().unwrap();
|
||||||
let server = self.server_conn.clone();
|
let server = self.server_conn.clone();
|
||||||
|
let name = self.name.clone();
|
||||||
|
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
|
info!("Player {} connected", name);
|
||||||
while let Ok(packet) = client.read_packet() {
|
while let Ok(packet) = client.read_packet() {
|
||||||
while !server.lock().unwrap().is_alive() {}
|
while !server.lock().unwrap().is_alive() {}
|
||||||
server.lock().unwrap().write_packet(&packet).ignore();
|
server.lock().unwrap().write_packet(&packet).ignore();
|
||||||
}
|
}
|
||||||
|
info!("Player {} disconnected", name);
|
||||||
|
server.lock().unwrap().close();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn disconnect(&self) {
|
||||||
|
self.client_conn.lock().unwrap().close();
|
||||||
|
self.server_conn.lock().unwrap().close();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kick(&self, text: String) -> Result<(), ProxyError> {
|
||||||
|
self.write_client_packet(&Packet::build(
|
||||||
|
0x1D, |p| p.write_string(&text)
|
||||||
|
).as_proxy()?)?;
|
||||||
|
self.disconnect();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn server_recv_loop(&self) {
|
pub fn server_recv_loop(&self) {
|
||||||
let mut server = self.server_conn.clone().lock().unwrap().try_clone().unwrap();
|
let mut server = self.server_conn.clone().lock().unwrap().try_clone().unwrap();
|
||||||
let client = self.client_conn.clone();
|
let client = self.client_conn.clone();
|
||||||
|
let server_name = self.server.as_ref().unwrap().name.clone();
|
||||||
|
let name = self.name.clone();
|
||||||
|
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
|
info!("Server {} connected player {}", server_name, name);
|
||||||
while let Ok(packet) = server.read_packet() {
|
while let Ok(packet) = server.read_packet() {
|
||||||
client.lock().unwrap().write_packet(&packet).ignore();
|
client.lock().unwrap().write_packet(&packet).ignore();
|
||||||
}
|
}
|
||||||
|
info!("Server {} disconnected player {}", server_name, name);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect(&self, config: &ProxyConfig, server_conn: TcpStream) -> Result<(), ProxyError> {
|
pub fn connect_server(&self, config: &ProxyConfig, server: ServerInfo) -> Result<(), ProxyError> {
|
||||||
self.server_conn.lock().unwrap().close();
|
self.server_conn.lock().unwrap().close();
|
||||||
let mut server_conn = MCConnTcp::new(server_conn);
|
let mut server_conn = MCConnTcp::connect(&server.host).as_proxy()?;
|
||||||
if let Some(login_info) = &self.login_info {
|
if let Some(login_info) = &self.login_info {
|
||||||
login_info.write(config, &mut server_conn).as_proxy()?;
|
login_info.write(config, &mut server_conn).as_proxy()?;
|
||||||
}
|
}
|
||||||
|
*self.server_conn.lock().unwrap() = server_conn;
|
||||||
self.server_recv_loop();
|
self.server_recv_loop();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect_server(&self, config: &ProxyConfig, server: ServerInfo) -> Result<(), ProxyError> {
|
|
||||||
self.connect(config, TcpStream::connect(&server.host).map_err(|_| ProxyError::ServerConnect)?)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write_client_packet(&self, packet: &Packet) -> Result<(), ProxyError> {
|
pub fn write_client_packet(&self, packet: &Packet) -> Result<(), ProxyError> {
|
||||||
self.client_conn.lock().unwrap().write_packet(packet).as_proxy()
|
self.client_conn.lock().unwrap().write_packet(packet).as_proxy()
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use log::{debug, error, info};
|
use log::{error, info};
|
||||||
use rust_mc_proto::{
|
use rust_mc_proto::{
|
||||||
read_packet, write_packet, DataBufferReader, DataBufferWriter, MCConnTcp, Packet
|
read_packet, write_packet, DataBufferReader, DataBufferWriter, MCConnTcp, Packet
|
||||||
};
|
};
|
||||||
@ -89,6 +89,7 @@ impl MeexProx {
|
|||||||
}
|
}
|
||||||
} else if next_state == 2 {
|
} else if next_state == 2 {
|
||||||
self.players.write().unwrap().push(Player::read(
|
self.players.write().unwrap().push(Player::read(
|
||||||
|
&self.config,
|
||||||
protocol_version,
|
protocol_version,
|
||||||
server_address,
|
server_address,
|
||||||
server_port,
|
server_port,
|
||||||
|
Loading…
Reference in New Issue
Block a user