Getting a handle to the initial connection + other questions

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Getting a handle to the initial connection + other questions

Alan Williamson
Good day to you all,

I am kinda new to Grizzly and on the face of it, it looks very
interesting and definitely something that may help us.  We currently
have our own HTTP frontend server performing load balancing infront of a
farm of JETTY servers.


___ Question #1 ___

One of the things we need to do, is to determine whether or not an IP
address is allowed to connect.   We basically want to nuke this
connection as soon as the "accept()" method has been called and the
Socket created.

This stops a lot of spammers from consuming resources they shouldn't be
anywhere near.  Our current frontend server sandboxes the IP for a small
period of time and we've noticed that this has reduced a load.

So in terms of the Grizzly how could one get a handle to the incoming
connection as soon as possible and determine whether or not they are
permitted to continue?

One the adapter code has triggered the "service()" method, then the
header is already in.  It's a bit late at that point.  Out of interest,
what is the cleanest way to nuke a connection at this stage

___ Question #2 ___

Running a large blog site you see a whole manner of nasty clients trying
to really mess with you.  One of things we see a lot of, is clients that
will attempt a subtle DoS attack.  They basically drip feed bytes to the
server in such a speed as not to trip up any of the SO_TIMEOUT alarms.
So one character a second for example, could tie up a connection for
minutes.  It doesn't take a lot of effort to really consume a server
connections waiting.

We've taken the approach, that if the complete HTTP header is not
received within X seconds (5 we have found to be acceptable) then we
deny this client from going on any further.

Again, how would one manage this with Grizzly?



Thanks again, and i look forward to hearing back and getting my sleeves
rolled up with this one.

alan

--
Alan Williamson
  "a wiki -and- a blog" @ http://www.Blog-City.com/

  b: http://alan.blog-city.com/

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Getting a handle to the initial connection + other questions

Jeanfrancois Arcand-2
Hi,

Alan Williamson wrote:

> Good day to you all,
>
> I am kinda new to Grizzly and on the face of it, it looks very
> interesting and definitely something that may help us.  We currently
> have our own HTTP frontend server performing load balancing infront of a
> farm of JETTY servers.
>
>
> ___ Question #1 ___
>
> One of the things we need to do, is to determine whether or not an IP
> address is allowed to connect.   We basically want to nuke this
> connection as soon as the "accept()" method has been called and the
> Socket created.
>
> This stops a lot of spammers from consuming resources they shouldn't be
> anywhere near.  Our current frontend server sandboxes the IP for a small
> period of time and we've noticed that this has reduced a load.
>
> So in terms of the Grizzly how could one get a handle to the incoming
> connection as soon as possible and determine whether or not they are
> permitted to continue?

The easiest way is to write a com.sun.grizzly.ProtocolFilter (or extends
the com.sun.grizzly.filter.ReadFilter). The way connection are handled
is the SelectorHandler execute the accept()/OP_ACCEPT, and then delegate
the read operations to a ProtocolChain (a chain is a collection of
filters). As an example, let's say you extends the ReadFilter (let's
call it MyReadFilter) with:

>     public boolean execute(Context ctx) throws IOException {
>         SelectionKey key = ctx.getSelectionKey();
>         SocketChannel channel = (SocketChannel)key.channel();
>         if (allow(channel.socket().getRemoteSocketAddress())){
>             return super.execute(ctx);
>         } else {
>             ctx.setKeyRegistrationState(
>                     Context.KeyRegistrationState.CANCEL);
>             // Do not invoke the next Filter
>             return false;            
>            
>         }

Just implement the allow() method to return true/false.

>
> One the adapter code has triggered the "service()" method, then the
> header is already in.  It's a bit late at that point.  Out of interest,
> what is the cleanest way to nuke a connection at this stage

Agree this is way to late in the process. So what you need to do is to
inject your ProtocolFilter like the following:

When you embed Grizzly, create the com.sun.grizzly.http.SelectorThread
using the following (assuming t

SelectorThread mySelectorThread = new SelectorThread(){

     /**
      * Adds and configures <code>ProtocolChain</code>'s filters
      * @param <code>ProtocolChain</code> to configure
      */
     protected void configureFilters(ProtocolChain protocolChain) {
         if (portUnificationFilter != null) {
             protocolChain.addFilter(portUnificationFilter);
         } else {
// =========== Inject your Filter here =======================//
             ReadFilter readFilter = new MyReadFilter();
             readFilter.setContinuousExecution(true);
             protocolChain.addFilter(readFilter);
         }

         if (rcmSupport){
             protocolChain.addFilter(createRaFilter());
         }

         protocolChain.addFilter(createHttpParserFilter());
     }
};

This way your filter will be the first invoked without all the overhead
of the http protocol being executed.


>
> ___ Question #2 ___
>
> Running a large blog site you see a whole manner of nasty clients trying
> to really mess with you.  One of things we see a lot of, is clients that
> will attempt a subtle DoS attack.  They basically drip feed bytes to the
> server in such a speed as not to trip up any of the SO_TIMEOUT alarms.
> So one character a second for example, could tie up a connection for
> minutes.  It doesn't take a lot of effort to really consume a server
> connections waiting.
>
> We've taken the approach, that if the complete HTTP header is not
> received within X seconds (5 we have found to be acceptable) then we
> deny this client from going on any further.
>
> Again, how would one manage this with Grizzly?

This is simple. Just set (this is a static method):

com.sun.grizzly.util.ByteBufferInputStream.setDefaultReadTimeout(//Timeout).
By default it is set to 30 seconds. This method tell Grizzly to wait
//timeout// seconds before considering it is a DoS when reading bytes.
This apply to both headers and body.

>
>
>
> Thanks again, and i look forward to hearing back and getting my sleeves
> rolled up with this one.

Thanks!

-- Jeanfrancois


>
> alan
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Getting a handle to the initial connection + other questions

Alan Williamson
This is great information and thank you for getting back to me so quick.

I have some more questions, which i will send under a different email.

For the moment:

This method for the header doesn't seem to work:

    ByteBufferInputStream.setDefaultReadTimeout( 5 );

If i set that, then open a telnet to the port, it will sit and wait for
input for 30 seconds.  So not sure what that value is actually doing.

Is it meant to be in seconds or milliseconds?

thanks

Jeanfrancois Arcand wrote:

>> ___ Question #2 ___
>>
>> Running a large blog site you see a whole manner of nasty clients
>> trying to really mess with you.  One of things we see a lot of, is
>> clients that will attempt a subtle DoS attack.  They basically drip
>> feed bytes to the server in such a speed as not to trip up any of the
>> SO_TIMEOUT alarms. So one character a second for example, could tie up
>> a connection for minutes.  It doesn't take a lot of effort to really
>> consume a server connections waiting.
>>
>> We've taken the approach, that if the complete HTTP header is not
>> received within X seconds (5 we have found to be acceptable) then we
>> deny this client from going on any further.
>>
>> Again, how would one manage this with Grizzly?
>
> This is simple. Just set (this is a static method):
>
> com.sun.grizzly.util.ByteBufferInputStream.setDefaultReadTimeout(//Timeout).
> By default it is set to 30 seconds. This method tell Grizzly to wait
> //timeout// seconds before considering it is a DoS when reading bytes.
> This apply to both headers and body.


--
Alan Williamson
  "a wiki -and- a blog" @ http://www.Blog-City.com/

  b: http://alan.blog-city.com/

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Getting a handle to the initial connection + other questions

Jeanfrancois Arcand-2


Alan Williamson wrote:

> This is great information and thank you for getting back to me so quick.
>
> I have some more questions, which i will send under a different email.
>
> For the moment:
>
> This method for the header doesn't seem to work:
>
>    ByteBufferInputStream.setDefaultReadTimeout( 5 );
>
> If i set that, then open a telnet to the port, it will sit and wait for
> input for 30 seconds.  So not sure what that value is actually doing.
>
> Is it meant to be in seconds or milliseconds?

Milliseconds. Hum look like a bug to me. Let me take a look on my side
as well. This is supposed to work :-) :-)

Thanks

-- Jeanfrancois


>
> thanks
>
> Jeanfrancois Arcand wrote:
>>> ___ Question #2 ___
>>>
>>> Running a large blog site you see a whole manner of nasty clients
>>> trying to really mess with you.  One of things we see a lot of, is
>>> clients that will attempt a subtle DoS attack.  They basically drip
>>> feed bytes to the server in such a speed as not to trip up any of the
>>> SO_TIMEOUT alarms. So one character a second for example, could tie
>>> up a connection for minutes.  It doesn't take a lot of effort to
>>> really consume a server connections waiting.
>>>
>>> We've taken the approach, that if the complete HTTP header is not
>>> received within X seconds (5 we have found to be acceptable) then we
>>> deny this client from going on any further.
>>>
>>> Again, how would one manage this with Grizzly?
>>
>> This is simple. Just set (this is a static method):
>>
>> com.sun.grizzly.util.ByteBufferInputStream.setDefaultReadTimeout(//Timeout).
>> By default it is set to 30 seconds. This method tell Grizzly to wait
>> //timeout// seconds before considering it is a DoS when reading bytes.
>> This apply to both headers and body.
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Hitting a small compilation problem with: new SelectorThread()

Alan Williamson
In reply to this post by Jeanfrancois Arcand-2
Jeanfrancois regarding this issue,

> When you embed Grizzly, create the com.sun.grizzly.http.SelectorThread
> using the following (assuming t
>
> SelectorThread mySelectorThread = new SelectorThread(){
>
>     /**
>      * Adds and configures <code>ProtocolChain</code>'s filters
>      * @param <code>ProtocolChain</code> to configure
>      */
>     protected void configureFilters(ProtocolChain protocolChain) {
>         if (portUnificationFilter != null) {
>             protocolChain.addFilter(portUnificationFilter);
>         } else {
> // =========== Inject your Filter here =======================//
>             ReadFilter readFilter = new MyReadFilter();
>             readFilter.setContinuousExecution(true);
>             protocolChain.addFilter(readFilter);
>         }
>
>         if (rcmSupport){
>             protocolChain.addFilter(createRaFilter());
>         }
>
>         protocolChain.addFilter(createHttpParserFilter());
>     }
> };
>
> This way your filter will be the first invoked without all the overhead
> of the http protocol being executed.

I hit up against a compilation error:

        The method createHttpParserFilter() from the type SelectorThread
        is not visible

And right enough, its a "private" method.

Can you make it protected?  :)



---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Hitting a small compilation problem with: new SelectorThread()

Jeanfrancois Arcand-2


Alan Williamson wrote:

> Jeanfrancois regarding this issue,
>
>> When you embed Grizzly, create the com.sun.grizzly.http.SelectorThread
>> using the following (assuming t
>>
>> SelectorThread mySelectorThread = new SelectorThread(){
>>
>>     /**
>>      * Adds and configures <code>ProtocolChain</code>'s filters
>>      * @param <code>ProtocolChain</code> to configure
>>      */
>>     protected void configureFilters(ProtocolChain protocolChain) {
>>         if (portUnificationFilter != null) {
>>             protocolChain.addFilter(portUnificationFilter);
>>         } else {
>> // =========== Inject your Filter here =======================//
>>             ReadFilter readFilter = new MyReadFilter();
>>             readFilter.setContinuousExecution(true);
>>             protocolChain.addFilter(readFilter);
>>         }
>>
>>         if (rcmSupport){
>>             protocolChain.addFilter(createRaFilter());
>>         }
>>
>>         protocolChain.addFilter(createHttpParserFilter());
>>     }
>> };
>>
>> This way your filter will be the first invoked without all the
>> overhead of the http protocol being executed.
>
> I hit up against a compilation error:
>
>     The method createHttpParserFilter() from the type SelectorThread
>     is not visible
>
> And right enough, its a "private" method.
>
> Can you make it protected?  :)

Done :-) I've uploaded the binary on Maven repo as well :-)

-- Jeanfrancois

>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Hitting a small compilation problem with: new SelectorThread()

Alan Williamson
>> Can you make it protected?  :)
>
> Done :-) I've uploaded the binary on Maven repo as well :-)

oooh damn your good!

i don't see it here yet:

    http://download.java.net/maven/2/com/sun/grizzly/http/1.6.1/

or am i not looking in the right place?

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Hitting a small compilation problem with: new SelectorThread()

Jeanfrancois Arcand-2


Alan Williamson wrote:
>>> Can you make it protected?  :)
>>
>> Done :-) I've uploaded the binary on Maven repo as well :-)
>
> oooh damn your good!
>
> i don't see it here yet:
>
>    http://download.java.net/maven/2/com/sun/grizzly/http/1.6.1/

here:

  http://download.java.net/maven/2/com/sun/grizzly/http/1.6-SNAPSHOT/

This is the nightly. We will soon release 1.7.0 that will contains the
fix as well.

Thanks!

-- Jeanfrancois

>
> or am i not looking in the right place?
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]