googleforgames / quilkin

Quilkin is a non-transparent UDP proxy specifically designed for use with large scale multiplayer dedicated game server deployments, to ensure security, access control, telemetry data, metrics and more.
Apache License 2.0
1.3k stars 94 forks source link

UDP Packet Routing based on Port #780

Open nshttpd opened 1 year ago

nshttpd commented 1 year ago

Is your feature request related to a problem? Please describe.

In an effort to reduce public IPv4 usage and rely on a Cloud Provider Load Balancer we would like the ability to route UDP packets through Quilkin to the game server based on the Port that the game server/matchmaking engine has provided to the game client. This is a thought process to make this solution viable for legacy titles that may only need slight modifications on the game server side without having to update clients with new mechanisms for token based routing through quilkin and the assorted other upstream changes that might be needed in matchmaking and other services.

Describe the solution you'd like

The ability to route from client to game server based on the Port that is contacted on the CSP Load Balancer. As game clients are matched to a game server in a K8S cluster the CSP Load Balancer would have listeners on the same range of ports that the game server pods are allocated from. As clients communicate with a game server have the packets route from the Load Balancer to quilkin and then to the game server based on the port that the packet landed at the load balancer on.

Describe alternatives you've considered

For one cloud provider we could write an even more custom port allocation mechanism based on a Global Accelerator product from the CSP, but that would be a single solution for a specific cloud provider. Having a solution that would work for all cloud providers would be preferred.

Additional context

There is an impending event in Feb of 2024 when AWS will begin charging for all IPv4 addresses in use and not just idle ones. Being able to route by port number that the client connects to is an attempt to try and rectify some of these costs with the least amount of changes needed to be uptaken by game teams and studios.

XAMPPRocky commented 1 year ago

Thank you for your issue! We discussed this at our last community meeting, and the work to support this feature should be minimal.

game server in a K8S cluster

Just to clarify, are your servers using agones? If they aren't that's fine we would just need to add support for watching generic k8s nodes or pods.

I think the solution we can implement on the Quilkin side is firstly update quilkin to accept a range of ports rather than be bound to a single port, and for Quilkin to attach the source port as metadata when running through the filters. Then I think we should update quilkin to pick up more metadata from the gameserver/pod, right now we only keep the quilkin.dev/tokens metadata, but we should store more than that. Lastly we should update TokenRouter filter to be just Router, and have it compare against any metadata rather than just bytes.

Altogether the configuration should look like this (except the endpoints are retrieved from k8s), you set their quilkin.dev/source_port metadata on gameserver allocation, Quilkin picks up that metadata from the watch, and then filters incoming traffic by matching the source port received to the endpoint's port metadata.

version: v1alpha1
filters:
  - name: quilkin.filters.router.v1alpha1.Router
    config:
        metadataKey: quilkin.dev/source_port
clusters:
  default:
    localities:
      - endpoints:
        - address: 127.0.0.1:26000
          metadata:
            quilkin.dev:
              source_port: 8888
        - address: 127.0.0.1:26001
          metadata:
            quilkin.dev:
              source_port: 7777
nshttpd commented 1 year ago

Just to clarify, are your servers using agones? If they aren't that's fine we would just need to add support for watching generic k8s nodes or pods.

Yes, for the primary use case the game servers are running via Agones. There is a secondary use case, but I would expect us to leverage Quilkin via xDS configuration control plane for that, where we would deal with the "watching" since that is already an aspect of Quilkin.

XAMPPRocky commented 1 year ago

There is a secondary use case, but I would expect us to leverage Quilkin via xDS configuration control plane for that, where we would deal with the "watching" since that is already an aspect of Quilkin.

FWIW if there is a standard and open source method of "watching" the resources (e.g. nomad, docker swarm, etc.), it would be great to upstream that to Quilkin directly.

nshttpd commented 1 year ago

We are working through some different scenarios for the one secondary use case and possibly another. Any of those that we can upstream back into Quilkin or googleforgames after various corporate flaming hoops being breached we shall.

markmandel commented 1 year ago

A big +1 on @XAMPPRocky 's initial implementation design. I like that a lot, and I think it will work well.

There is a secondary use case, but I would expect us to leverage Quilkin via xDS configuration control plane for that,

Something I've been meaning to write a ticket on for a while, which would be a Redis provider, wherein you could store your configuration information in Redis and update it there, and we'd handle the xDS communications. Similar to what Traefik does - would something like that suit your needs?