Server-Side vs Client-Side Trust

Server-Side vs Client-Side Trust

I like to pretend I’m an avid gamer. I try to keep up with the latest gaming trends, well.. at least I try to. I have a few games I typically go to, and a few games I am excited to play once they release (and I wait until a sale, or until they’ve been out long enough that the price drops… I am an adult with responsibilities after all…). I’ve played some games that are great (like Diablo III) and some games that are great in concept but lacking in execution (like Tom Clancy’s: The Division). My go-to games are generally networked and have other players playing them either in a cooperative or adversarial capacity. There are some games, however, that draw more hackers to than others. Why is that? This article is an attempt to explain the exploitation practices of these so-called “hackers” and their drive behind their exploits.

First, before we talk about how “hacking” works, we should set up some basics of network based game play. There are many methods of accomplishing this type of play I’d like to discuss with the pros and cons of each


Peer-to-peer, sometimes referred to as P2P, is exactly as it sounds. One player is the physical host of a game and other players make connections to the host. In this type of networked gaming, the host has an advantage when it comes to latency (aka lag). The inputs from the host have a latency of 0 while all other players have a latency based on the connection speed of the host player.

The pros of this type of networking is the easy of use. It doesn’t require any specific setup or resources for a player to host a game. It also does not require the gaming company to establish and maintain any dedicated servers. Many console games typically use this type of setup as the network demand is low and the games are typically casual.

Dedicated Server

Dedicated servers are hosted game servers that are specifically build to host a specific game. In games that use this type of connection, all players connect to the dedicated server and all player’s latency is based on their individual connections to the hosting server. Typically, the dedicated server is geographically positioned close to an internet backbone. This type of server is generally used for more competitive play (like Overwatch, or Counter-Strike) and can be set up in a local LAN environment for offline play.

Cloud Hosted

Cloud hosted servers are rather new to the gaming industry. These types of servers are typically allocated on-demand for a particular game and are shut down after the game resolves. This reduces the overall cost of a company for having dedicated servers as the capacity for players expands and contracts with demand. Games that utilize this type of server generally have a match-making system that finds and groups players, allocates a new server, then loads the players on the server. As technology expands, this type of gaming server is likely to become more adopted for many games.

Building Trust

With any game comes some level of trust between players. For video games, this trust can be enforced by the server hosting the multiplayer game or by the game itself. Server-side trust is generally the most trustworthy: commands come in from each player’s game, are validated, then the game state is updated and sent to each player’s client. Client-side trust, however, is more untrustworthy as the server assumes the commands it receives from each client are true and no validation is performed.

Server Side Trust

In Server Side Trust, when a command is received from any player’s client, it is validated against the rules of the game and the game state. If a player’s client sends a fake command “Player A shot Player B on the other side of the map and did a million damage” this is logically checked against the game state (Is Player A in range of Player B?) and the rules of the game (Does the weapon Player A uses allow a million damage?). If any of the commands violate the game state or game rules, the command is either ignored or flagged as suspicious. If enough suspicious commands are flagged for a player, that player could be banned from the game as it indicates cheating.

Client Side Trust

In Client Side Trust, when a server receives a command from a player’s client, it is regarded as the truth. If, somehow, a fake command is sent from a client (say, “Player A shot Player B on the other side of the map and did a million damage”), the server trusts this command as a true and accurate command, updates the game state, then relays the state to each player’s client. The result to Player B would be that they just suddenly were killed by Player A. This is obviously a problem. Client side trust assumes the game client is secure and extra steps are necessary to ensure client is not modified and the messages sent to the server are the original. In transit communications can be protected through encryption, provided the encryption is one-way and messages cannot be intercepted before or after decryption (very unlikely).

Never Trust the Client

There’s a saying in software development: “Never trust the client.” This does not refer to a person, but rather a consumer of server-side processes. Be it a web application, game client, or anything else processes transactions with a central (or distributed) server. Client side trust is inherently insecure. Server side validation is always required when communicating with a third-party (in this case a client application). This validation is crucial to ensuring the integrity of the system as a whole. Once validation breaks down, which is most likely will in very creative ways, recovering from this becomes easier if the server is already validating incoming messages against the rules of the system. Assuming everything that comes into a server side system from a third-party client is an attempt at breaking the system is a heavy-handed approach, but will reap major benefits as the system grows. Having a validation system in place to thwart adversarial communications will always provide benefits for your trustworthy clients.

