Skip to content

Turn Bedrock HAProxy protocol on by listing proxies, and read PROXY protocol from WebRTC relays - #6843

Open
irrld wants to merge 5 commits into
GeyserMC:masterfrom
irrld:master
Open

irrld wants to merge 5 commits into
GeyserMC:masterfrom
irrld:master

Conversation

@irrld

@irrld irrld commented Oct 28, 2026

Copy link
Copy Markdown
Contributor

Replaces advanced.bedrock.use-haproxy-protocol with its proxy list, adds PROXY protocol for UDP relays in front of the NetherNet media port, and asks extensions about a NetherNet player with the address it ends up connected from.

HAProxy protocol follows the proxy list

  • use-haproxy-protocol under advanced.bedrock is gone. Listing a proxy in haproxy-protocol-whitelisted-ips turns HAProxy protocol on for RakNet and built-in signaling, and an empty list turns it off.
  • On RakNet, the switch on with an empty list took a HAProxy header from any address, and a list with the switch off did nothing. Neither setup exists anymore.
  • RakNet only admits listed proxies. When entries are listed but none can be read (typos, an unreachable URL), every RakNet connection is refused with a warning, instead of the protocol turning off.
  • The startup warning, geyser connectiontest and the bedrockHaProxyProtocol bStats chart follow the list.

Config version 12

  • Switch on, proxies listed: no change.
  • Switch off: the list is emptied, since it was ignored before and would turn the protocol on now.
  • Switch on, empty list: HAProxy protocol ends up off, with a warning to list the proxies, as taking headers from anyone is what this removes.
  • A list comment naming the removed switch, including Geyser's default from before August, is replaced with the current one. A comment of the user's own stays.

PROXY protocol from WebRTC relays

  • New advanced.bedrock.webrtc-proxy-protocol-relays: UDP relays in front of the NetherNet media (WebRTC) port that send a PROXY protocol v2 header with each player's address. Built-in signaling and NXS both use it.
  • While it is set, players reach the media port only through the relays, so bedrock.signaling.advertise-addresses has to name them. NetherNet does not start otherwise, and logs why.
  • It is separate from the two lists above, which cover RakNet and the signaling TCP listener.

NetherNet connection requests

  • ConnectionRequestEvent for NetherNet now fires when the channel goes active, with the address the channel reports once connected, rather than at channel init with the signaling address. A player that came through a relay or proxy carries it as the proxy address, as on RakNet.
  • The connection attempt debug line names where the address came from (such as ICE_PROXY_PROTOCOL via <relay>), and where signaling met the player when that was a different address. Both respect log-player-ip-addresses.

Smaller changes

  • A connection whose transport failed with an IOException, such as a player aborting it on leaving, is closed with the transport's own disconnect reason and a debug line, instead of an error with a stack trace and "An internal error occurred!".
  • Drops the hybrid mode TODO in NetherNetServer, as built-in and NXS joins were seen sharing the WebRTC port.

From network VERSION

  • A NetherNet channel takes its address from the selected ICE pair once, as it goes active, the same way for built-in, NXS and client channels. A TURN pair keeps the signaled address when that cannot be forged.
  • Channels say where their addresses came from (AddressSource), and which relay a peer came through.
  • With relays on the ICE port only STUN lookups pass besides relay traffic, so configured TURN servers are refused there.
  • X-Forwarded-For takes the client as the rightmost entry no trusted proxy accounts for.
  • RakNet takes a datagram for a PROXY v1 header only when it starts with one.
  • A join that stalled after ICE connected is told apart from one that found no path, and the warning points at a firewall or DDoS filter.

Testing

Retail clients in 16 setups: direct, through a PROXY protocol relay (an unlisted relay and a headerless one are refused), built-in signaling behind a Cloudflare tunnel with X-Forwarded-For, NXS through a local Warden, hybrid, and RakNet behind a relay.
:core:test, including the v11 to v12 migration cases and the RakNet admission rule.

This PR used Claude Code to help write the code, the tests and this description. I reviewed every change and tested it as described above.

@tommasov03

Copy link
Copy Markdown

Since this builds on the work from #6839 and CloudburstMC/Network#106, would you mind adding me as co-author when it's squashed?

Co-authored-by: tommasov03 <110355739+tommasov03@users.noreply.github.com>

Also happy to test it in production behind Infinity Filter, which already sends PPv2 on our NetherNet media, once it's out of draft. Thanks!

@onebeastchris onebeastchris removed the PR: Needs Testing When a PR needs testing but is currently not under review label Oct 29, 2026
@irrld
irrld marked this pull request as ready for review October 29, 2026 11:08
irrld added 4 commits October 29, 2026 14:27
…otocol, and read PROXY protocol headers from the WebRTC relays listed in webrtc-proxy-protocol-relays
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.

4 participants