nex-go icon indicating copy to clipboard operation
nex-go copied to clipboard

Experimental proxy mode

Open jonbarrow opened this issue 1 month ago • 4 comments

Resolves #XXX

Changes:

Adds in an experimental "ProxiedMode" setting. This setting allows a PRUDP server to sit behind a proxy server, so long as the proxy server can properly encode/decode/forward the server/client packets. This is mostly useful for features such as balancing multiple server instances, in-flight packet inspection, etc.

When in this mode, all packets hitting the PRUDP server will be prepended with the original clients IP/port, so that NEX can still track this for features like matchmaking, and all packets sent from the server will have this data also attached so that the proxy server can route the response back to the destination. The proxy server is expected to strip this data before forwarding to the client.

When in this mode, the clients SocketConnection.ProxyAddress is populated to the proxy servers address, and its SocketConnection.Address value is overwritten with the data from the new packet header. This is done in an attempt to let the NEX protocol handlers continue to rely on SocketConnection.Address without worrying about whether or not the client is behind a proxy.

Also includes an example proxy server, though all it does is map between proxy ports and upstream servers. It does not do any inspection, balancing, etc.

Untested, but should work. At least for non-matchmaking connections. I need some help making sure this won't break matchmaking.

  • [x] I have read and agreed to the Code of Conduct.
  • [x] I have read and complied with the contributing guidelines.
  • [ ] What I'm implementing was an approved issue.
  • [ ] I have tested all of my changes.

jonbarrow avatar Nov 04 '25 15:11 jonbarrow

It's worth noting there's a standardised protocol for this sort of thing (also includes IPv6 and TCP for wss): https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt Using the standard one would make packet captures easier

It's probably fine to do our own thing to start with though.

ashquarky avatar Nov 04 '25 22:11 ashquarky

I think it would be a good idea to add a special header (with magic and version number), that way we can expand the proxy in the future without too much issues of making changes (since those could be identified with the version)

DaniElectra avatar Nov 04 '25 23:11 DaniElectra

It's worth noting there's a standardised protocol for this sort of thing (also includes IPv6 and TCP for wss): haproxy.org/download/1.8/doc/proxy-protocol.txt

This doesn't include UDP though, making something custom in this case should be good

DaniElectra avatar Nov 04 '25 23:11 DaniElectra

Using the standard one would make packet captures easier

Normal packet captures, such as those taken with Hokaku, wouldn't be affected by this. The client is still sending and receiving normal, unmodified, PRUDP packets. A packet capture would see the client talking to the proxy, thinking it's the real origin server like any other. The modification happens purely on the servers side of things, where the source/destination sections are added/removed by the PRUDP server/proxy prior to the packet being processed by the NEX server/sent back to the client

jonbarrow avatar Nov 04 '25 23:11 jonbarrow

@ashquarky @DaniElectra I've made it so that the proxy handling is now modular like we have for the encryption/compression implementations, as well as added 2 more protocol headers

I don't super love the fact that it modifies the addresses the way it does, but it was the cleanest way I could get it working for now

That said, I'm not confident that the PROXY protocol v2 implementation is 100% correct, and maybe SocketConnection.ProxyAddress could be renamed since now it's being used even when not proxying?

jonbarrow avatar Nov 07 '25 16:11 jonbarrow