In The Wild

Now that we all understand the different types of network based systems, let’s take a look at real world applications, how they are built, and the effects of the architecture of these systems.

Tom Clancy’s The Division

This game is build with client side trust as a benefit. There are trade-offs for this, of course, but an unfortunate side effect is that the game client or the traffic the game client is sending to a server can be manipulated. This particular game does have a lot of computational complexities, including world state and physics. These complexities would need to reside on the server if server side trust were to be leveraged. This, in turn, becomes expensive. Having a server powerful enough to model the physics of enemies and the world (which has a large interactive part in game play) becomes almost cost prohibitive. Ubisoft’s approach to Tom Clancy’s: The Division was to enable client side trust from the beginning of development. This allowed the development team to quickly deliver a working (and beautiful!) game to their customers. As a side effect, the game is rampant with cheaters in the PVP areas where competition is high. In this case, the negative cost of cheaters in a PVP area affected a smaller base of their customers as the PVP area was opt-in. The positive benefits involve very complex processes run on each player’s platform (PC, console, etc.) and reduced the cost of server hosting for the game. As a partial list of computations the server would need to validate from each client:

  1. Enemy position, inventory, and state (fire, poison, bleed, etc)
  2. Player position, inventory, and state
  3. NPC position, inventory, and state
  4. Projectile information (bullet drop, grenade location, damage, etc)
  5. Objective information (for each player connected)

This becomes cumbersome is a vast game like Tom Clancy’s: The Division. It also would require a lot of changes to the game client if the game were to switch to server side trust. The server would have to maintain the entire game state with each message from each client. It would also eliminate the unique aspect of Tom Clancy’s: The Division where each player has their own world in it that has it’s own state. This allows a player to join another player’s game (in a completely different state) and help them in their quest line. This also enables a changing world where certain impact on a player’s world permanently changes the world somehow. World of Warcraft accomplished this in their many expansions, but the calculations for combat in World of Warcraft and the overall computations required are minimized and streamlined for server side trust.

World of Warcraft

Possibly the best example for server side trust is World of Warcraft. This game is very light on many aspects while still immersing a player into the world through rich lore. The game itself is broken into different servers with a maximum capacity for players. Each area within any given server is then broken up into smaller worlds. Each of those worlds are broken down further into smaller areas. This is called server sharding and helps balance the overall load of any sharded area based on population. This sharding is also why some of the characters you see in a major city disappear when they leave the city: they are migrated to a different server shard. It also explains when you enter an area after an event and that area is changed: you’ve moved to a typed shard based on your quest progress.

Aside from sharding, there isn’t very complex battle calculations. There is no bullet drop, there is no projectile pathing, there is no enemy inventory (enemy loot drops are calculated at the time of enemy death based on loot tables). The entire game has been developed for server side trust and some sacrifices were made to accomplish this. These sacrifices were made up for through rich storytelling and an immersive world.

Player Unknown’s Battlegrounds

Another popular and competitive game that uses client side trust. This particular game has accumulated many cheaters due to its competitive nature. Among the things that have client side trust within the game client are:

  1. Inventory
  2. Hit Detection
  3. Collision
  4. Ammo
  5. Health
  6. Momentum

Any one of these things could be replaced with a message indicating another value. If I sent a message saying I just picked up the best gun in the game, I’d have the best gun in the game conjured up out of thing air. I could also send a message indicating I hit a player anywhere on the map and that player would take damage. This game has recently adopted Easy Anti-Cheat as a measure to prevent tampering with the client side trust. This works by providing a middle layer between the application itself and any process interacting with it. It verifies the integrity of data before sending it to the server and flags any suspicious messages. It also monitors processes that would tamper with the game client and also flag these actions. Enough flags and Easy Anti Cheat notifies the game company who can later ban the player. This effectively moves server side trust to a client side layer while also not being part of the client itself. This type of middleware is currently a better solution for applications with client side trust than rewriting or introducing server side trust.

Wrap Up

Competitive games are generally the target of cheaters and many of them opt for client side trust for the low traffic latency and increased complexity of algorithms. The only solution for applications with client side trust that require a level of integrity are the middleware applications that monitor the application process and any interactions with the process. This is not entirely fault proof, but does offer a greater deal of protection for other players against cheaters. But, as with anything that gives someone an edge in a competition, if there’s a will, there’s a way.



