How to deal with network port abuse in sockets - c++

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.

Ok, did some research and I have an answer that works for me, based on TCP_REPAIR. It is a little more complex than I thought at first:
if ( abuse )
{
// read some bytes from the spammer - to establish the connection
u32 tries = 20;
while ( tries )
{
sleep( 1000 );
char tmpBuf[32];
s32 readCount = recv( mSocket, &tmpBuf[0], 32, 0 );
if ( readCount > -1 ) break;
tries--;
}
#ifdef TCP_REPAIR
int aux = 1;
if ( setsockopt( mSocket, SOL_TCP, TCP_REPAIR, &aux, sizeof( aux )) < 0 )
{
reportError( "could not turn on repair mode" );
}
#else // !TCP_REPAIR
// no TCP REPAIR - best we can do is an abort close
struct linger so_linger;
so_linger.l_onoff = 1;
so_linger.l_linger = 0;
if ( setsockopt( mSocket, SOL_SOCKET, SO_LINGER, &so_linger, sizeof so_linger ) < 0 )
{
reportError( "Cannot turn off SO_LINGER" );
}
#endif // TCP_REPAIR
}
close( mSocket );
At the kernel level, the TCP stack will either send a FIN or RST packet if you close a connection, no matter how you do it ( with either close or shutdown ). Either way the attacker is notified that you closed the connection.
We want to silently close the connection and let them wait around to realize you're not answering... because we're vindictive.
TCP_REPAIR is a new socket API designed to allow you to 'freeze' a socket, save its state, and reload the socket state on another process or even another system. Under normal usage the client would never know their connection was transferred elsewhere.
But we can abuse this API, we put the socket in repair mode, but don't save its state and never restore it. When we close the socket in repair mode - it gets silently deleted.
This works for abusive requests that have already begun. That is we've read the spammer's request and decided it was fraud and TCP_REPAIR killed it.
But if you block requests by IP, right after connect, without first reading the socket, somehow the remote party is notified. They get an RST. Or probably something in the connection never quite completes and the remote system aborts the request almost immediately.
So we first read a few bytes from the hacker's socket. In my case the socket is already in non-blocking mode. But if not you want to set the socket to non-block, or else you open yourself up to the hacker opening connection, but sending no packets and leaving your server hanging - like you plan to do to him. If after a few microseconds you don't get a packet you shut him down anyway.
But if you read a few bytes from him, then his program is left waiting for a response from you that never comes.
TCP_REPAIR is only available on Linux Kernels 3.5 and above. Below that the best I can do is a 'dirty' socket close. This is where instead of sending him a FIN you send him and RST. It will look to him like a valid connection was never established. To do this, you turn off SO_LINGER, to essentially break the socket connection close handshake, and then call close.
Works like a charm, point your browser here:
http://oroboro.com/fail
Chrome at least will hang there for 5-10 seconds. Looking at my logs where I was getting 10 hits per second - he's only able to hit me every 10 seconds or so. Load on my system from this: 0.
See ya sucker!

When you detected a malicious client, I would recommend you to not just close the connection, but to also refuse any new connections originating from the same IP address.
What you can do at least is blacklist the IP in your application. Keep a list of banned IP addresses and immediately close any accepted socket which originates from an IP on that list.
But to protect more of your resources, it would be even better to block the connection further outward in the network architecture. When you are able to do so, notify the gateway router to block it. When that's impossible, try to get the load balancer to block it. Failing that, at least add a rule to the local firewall of the server.
But keep in mind that many such attacks originate from consumer-grade internet connections (with or without the user being aware). That usually means their IP addresses are assigned and regularly re-assigned dynamically. An IP which was used by a spammer a few days ago might now be used by a legitimate user. So IP-based bans shouldn't last forever.

Use this:
#include <sys/socket.h>
int shutdown(int socket, int how);
It will send a RST and close (the connection) immediately. This will make it seem, that there's no service on that port and the attacker will hopefully cease spamming on that port. Call close() to free the handle.

When you detect an abuse
have a pool of sockets for "spammers" whenever you detect abuse you put them in the pot using one of those sockets. if no free socket is available recycle the oldest and just shutdown and close it.
if a connection qualifies as !abuse let them use a proper socket.

Related

boost::asio::read in TCP client app takes long time to return if connectivity is lost

I have tried to search this a lot. I am new to network+tcp-sockets programming.
I am using TCP sockets to communicate data over network. I have a host app & a client app both written in C++ & using boost::asio on both ends to communicate data.
In the client app, I am using boost::asio::read to read some data from a socket in my C++ client application. The host application runs on a different machine.
Following is the code where I read some data & try to determine if there are errors.
boost::system::error_code error_code;
std::size_t data_received = boost::asio::read(socket, boost::asio::buffer(&data_to_read, sizeof(data_to_read)), error_code);
if (error_code == boost::asio::error::eof) {
//ends here if the host app closes the socket
//log error & return
}
if (data_received <= 0) {
//log error & return
}
I receive a boost::asio::error::eof when host app closes the socket and it works to update my UI to show that I have lost the connection.
But here is the problem: When the network/wifi goes off on the host app then boost::asio::read takes a long time to return. Something like 2 minutes. Then I get a boost::asio::error::eof error after a long delay. Strange ! I cannot afford this latency as I need to quickly update UI for user that data could not be fetched from the host app.
Why doesn't asio return quickly when network is turned off or connectivity is down ? Is there some other way to detect this or handle this ?
PS: Note that boost::asio::read is a blocking call but it does not lock my UI thread if it takes time to return because I am doing this in a worker thread.
TCP is designed to be "reliable," even in the face of seemingly catastrophic problems. It does this with a series of timers and retransmissions when the other end of a connection does not respond. How often, and how long, the retransmissions take place depends on the OS. It can be minutes, or even hours, before a connection is reported down.
Internally sockets have a group of options to control keep alive settings that you can set on the socket (if boost::asio exposes them). A quick google search for 'tcp keepalive' brought up a bunch of examples.
Another option is to implement your own timing mechanism where you constantly send packets & responses over the tcp connection & define yourself what the appropriate timing should be.

interface is down but netstat still shows the connection established? [duplicate]

This question already has answers here:
Java socket API: How to tell if a connection has been closed?
(9 answers)
Closed 5 years ago.
When I'm using e.g. PuTTY and my connection gets lost (or when I do a manual ipconfig /release on Windows), it responds directly and notifies my connection was lost.
I want to create a Java program which monitors my Internet connection (to some reliable server), to log the date/times when my internet fails.
I tried use the Socket.isConnected() method but that will just forever return "true". How can I do this in Java?
Well, the best way to tell if your connection is interrupted is to try to read/write from the socket. If the operation fails, then you have lost your connection sometime.
So, all you need to do is to try reading at some interval, and if the read fails try reconnecting.
The important events for you will be when a read fails - you lost connection, and when a new socket is connected - you regained connection.
That way you can keep track of up time and down time.
Even though TCP/IP is "connection oriented" protocol, normally no data is sent over an idle connection. You can have a socket open for a year without a single bit sent over it by the IP stack. In order to notice that a connection is lost, you have to send some data on the application level.(*) You can try this out by unplugging the phone cable from your ADSL modem. All connections in your PC should stay up, unless the applications have some kind of application level keepalive mechanism.
So the only way to notice lost connection is to open TCP connection to some server and read some data from it. Maybe the most simple way could be to connect to some FTP server and fetch a small file - or directory listing - once in a while. I have never seen a generic server which was really meant to be used for this case, and owners of the FTP server may not like clients doing this.
(*) There is also a mechanism called TCP keepalive but in many OS's you have to activate it for all applications, and it is not really practical to use if you want to notice loss of connection quickly
If the client disconnects properly, a read() will return -1, readLine() returns null, readXXX() for any other X throws EOFException. The only reliable way to detect a lost TCP connection is to write to it. Eventually this will throw an IOException 'connection reset', but it takes at least two writes due to buffering.
Why not use the isReachable() method of the java.net.InetAddress class?
How this works is JVM implementation specific but:
A typical implementation will use ICMP ECHO REQUESTs if the privilege can be obtained, otherwise it will try to establish a TCP connection on port 7 (Echo) of the destination host.
If you want to keep a connection open continually so you can see when that fails you could connect to server running the ECHO protocol yourself rather than having isReachable() do it for you and read and write data and wait for it to fail.
You might want to try looking at the socket timeout interval. With a short timeout (I believe the default is 'infinite timeout') then you might be able to trap an exception or something when the host becomes unreachable.
Okay so I finally got it working with
try
{
Socket s = new Socket("stackoverflow.com",80);
DataOutputStream os = new DataOutputStream(s.getOutputStream());
DataInputStream is = new DataInputStream(s.getInputStream());
while (true)
{
os.writeBytes("GET /index.html HTTP/1.0\n\n");
is.available();
Thread.sleep(1000);
}
}
catch (IOException e)
{
System.out.println("connection probably lost");
e.printStackTrace();
}
Not as clean as I hoped but it's not working if I leave out the os.writeBytes().
You could ping a machine every number of seconds, and this would be pretty accurate. Be careful that you don't DOS it.
Another alternative would be run a small server on a remote machine and keep a connection to it.
Its probably simpler to connect to yahoo/google or somewhere like this.
URL yahoo = new URL("http://www.yahoo.com/");
URLConnection yc = yahoo.openConnection();
int dataLen = yc.getContentLength() ;
Neil
The isConnected()method inside Socket.java class is a little misleading. It does not tell you if the socket is currently connected to a remote host (like if it is unclosed). Instead, it tells you whether the socket has ever been connected to a remote host. If the socket was able to connect to the remote host at all, this method returns true, even after that socket has been closed. To tell if a socket is currently open, you need to check that isConnected() returns true and isClosed() returns false.
For example:
boolean connected = socket.isConnected() && !socket.isClosed();

Non-blocking TCP socket and flushing right after send?

I am using Windows socket for my application(winsock2.h). Since the blocking socket doesn't let me control connection timeout, I am using non-blocking one. Right after send command I am using shutdown command to flush(I have to). My timeout is 50ms and the thing I want to know is if the data to be sent is so big, is there a risk of sending only a portion of data or sending nothing at all? Thanks in advance...
hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
u_long iMode=1;
ioctlsocket(hSocket,FIONBIO,&iMode);
connect(hSocket, (sockaddr*)(&sockAddr),sockAddrSize);
send(hSocket, sendbuf, sendlen, 0);
shutdown(hSocket, SD_BOTH);
Sleep(50);
closesocket(hSocket);
Non-blocking TCP socket and flushing right after send?
There is no such thing as flushing a TCP socket.
Since the blocking socket doesn't let me control connection timeout
False. You can use select() on a blocking socket.
I am using non-blocking one.
Non sequitur.
Right after send command I am using shutdown command to flush(I have to).
You don't have to, and shutdown() doesn't flush anything.
My timeout is 50ms
Why? The time to send data depends on the size of the data. Obviously. It does not make any sense whatsoever to use a fixed timeout for a send.
and the thing I want to know is if the data to be sent is so big, is there a risk of sending only a portion of data or sending nothing at all?
In blocking mode, all the data you provided to send() will be sent if possible. In non-blocking mode, the amount of data represented by the return value of send() will be sent, if possible. In either case the connection will be reset if the send fails. Whatever timeout mechanism you superimpose can't possibly change any of that: specifically, closing the socket asynchronously after a timeout will only cause the close to be appended to the data being sent. It will not cause the send to be aborted.
Your code wouldn't pass any code review known to man. There is zero error checking; the sleep is completely pointless; and shutdown before close is redundant. If the sleep is intended to implement a timeout, it doesn't.
I want to be sending data as fast as possible.
You can't. TCP implements flow control. There is exactly nothing you can do about that. You are rate-limited by the receiver.
Also the 2 possible cases are: server waits too long to accept connection
There is no such case. The client can complete a connection before the server ever calls accept(). If you're trying to implement a connect timeout shorter than the default of about a minute, use select().
or receive.
Nothing you can do about that: see above.
So both connecting and writing should be done in max of 50ms since the time is very important in my situation.
See above. It doesn't make sense to implement a fixed timeout for operations that take variable time. And 50ms is far too short for a connect timeout. If that's a real issue you should keep the connection open so that the connect delay only happens once: in fact you should keep TCP connections open as long as possible anyway.
I have to flush both write and read streams
You can't. There is no operation in TCP that will flush either a read stream or a write stream.
because the server keeps sending me unnecessarly big data and I have limited internet connection.
Another non sequitur. If the server sends you data, you have to read it, otherwise you will stall the server, and that doesn't have anything to do with flushing your own write stream.
Actually I don't even want a single byte from the server
Bad luck. You have to read it. [If you were on BSD Unix you could shutdown the socket for input, which would cause data from the server to be thrown away, but that doesn't work on Windows: it causes the server to get a connection reset.]
Thanks to EJP and Martin, now I have created a second thread to check. Also in the code I posted in my question, I added "counter=0;" line after the "send" line and removed shutdown. It works just as I wanted now. It never waits more than 50ms :) Really big thanks
unsigned __stdcall SecondThreadFunc( void* pArguments )
{
while(1)
{
counter++;
if (counter > 49)
{
closesocket(hSocket);
counter = 0;
printf("\rtimeout");
}
Sleep(1);
}
return 0;
}

Ensuring data is being read with async_read

I am currently testing my network application in very low bandwidth environments. I currently have code that attempts to ensure that the connection is good by making sure I am still receiving information.
Traditionally I have done this by recording the timestamp in my ReadHandler function so that each time it gets called I know I have received data on the socket. With very low bandwidths this isn't sufficient because my ReadHandler is not getting called frequently enough.
I was toying around with the idea of writing my own completion condition function (right now I am using tranfer_at_least(1)) thinking it would get called more frequently and I could record my timestamp there, but I was wondering if there wasn't some other more standard way to go about this.
We had a similar issue in production: some of our connections may be idle for days, but we must detect if the remote is dead ASAP.
We solved it by enabling the TCP_KEEPALIVE option:
boost::asio::socket_base::keep_alive option(true);
mSocketTCP.set_option(option);
which had to be accompanied by new startup script that writes sensible values to /proc/sys/net/ipv4/tcp_keepalive_* which have very long timeouts by default (on LInux)
You can use the read_some method to get partial reads, and deal with the book keeping. This is more efficient than transfer_at_least(1), but you still have to keep track of what is going on.
However, a cleaner approach is just to use a concurrent deadline_timer. If the timer goes off before you are finished, then is taking too long and cancel whatever is going on. If not, just stop the timer and continue. Something like:
boost::asio::deadline_timer t;
t.expires_from_now(boost::posix_time::seconds(20));
t.async_wait(bind(&Class::timed_out, this, _1));
// Do stuff.
if (!t.cancel()) {
// Timer went off, abort
}
// And the timeout method
void Class::timed_out(error_code const& error)
{
if (error == boost::asio::error::operation_aborted) return;
// Deal with the timeout, close the socket, etc.
}
I don't know how to handle low latency of network from within application. Can you be sure if it's network latency, or if peer server or peer application busy and react slowly. Does it matter if it network/server/application quilt?
Even if you can discover network latency and find it's big, what are you going to do?
You can not improve the situation.
Consider other critical case which is a subset of what you're trying to handle - network is down (e.g. you disconnect cable from your machine). Since it a subset of your problem you want to handle it too.
Let's examine the network down effect on active TCP connection.How can you discover your active TCP connection is still alive? Calling send() will success, but it merely says that the message queued in TCP outgoing queue in kernel. TCP stack will try to send it, but since TCP ACK won't be sent back, TCP stack on your side will try to resend it again and again. You can see your message in netstat output (Send-Q column).
I'm aware of the following ways to deal with it:
One standard way is TCP keep alive proposed #Cubby.
Another way is to implement Keep Alive mechanism. Send Keep Alive req message and peer is obligated to send back Keep Alive ack message.
If you don't receive ack message after predefined timeout, try to send Keep Alive req N more times (e.g. N=2). If still no success, close the socket and open it again. If peer server is not available you'll not be abable to open connection, since TCP 3 way handshake requires peer to respond.

C++ Winsock P2P

