<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
  <title></title>
</head>
<body bgcolor="#ffffff" text="#000000">
Hello,<br>
<br>
I tried a few times to create an entry on the jboss wiki.<br>
But it hangs every time I click the create new entry.<br>
<br>
I am therefore including it here:<br>
<br>
<h3>Netty Example: implementing a simple WAF (Web Application Firewall)</h3>
<br>
This example shows how to implement a simple WAF (<a
 href="http://de.wikipedia.org/wiki/Web_Application_Firewall">Web
Application Firewall</a>) using netty.<br>
For this we create a proxy server which receives the http requests. If
 the request is ok, the "bytes"<br>
received are forwarded to the web server.<br>
<br>
As starting point we use the <span style="font-weight: bold;">HexDumpProxy</span>
example which comes with the netty distribution.<br>
We adapt the PipelineFactory from the example by adding the <span
 style="font-weight: bold;">InterceptStart</span>, <span
 style="font-weight: bold;">HttpDecoder</span> and <span
 style="font-weight: bold;">InterceptStop</span> handlers.<br>
<br>
<address>
public class WafPipelineFactory implements ChannelPipelineFactory {</address>
<address>
    </address>
<address>
    private final ClientSocketChannelFactory cf;</address>
<address>
    private final String remoteHost;</address>
<address>
    private final int remotePort;</address>
<address><br>
    public WafPipelineFactory(ClientSocketChannelFactory cf, String
remoteHost, int remotePort) {</address>
<address>
        this.cf = cf;</address>
<address>
        this.remoteHost = remoteHost;</address>
<address>
        this.remotePort = remotePort;</address>
<address>
    }</address>
<address>
   </address>
<address>
        public ChannelPipeline getPipeline() throws Exception {</address>
<address>
            ChannelPipeline pipeline = pipeline();</address>
<address>
           <b> pipeline.addLast("interceptStart", new InterceptStart());</b></address>
<address>
           <b> pipeline.addLast("decoder", new HttpRequestDecoder());</b></address>
<address><b>
            pipeline.addLast("aggregator", new
HttpChunkAggregator(1048576));</b></address>
<address><b>
             pipeline.addLast("interceptStop", new InterceptStop());</b></address>
<address>
           
pipeline.addLast("handler", new HexDumpProxyInboundHandler(cf,
remoteHost, remotePort));</address>
<address><br>
            return pipeline;</address>
<address>
        }    </address>
<address>
}</address>
<br>
<span style="font-weight: bold;">InterceptStart</span> intercepts all
incoming messages and makes a copy into a local buffer<br>
<br>
<address>
public class InterceptStart extends SimpleChannelUpstreamHandler {</address>
<address><br>
    ChannelBuffer buf = null;</address>
<address>
    </address>
<address>
    @Override</address>
<address>
     public void messageReceived(ChannelHandlerContext ctx,
MessageEvent evt) throws Exception</address>
<address>
     {</address>
<address>
         ChannelBuffer m = (ChannelBuffer) evt.getMessage();</address>
<address>
         ChannelBuffer buf = (ChannelBuffer) ctx.getAttachment();</address>
<address>
         if (buf == null)</address>
<address>
         {</address>
<address>
             // if this is a new connection create a new buffer and
attach it to the context</address>
<address>
             buf = dynamicBuffer();</address>
<address>
             ctx.setAttachment(buf);</address>
<address>
         }</address>
<address>
         // copy the incoming bytes to the buffer</address>
<address>
         m.markReaderIndex();</address>
<address>
         buf.writeBytes(m);</address>
<address>
         m.resetReaderIndex();</address>
<address>
         // send the buffer further upstream to the HttpDecoder</address>
<address>
         super.messageReceived(ctx, evt);</address>
<address>
        }</address>
<address>
}</address>
<br>
<span style="font-weight: bold;">InterceptStop</span> receives the http
request, analyzes it, and if ok gets
the copy buffer from InterceptStart and forwards it to the http proxy<br>
<br>
<address>
public class InterceptStop extends SimpleChannelUpstreamHandler {</address>
<address><br>
            @Override</address>
<address>
             public
void messageReceived(ChannelHandlerContext ctx, MessageEvent evt) {</address>
<address>
                 if (evt.getMessage() != null)</address>
<address>
                 {</address>
<address>
           
         HttpRequest request =
(HttpRequest) evt.getMessage();</address>
<address>
                     // make sure that the http request is complete<br>
                    // this may not be necessary ??<br>
</address>
<address>
              
     if (request.getContentLength() == 0 ||
request.getContentLength() == request.getContent().writerIndex())</address>
<address>
                     {</address>
<address>
           
         ChannelBuffer buf =
(ChannelBuffer)
ctx.getPipeline().getContext("interceptStart").getAttachment();</address>
<address>
                    if (buf == null)</address>
<address>
                     {</address>
<address>
           
           
 System.out.println("this should not happen");</address>
<address>
                     }</address>
<address>
           
         else if (buf.writerIndex()
!= 0)</address>
<address>
                     {</address>
<address>
           
             
 // check the request</address>
<address>
                          if ( ! wafCheck(request))</address>
<address>
                          {</address>
<address>
           
           
            // bad request
-&gt; close the channel</address>
<address>
                   
             
 cts.getChannel.close();</address>
<address>
                   
               return;</address>
<address>
           
           
    }</address>
<address>
                   
       // request is ok, remove the copy the
interceptor</address>
<address>
            
           
 ctx.getPipeline().getContext("interceptStart").setAttachment(null);</address>
<address>
                          // forward the buffer to the proxy</address>
<address>
             
           
ctx.sendUpstream(new UpstreamMessageEvent(evt.getChannel(), buf,
evt.getRemoteAddress()));</address>
<address>
                     }</address>
<address>
                     }</address>
<address><br>
                 }</address>
<address>
                }</address>
<address>
}</address>
<br>
To check the http request one may use the <a
 href="http://www.owasp.org/index.php/Category:OWASP_Stinger_Project">OWASP
Stinger Project</a> or a similar framework.<br>
Since these frameworks generally analyze a <a
 href="http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/servlet/http/HttpServletRequest.html">HttpServletRequest</a>
we need an <a href="http://en.wikipedia.org/wiki/Adapter_pattern">adapter</a>
to adapt to the netty HttpRequest.<br>
Implementing the adapter is straight forward.<br>
<br>
<br>
<br>
<br>
</body>
</html>