I am a fan of efficient processes. When I see potential for process improvement, I find myself drawn to making it better. I’ve done this in a past company I worked for when they did not have a proper defined software development life-cycle. I developed a process within my own teams that I though was better. It certainly felt better than “could someone build this deliverable on their machine and email it to the delivery guy?” Nothing was repeatable. Nothing was automatic. Nothing was tested unless someone remembered to test it. And nothing was guaranteed to work. Sound scary? It was. My proof of concept that I would eventually pitch to the company at large revolved around automation. Automation at this company meant a few upgrades.

The company was on Subversion at the time and this new thing called Git was around that everyone else was using and everyone else found it was better. In one afternoon I copied one of the projects I was leading and converted it to Git while retaining all the history. It was easy to convert. It was certainly faster than I was expecting given how slow Subversion is. And it was simple. I find Occam’s Razor to be a great mediator when arguing with myself. The simplest solution is often the right one. Switching to Git opened up a lot of doors for faster development without the feared SVN Merge Conflict (which happened multiple times a day). Git seemed more efficient in the use of my team’s time. I was sold on Git. My team was sold on Git before I even installed it. How could I get the company to upgrade? I had to show them how awesome it was.

Next up was not having to ask my developers to build a deliverable. If there’s one thing I’ve learned about the inefficiencies of doing anything manual, human error is that thing. Human error exists and can never, ever, ever be mitigated without completely removing it. Jenkins to the rescue! I’ve set up Jenkins in past jobs before so setting it up for a proof-of-concept was not big deal. About 10 minutes later it was up and running on my local computer along side the Git server (I know, I know, bad form! This was before containers people!). Having Git tell Jenkins that a thing was changed was easy. Almost too easy. A few manual builds to work out kinks in the Jenkins build then a few configurations on my local Git server and viola! The Git server was talking to the Jenkins server and a tag triggered a Jenkins build which stored the build artifacts indefinitely. Now, when we wanted to show something, we just cut a tag! (I would later expand this to an automated deployment, but this was a proof-of-concept that I need so I could change a company’s process).

My teams use this process for a few weeks tweaking things as we came across it. We knew (yes by this time the entire team was on board with the new way since it saved so much time) that we only had one chance at this pitch. After a few weeks I ran it by another team local to my office. They wanted in before I had finished the first sentence before I could ask if their team wanted in as a guinea pig. They were on it within an hour.

Some times it is better to ask forgiveness than permission. In this case, I asked for a dedicated VM (again, before containers!) located in HQ for my project. I got one after about 2 weeks and started migrating Git and Jenkins to it. Once we were migrated everything was going great! We had buy-in from the entire local office and things seemed to be going well with this out-of-control proof-of-concept-turned-beta project. Interestingly enough, productivity had increased enough that all this non-project-specific work was never noticed. I’m not saying you should go rogue, but I definitely should have pitched this sooner than I did. By this time, I asked for a meeting with the CTO and other Lead Engineers. After we figured out a time we could all be on a Skype call (migrating to Slack is a story for another time) I showed them what we were working on. I showed them Git. I showed them Jenkins. I showed them the entire process from new repository, through the Git Flow branching pattern, to first automated build. Boy am I’m glad this was a Skype call. After the initial “you shouldn’t have done this without permission” speech came the “I’m glad you did though.” They definitely liked what they saw. In my defense (and I believe everyone else in my local office at this point) we had tried to get continuous integration up and running but were continuously shot down. I felt like the poor guy behind the cart in this picture:

If you find yourself slowed by processes, think about how you can improve them!

So, the IT team in HQ took over the project and I walked them through some of the setup for Git and Jenkins. They, of course, made improvements (LDAP authentication, separate VMs, etc.) when they installed Git and Jenkins.

So, after about 2 months of this entire process, the company had adopted Git and Jenkins for a better solution. Teams were starting to migrate to Git and learn the Git Flow branching pattern. Everything was looking up! It sparked a bit of an overhaul to other processes and happened to fall right in line with their CMMI Level 3 efforts (more on that in another post). Everything seemed right in this process — everything was much more simple.

I’ve learned a lot from this experience. For my own projects I have my Git repositories hosted on GitLab. It uses a build server I host on DigitalOcean. These builds are automatically deployed (within containers!) and freely available. Heck, this site has a GitLab repository with the configurations to repeat deployment. So does my Division Gear discord bot. If you ever find yourself repeatedly building the same things manually, it might be time to fix that.