Friday, September 24, 2010

Ubuntu, Linode and Locales

How annoying. The default locale on a default Ubuntu 10.4 on Linode is...well I'm not sure that it's even set to anything. So how do you fix this and ensure that you get full UTF-8 goodness? Well...I'm still not entirely sure, but I think I'm on to something. I'm sure I'm doing it completely wrong, but after spending upwards of an hour trying to figure out how to fix this I just don't really care anymore as long as it works.

The magic incantation appears to be update-locale LANG=en_US.UTF-8. Doing this and rebooting your computer you will be greeted with...something that's still not UTF-8, as for some reason it still decides that it wants to default to ISO-8859. However, if you start screen, you will find out that your screen session is UTF-8 enabled and everything works peachy.

Yeah. Pretty dumb, especially when there appear to have been perfectly fine and easy ways to configure the locale in previous versions of ubuntu. Unfortunately, localeconf no longer exists as a package and dpkg-reconfigure locales doesn't actually give you any interactive prompts. The only clue I have to go on is that /var/lib/locales/supported.d/local appears to list both ISO-8859 and UTF-8 versions of en_US. I don't want to delete ISO-8859, since I'm pretty sure it's needed for some legacy applications that don't support UTF-8, but I don't have a clue how to make UTF-8 the default when logging in.

EDIT: In debian I can't get any further but the reconfigure command is aptitude install locales and then dpkg-reconfigure locales.

EDIT #2: Another Ubuntu VPS that I have tried recently doesn't even give you the any locales out of the box. aptitude install language-pack-en should give you what you need.

Doom server management 101

After having spent a considerable amount of time running servers of my own, I have happened upon a process for putting Doom servers up that I would like to share with any who care to listen. This allows me to get servers up and running rather quickly, without having to fiddle around with a directory full of shell scripts or whatever else most server owners use. I will give everything to you on a silver platter at the end of this post, but I think it's important to comprehend the fundamentals behind my organization first, otherwise it will make no sense to you.

1. Split your configuration up


How many times have you wanted to start a generic Deathmatch server, or a generic TDM server, or a generic CTF server, and simply copied the config file from another server? Now, assume that a new version of your port of choice comes out and suddenly, there is a neat new flag or feature that you want to enable on every single server. Or lets say that after some experimentation your players demand a change to a gametype (for example, changing the fraglimit on your TDM servers). You could go back through every single one of your config files and add those configuration pieces to every single file, hoping you don't skip one. Or you could harness the power of exec.

exec is a simple command that executes another config file, and is usually used at the end of a server startup string. However, it's just as usable inside of a configuration file. To wit:

doom2-coop.cfg


// Execute base Team Deathmatch params
exec "/opt/skulltag/cfg/coop.cfg"
sv_hostname "[MS] My Servers || Doom 2 Cooperative"

Just keep all your TDM configuration inside of tdm.cfg, and you're golden.

2. Abuse the "working directory"


Now you're probably wondering. "That's awesome. However, what if I move my configuration files? Then they'll all break again!" Yep, absolute paths will do that do you. However, before you embark on using relative paths, you need to know something that will catch you off guard. If you specify a path in a config file and it references something other than an absolute path (i.e. one with a C:\ or / at the beginning), it will attempt to use a path relative to the location that the program was started. This is not necessarily the same thing as the directory the server binary is located in either, as you can run programs from any directory. For example:

$ cd /opt/skulltag
$ ./bin/98c/skulltag-server +exec "cfg/doom2-coop.cfg"


This will load /opt/skulltag/cfg/coop.cfg, not /opt/skulltag/bin/98c/cfg/coop.cfg, all because you started it from /opt/skulltag.

Neat-o, right? However, this doesn't just work for configuration files. It works for anything that uses a path. Observe:

$ cd /opt/skulltag
$ ./bin/98c/skulltag-server -iwad "wad/doom2.wad" +sv_banfile "list/banlist.txt" +exec "cfg/doom2-coop.cfg"


Now you're cooking with gas. Your server binaries are separated from your wad files, which are separated from your banlists, which are separated from your config files.

Putting it all together


Here is a sample skeleton config file that I use for my own servers. I put this in /opt/skulltag/cfg/skeleton.cfg and whenever I need a new server I simply copy the config file and then +exec it from the command line.

cfg/skeleton.cfg


// SKULLTAG SERVER CONFIGURATION FILE
// by AlexMax

// INCLUDE FILES
// Do not remove any of these commands.
exec "cfg/include/reset.cfg"
exec "cfg/include/global.cfg"
exec "cfg/include/alias.cfg"

