By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,876 Members | 1,239 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,876 IT Pros & Developers. It's quick & easy.

How to protect socket against dos attack

P: 11
Hi,

I am learning csharp and have a question:

My question is about handling a receiving socket.
I use the backgroundworker class for multithreading.

In the doWork event there is a while loop that uses the blocking receive method.
Once bytes are received they are passed to the reportProgress method.

The ProgressChanged event handler will convert the bytes to a string and will use this string to update the user interface (append it to a textbox). For now i do not concern with message framing.

My problem:

I wrote a seperate test program that sends massive amounts of data to my program, it sends a string of length 3000 and does this 1000 times.

The receiving program becomes unresponsive. I can overcome this by using thread.sleep( 10 ) in the receive loop. But this does not feel "right", it feels like a hack.

So the bottleneck is the user interface (right?) it can not handle all the reportProgress events fast enough.

How is this handled ? should i detect such an "flood attack" and then close the connection? In a normal situation there is no way a flood can happen it must be an attack. I am just curious in how to protect my application, it is just for learning purposes.
Oct 26 '09 #1
Share this Question
Share on Google+
15 Replies


tlhintoq
Expert 2.5K+
P: 3,525
and will use this string to update the user interface (append it to a textbox).
Stop there. Directly tying your socket code to your user interface controls means you won't be able to turn this socket into a self-contained class that you can easily re-use later. After all, once you get the bugs worked out of this you don't want to have to copy/paste this into every other program do you? Its a lot nicer to be able to put this into a user control in your tool box, or part of your personal namespace so you only have one socket handling class that you use in all your applications.

Try having the socket handler raise an event with the new text.
Have your form subscribe to the socket class "NewTextEvent"
Then when the form 'hears' the socket class 'yell' "I have new text of xxxxx" it can react how is correct for the form. Maybe that is to put it into a textbox. Maybe it is to parse it for a file name and load it. Maybe it is to log it to a text file.

The important thing is that the socket class doesn't need to know or care about what form(s) are listening to it, or what they will do with the data. It just listens for information, and yells it out in an event. - The listening classes (forms) don't really know that much about sockets: They just have one line that subscribe them to the socket class. When you create a better socket class in 6 months every program that is tied to automatically gets the improvements without you having to go back and copy/paste/customize.

I can overcome this by using thread.sleep( 10 ) in the receive loop. But this does not feel "right", it feels like a hack.
Thread.sleep is rarely the right thing. How about putting up the actual code for this so we can take a look? Its also possible that when your socket class is unhooked from your UI form that this will clear itself up.
Oct 26 '09 #2

P: 11
Thanks for your response,

I have thought about reuse :)
What you say I have allready done, i made a class that fires my own events: (ConnectionFailed, ConnectionSucceeded, ReceivedData, StoppedReceiving, etc)
Sorry for not mentioning that

code to react to "ReceivedData" event: (in the form)
Expand|Select|Wrap|Line Numbers
  1. private void clientSocket_ReceivedData(object sender, ReceivedDataEventArgs e)
  2. {
  3.     string receivedString = System.Text.Encoding.UTF8.GetString(e.Buffer);
  4.     receivedString = receivedString.Trim(new char[] {(char)0});
  5.  
  6.     this.textBox.AppendText(receivedString + "\r\n");
  7.     this.textBox.SelectionStart = textBox.Text.Length;
  8.     this.textBox.ScrollToCaret();
  9. }
doWork code (In socket wrapper class):
Expand|Select|Wrap|Line Numbers
  1. private void bgWorkerReceive_DoWork(object sender, DoWorkEventArgs e)
  2. {
  3.     BackgroundWorker bgWorker = (BackgroundWorker)sender;
  4.     byte[] buffer;
  5.     int numBytesRead;
  6.  
  7.     while (true)
  8.     {
  9.         buffer = new byte[1024];
  10.  
  11.         try
  12.         {
  13.             numBytesRead = this.socket.Receive(buffer);
  14.  
  15.             if (numBytesRead > 0)
  16.             {
  17.                 System.Threading.Thread.Sleep(10);
  18.                 bgWorker.ReportProgress(0, buffer);
  19.             }
  20.             else if (numBytesRead == 0)
  21.             {
  22.                 break;
  23.             }
  24.         }
  25.         catch (SocketException ex)
  26.         {
  27.             if (ex.NativeErrorCode.Equals(10054))
  28.             {
  29.                 //System.Windows.Forms.MessageBox.Show("10054\nREMOTE HOST DID A HARD CLOSE");
  30.             }
  31.             else if (ex.NativeErrorCode.Equals(10004))
  32.             {
  33.                 //System.Windows.Forms.MessageBox.Show("10004\nBLOCKING OPERATION CANCELLED BY LOCAL");
  34.             }
  35.             break;
  36.         }
  37.         catch (ObjectDisposedException ex)
  38.         {
  39.             break;
  40.         }
  41.     }
  42. }
