## recent communique | "Clients, Servers, and Tokens Oh My" | Thu Feb 29 2024

So I got myself in a bit of a pickle. So I knew at some point I would need to start creating logic in the game for handling connecting to Project 24's API to send information to and from the game client. The problem I came to realize was the issue of security. After spending four or so years as a web developer I have come across numerous articles and blog posts about hacks and various attacks on services. Stories from colleagues about their experiences in negating attack surfaces and handling API security. It all taught me an important lesson: thinking about and planning how you will secure your infrastructure comes first not later.

a cartoon monkey in a hat with a blank look with math equations floating all around their face

That being said I had a couple of problems:

  • Unreal Engine games can be "unpacked" or decompiled pretty easily even with Unreal's built-in encryption tools. So relying on that was a bad idea as far as sticking tokens or other auth methods in the game client

  • Games are notorious for being susceptible to "memory injection" or other methods that modify memory values at runtime. Meaning users can change the values of things in Project 24 like a player's score, enemy health, and time remaining with a little bit of know-how and some tools.

To put it simply if the game client is the one talking to the API without any validation or way to trust the information it's receiving the game would become "client-side authoritative". A friend of mine Ulises explained why this is such a bad idea with a pretty fun example:

a Linkedin post from one Ulises Himely that reads: Why does server-side validation matter?   Remember this scene from Harry Potter and the Goblet of Fire? Fred and George were able to trick the "circle" (client-side validation) and get inside. They were able to put their names in the Goblet (the server).   But, the Goblet did not trust the client at all, and immediately rejected their request to participate in the Triwizard Tournament.   Client-side validation is easy to bypass. Never trust the client (browser, mobile app, etc), and always perform additional checks in a trusted environment.

animated gif from harry potter of a set of twins jumping over the protective barrier around the goblet of fire

"Never trust the client", with those words fresh in my mind I began to look for ways to solve this problem. Lucky for me Unreal Engine has a built-in networking stack that has a solution for this: dedicated servers. Dedicated servers in Unreal Engine are built to be "server-side authoritative" out of the box, meaning you can basically look at it like a game of "Mother May I". A game client will send a command to a server such as "Do Damage to this Enemy", the server will then apply the damage to the enemy and send back a response to the like such as "The Enemy is Dead" or "The Enemy Now Has 10 HP". The client can be bound to only be able to attempt to do something and the server decides if that can happen or not.

The server, as the host of the game, holds the one true, authoritative game state. In other words, the server is where the multiplayer game is actually happening. The clients each remote-control Pawns that they own on the server, sending procedure calls to them in order to make them perform ingame actions. However, the server does not stream visuals directly to the clients' monitors. Instead, the server replicates information about the game state to each client, telling them what Actors should exist, how those Actors should behave, and what values different variables should have. Each client then uses this information to simulate a very close approximation of what is happening on the server. Networking Overview for Unreal Engine | Epic Games

So that solves things like memory injection and other forms of client-based cheating but what about talking to the Project 24 API? Glad you asked another great thing about dedicated servers is being able to have "Server-only" logic. I can write code that can only be run when in a server environment. Meaning by having the API code only enabled on the server and making the game client run all its information by the server for validation I can ensure that the players don't have direct access to the values sent to the API.

void AProject24GameMode::DoTheThing(){
#if UE_SERVER
  //... code in here will only run if its being run by a Unreal server. NEAT!
UE_LOG(LogTemp, Display, TEXT("HI FROM SERVER LAND"));
#endif
}

Example of using a UE_SERVER macro, one of many ways to bind logic to just a game server

"Hooray" were all good...right? Well, this however created a new problem....hosting game servers can be very, very, very, expensive and a complex undertaking. With the goal of shipping this title in a relatively short amount of time and being mostly self-funded I began looking high a low for a solution. Imagine my joy and surprise when I came across Rivet.

Rivet is an open-source platform for hosting and running multiplayer game servers. I have had an INCREDIBLE developer experience thus far with Rivet and a massive thank you to Nathan and the Rivet team for helping get Project 24 up in running in a little under a week, which in and of itself is incredible. Here are a few highlights of my time with Rivet so far:

  • Most everything can be controlled via a CLI and/or a web dashboard in just a few commands you can build and deploy and containerized Unreal Engine server via Docker. Did I mention it has one-click rollback for any deployment?...man I live for s&!@ like that these days.

  • A rivet.yaml file acts as your infrastructure as code. You can specify all sorts of things like how many players can be in a lobby, ports, and what docker image to use. chefs kiss

# yaml-language-server: $schema=https://rivet.gg/rivet.schema.json

#           ┌───────────────────────────────────────────────────────┐
#           │                                                       │
#           │           This configuration file is empty.           │
#           │                                                       │
#           │      Get started: https://rivet.gg/learn/unreal       │
#           │    Reference: https://rivet.gg/docs/general/config    │
#           │                                                       │
#           └───────────────────────────────────────────────────────┘


engine:
  unreal:
    game_module: Project24

# How the game lobbies run and how players connect to the game.
#
# https://rivet.gg/docs/matchmaker
matchmaker:
  # How many players can join a specific lobby.
  #
  # Read more about matchmaking: https://rivet.gg/docs/matchmaker/concepts/finding-lobby
  max_players: 1

  # The hardware to provide for lobbies.
  #
  # Available tiers: https://rivet.gg/docs/dynamic-servers/concepts/available-tiers
  tier: basic-1d1

  # What game modes are available.
  #
  # Properties like `max_players`, `tier`, `dockerfile`, `regions`, and more can
  # be overridden for specific game modes.
  game_modes:
    default: {}

  # Runtime configuration for running the Unreal game server.
  docker:
    dockerfile: server.development.Dockerfile
    ports:
      default:
        port: 7777
        protocol: udp

The rivet.yaml of Project 24, this is only a small sample of what you can configure

  • Servers are brought up and down based on need so you are only paying for what you use, also with regions covered all over the globe you can ensure your players are getting matched to the best service

  • My personal favorite all API commands are token-based AND you can interact with production APIs locally. This means you can build and run a containerized server locally and still hit Rivet's API. This means you can be sure things will behave as they should come release time.

Needless to say, if you are building any kind of multiplayer game I cannot recommend Rivet enough. Once I get more of the game built out with multiplayer functionality I play on doing a full review of how things are shaping up with Rivet. Now my only caveat is Rivet is still currently in beta, however, if this beta is any indication of how the platform is shaping up I feel like this will become a real contender in the game server hosting space. If you do end up taking a look at Rivet be sure and join the Discord the Rivet team is super active there and loves seeing what people are building with the platform. Be sure and give me a ping if you do!

As always here are a few links with details of everything I've discussed and resources I came across this month. See ya next time. Stop Dreaming. Start Creating.

Cheers,

Simon Norman

Director, Agents of SWARM

@zhymon.bsky.social

@Zhymon@mastodon.online

Follow SWARM on Social for even more updates