Skip to content

Add additional support for Proxy #5730

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 13 commits into
base: master
Choose a base branch
from

Conversation

Daodanfd5
Copy link

No description provided.

Tried to fix slice proxy protocol header and payload
retry to support all header mode
Based on many implementations of the proxy protocol, some applications send the proxy header as a standalone packet without payload, some applications add the proxy header to the first packet in the stream (which, unlike the first type, contains its own payload), and some applications prepend the proxy header to every packet. All header modes should now properly supported and functioning correctly.
ByteBuf content = packet.content();
GeyserBedrockPeer peer = (GeyserBedrockPeer) ctx.pipeline().get(BedrockPeer.NAME);
int detectedVersion = peer != null ? -1 : ProxyProtocolDecoder.findVersion(content);
ByteBuf content = packet.content().copy();
Copy link
Member

Choose a reason for hiding this comment

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

Why's it copied now?

final HAProxyMessage decoded;
try {
if ((decoded = ProxyProtocolDecoder.decode(content, detectedVersion)) == null) {
// PROXY header was not present in the packet, ignore.
Copy link
Member

Choose a reason for hiding this comment

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

Why was this removed?

GeyserImpl.getInstance().getGeyserServer().getProxiedAddresses().put(packet.sender(), presentAddress);
} else {
log.trace("Reusing PROXY header: (from {}) {}", packet.sender(), presentAddress);
// --- Subsequent packet processing logic ---
int detectedVersion = ProxyProtocolDecoder.findVersion(content);
Copy link
Member

Choose a reason for hiding this comment

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

Given that this is used in both cases of the if block, this can be moved outside it to reduce code duplication

GeyserImpl.getInstance().getGeyserServer().getProxiedAddresses().put(packet.sender(), presentAddress);
} else {
log.trace("Reusing PROXY header: (from {}) {}", packet.sender(), presentAddress);
// --- Subsequent packet processing logic ---
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// --- Subsequent packet processing logic ---
// Some proxy protocol implementations always send the proxy protocol header, which we should strip after reading it in the first message

Maybe also link the related issue here; that'd be useful too

// If a subsequent packet also contains a header, only strip it without using its content
try {
if (ProxyProtocolDecoder.decode(content, detectedVersion) == null) {
content = packet.content();
Copy link
Member

Choose a reason for hiding this comment

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

why is this re-assigning the content variable? This should already just be this value

}
} catch (HAProxyProtocolException e) {
log.debug("{} sent malformed subsequent PROXY header", packet.sender(), e);
content = packet.content();
Copy link
Member

Choose a reason for hiding this comment

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

why is this re-assigning the content variable? This should already just be this value

Comment on lines 80 to 93
ctx.fireChannelRead(packet.retain());
// --- Unified packet reconstruction and forwarding logic ---
// Regardless of whether the packet originally contained a header, `content` now represents the pure payload.
// To ensure consistency in the behavior of downstream handlers, we always create a new packet instance to forward.
// This avoids any issues that may arise from the difference in object instances between the original packet (retain) and a new packet.
ByteBuf payloadOnly = content.copy();
DatagramPacket newPacket = new DatagramPacket(payloadOnly, packet.recipient(), packet.sender());
ctx.fireChannelRead(newPacket);
Copy link
Member

Choose a reason for hiding this comment

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

This diff doesn't seem to be of much use? The content is now a second copy of the packets' content, nor does the construction of a new datagram packet seem necessary

…xyServerHandler.java

Co-authored-by: chris <github@onechris.mozmail.com>
@Daodanfd5 Daodanfd5 marked this pull request as draft August 11, 2025 09:27
Improves the logic for detecting, decoding, and stripping PROXY protocol headers from incoming packets. Ensures the buffer's reader index is managed correctly, avoids unnecessary buffer copies, and adds debug logging for malformed or incomplete headers. This change streamlines packet processing and reduces overhead by retaining and forwarding the original packet when possible.
Simplifies and restructures the logic for decoding and validating PROXY protocol v2 headers in UDP packets. Adds explicit whitelisting checks for proxier addresses using CIDR matchers, improves buffer handling by marking and resetting reader indices, and consolidates header decoding into a dedicated method for clarity and maintainability.
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.

2 participants