Archived

This forum has been archived. Please start a new discussion on GitHub.

Spam/DoS protection/connection denial?

Hello,

story: (You may skip the story :o )
we develop an open-source game (NOT an MMORPG :D)

I want to protect my server against malicious clients that spam the server (DoS-attack him).

First, Glacier2 is not an option (at the moment) as there is no way for the server to get the client's IP (when not using SSL) and I cannot rely on the client finding out its external IP and giving it to the server ...

I began implementing an own strategy to detect spamming. My server can now detect two things: "spam warning" (=this may be the start of a spam) and "spam" (=I am being spammed). This detection is done at the very beginning of any RPC.

My first idea was to just have the (RPC-called) method sleep for 1s on spam warning and sleep for 10s on spam, thus the client that spams me will not cause much damage.

Now I realised the sleeping is really stupid ; what if the client uses AMI, or if say 10 clients are spamming and my max thread pool is set to 10? All threads are asleep, thus the server is dead for up to 10s!

My second idea was to just throw an exception when spam is detected, but that does not solve spamming either: if the client just ignores any server-answer, he keeps on invoking a method that keeps on throwing an exception and waisting lots of precious CPU cycles.

My final idea is that if spam is detected, we could close the connection and ignore any incoming connections from the IP that caused spam for the next 10 seconds. That sounds like a viable solution to me.

Now the question:
Is it possible to tell the Ice (server-side) run-time to deny incoming connections from a certain IP?

I searched the whole last day for this, in the forums and the docs...

Maybe this can be done in the adapter, by changing its published endpoints and refreshing them. But the adapters endpoints seem only to be able to say "I want a connection from xxx and yyy" in contrast to "I want a connection from anybody but not xxx and yyy"?

How can I do this? Or is my attempt completely stupid? Any help is appreciated.

PS: I'm not asking for security consultation, we're an open-source project and thus can't afford consultations :)

PPS: Just a little side-question: Can I suppose that Ice is robust against attacks with faked, manipulated and unexpected messages that try to make it crash/overflow?

If you read the whole message, big big thanks for all your patience ;)

Comments

  • benoit
    benoit Rennes, France
    Hi,

    Not using Glacier2 seems like a bad idea :) Can you elaborate on the reasons why you don't use it at present?

    With Glacier2, your servers don't have to worry about such things. Clients connect to Glacier2 only and Glacier2 forwards requests to your backend servers. In addition, Glacier2 provides a session and authentication mechanism for your clients. This allows to implement some policies to limit the number of connected clients. You can for example restrict a given client (identified by a user ID or SSL identity) to only login once to your game. A client wich fails to create a session with the Glacier2 router won't be able to waste CPU time on your backend servers.

    That being said, a Glacier2 router can still be subject to DoS attacks: a malicious client can try to flood the Glacier2 router by attempting to create many sessions. There isn't much that can be done against this at the Glacier2 level. Instead, you should look into firewall solutions that allows to protect against such DoS attacks (by throttling the number of incoming connections for example).

    In any case, to answer your questions, it's not possible to configure Ice to reject connections for a given IP address. It would also indeed be a bad idea to sleep in the threads from the Ice server thread pool, a better approach consist in using AMD and scheduling a timer to send the response for the dispatched request after 10s. Anyway, I strongly recommend using Glacier2 instead. Again, you shouldn't have to worry about this in your server code :)

    Cheers,
    Benoit.
  • Hi and thanks for the elaborate answer,

    Indeed, I do understand that Glacier2 is cool and very useful and that it's stupid to re-invent the wheel :) It's just the fact with the IP address that is bothering us:

    The server is only there for the players to chat and to hold a list of open games and their location (=IP Address). The games are running on the client's PC, as usual in RTS Games (Age of Empires, Warcraft, ...) and in FPS games (CounterStrike, ...).

    Now without using Glacier2, when the client registers a new game, the server just takes the ip of the client and puts it in the game's details.

    With Glacier2, this is no more possible! The trivial solution seems to be: just have the client send its IP along with the game details. This is not as trivial as it seems: how should the client know its public IP?? The only way I found out is having another server available so the client can connect to it, ask: "give me my IP plz" and get it. This, I think, is even more stupid than ignoring Glacier2! As all the problems would just shift over to that server....

    So, I really would like to use Glacier2, but it does not seem possible. I could hack this feature into Glacier2 (love open source), but it seemed not worth the investigation ; Maybe it is now :) Or do you have any other idea?

    If I understand you, it is not possible for the Ice server to reasonably protect himself against DoS attacks? He has to trust the admin to setup a good firewall etc.?
    Too bad :(

    Again, thanks for your patience and free support!
  • benoit
    benoit Rennes, France
    Hi,

    Glacier2 in the up-coming Ice 3.4 will allow accessing the IP address of the client so this won't be an issue anymore :).

    In the meantime, you could implement the solution you mentioned based on this external server to figure out the client's IP address. Another option would be to fix Glacier2 to pass the result of Connection::toString() in the context of the session manager create() operation by changing line 266 in src/Glacier2/SessionRouterI.cpp with:
            Ice::Context ctx = _current.ctx;
            ctx["connection"] = _current.con->toString();
            _sessionRouter->_sessionManager->create_async(new CreateCB(this), _user, _control, ctx);
    

    If you want to pass this information in each forwarded call to the back-end servers, you can look into adding it to the _sslContext attribute of Glacier2::Blobject (in src/Glacier2/Blobject.cpp). Your backend sever will then have to parse the information from this context to extract the client's IP address. Let me know if you need more information on these fixes.

    Like any TCP/IP server, an Ice server or Glacier2 can't really do much more than closing the accepted connection right away after it has accepted it and figured out it was a non-authorized connection. As long as the server can keep up with the flood of connection attempts, there shouldn't be any issue. Whether or not your server can keep up with these connection attempts depends on many things however (configuration of the TCP/IP stack, whether or not connection attempts are throttled, etc).

    Also note that many DoS attacks are not even application level attacks. For more information on this, Wikipedia's Denial of Service Attack article is a good start.

    Cheers,
    Benoit.
  • benoit wrote: »
    Glacier2 in the up-coming Ice 3.4 will allow accessing the IP address of the client so this won't be an issue anymore :).
    nice! Can you say if it will be a rather long or a rather short wait for the release?
    benoit wrote: »
    to fix Glacier2 to pass the result of Connection::toString() in the context of the session manager create() operation by changing line 266 in src/Glacier2/SessionRouterI.cpp with:
    ...
    If you are allowed to, could you please tell me how you make it in the up-coming version so I can hack it in now and won't need to change our server once I upgrade to the new Ice? I mean if you make it like this, tell me the context's entry name and what data you write in it. If not, thanks anyway :)
    benoit wrote: »
    Also note that many DoS attacks are not even application level attacks. For more information on this, Wikipedia's Denial of Service Attack article is a good start.
    How is it possible that I didn't read this yet :eek: After reading it, I still have the feeling I need to protect our server. But my initial question has been answered.

    I still doubt Glacier2 protects me.
  • benoit
    benoit Rennes, France
    Pompei2 wrote: »
    If you are allowed to, could you please tell me how you make it in the up-coming version so I can hack it in now and won't need to change our server once I upgrade to the new Ice? I mean if you make it like this, tell me the context's entry name and what data you write in it. If not, thanks anyway :)

    We didn't decided how exactly this will be implemented so I'm afraid I can't provide you this information at this time.

    Cheers,
    Benoit.