// GAMEPLAY INCLUDES
// Uncomment one of the following commands to select which flavor of doom
// gameplay you wish to use.
//exec "cfg/include/os.cfg" // Oldschool settings (-deathmatch)
//exec "cfg/include/os-altdeath.cfg" // Oldschool settings (-altdeath)
//exec "cfg/include/ns.cfg" // Newschool settings
//exec "cfg/include/st.cfg" // Skulltag settings

// GAMETYPE INCLUDES
// Uncomment one of the following commands to determine which gametype you
// wish to play.
//exec "cfg/include/duel.cfg"
//exec "cfg/include/dm.cfg"

// ADDITIONAL SETTINGS
// If there is a setting that is either not covered by the above includes or
// is a setting you wish to overide, you should place such settings here.
// Please read the Skulltag Wiki for a full list of possible server settings.

// MAP ROTATION
clearmaplist

// Shuffle Maplist. If set, maps will be picked randomly from the available
// added maps.
sv_randommaprotation false

// Add any maps that you would like to be included in the map rotation
// to the section below.
// -- START MAPLIST --
addmap map01
addmap map02

addmap map03
addmap map04

addmap map05
// -- END MAPLIST --

// Set the map that you want to be loaded when the server starts here.
map map01

cfg/include/reset.cfg


// RESET CONFIGURATION FILE
// by AlexMax

// There should never be a reason to edit this file. This merely sets up sane
// defaults so your configuration doesn't keep any residual cvars from other
// servers.

crashlogs 2
crashlog_dir "crashlogs/"
duellimit 0
fraglimit 0
pointlimit 0
timelimit 0
winlimit 0

sv_adminlistfile "list/adminlist.txt"
sv_banexemptionfile "list/whitelist.txt"
sv_banfile "list/banlist.txt"
sv_banfilereparsetime 60
sv_broadcast false
sv_colorstripmethod 1
sv_defaultdmflags false
sv_disallowbots true
sv_enforcemasterbanlist true
sv_enforcebans true
sv_forcepassword false
sv_forcejoinpassword false
sv_joinpassword ""
sv_logfile_append true
sv_logfilenametimestamp false
sv_logfiletimestamp true
sv_logfiletimestamp_usedate true
sv_maprotation true
sv_markchatlines true
sv_minvoters 1
sv_password ""
sv_pure true
sv_timestamp true
sv_timestampformat 0
sv_updatemaster true

cfg/include/global.cfg


// GLOBAL CONFIGURATION FILE
// by AlexMax

// Put your configuration changes that you want to see across all servers
// in this file. You should keep this file hidden, for obvious reasons.

// Server title. This is used anytime you forget to set the hostname from
// the command line or another config file. I suggest using your server name,
// followed by "Skulltag Server" or something equally vague.
set sv_hostname "My Skulltag Server Farm || Skulltag Server"

// Host e-mail. If you want your users to be able to contact you via e-mail,
// put it here. Anybody who queries the server in a server browser can see
// this e-mail, so make sure it is an e-mail address that you don't mind
// being public-facing and unobfuscated.
sv_hostemail "user@example.com"

// Message of the day. This message will display to your users when they join
// your servers. Line breaks can be used here by using \n.
sv_motd "Welcome to Skulltag!\n\nHave fun!"

// RCON password. This is used to obtain access to the Skulltag server
// console while you're playing on the server as a client or through an
// RCON utility.
sv_rconpassword "changeme"

// Server website. If your server has any custom WAD files and you wish for
// them to be downloaded by server browsers such as Odalauncher, IDE or
// Doomseeker when connecting to your server, put the URL where the files can
// be located here.
sv_website "http://www.example.com/"


Take a good look at these config files so you can tell where files belong and what other config files you need to populate yourself, such as cfg/include/os.cfg and cfg/include/duel.cfg.

Finally, you need to start the server. I don't actually use shell scripts, but here's a sample one that ought to work, just substitute in your server parameters, and put it in the "root" directory of your skulltag installation.

Sample shell script


#/bin/sh
cd /opt/skulltag
./bin/98c/skulltag-server -iwad wads/doom2.wad -file wad/WADNAME.WAD -useip YOURIP -port PORT +sv_hostname "YOUR SERVER NAME" +exec cfg/CONFIG.CFG +logfile log/LOGFILE.LOG

Friday, September 17, 2010

A few thoughts on policing multiplayer communities

The other day, I had someone privately confide in me that they were overwhelmed by the amount of hacker witch hunts that were going on in their multiplayer community. I won't name who brought the concern up, or the name of the community, but an interesting question follows: how do you keep hackers out of a free multiplayer game while at the same time not making it too difficult for legitimate players, especially those who play casually and do not participate in the community proper, to play the game.

