Skip to content

Update hytale protocol to current latest - #5

Open
SantioMC wants to merge 19 commits into
xyzeva:mainfrom
Minehut:alexandresequeira/mhg-1132-update-protocol
Open

Update hytale protocol to current latest#5
SantioMC wants to merge 19 commits into
xyzeva:mainfrom
Minehut:alexandresequeira/mhg-1132-update-protocol

Conversation

@SantioMC

Copy link
Copy Markdown
Contributor

Based on internal pr: Minehut#1

@xyzeva xyzeva left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for trying to update hyproxy to latest, while i really appreciate this pr, its riddled with issues and excessive ai usage and unneeded changes

if you are willing to fix all of my review comments, i can take another look at it. but at its current state it is heavily blocked from being merged and i would say you shouldn't use this in production

if you don't want to fix the issues, i plan to update to latest sometime soon myself anyway.

Packet packet = packetInfo.deserializeFunction().apply(payload);
out.add(packet);
} catch (Exception e) {
log.warn("failed to decode packet id {} - dropping packet", packetId, e);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a security issue, we want these to be captured by the netty pipeline which will properly close the connection after logging, or not log at all if the player hasn't authenticated yet to prevent console spam

import java.util.Arrays;
import java.util.Map;

/**

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we dont need this large javadoc for a completely internal class describing all of what it does, it simply isn't needed or wanted

for (int i = 0; i < length; i++) {
int oldParamOffset = buf.readerIndex();
String key = ProtocolUtil.readVarString(buf, 128);
String key = ProtocolUtil.readVarString(buf, 4096000);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do not use string sizes as large as this, even if the original server uses them. use a more appropriate amount for the situation

for (int i = 0; i < length; i++) {
int oldParamOffset = buf.readerIndex();
String key = ProtocolUtil.readVarString(buf, 128);
String key = ProtocolUtil.readVarString(buf, 4096000);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do not use string sizes as large as this, even if the original server uses them. use a more appropriate amount for the situation

if ((nullBits & 0x2) != 0) {
int offset = varsOffset + motdOffset;
Pair<String, Integer> varString = ProtocolUtil.readVarString(buf, offset, 500);
Pair<String, Integer> varString = ProtocolUtil.readVarString(buf, offset, 4096000);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do not use string sizes as large as this, even if the original server uses them. use a more appropriate amount for the situation


JWTVerifier.IdentityTokenClaims claims = connection.getProxy().getJwtVerifier().validateIdentityToken(identityToken);
if (claims == null) {
log.warn("rejecting Connect: identity token failed validation (validateIdentityToken returned null)");

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we do not need a log for this

return;
}

connection.getProxy().registerPlayer(player);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why was this moved? very intentional decision to not do this

return true;
}

player.setUsername(tokenUsername);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a huge security issue, why was this check removed?

public void unregisterPlayer(HyProxyPlayer player) {
if (this.getPlayerByProfileId(player.getProfileId(), true) == null) {
throw new IllegalArgumentException("player profile id " + player.getProfileId() + " not registered");
return;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is an intentional decision to return an error here


this.playersByProfileId.remove(player.getProfileId());
this.playersByUsername.remove(player.getUsername().toLowerCase(Locale.ROOT));
if (player.getUsername() != null) {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i dont get why this check is needed, but i guess it might be good to have it?

alepaez added 2 commits July 21, 2026 14:39
Players intermittently disconnect when the Hytale proxy runs behind
Cloudflare Spectrum. Spectrum does not fragment UDP and drops any datagram
too large to forward. The client-facing QUIC codec advertised the quiche
default max_udp_payload_size (65527) and ran DPLPMTUD (discoverPmtu=true),
so datagrams grew past the Spectrum-forwardable size and were blackholed,
stalling sessions until the 60s idle timeout dropped the player.

Cap the datagram size in both directions and disable PMTU probing, both
driven by new config keys so the value can be tuned per deployment without
a rebuild:

- max-udp-payload-size (default 1200, QUIC's universal floor) sets both
  maxRecvUdpPayloadSize (advertised to the client, caps client->proxy, the
  direction Spectrum blackholes) and maxSendUdpPayloadSize (caps proxy->client)
- discover-pmtu (default false) drives discoverPmtu(...)

Behind Spectrum start at 1200 and raise toward 1350 once stability is
confirmed. For direct (non-Spectrum) UDP exposure set discover-pmtu=true.
Addresses the review on xyzeva#5.

Security:
- PacketDecoder: stop swallowing deserialization failures. Let them
  propagate so the netty pipeline closes the connection instead of
  letting a client spam malformed packets while staying connected.

Protocol string limits (were 4096000):
- FormattedMessage: rawText 4096, messageId 256, param keys 256,
  color 256, link 4096
- ServerInfo: serverName 256, motd 4096
  Applied to all 8 sites, not only the 4 flagged, to stay consistent.

Noise removal:
- Drop javadoc from internal classes (PlayerSkin, InsecurePlayerOptions,
  RequestInsecurePlayerOptions)
- Drop `final` on locals; it is not used elsewhere in the codebase
- Drop verbose explainer comments in Connect and InboundInitialPacketHandler
- Drop log.warn on rejected pre-auth connections (console spam vector)
- Lowercase internal disconnect messages, matching the existing
  "invalid referral data" convention

Intentionally unchanged: the username now comes from the verified access
token rather than a Connect field, because the 0.5.5 Connect packet no
longer carries a username. registerPlayer moving after auth, the
unregisterPlayer early return and the username null guard all follow from
that. Restoring the old equality check would compare against null and
reject every login; the UUID cross-check against the token is retained.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants