I have a web app written in c++ using TCP/IP over standard network sockets, running on Linux. The service is open to the wild and woolly internet.
Periodically I get bursts of abusive requests from spammers running automated scripts. I can detect these and close down the socket. Right now I just do a polite socket close like I would do to any valid request that has completed, with a socket lib close like this:
close( mSocket );
But sometimes closing the socket normally notifies the spam script that the socket connection has terminated, and they immediately initiate another fraudulent request.
What is the best way to terminate a TCP/IP connection that cleans up the open socket on my system, but leaves the remote party hanging. That is I want to close a socket in the way that is lowest cost for me, but highest cost for them.
@Nicholas Wilson:
Using TCP_REPAIR seems like a good idea. When a socket is closed in TCP_REPAIR mode no FIN or RST packet is sent. The remote socket is left hanging. I'm going to try it and report back. Here is my (untested) code:
if ( abuse )
{
int aux = 1;
if ( setsockopt( mSocket, SOL_TCP, TCP_REPAIR, &aux, sizeof( aux )) < 0 )
reportError( "Tried to do a rude socket close... but could not turn on repair mode.\n" );
}
close( mSocket );
I'll report back if this works. (@edit: tested answer below)
@ The "leave the socket open" idea:
This works but is sub optimal. The attacker has the ability to saturate your system with open sockets. Each request creates a new socket that is left open. With DOS attack you eventually run out of sockets.
Then there is also the problem with managing the open sockets:
- Just don't close it. Open sockets last forever. Cost for attacker: high - they get no fin. Cost for me: higher. All my file descriptors eventually get used.
- Spawn a thread per socket to sleep 10 minutes and then close the socket. Cost for attacker: high - they get no fin. Cost for me: higher. While I eventually do close the socket, for each request I have a socket used up for longer than the attacker does, and I have the overhead of a thread.
- Spawn a thread that handles expiring all abused sockets. Cost for attacker: high - they get no fin. Cost for me: higher. Like 2, lots of sockets held open. Overhead of a single thread to manage it. Code complexity, annoyance.