Before we continue, as someone who primarily plays Doom, I will list the three major multiplayer ports and their policing policies:
  • Odamex: Bans are purely done on an IP basis. Server owners can ban an IP or a whole range of them, and can store them in a banlist kept locally on the server.

  • Skulltag: Has the same local banlist as Odamex. In addition, there is a banlist handed out by the Skulltag master server that servers are required to use. Also, the source of the port is closed to prevent cheating.

  • ZDaemon: Has the same local and global banlist as Skulltag. In addition, you are required to create an account in order to play on a public server. Account creation is automated. In addition, access to the official forums is tightly controlled, your forum account must be verified manually by an administrator.

I am of the opinion that some of these policing systems are defective. Some of them are more defective than others, but they are all either deficient or defective in some way, and I'll list the primary reason why:

Using IP addresses to ban hackers will never be a comprehensive solution

If someone really wants to play on your servers, they will find a way. If you disable their account, they will create another one. If you ban them by IP, they will proxy around it. If you figure out a way to ban all open proxies, they will find less common ones. If you require some form of real life identification, they will steal it.

However, IP bans are not entirely useless. Many firewalls and intrusion detection systems use IP bans to deal with potential attackers, by blocking IP's after X failed attempts, or by whitelisting IP ranges where users are unlikely to come from. There is also the fact that banning an IP from a server is often enough to keep less ambitious undesired players out, perhaps those who are guilty of merely annoying the patrons of the server

So IP bans do have a use. However, these controls should be made available on a server-by-server basis, as the notion of there being one "blessed" central body that is capable of professionally and timely handling accusations of hacking for an entire free game is laughable at best.

The prospect of being able to keep an accused hacker or a supremely annoying user off of all servers is an appealing one, but the usage of the IP ban far too often promotes ban ranges that cover entire /24's or /16's, often banning entire countries or continents in the vain hopes that the problem will go away. Realistically, all it means is that a hacker now needs to find a proxy outside the range, and any legitimate players inside that range are out of luck unless they take the extraordinary step of pleading to the administrators in charge to let their IP range through. Most users will not take this step and instead play something else, since getting a "master ban" on their IP means that they can not play on literally any server on the server list.

There is also the question of community drama. Skulltag and ZDaemon have one "blessed" master banlist. If servers refuse to use the master banlist, they are not allowed to be listed on the master server list. In the past, there have been several incidents where IP ranges of players have been banned by the "blessed" administration for reasons other than hacking, and yet the server administrators are powerless to whitelist these IP ranges if they decide that they would rather "risk it" or otherwise disagree with the global bans. Arguments for preserving the "purity" of listed servers is a pretty laughable when you take into consideration that even with such a master banlist, there are rampant rumors of players hacking anyway. Far more popular games such as Battlefield Bad Company 2 and Team Fortress 2 both allow the server administrator to disable their "master banlists", and many free games don't even have a master banlist at all, such as Warsow and Urban Terror.

To sum things up: Globally-enforced IP banlists don't prevent hackers from using your servers, and can victimize perfectly innocent players, either knowingly (through community drama) or not (random player who is caught in the master banlist).

A note on user accounts.

Although I am clearly not a fan of using IP banlists for global policing of multiplayer game communities, this does not mean that I am also not a fan of user account systems. In fact, I love the idea of them. First, accounts give you player verification; it's much harder to pretend that you are a specific player when you don't have their credentials. They also give you persistence; an older, established account is much less likely to be someone who is on your server to ruin other players experience. It also opens up the doors to other neat features, such as the possibility of using your account as Remote Console credentials, or Modern Warfare-style experience points (which could be used by modifications).

One common mistake I've seen from time to time is where account systems are based on a username. I personally prefer something along the lines of Steam or Quakenet's Q, which does not guarantee you a nickname, as it also doesn't force you into a nickname either and allows it to change it later. And honestly, for a free game, I think that it would be a better idea if logins were optional, so players could play anonymously.

This is the area, in my opinion, where Odamex could use some improvement. Some form of optional user authentication would allow telling the legit players from the fakes a lot easier.

An additional note: I have been asked how these views extend to attacks against a game master server itself, for example a malicious server host that spams the master server with 255 servers running bot matches that advertise hacks in the hostname. I would consider that an attack against the master server itself. Those attacks ought to be blockable at the master server level by using an X server per IP limit, or filtering out heartbeats from malicious servers at the firewall level. But you don't need a forcibly distributed master banlist for that.