Progress changed event handler: (In socket wrapper class)
Expand|Select|Wrap|Line Numbers
  1.         private void bgWorkerReceive_ProgressChanged(object sender, ProgressChangedEventArgs e)
  2.         {
  3.             byte[] buffer = (byte[])e.UserState;
  4.             this.onReceivedData(buffer);
  5.         }
Fire my own event (In socket wrapper class)
Expand|Select|Wrap|Line Numbers
  1.         protected void onReceivedData(byte[] buffer)
  2.         {
  3.             if (this.ReceivedData != null)
  4.             {
  5.                 this.ReceivedData(this, new ReceivedDataEventArgs(buffer));
  6.             }
  7.         }
Oct 26 '09 #3

tlhintoq
Expert 2.5K+
P: 3,525
Expand|Select|Wrap|Line Numbers
  1. private void clientSocket_ReceivedData(object sender, ReceivedDataEventArgs e)
  2. {
  3.     string receivedString = System.Text.Encoding.UTF8.GetString(e.Buffer);
  4.     receivedString = receivedString.Trim(new char[] {(char)0});
  5.  
  6.     this.textBox.AppendText(receivedString + "\r\n");
  7.     this.textBox.SelectionStart = textBox.Text.Length;
  8.     this.textBox.ScrollToCaret();
  9. }
  10.  
I'm hesitant about this. From what you said this textbox is growing to thousands of lines. It just seems you could be hammering the textbox beyond what it can do quickly.

I've always gone with listboxes so I can just add a new line to its .Items property.
The nice thing about that is you can take things off the back end of the list rather quickly to keep the listbox from growing beyond reasonable behavior

Expand|Select|Wrap|Line Numbers
  1. LIstbox1.Items.Add(receivedString);
  2. if (Listbox1.Items.Count > 500) Listbox1.Items.Removeat(0);
  3.  
We can control how many items it displays rather easily.
You can compare items to see if you are getting the same item over and over
Expand|Select|Wrap|Line Numbers
  1. if (Listbox1.Items[Listbox1.Items.Count-1] == Listbox1.Items[Listbox1.Items.Count-2])
  2. {
  3.    // We have a duplicate
  4.    // Increase the duplicate counter variable
  5.    // if the duplicate counter variable hits 250 in 1 second maybe its an attack.
  6.    // Otherwise just indicate a duplicate item received somewhere on the form
  7.    // rather than add 500 duplicates in the Listbox
  8. }
  9. else
  10. {
  11.    // Its a geniunly different item we receives so we should react accordingly
  12. }
  13.  
Oct 26 '09 #4

P: 11
Thanks for your reply

The listbox is indeed way faster, probably bacause it uses a datastructure for the items instead of a single string.

But the form still freezes, it is overwhelmed by the events triggered by the socket.

What comes to my mind is some timer to check each second how much buffers have been received since the last second. if it exceeds a limit then close the connection.
Oct 26 '09 #5

GaryTexmo
Expert 100+
P: 1,501
On the topic of DoS counter-measures, this article looks like it might be interesting to you...

http://weblogs.asp.net/omarzabir/arc...plication.aspx
Oct 26 '09 #6

tlhintoq
Expert 2.5K+
P: 3,525
@learner247
Try adding "Application.DoEvents();" right after adding the new text to the listbox.items collection. This will force a little processor time to the UI thread so the Form and ListBox can get a couple cycles to update.
Oct 26 '09 #7

P: 11
This emmediately gave me a stackOverflow exception
Oct 26 '09 #8

P: 11
Sorry guys need to go,
I really appreciate you guys help!
back in a few hours
Oct 26 '09 #9

P: 11
For anyone who wants to know this is how i solved the problem:

This code must sit at the socket level not at the event handling level, because the events are triggered at an insane rate and in one second tens of thousands events are triggered. All those events will be queued and the form will try to handle them. In this way i stop the events from triggering.

