Advertisement

Game server (security) for Android game.

Started by September 11, 2015 01:46 PM
4 comments, last by menyo 9 years, 2 months ago

I worked a bit with KryoNet and created a simple Android chat client/server where the server just forwards messages to the connected clients. It was incredibly easy to setup and now I want to create a turn based combat game with some RPG elements for android. You have several professional games like this around. They all heavily rely on the server to do the logic and retrieving player information like inventory, characters etc., for good reasons of course. But I'm still wondering about some things and a couple of practical examples would be great.

  1. What would be a good way to store things on the server side? If we have a look at my Heroes they can be customized so there will be many of the same types of heroes but they will mostly. Same goes for items, attributes on items get rolled randomly. So all this needs to be stored individually.
    • A database on the server side sounds good. I can add all items to a player inventory and link them when a Hero equips them.
      • I expect the database will grow very quickly even if my game just has a couple of hundred active players. And I am not certain how well a Raspberry Pi will handle a ton of queries.
      • I have some experience with MySQL and MSSQL and know how to build prepared statments against injection. How different would this be security wise? Can a published APK be unpacked and show all my queries? And where to store the DB credentials. If I'm going to do this I pretty much want this to be water tight and worse case scenario have frequent backups.
    • Raw files like XML files would be pretty good too I think.
      • I have to write and read files every time the player changes or requests information. But these files will generally be very short and I know the exact location of them. This means no multiple complicated DB queries.
      • Security wise I have no clue how good this is, or should I say how bad this is? A database can obviously be protected very well, files are just files, whenever someone gets access to the server I will be screwed I guess.
  2. Regarding combat and other player interactions, should I do all the calculations on the server side? Or can I let the client handle most things? How do (semi) professional games handle this?
    • Should I sent something like "playerX wants to attack heroA from playerY with heroB". And do all calculations at the server.
      • A lot of data need to travel through the server this way.
      • Very secure I guess in terms of cheating. But is this really nececary?
    • I could resolve combat on the client side and just send the damage and a heroID or other small data over.
      • Small packets relieving stress on the server.
      • Prone to cheating? How big is the chance that someone sends packages to my server and accepts that package? For KryoNet they have to be sending the same package class and I can add additional protection for this.
  3. I initially want to run my server on my own network on a Raspberry Pi. After publishing, would this be a bad idea for any reason and should I pay for a host?

1. What would be a good way to store things on the server side?

There are many things that need to be stored and manipulated. How you do what depends on what it is. Storage directly in data files and configuration files works for some values, particularly those read once and never worked with again. In-game stuff that doesn't persist belongs in memory, never stored. Stuff that persists is usually sent to a database of some type after critical transactions take place or at regular intervals. Some bigger transactions that need to be saved off are stuff that affects more than one player (trading goods between people) and any equivalent of a save point, like player leaving the game. Relatively minor stuff like player equipment can remain in memory until hitting one of those major checkpoints.

For the security questions, players should never have any direct interaction with the database. There are many books and resources about securing these resources. Some of the most basic things you mention -- sanitizing your input and always treating SQL parameters as queries with parameters and never as raw text strings -- are among the easiest of the requirements.

Securing your network and your software is not a task that is done once and considered complete. It is a never-ending task that must be considered in everything you do.


2. Regarding combat and other player interactions, should I do all the calculations on the server side?

Never trust the client. Validate everything.

It is trivially easy to fake or inject network commands. Nothing you do can ever prevent this, and solutions that some people naively think will protect against it, like encryption, actually do not. Your attackers control the external endpoint, including what gets passed into and through the encryption; encryption protects from outsiders tampering, but is enemy is already inside the gate.

Whenever something fails validation, the least you need to do is log it. Even better if you can take action, but always log anomalies.

Conveniently there are many log analysis tools you can use that continuously monitor log output and allow for automated response. For example, a log monitor could make a request to a running process or fire some other event that your server accepts which triggers banning a player for blatant cheating. Other log monitors could detect DDoS attacks and block machines in IP tables. Another could detect rapid login failure events and block the IP address. Another could detect non-validating commands and email them to a developer to check either for code errors or hack attempts. All of this can be powered by logging.


3. After publishing, would this be a bad idea for any reason and should I pay for a host?

Your server needs to be publicly visible. Is your Raspberry Pi accessible from the public Internet?

Deciding if it meets your needs or not is up to you. Raspberry Pi is a capable little box. I've seen people who run small servers on their NAS or other similar small box. It doesn't matter what the box is, what matters is the box is powerful enough and available/reachable to do the work. If both are true, it is fine.

However, if you do change direction and want to host it elsewhere, cloud providers are currently very popular because they automatically scale up or down based on load, and have very reliable publicly available connections. You probably aren't anywhere near this point, but one of the big benefits of services like AWS is the ability to automatically add more servers during peak time, and have servers drop off when they are no longer needed.

Advertisement


Whenever something fails validation, the least you need to do is log it. Even better if you can take action, but always log anomalies.

Didn't think about that and now you mentioned it I realize it's importance.


Conveniently there are many log analysis tools you can use that continuously monitor log output and allow for automated response. For example, a log monitor could make a request to a running process or fire some other event that your server accepts which triggers banning a player for blatant cheating. Other log monitors could detect DDoS attacks and block machines in IP tables. Another could detect rapid login failure events and block the IP address. Another could detect non-validating commands and email them to a developer to check either for code errors or hack attempts. All of this can be powered by logging.

