RFC: Proposal for Transfer Packets
A proposal for implementing secure transfer packets in Minecraft Java Edition
Goals
A transfer packet has been asked for by Minecraft Java developers for over a decade. This feature would reduce the need for huge proxies - greatly reducing server cost, improving load distribution, and allowing for greater creativity.
The only reason I can think for Mojang not adding this is that it requires some security considerations. A client should not be sent to a new server without having some kind of trust that it arrives at the intended destination. On the other hand, they shouldn't be bombarded with consent prompts and warnings as to not desensitise the user.
This proposal is created in such a way that it could be implemented by existing
servers, with minimal patches to core server software and only a plugin/mod for
the protocol changes.
Proposal
First: allow configuration of the keypair used for protocol encryption. Change it so that it is only generated during the first run. The key can be longer for added security, given that it's no longer being generated each time. This requires no client changes, only server-side. My reason for suggesting this will be clearer in the next part. Servers on the same network should use the same keypair.
A transfer packet includes the domain/address and port of the destination server, and a unique transfer ID. Optionally, it can include the public key of the destination server. Upon receiving this packet, if the client consents, it opens a connection to the destination server. If the public key provided in Encryption Request does not match the expected key, then it disconnects from the destination server and sends a decline response to the original transfer packet, using the corresponding transfer ID. Otherwise, it will send an acknowledgement to the original transfer packet (again, using the corresponding transfer ID). Any and all custom packets are sent through pre-registered plugin channels.
With regards to "expected keys": If the public key was not provided in the transfer packet, but it matches that of the current server, then the client should accept the transfer. If it does not match and was not provided, but the client has seen this public key before (for example, a transfer between Hypixel and Mineplex), then it should accept the transfer. If none of that is true, then the user MUST be prompted to trust the server before connecting. Also, just in case, there ought to be an option for the client to prompt on ANY unseen public key, even if it was provided by the transfer packet.
Pros and Cons
Pros
- Transfer packet
- Minimal protocol changes; practically no changes to destination server
- Possible added benefit of detecting if a server is compromised if the key is changed
- User consent is maintained
Cons
- Complex to integrate with existing proxy setups
- Servers require a patch to use the same keypair
- Potential reduced security by re-using the same keypair?
- Requires potentially complex (?) client modification
Compatibility
I want to talk about this because I think it's possibly the most crucial part - especially if this is something that gets implemented by the community before an official addition (which is what got me thinking about this).
Currently, the way one sets up a Minecraft Java network is by having several servers behind a single proxy. Each individual server only listens to the proxy, however, and not the wider internet. Doing so could allow a player to connect their own proxy and bypass authentication (since that is handled by the proxy).
If this is something we want to implement as a project for the Minecraft developer community, we must ensure that it's backwards compatible with existing proxy setups. The problem is: if it's going to be backwards compatible with proxies, then you need to find a different way of securing internal servers. Perhaps it's possible to setup an option for a 'trusted address' where the proxy is located, and get the internal server to handle authentication for everything else, but this again requires more server modification and might be a risk that a major server owner wouldn't be willing to take.
Conclusion
Overall, I think this works. The only major problem is compatibility with existing proxy setups, and I'd like some feedback on that. Also, does anyone know if the session servers would explode if you had to re-authenticate every transfer? Maybe there should be some extra stuff to handle that.
I think this would need some major support behind it for it ever to be adopted unofficially, but I don't think that's necessarily out of the question. Plenty of people are already playing with mods now, like Sodium and Phosphor, and it could be possible that the costs of running a huge proxy would be massively reduced by something like this (that is, if enough users could take the load off).
Anyway, this is a request for comments. Not the requests for comments, I don't think they care about Minecraft. Let me know what you think!