Sign in to follow this  
Ryan Lepidi

Which server technology to use?

Recommended Posts

I am making a game in flash that is essentially a turn based game. It doesn't need much database interaction, it needs to communicate with the server only every 30 seconds or so. I had originally planned on having it communicate with the database using php and passing variables in the url like http://server.com/login.php?user=bob&password=abc123. Now I am contemplating writing the server as a standalone program. I know it would be more work, but would it be worth it? On that note, how would it interact with the database? Do you have the database in memory and then just actually write any updates to the actual database server every minute or so?

Share this post


Link to post
Share on other sites
The nice thing with using HTTP (such as a PHP server) is that it's easy to find web hosting plans that can run your server, and your code will work through most firewall and proxy set-ups. If you use some other protocol (such as your own server), then the available hosting plans will be severely limited. Basically, you have to use a virtual hosting program like Amazon ECC, or a self-managed dedicated server, both of which are significantly more expensive than a "regular" web hosting plan at a reputable host like dreamhost.com.

If you choose to go your own server route, then you might not need to use a memory cache, because the back-end database server already caches reads and writes for you (something like PostgreSQL or MySQL). At one transaction per player per 30 seconds, I would expect you to support at least 300 simultaneous online players on a simple shared virtual plan (like the cheapest Amazon ECC offering) with no problems. After that, you can start considering what to do to scale up, which might be as simple as paying more for a faster machine, rather than changing the code.

Share this post


Link to post
Share on other sites
You don't have to put passwords anywhere but on the client. Assuming that the server knows the cleartext of the password, then you can do the following:

1) Server keeps a mapping from "current time" to "challenge." Typically the challenge is a hash of the concatenation of the current time and a server-secret nonce. Sometimes, this is also salted with the user name. For extra security, include the client IP address (but not port) in the challenge.

2) Client requests login credentials for a given name. Server replies with the current challenge, and time used to generate that challenge.

3) Client now computes hash(name, password, challenge) and makes a new request, with name, time and computed hash.

4) The server uses the provided time and name to re-construct the challenge (after verifying that the time is reasonably recent, to avoid playback attacks). It then re-computes hash(name, password, challenge) and verifies that it's the same as that provided by the client.

5) If the hash matches, then the server can be sure that user has provided the right password to the client, but the password was never transmitted over the wire (encrypted or not).

Share this post


Link to post
Share on other sites
Quote:
Original post by hplus0603
You don't have to put passwords anywhere but on the client. Assuming that the server knows the cleartext of the password, then you can do the following:

1) Server keeps a mapping from "current time" to "challenge." Typically the challenge is a hash of the concatenation of the current time and a server-secret nonce. Sometimes, this is also salted with the user name. For extra security, include the client IP address (but not port) in the challenge.

2) Client requests login credentials for a given name. Server replies with the current challenge, and time used to generate that challenge.

3) Client now computes hash(name, password, challenge) and makes a new request, with name, time and computed hash.

4) The server uses the provided time and name to re-construct the challenge (after verifying that the time is reasonably recent, to avoid playback attacks). It then re-computes hash(name, password, challenge) and verifies that it's the same as that provided by the client.

5) If the hash matches, then the server can be sure that user has provided the right password to the client, but the password was never transmitted over the wire (encrypted or not).


Do I understand this correctly?

1) Client wants to login to username Bob with password abc123. Client sends username to server.
2) In database, server stores an entry with the current time as the key, and the challenge is hash(currenttime() . $username . $password . getConnectingIP()).
3) Server replies with the time it just used to generate the challenge, and the challenge we just hashed.
4) Client generates hash($username . $password . $challenge) and sends a request with the hash, username, and the initial time that the request was sent (right? Not the current time?)
5) The server then takes the challenge sent by the client, and after verifying that the current time is within a minute or so of the initial request, it regenerates a hash based on the username, password, and the challenge it generates. If the client and server match, success.

Let me know if I misunderstood something.

Share this post


Link to post
Share on other sites
No, that's not quite right. The server needs to store nothing in the database per connection. The server has a secret password (call it "serversecret").

The server first does:

$time = currenttime();
$challenge = hash($time . $serversecret . $connectingIp . $in_userName);
$sentData = array("challenge" => $challenge, "time" => $time);


The client then responds by calculating:

$response = hash($in_challenge . $password);
$sentData = array("response" => $response, "username" => $userName, "time" => $in_time);


The server then verifies that the client provided proper credentials by calculating:

if ($in_time < currenttime() - 30) { too_old_request(); }
$challenge = hash($time . $serversecret . $connectingIp . $in_userName);
$password = read_password_from_database_for_user($in_userName);
$result = hash($challenge . $password);
if ($result != $in_response) { wrong_password(); }


Share this post


Link to post
Share on other sites
At the risk of sounding naive, what is the advantage of using the time and ip?

* Assuming the database does not save pure text passwords but a hash.

1) The server creates a small challenge buffer of pseudo random characters and sends that to the client as a challenge.

2) The client creates a hash of the password hash and the challenge buffer then sends that new hash to the server with the username.

3) The server uses the username to look up the correct password hash in the database. Using the password hash from the database. The server calculates the hash of the password hash and the challenge that it sent earlier.

4) Assuming a correct password on the client side the server's new hash should match that of the client's transmitted hash.

The password was never sent over the internet and assuming a quality modern hash function both of these algorithms should be nearly impossible to extract the password from. Although I don't know of every possible attack that can be done.



Edit: I may have just figured out my own question. The algorithm I wrote above does not work with a stateless HTTP connection. The time guarantees the challenge was responded to within a reasonable time frame and requires nothing to be stored on the server for un-authenticated clients.

I guess this could be used for UDP connections as well to authenticate clients without the need to create any server side data about the connection until after the client has been authenticated.

[Edited by - Wolfdog on November 21, 2008 7:47:16 PM]

Share this post


Link to post
Share on other sites
You're right; the time stamp guards against replay attacks, and the IP guards against impostoring/hi-jacking to some extent.

If the client signs the hash of the password, and the server stores the hash of the password, then the HASH of the password becomes the new password -- you don't need to know the password, just the hash of it, to authenticate. Hence, with this mechanism, the server needs to store something in clear text.

The alternative is to create an encrypted, authenticated channel using public key cryptography and certificates, and then let the client send the password to the server, where the server can hash the password and compare to a hash in the database. This is what SSL does. However, this requires an exchange of trusted public keys ahead of time (such as certificates), and, more importantly, the server still sees the plaintext password at the point of authentication, so the security gains over storing the plaintext password are slim; the attack surface to an intruder or malignant operator is similar.

Share this post


Link to post
Share on other sites
Quote:
Original post by Ryan Lepidi
I still don't really have an answer to my initial question:


You have the answer, but choice wasn't made for you.

Given the amount of work with actual logic and all other details, unless you have a business plan, funding and deadlines, as well as some help, it's not worth worrying too much about the future.

Use PHP (LAMP/WAMP package) and you'll have the networking and database part taken care of in under one hour.

Can you accomplish the same using sockets and mysql C api? I think the final choice is somewhat obvious.

However, if you do have the above things, then simply decide which approach fits your plan, funding and resources better.

Share this post


Link to post
Share on other sites
if you only need to query the server every 30 seconds or so, i see no need of having a persistent connection.

If you do go with an actual server instead of php scripts, I also see no point of having memory cache (assuming we are still talking about a small turn based game). If profiling proves me wrong, this optimization can be done at a later stage once you have your prototype up and running.

(oracle has a hard limit of about 1,000 transactions per second as far as i remember)

Share this post


Link to post
Share on other sites
If you want to send data safe use something well proven like diffie hellmann.
http://en.wikipedia.org/wiki/Diffie-Hellman_key_exchange

i guess google will turn up a few written code examples both for most programming languages.

Share this post


Link to post
Share on other sites
Quote:
diffie hellmann


It turns out that diffie-hellman isn't secure against man-in-the-middle attacks, because the man in the middle can run a separate exchange towards each end, and decrypt/convert in the middle. You need some way of authenticating the sender and receiver, which means that you need either a shared secret or public-key cryptography, which means that Diffie-Hellman isn't actually needed in the end.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this