In the meantime I have chosen for plain old MySQL. I'm currently simpy running Xamp to set things up eventually I can migrate it to something that fits my needs better but I feel comfortable with it as I developed many websites with it. That is one of the reasons I use it. Another is that it is very easy to migrate and popular in use. The last reason is that among a chat discussion I had a number of people said that MySQL would be as good as any database. Some opted for a non relational database but I have no experience at all with that. No technical choices but I am still early in developing the DB so tell me what you think.

Anyway, with a quick search I have seen that MySQL has logging features. Do you consider this adequate for a average multiplayer game that stores login credentials? Or are there perhaps 3th party logging applications that are better at the job?

One more specific burning question, where and how do I store the DB password to consider it relatively save in an architecture like this?


Your server needs to be publicly visible. Is your Raspberry Pi accessible from the public Internet?

Yes it is, well currently my PC is ;).


One more specific burning question, where and how do I store the DB password to consider it relatively save in an architecture like this?

In my experience, the most common place for security credentials is an environment variable on the machine.

The next most common place is a configuration file, but that comes with a higher risk of getting accidentally overwritten, destroyed on a deploy, or checked in to version control (meaning unauthorized people who view the code could access production machines).

1. Storing the data


You can use a SQL database, a document/key-value store, or files on disk. Either can work.

Files on disk are simple but may scale poorly to zillinos of characters. At a minimum, make the "disk" be a distributed file system, and use a/ab/abc/abcdefghij sub-path-construction. Transactions across multiple characters (secure trade, etc) aren't robust in this option unless you basically re-implement a database storage engine to keep track of logging, roll-forward, log-back, ... Scaling is not too bad; ghetto would be to map a/ to one NFS server, b/ to another NFS server, CEPH server, or whatever file system you use, .... for a top-level sharding scheme. This can then expand as needed.

SQL databases require that you define the schema reasonably rigidly, and have a method of updating the schema as your game evolves. This is the most robust method IMO, though. Transactions are typically easy. At some point, you will run out of "oomph" on a single server, no matter how big that server is. Is this at a million users? A hundred million? Ten thousand? It depends on how heavy each user is on the system.

Document stores and key-value stores, like Redis/Cassandra/Riak or just SQL table mapping "ID" to "TEXT" are a nice intermediary. You don't need to worry about the specific problems of file systems, but you still get to treat a character as a "blob of stuff" that can be XML, JSON, or whatever. Transactions are still possible, but often very hard and/or slow. Scaling is easy, though; partition/shard the data.

2. trusting the client


It is possible to trust the client and build a fantastically fun to play game. If your game gets so big that lots of players get really invested in it, and especially if you include a bunch of dollars in the equation (in-game purchases, etc,) then the temptation to cheat will increase, and once someone creates a cheat, your game can very quickly die. Most games don't die because of this, though; they die because they're not very fun/successful games!

Doing everything on the server is the "robust" way of doing it, at a cost in hosting resources needed.

3. Raspberry Pi


I love the Raspberry Pi. I own several (including several Raspberry Pi 2, which is a significant upgrade over the original.)
The main problem with the RPi for serving is that the SD-card has limited lifetime. The rigors of a database server will wear out the flash very quickly.
A USB-mounted "thumb drive" is not much better for longevity (although brands are different here.)
Thus, for anything permanent, you'd want a USB-based hard drive to put the changing data on (database, logs, etc.)
That being said, a Raspberry Pi is for doing image recognition on a robot that's driving around a lawn, or for powering a MAME arcade cabinet. It's not for running production servers.

Putting a server in a closet at home means that DNS, firewall/DMZ, continuous power, network outages, and such, will have more impact on your player base. For a development-level game, that's likely just fine. For something you want people to pay money for, you're going to want to start hosting at a VPS/"slice"/"node" service of some sort. Amazon ECC, Linode, Interserver, DreamHost ... they all have different pros and cons. (higher-level application services like Google App Engine, Heroku, Parse, etc, also exist)

that comes with a higher risk of getting accidentally overwritten, destroyed on a deploy, or checked in to version control


Structured configuration approaches like puppet/chef/cfengine, and immutable-infrastructure approaches like containers and VMs, make this kind of failure largely impossible. This assumes that you separate hardware between "development" and "production" of course -- if you develop on the same machine as you let the world in, hilarity will eventually ensue!

Also, the environment variable needs to live somewhere. That somewhere is a file that is equivalent to a config file (be it /etc/rc.local, /etc/profile, /home/dbuser/.profile, or whatnot)
enum Bool { True, False, FileNotFound };

Thanks, I eventually picked MySQL.


Putting a server in a closet at home means that DNS, firewall/DMZ, continuous power, network outages, and such, will have more impact on your player base. For a development-level game, that's likely just fine. For something you want people to pay money for, you're going to want to start hosting at a VPS/"slice"/"node" service of some sort. Amazon ECC, Linode, Interserver, ... they all have different pros and cons. (higher-level application services like Google App Engine, Heroku, Parse, etc, also exist)

Yeah, if I ever get to the point of having players pay I will be migrating to a professional host for sure. But the rest I have pretty much covered I think I cannot remember when my last Network outage was and running the Pi the whole day costs a couple of cents I'm also running a DNS just the firewall I have to look into some more.

This topic is closed to new replies.

Advertisement