aboutsummaryrefslogtreecommitdiff
path: root/azalea-client/src/plugins
diff options
context:
space:
mode:
authormat <27899617+mat-1@users.noreply.github.com>2025-12-11 22:47:16 -0600
committerGitHub <noreply@github.com>2025-12-11 22:47:16 -0600
commit4a66f002c276a57e028e9456f6800b0b3c248885 (patch)
treef87cbdc51c09d497548f972b9b1633ceb7606443 /azalea-client/src/plugins
parentff1e28f88e93ba83cf76569b5613445b841efd45 (diff)
downloadazalea-drasl-4a66f002c276a57e028e9456f6800b0b3c248885.tar.xz
Add options to request Mojang sessionserver with a proxy (#293)
* add options to request mojang sessionserver with a socks5 proxy * update changelog * rename auth_proxy to sessionserver_proxy
Diffstat (limited to 'azalea-client/src/plugins')
-rw-r--r--azalea-client/src/plugins/join.rs17
-rw-r--r--azalea-client/src/plugins/login.rs51
2 files changed, 52 insertions, 16 deletions
diff --git a/azalea-client/src/plugins/join.rs b/azalea-client/src/plugins/join.rs
index a8f6e3c5..538369b0 100644
--- a/azalea-client/src/plugins/join.rs
+++ b/azalea-client/src/plugins/join.rs
@@ -64,9 +64,22 @@ pub struct StartJoinServerEvent {
/// This is inserted as a component on clients to make auto-reconnecting work.
#[derive(Debug, Clone, Component)]
pub struct ConnectOpts {
+ /// The unresolved address that we're going to tell the server that we used
+ /// to connect.
pub address: ServerAddress,
+ /// The actual IP and port that we're going to make a connection to.
pub resolved_address: SocketAddr,
- pub proxy: Option<Proxy>,
+ /// The SOCKS5 proxy used for connecting to the Minecraft server.
+ pub server_proxy: Option<Proxy>,
+ /// The SOCKS5 proxy that will be used when authenticating our server join
+ /// with Mojang.
+ ///
+ /// This should typically be either the same as [`Self::server_proxy`], or
+ /// `None`.
+ ///
+ /// This is useful to set if a server has `prevent-proxy-connections`
+ /// enabled.
+ pub sessionserver_proxy: Option<Proxy>,
}
/// An event that's sent when creating the TCP connection and sending the first
@@ -158,7 +171,7 @@ pub fn handle_start_join_server_event(
async fn create_conn_and_send_intention_packet(
opts: ConnectOpts,
) -> Result<LoginConn, ConnectionError> {
- let mut conn = if let Some(proxy) = opts.proxy {
+ let mut conn = if let Some(proxy) = opts.server_proxy {
Connection::new_with_proxy(&opts.resolved_address, proxy).await?
} else {
Connection::new(&opts.resolved_address).await?
diff --git a/azalea-client/src/plugins/login.rs b/azalea-client/src/plugins/login.rs
index 46ff8ea9..46ab20c4 100644
--- a/azalea-client/src/plugins/login.rs
+++ b/azalea-client/src/plugins/login.rs
@@ -1,19 +1,20 @@
#[cfg(feature = "online-mode")]
use azalea_auth::sessionserver::ClientSessionServerError;
-use azalea_protocol::packets::login::{
- ClientboundHello, ServerboundCustomQueryAnswer, ServerboundKey,
+use azalea_protocol::{
+ connect::Proxy,
+ packets::login::{ClientboundHello, ServerboundCustomQueryAnswer, ServerboundKey},
};
use bevy_app::prelude::*;
use bevy_ecs::prelude::*;
use bevy_tasks::{IoTaskPool, Task, futures_lite::future};
use thiserror::Error;
-use tracing::{debug, error, trace};
+use tracing::{debug, error, trace, warn};
use super::{
connection::RawConnection,
packet::login::{ReceiveCustomQueryEvent, ReceiveHelloEvent, SendLoginPacketEvent},
};
-use crate::Account;
+use crate::{Account, join::ConnectOpts};
/// Some systems that run during the `login` state.
pub struct LoginPlugin;
@@ -24,15 +25,29 @@ impl Plugin for LoginPlugin {
}
}
-fn handle_receive_hello_event(receive_hello: On<ReceiveHelloEvent>, mut commands: Commands) {
+fn handle_receive_hello_event(
+ receive_hello: On<ReceiveHelloEvent>,
+ mut commands: Commands,
+ query: Query<&ConnectOpts>,
+) {
let task_pool = IoTaskPool::get();
let account = receive_hello.account.clone();
let packet = receive_hello.packet.clone();
- let player = receive_hello.entity;
+ let client = receive_hello.entity;
+
+ // we store the auth proxy in the ConnectOpts component to make it easily
+ // configurable. that component should've definitely been inserted by now, but
+ // if it somehow wasn't then we should let the user know.
+ let connect_opts = if let Ok(opts) = query.get(client) {
+ opts.sessionserver_proxy.clone()
+ } else {
+ warn!("ConnectOpts component missing on a client ({client}) that got ReceiveHelloEvent");
+ None
+ };
- let task = task_pool.spawn(auth_with_account(account, packet));
- commands.entity(player).insert(AuthTask(task));
+ let task = task_pool.spawn(auth_with_account(account, packet, connect_opts));
+ commands.entity(client).insert(AuthTask(task));
}
/// A marker component on our clients that indicates that the server is
@@ -92,6 +107,7 @@ pub enum AuthWithAccountError {
pub async fn auth_with_account(
account: Account,
packet: ClientboundHello,
+ proxy: Option<Proxy>,
) -> Result<(ServerboundKey, PrivateKey), AuthWithAccountError> {
let Ok(encrypt_res) = azalea_crypto::encrypt(&packet.public_key, &packet.challenge) else {
return Err(AuthWithAccountError::Encryption(packet));
@@ -116,22 +132,29 @@ pub async fn auth_with_account(
// after too many
let mut attempts: usize = 1;
+ let proxy = proxy.map(Proxy::into);
+
while let Err(err) = {
+ use azalea_auth::sessionserver::{self, SessionServerJoinOpts};
+
let access_token = access_token.lock().clone();
let uuid = &account
.uuid
.expect("Uuid must be present if access token is present.");
+ let proxy = proxy.clone();
+
// this is necessary since reqwest usually depends on tokio and we're using
// `futures` here
- async_compat::Compat::new(azalea_auth::sessionserver::join(
- &access_token,
- &packet.public_key,
- &private_key,
+ async_compat::Compat::new(sessionserver::join(SessionServerJoinOpts {
+ access_token: &access_token,
+ public_key: &packet.public_key,
+ private_key: &private_key,
uuid,
- &packet.server_id,
- ))
+ server_id: &packet.server_id,
+ proxy,
+ }))
.await
} {
if attempts >= 2 {