Scenario
Does anyone have any good examples of peer-to-peer (p2p) networking in C++ using Winsock?
It's a requirement I have for a client who specifically needs to use this technology (god knows why).
I need to determine whether this is feasible.
Any help would be greatly appreciated.
EDIT
And I would like to avoid using libraries so that I can understand the underlying source code and further my knoweldge.
Since I don't know what information you are looking for, I'll try to describe how to set up a socket program and what pitfalls I've run into.
To start with, *read the Winsock tutorial at MSDN. This is a basic program to connect, send a message and disconnect. It's great for getting a feel for socket programming.
With that, lets start:
Considerations:
Blocking or non-blocking
First off, you need to decide whether you want a blocking or non-blocking program. If you have a GUI you would need to use non-blocking or threading in order to not freeze the program. The way I did it was to use the blocking calls, but always calling select before calling the blocking functions (more on select later). This way I avoid threading and mutex's and whatnot but still use the basic accept, send and receive calls.
You cannot rely that your packets will arrive the way you send them!
You have no control over this either. This was the biggest issue I ran into, basically because the network card can decide what information to send and when to send it. The way I solved it was to make a networkPackageStruct, containing a size and data, where size is the total amound of data in that packet. Note that a message that you send can be split into 2 or more packets and can also be merged with another message you send.
Consider the following:
You send two messages
"Hello"
"World!"
When you send these two messages with the send function your recv function might not get them like this. It could look like this:
"Hel"
"loWorld!"
or perhaps
"HelloWorld!"
whatever the underlying network feels like.
Log (almost) everything!
Debugging a network program is hard because you don't have full control over it (since it's on two computers). If you run into a blocking operation you can't see it either. This could as well be called "Know your blocking code". When one side sends something, you don't know if it will arrive on the other side, so keep track of what is sent and what is received.
Pay attention to socket errors
Winsock functions return a lot of information. Know your WSAGetLastError() function. I'll won't keep it in the examples below, but note that they tend to return alot of information. Every time you get a SOCKET_ERROR or INVALID_SOCKET check the Winsock Error Messages to look it up.
Setting up the connection:
Since you don't want a server, all clients would need a listening socket to accept new connections. The easiest is:
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in localAddress;
localAddress.sinfamily = AF_INET;
localAddress.sin_port = htons(10000); // or whatever port you'd like to listen to
localAddress.sin_addr.s_addr = INADDR_ANY;
INADDR_ANY is great - it makes your socket listen on all your IP addresses instead of just one IP address.
bind(s, (SOCKADDR*)&localAddress, sizeof(localAddress));
listen(s, SOMAXCONN);
Here comes the interesting part. bind and listen won't block but accept will. The trick is to use select to check if there is an incoming connection. So the above code is just to set the socket up. in your program loop you check for new data in socket.
Exchanging data
The way I solved it is was to use select alot. Basically you see if there are anything you need to respond to on any of your sockets. This is done with the FD_xxx functions.
// receiving data
fd_set mySet;
FD_ZERO(&mySet);
FD_SET(s, &mySet);
// loop all your sockets and add to the mySet like the call above
timeval zero = { 0, 0 };
int sel = select(0, &mySet, NULL, NULL, &zero);
if (FD_ISSET(s, &mySet)){
// you have a new caller
sockaddr_in remote;
SOCKET newSocket = accept(s, (SOCKADDR*)&remote, sizeof(remote));
}
// loop through your sockets and check if they have the FD_ISSET() set
In the newSocket you now have a new peer. So that was for receiving data. But note! send is also blocking! One of the head-scratching errors I got was that send blocked me. This was however also solved with select.
// sending data
// in: SOCKET sender
fd_set mySet;
FD_ZERO(&mySet);
FD_SET(sender, &mySet);
timeval zero = { 0, 0 };
int sel = select(0, NULL, mySet, NULL, &zero);
if (FD_ISSET(sender, &mySet)){
// ok to send data
}
Shutting down
Finally, there are two ways to shutdown. You either just disconnect by closing your program, or you call the shutdown function.
Calling shutdown will make your peer select trigger. recv will however not receive any data, but will instead return 0. I have not noticed any other case where recv returns 0, so it is (somewhat) safe to say that this can be considered a shutdown-code. calling shutdown is the nicest thing to do.
Shutting down the connection without calling shutdown just is cold-hearted, but of course works. You still need to handle the error even if you use shutdown, since it might not be your program that closes the connection. A good error code to remember is 10054 which is WSAECONNRESET: Connection reset by peer.
If you just want to implement a P2P application on Microsoft Windows, you can try with Windows Peer-to-Peer Networking
If you want to implement a new P2P protocol of your own, you can study the eMule protocol, and eMule source code. You could do further if you look into Shareaza source code, it do eMule/Guntella/Gnutella/BitTorrent.