Expand|Select|Wrap|Line Numbers
  1. private bool canHandleBuffer()
  2. {
  3.     if ( ! this.bufferLimitIsSet)
  4.     {
  5.         return true;
  6.     }
  7.  
  8.     this.bufferCounter++;
  9.  
  10.     if (this.bufferCounter > this.maxBuffersPerSecond)
  11.     {
  12.         // COUNTER HAS BECOME TO HIGH
  13.         return false;
  14.     }
  15.  
  16.     TimeSpan span = DateTime.Now - this.dateTimeMarker;
  17.  
  18.     if (span.Seconds > 1)
  19.     {
  20.         // MORE THAN A SECOND IS PASSED SO RESET THE COUNTER AND MARK A NEW TIME
  21.         this.bufferCounter = 0;
  22.         this.dateTimeMarker = DateTime.Now;
  23.     }
  24.  
  25.     return true;
  26. }
Oct 27 '09 #10

tlhintoq
Expert 2.5K+
P: 3,525
If your problem was that you were unable to handle all the events and they queued up, there is a way to stop that from happening.


Expand|Select|Wrap|Line Numbers
  1. bool  IsProcessing = false; // Class-wide field, visible to all methods
  2.  
  3. public void MyEventHandler(object sender, eventargs e)
  4. {
  5.     if (!IsProcessing)
  6.     {
  7.         IsProcessing = true; // Next event will therefore skip this part
  8.         // Do my actual processing here
  9.         //  Many lines of processing
  10.         //  Lots of cool stuff going on here
  11.  
  12.  
  13.  
  14.        IsProcessing = false;  // Because I'm done and want to handle the next event
  15.     }
  16. }
  17.  

In this way it is not the responsiblity of the class raising the event to decide of the class(es) subscribed can keep up or not.

This way one class that requires 5 seconds to process can have it, while another class that only needs 100ms can respond to more events.
Oct 27 '09 #11

P: 11
if all the events are waiting to be handled in one long queue then it does not matter if i keep track of some boolean right? when the event is done it will be false, so when the next one starts it is also false.

and even if some events are skipped, blocked, or ignored the massive number of events will still ensure that the form class is constantly buzzy so it wont have time to do other gui things like dragging the form around the screen.
Oct 27 '09 #12

tlhintoq
Expert 2.5K+
P: 3,525
if all the events are waiting to be handled in one long queue then it does not matter if i keep track of some boolean right?
I thought you said the problem was the queue. That you couldn't process in real time that fast. The point of the bool is to have the event get handled, but not really processed. This way the event is heard and handled, but nothing is done about it. Thus, no queue builds up.

Depending on what your 'processing' is, doing it late when the queue gets handled may not be realistic. If you have to process based on other real-time data, then processing 5 seconds late doesn't work.

While you are processing info from one event the bool is true
When the second event comes in and the event is true, processing is skipped but the event was handled.
When 500 more events come in while you are still processing the events are handled, no queue.
When you are done processing, the bool goes back to false.
When the next event comes in, it is false, so you now process
[repeat]
Oct 27 '09 #13

P: 11
While you are processing info from one event the bool is true
When the second event comes in and the event is true, processing is skipped but the event was handled.
When 500 more events come in while you are still processing the events are handled, no queue.
When you are done processing, the bool goes back to false.
When the next event comes in, it is false, so you now process
[repeat]
I knew you ment this, but this is not happening in my program. A queue is like a waiting line, the all WAIT. So when one event is handled the next one is happy: it is his turn to be processed.

I tested it with a else block to see if the boolean was allready true when the handler started execution, tried both a messagebox and System.Diagnostics.Debug.WriteLine( );
So the bool is allways false when the event starts and returns.
Oct 27 '09 #14

tlhintoq
Expert 2.5K+
P: 3,525
Show me what you did please
Oct 27 '09 #15

P: 11
clientSocket_ReceivedData is a handler of the ReceivedData event.
ReceivedData is fired by the socket wrapper class when the background worker reportsprogress. (see code a few posts back).

the code is not different than yours.

Expand|Select|Wrap|Line Numbers
  1. private bool isBuzzy = false;
  2.  
  3. private void clientSocket_ReceivedData(object sender, ReceivedDataEventArgs e)
  4. {
  5.     if( ! this.isBuzzy)
  6.     {
  7.         this.isBuzzy = true;
  8.         System.Diagnostics.Debug.WriteLine("NOT BUZZY, NOT SKIPPED");
  9.  
  10.         // Do stuff
  11.  
  12.         this.isBuzzy = false;
  13.     }
  14.     else
  15.     {
  16.         System.Diagnostics.Debug.WriteLine("BUZZY,
  17. HANDLED AND GONE FROM QUEUE");
  18.     }
  19. }
Oct 27 '09 #16

Post your reply

Sign in to post your reply or Sign up for a free account.