[Snort-devel] new plugin targetted at speeding up snort

Brian Caswell bmc at ...835...
Sun May 4 20:06:19 EDT 2003


I've been working on a plugin that should speed up snort in most cases
called outquick.  (think pf/ipf/iptables out quick)

This is a just a first go-round.  On my home network, which is 80% http
traffic, outquick has sped up snort by ~20%.  On pure HTTP traffic, you
should see even more of a speedup.

Again, this is a work in progress.  The configuration storage is ... gross.
If people find this useful, I'll rework it to not use so much memory.

The diff applies cleanly to current.  I've added a few example usages to
snort.conf.  If you want to watch outquick process packets, I've added a
debug code to make debugging outquick easier.

   ./configure --enable-debug
   make
   SNORT_DEBUG=2097152 src/snort -c etc/snort.conf -l /tmp

I had to make very small additons to stream4 to allow outquick specific
state information, but the additions are VERY small.  (Chris, I promise :P)

Ok, so on to how outquick works... outquick allows snort to speed up 
processing packets by turning off detection for portions of protocols that 
have lots of traffic that we don't really want to spend time doing pattern
matching on.  

http and encrypted traffic are great examples of protocols that some 
traffic we are interested in with major portions that we don't really 
care about.

With http, we care about all of the client side data.  In the general case,
we really only care about the first 300 or so bytes of server data in the
session.  When a user downloads a 20 meg file, we spend lots of time doing
pattern matching on over 20 megs of data that we don't really care about.
So, outquick allows us to stop doing pattern matching on streams of data
after we have reached a specific point.  In the http case, we want to
be able to turn detection back on whenever we see client data again thanks
to HTTP/1.1 persistent connections.

So our outquick configuration would look something like this:

    preprocessor outquick: until_response server_data 300 80 3128 8080

In the ssh case, we can safely ignore ssh traffic after seeing 5000 bytes
in either direction.  As such, we look at the total number of bytes between
the server & client.  As such, our outquick configuration would look 
something like this:

    preprocessor outquick: quick all 5000 22 

In the imap/ssl case, we can safely ignore traffic after seeing 400 bytes
of the session.  (After the encryption has been set up.)  As such, our 
configuration looks something like this:

    preprocessor outquick: quick client_data 400 993

Lets look at the syntax:

     preprocessor outquick: <type> <data_src> <bytes> <server_port> \
         [<server_port> <server_port>...]

As described above, there are two available outquick types:
     quick - as soon as we see the required number of bytes, stop detection
        on the rest of the stream
     until_response - as soon as we see the required number of bytes, stop
        detection on the rest of stream until we see client traffic, then
        reset our 'required number of bytes' check to 0.

There are three types for data sources (of course, you can't use all in
the until_response outquick type):
     client_data - look at bytes sent from the client in the flow
     server_data - look at bytes sent from the server in the flow
     all - look for the combined bytes sent from the server in the flow

I've added foo to allow the user to specify multiple configurations since
different protocols have different detection requirements.
 
So, this is our combined configuration
     preprocessor outquick: until_response server_data 300 80 3128 8080
     preprocessor outquick: quick client_data 400 993
     preprocessor outquick: quick all 5000 22 

-brian
-------------- next part --------------
--- etc/snort.conf	2003-04-03 15:17:20.000000000 -0500
+++ etc/snort.conf	2003-05-04 22:22:14.000000000 -0400
@@ -234,6 +234,10 @@
 
 preprocessor stream4: detect_scans, disable_evasion_alerts
 
+preprocessor outquick: until_response server_data 300 80 3128 8080
+preprocessor outquick: quick client_data 400 993
+preprocessor outquick: quick all 5000 22 443
+
 # tcp stream reassembly directive
 # no arguments loads the default configuration 
 #   Only reassemble the client,
--- src/debug.h	2003-03-28 15:09:52.000000000 -0500
+++ src/debug.h	2003-05-04 18:41:12.000000000 -0400
@@ -45,6 +45,7 @@
 #define DEBUG_HTTP_DECODE     0x00040000  /* 262144 */
 #define DEBUG_PORTSCAN2       0x00080000  /* 524288 / (+ conv2 ) 589824 */
 #define DEBUG_RPC             0x00100000  /* 1048576 */
+#define DEBUG_OUTQUICK        0x00200000  /* 2097152 */
 
 #ifdef DEBUG
 
--- src/decode.h	2003-04-28 09:08:07.000000000 -0400
+++ src/decode.h	2003-05-04 18:36:32.000000000 -0400
@@ -1082,6 +1082,9 @@
     u_int32_t pkts_sent;   /* track the number of packets in this stream */
     u_int32_t bytes_sent;  /* track the number of bytes in this stream */
     u_int32_t bytes_tracked; /* track the total number of bytes on this side */
+    
+    u_int32_t outquick_bytes;  /* track the number of bytes in this stream */
+    u_int32_t outquick_packets; /* track the total number of bytes on this side */
     ubi_trRoot data;
 } Stream;
 
--- src/plugbase.c	2003-03-26 16:59:27.000000000 -0500
+++ src/plugbase.c	2003-05-02 19:33:59.000000000 -0400
@@ -59,6 +59,7 @@
 #include "preprocessors/spp_portscan2.h"
 #include "preprocessors/spp_httpflow.h"
 #include "preprocessors/spp_perfmonitor.h"
+#include "preprocessors/spp_outquick.h"
 
 /* built-in detection plugins */
 #include "detection-plugins/sp_pattern_match.h"
@@ -396,6 +397,7 @@
     SetupScan2();
     SetupHttpFlow();
     SetupPerfMonitor();
+    SetupOutQuick();
 }
 
 /****************************************************************************
--- src/preprocessors/Makefile.am	2003-03-26 16:59:43.000000000 -0500
+++ src/preprocessors/Makefile.am	2003-05-02 19:34:30.000000000 -0400
@@ -16,6 +16,6 @@
 perf-flow.c perf-flow.h \
 perf-event.c perf-event.h \
 http-resp.c http-resp.h \
-sfprocpidstats.c sfprocpidstats.h
+sfprocpidstats.c sfprocpidstats.h spp_outquick.c  spp_outquick.h
 
 INCLUDES = @INCLUDES@
--- src/preprocessors/spp_outquick.c	1969-12-31 19:00:00.000000000 -0500
+++ src/preprocessors/spp_outquick.c	2003-05-04 22:31:35.000000000 -0400
@@ -0,0 +1,590 @@
+/* $Id$ */
+
+/*
+** Copyright (C) 2003 Brian Caswell <bmc at ...835...>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file   spp_outquick.c
+ * @author Brian Caswell <bmc at ...835...>
+ *
+ * This plugin is supposed to allow snort to speed up processing by turning
+ * off detection for portions of protocols that have lots of traffic that we 
+ * don't really want to spend time doing pattern matching on.  
+ *
+ * http and encrypted traffic are great examples of protocols that some 
+ * traffic we are interested in with major portions that we don't really 
+ * care about.
+ *
+ * With http, we care about all of the client side data.  In the general case,
+ * we really only care about the first 300 or so bytes of server data in the
+ * session.  When a user downloads a 20 meg file, we spend lots of time doing
+ * pattern matching on over 20 megs of data that we don't really care about.
+ * So, outquick allows us to stop doing pattern matching on streams of data
+ * after we have reached a specific point.  In the http case, we want to
+ * be able to turn detection back on whenever we see client data again thanks
+ * to HTTP/1.1 persistent connections.
+ *
+ * So our outquick configuration would look something like this:
+ *      preprocessor outquick: until_response server_data 300 80 3128 8080
+ *
+ * In the ssh case, we can safely ignore ssh traffic after seeing 5000 bytes
+ * in either direction.  As such, we look at the total number of bytes between
+ * the server & client.  As such, our outquick configuration would look 
+ * something like this:
+ *      preprocessor outquick: quick all 5000 22 
+ *
+ * In the imap/ssl case, we can safely ignore traffic after seeing 400 bytes
+ * of the session.  (After the encryption has been set up.)  As such, our 
+ * configuration looks something like this:
+ *      preprocessor outquick: quick client_data 400 993
+ *
+ * Lets look at the syntax:
+ *
+ *      preprocessor outquick: <type> <data_src> <bytes> <server_port> \
+ *          [<server_port> <server_port>...]
+ *
+ * Available types:
+ *      quick - as soon as we see the required number of bytes, stop detection
+ *         on the rest of the stream
+ *      until_response - as soon as we see the required number of bytes, stop
+ *         detection on the rest of stream until we see client traffic, then
+ *         reset our 'required number of bytes' check to 0.
+ *
+ * Available data sources:
+ *      client_data - look at bytes sent from the client in the flow
+ *      server_data - look at bytes sent from the server in the flow
+ *      all - look for the combined bytes sent from the server in the flow
+ *
+ * I've added foo to allow the user to specify multiple configurations since
+ * different protocols have different detection requirements.
+ *  
+ * So, this is our combined configuration
+ *      preprocessor outquick: until_response server_data 300 80 3128 8080
+ *      preprocessor outquick: quick client_data 400 993
+ *      preprocessor outquick: quick all 5000 22 
+ */
+
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "snort.h"
+#include "plugbase.h"
+#include "debug.h"
+#include "mstring.h"
+#include "util.h"
+#include "parser.h"
+
+#define OUTQUICK_MAX_TOKENS 128
+
+#define OUTQUICK_TYPE_NONE 0
+#define OUTQUICK_TYPE_QUICK 1
+#define OUTQUICK_TYPE_UNTIL_RESPONSE 2
+
+#define OUTQUICK_SRC_SERVER 1
+#define OUTQUICK_SRC_CLIENT 2
+#define OUTQUICK_SRC_ALL    3
+
+#define CLIENT_TRAFFIC 1
+#define SERVER_TRAFFIC 2
+
+typedef struct _OUTQUICK 
+{
+    int type;
+    int src;
+    u_int32_t depth;
+} OUTQUICK;
+
+/*
+ * this is a nasty solution.  Its really huge.  Ok, so this configuration 
+ * mechanism sucks.  If we decide this is useful, then I'll look at using 
+ * some sort of tree or hash or something than a great big static array.
+ */
+static OUTQUICK outquickConfig[65536];
+static int outquick_used = 0;
+
+/*
+**  Functions
+*/
+static void InitOutQuick(u_char *args);
+static void ParseOutQuickArgs(char *args);
+static void OutQuick(Packet *p);
+
+/**
+ * Register spp_outquick (oh, and memset outquick's memory)
+ */
+void SetupOutQuick()
+{
+    /* link the preprocessor keyword to the init function in the preproc list */
+    RegisterPreprocessor("outquick", InitOutQuick);
+
+    memset(&outquickConfig, 0, sizeof(outquickConfig));
+
+    DEBUG_WRAP(DebugMessage(DEBUG_OUTQUICK,"outquick is setup.\n"););
+}
+
+
+/**
+ * initialize outquick
+ *
+ * @param args plugin configuration arguements
+ *
+ */
+static void InitOutQuick(u_char *args)
+{
+   DEBUG_WRAP(DebugMessage(DEBUG_OUTQUICK,"outquick Initialized\n"););
+
+    /* parse the argument list from the rules file */
+    ParseOutQuickArgs(args);
+
+    /*
+     * ok, so we are going to cheat and only use one instance of the 
+     * preprocessor but allow the user to have multiple configurations
+     * without additonal overhead.
+     */
+    if (!outquick_used) 
+    {
+        /* Set the preprocessor function into the function list */
+        AddFuncToPreprocList(OutQuick);
+        outquick_used = 1;
+    }
+}
+
+/**
+ * display outquick configuration
+ */
+static int DisplayConfig()
+{
+    int i;
+
+    LogMessage("outquick config:\n");
+    for (i = 0; i < 65536; i++) 
+    {
+        if (outquickConfig[i].type > 0)
+        {
+            LogMessage("    Port: %d\tDepth: %d", i, outquickConfig[i].depth);
+            if (outquickConfig[i].type == OUTQUICK_TYPE_QUICK) 
+            {
+                LogMessage("\tType: quick\n");
+            } else {
+                LogMessage("\tType: until_response\n");
+            }
+       }
+    }
+    return 0;
+}
+
+/**
+ * parse outquick arguements
+ *
+ */
+static void ParseOutQuickArgs(char *args)
+{
+    char **Toks;
+    int num_toks;
+    int i;
+
+    int type = 0;
+    u_int32_t depth = 0;
+    int data_src = 0;
+
+    /* 
+     * we can only work if we are after stream4.  so if we ain't stateful,
+     * then die.
+     */
+    if(!pv.stateful)
+    {
+        FatalError("%s(%d) => outquick REQUIRES being in stateful mode.\n"
+              "    Enable stream4 and try again.\n", file_name, file_line);
+    }
+
+    /* if we don't have arguements, then die. */
+    if(args == NULL)
+    {
+        FatalError("%s(%d)=> No arguments to outquick preprocessor"
+                   "!\n", file_name, file_line);
+    }
+
+    Toks = mSplit(args, " \t", OUTQUICK_MAX_TOKENS , &num_toks, '\\');
+    
+    /*
+     * we have two types of output.  quick, and until_response.
+     * look at the comments above as to what the differences are.
+     */
+
+    if (!strcmp("quick",Toks[0])) {
+       type = OUTQUICK_TYPE_QUICK;
+    } else if (!strcmp("until_response",Toks[0])) {
+       type = OUTQUICK_TYPE_UNTIL_RESPONSE;
+    } else {
+       FatalError("%s (%d) => Invalid outquick type (%s).  only quick and "
+             "until_response are valid. \n", file_name, file_line, Toks[0]);
+    }
+
+    /* then look which side of the session we want to check the byte count on */
+    if (!strcmp("all",Toks[1])) {
+        if (type == OUTQUICK_TYPE_UNTIL_RESPONSE) 
+        {
+            FatalError("%s (%d) => outquick: until_response can't have all for"
+                    " a valid dataset.\n", file_name, file_line);
+
+        }
+       data_src = OUTQUICK_SRC_ALL;
+    } else if (!strcmp("server_data",Toks[1])) {
+       data_src = OUTQUICK_SRC_SERVER;
+    } else if (!strcmp("client_data",Toks[1])) {
+       data_src = OUTQUICK_SRC_CLIENT;
+    } else {
+       FatalError("%s (%d) => Invalid outquick data source (%s).  only "
+             "all, server data, and client_data are valid.\n", 
+             file_name, file_line, Toks[1]);
+    }
+
+    /* then check that the byte count is numeric... */
+    if(isdigit((int)Toks[2][0]))
+    {
+        char *num_p = NULL; /* used to determine last position in string */
+        long t_num;
+
+        t_num = strtol(Toks[2], &num_p, 10);
+
+        if(*num_p != '\0') {
+           FatalError("%s (%d) => invalid bytes: %s\n", file_name, file_line,
+                 Toks[2]);
+        }
+        else if(t_num < 0) 
+        {
+           FatalError("%s (%d) => invalid bytes: %s\n", file_name, file_line,
+                 Toks[2]);
+        } 
+
+        depth = t_num;
+    } 
+    else 
+    {
+        FatalError("%s (%d) => invalid bytes: %s\n", file_name, file_line,
+                Toks[2]);
+    }
+
+    /* everything else is a port that we apply this configuration on... */
+    for(i = 3; i < num_toks; i++)
+    {
+        if(isdigit((int)Toks[i][0]))
+        {
+            char *num_p = NULL; /* used to determine last position in string */
+            long t_num;
+
+            t_num = strtol(Toks[i], &num_p, 10);
+
+            if(*num_p != '\0')
+            {
+                FatalError("%s (%d) => invalid port: %s\n",
+                           file_name, file_line, Toks[i]);
+            }
+            else if(t_num < 0 || t_num > 65535)
+            {
+               FatalError("%s(%d) => invalid port: %ld\n",
+                     file_name, file_line, t_num);
+            }
+
+            outquickConfig[t_num].type  = type;
+            outquickConfig[t_num].depth = depth;
+            outquickConfig[t_num].src   = data_src;
+        }
+    }
+
+    /* dump our config */
+    DisplayConfig();
+}
+
+/**
+ * Process packets and jump out quick if it's bad
+ *
+ * @param p packet
+ */
+static void OutQuick(Packet *p)
+{
+    Session *ssn = p->ssnptr;
+    int server_port;
+    int traffic_type;
+    int type;
+    int data_src;
+    u_int32_t depth;
+
+    extern int do_detect;
+
+    /*
+     * this should never happen, thanks to us FatalErroring above, but 
+     * what the hell...
+     */
+    if(!pv.stateful)
+    {
+        /* if we're not in stateful mode we ignore this plugin */
+        DEBUG_WRAP(DebugMessage(DEBUG_OUTQUICK, "outquick: not stateful mode\n"););
+        return;
+    }
+
+
+    /*
+     * if we are not tcp, then we don't care
+     */
+    if(p->tcph == NULL)
+    {
+        DEBUG_WRAP(DebugMessage(DEBUG_OUTQUICK, "outquick: no tcp header\n"););
+        return;
+    }
+
+    /*
+     * if we arn't a session, then we don't care
+     */
+    if(!ssn)
+    {
+        DEBUG_WRAP(DebugMessage(DEBUG_OUTQUICK, "outquick: not part of a session\n"););
+        return;
+    }
+
+    /*
+     * if we are a mid-stream re-established session, then we can't be sure
+     * who is the client and who is the server.  So we return.
+     */
+    if (ssn->session_flags & SSNFLAG_MIDSTREAM) 
+    {
+        DEBUG_WRAP(DebugMessage(DEBUG_OUTQUICK, "outquick: rebuilt session.  we can't handle these...\n"););
+        return;
+    }
+
+    /* 
+     * we look at bytes_tracked, since thats where stream4 handles the retrans
+     * foo
+     */
+
+    /*
+     * set the client traffic and set the server port (so we can grab our 
+     * configuration later.)
+     */
+    if (p->packet_flags & PKT_FROM_CLIENT || 
+            !(p->packet_flags & PKT_FROM_SERVER))
+    {
+        traffic_type = CLIENT_TRAFFIC;
+        server_port = p->dp;
+    } 
+    else 
+    {
+        traffic_type = SERVER_TRAFFIC;
+        server_port = p->sp;
+    }
+
+    type  = outquickConfig[server_port].type;
+    depth = outquickConfig[server_port].depth;
+    data_src   = outquickConfig[server_port].src;
+
+    /* check if the type is NONE, if so, we don't have a config, so return */
+    if (type == OUTQUICK_TYPE_NONE) 
+    {
+        DEBUG_WRAP(DebugMessage(DEBUG_OUTQUICK, "outquick: no configuration for this server port : %d\n", server_port););
+        return;
+    }
+
+    /* Are we doing the quick thing? */
+    if (type == OUTQUICK_TYPE_QUICK) 
+    {
+        if (data_src == OUTQUICK_SRC_SERVER) {
+            if (ssn->server.bytes_tracked > depth) {
+                /*
+                 * we let the first one pass, since that may be the single
+                 * packet that pushed us over the limit... 
+                 */
+                if (ssn->server.outquick_packets == 0) 
+                {
+                    DEBUG_WRAP(DebugMessage(DEBUG_OUTQUICK, "outquick: let this one pass, but dump out on the next one...\n"););
+                    ssn->server.outquick_packets++;
+                }
+                else 
+                {
+                    DEBUG_WRAP(DebugMessage(DEBUG_OUTQUICK, "outquick: dumping out quick... saw %d bytes\n", ssn->server.bytes_tracked););
+                    do_detect = 0;
+                    p->preprocessors = 0;
+
+                    p->preprocessors |= PP_PORTSCAN;
+                    p->preprocessors |= PP_STREAM4;
+                }
+            } 
+            else 
+            {
+                DEBUG_WRAP(DebugMessage(DEBUG_OUTQUICK, "outquick: only sent %d bytes (looking for %d\n", ssn->client.bytes_tracked, depth););
+            }
+        } 
+        else if (data_src == OUTQUICK_SRC_CLIENT) 
+        {
+            if (ssn->client.bytes_tracked > depth) 
+            {
+                /*
+                 * we let the first one pass, since that may be the single
+                 * packet that pushed us over the limit... 
+                 */
+                if (ssn->client.outquick_packets == 0)
+                {
+                    DEBUG_WRAP(DebugMessage(DEBUG_OUTQUICK, "outquick: let this one pass, but dump out on the next one...\n"););
+                    ssn->client.outquick_packets++;
+                } 
+                else
+                {
+
+                    DEBUG_WRAP(DebugMessage(DEBUG_OUTQUICK, "outquick: dumping out quick... saw %d bytes\n", ssn->client.bytes_tracked););
+                    do_detect = 0;
+                    p->preprocessors = 0;
+
+                    p->preprocessors |= PP_PORTSCAN;
+                    p->preprocessors |= PP_STREAM4;
+                }
+            }
+            else 
+            {
+                DEBUG_WRAP(DebugMessage(DEBUG_OUTQUICK, "outquick: only sent %d bytes (looking for %d\n", ssn->client.bytes_tracked, depth););
+            }
+
+        }
+        else if (data_src == OUTQUICK_SRC_ALL) 
+        {
+            if ((ssn->client.bytes_tracked + ssn->client.bytes_tracked) > depth)
+            {
+                /*
+                 * we let the first one pass, since that may be the single
+                 * packet that pushed us over the limit... 
+                 */
+                if ((ssn->client.outquick_packets + 
+                            ssn->server.outquick_packets) == 0)
+                {
+                    DEBUG_WRAP(DebugMessage(DEBUG_OUTQUICK, "outquick: let this one pass, but dump out on the next one...\n"););
+                    ssn->client.outquick_packets++;
+                    ssn->server.outquick_packets++;
+                } 
+                else
+                {
+                    DEBUG_WRAP(DebugMessage(DEBUG_OUTQUICK, "outquick: dumping out quick... saw %d + bytes\n", ssn->client.bytes_tracked, ssn->client.bytes_tracked););
+                    do_detect = 0;
+                    p->preprocessors = 0;
+
+                    p->preprocessors |= PP_PORTSCAN;
+                    p->preprocessors |= PP_STREAM4;
+                }
+            }
+            else 
+            {
+                DEBUG_WRAP(DebugMessage(DEBUG_OUTQUICK, "outquick: only sent %d+%d bytes (looking for %d\n", ssn->client.bytes_tracked, ssn->server.bytes_tracked, depth););
+            }
+        }
+    
+    }
+    /* so, are we handling the until_response configuration */
+    else if (type == OUTQUICK_TYPE_UNTIL_RESPONSE)
+    {
+        if (data_src == OUTQUICK_SRC_SERVER) 
+        {
+            /*
+             * check if we have new client data.  if we have, then reset the
+             * server data counter and don't disable detection
+             */
+            if (ssn->client.outquick_bytes > 0) 
+            {
+                DEBUG_WRAP(DebugMessage(DEBUG_OUTQUICK, "outquick: saw client traffic resetting counts...\n", ssn->client.bytes_tracked););
+                ssn->server.outquick_bytes = 0;
+                ssn->server.outquick_packets = 0;
+                ssn->client.outquick_bytes = 0;
+                ssn->client.outquick_packets = 0;
+            } 
+            /*
+             * otherwise, check if the server has sent more than its 
+             * configured amount.  if so, then turn off detection.
+             */
+            else if (ssn->server.outquick_bytes > depth) 
+            {
+                /*
+                 * we let the first one pass, since that may be the single
+                 * packet that pushed us over the limit... 
+                 */
+                if (ssn->server.outquick_packets == 0) 
+                {
+                    DEBUG_WRAP(DebugMessage(DEBUG_OUTQUICK, "outquick: let this one pass, but dump out on the next one...\n"););
+                    ssn->server.outquick_packets++;
+                } 
+                else 
+                {
+                    DEBUG_WRAP(DebugMessage(DEBUG_OUTQUICK, "outquick: dumping out quick... saw %d bytes in the second server packet\n", ssn->server.outquick_bytes););
+                    ssn->client.outquick_packets++;
+                    ssn->client.outquick_bytes = 0;
+                    do_detect = 0;
+                    p->preprocessors = 0;
+
+                    p->preprocessors |= PP_PORTSCAN;
+                    p->preprocessors |= PP_STREAM4;
+                }
+            }
+        } 
+        else if (data_src == OUTQUICK_SRC_CLIENT) 
+        {
+            /*
+             * check if we have new server data.  if we have, then reset the
+             * client data counter and don't disable detection
+             */
+            if (ssn->server.outquick_bytes > 0) 
+            {
+                DEBUG_WRAP(DebugMessage(DEBUG_OUTQUICK, "outquick: saw server traffic resetting counts...\n", ssn->server.bytes_tracked););
+                ssn->server.outquick_bytes = 0;
+                ssn->server.outquick_packets = 0;
+                ssn->client.outquick_bytes = 0;
+                ssn->client.outquick_packets = 0;
+            } 
+            /*
+             * otherwise, check if the server has sent more than its 
+             * configured amount.  if so, then turn off detection.
+             */
+            else if (ssn->client.outquick_bytes > depth) 
+            {
+                /*
+                 * we let the first one pass, since that may be the single
+                 * packet that pushed us over the limit... 
+                 */
+                if (ssn->client.outquick_packets == 0) 
+                {
+                    DEBUG_WRAP(DebugMessage(DEBUG_OUTQUICK, "outquick: let this one pass, but dump out on the next one...\n"););
+                    ssn->client.outquick_packets++;
+                } 
+                else 
+                {
+                    DEBUG_WRAP(DebugMessage(DEBUG_OUTQUICK, "outquick: dumping out quick... saw %d bytes in the second client packet\n", ssn->client.outquick_bytes););
+                    ssn->server.outquick_packets++;
+                    ssn->server.outquick_bytes = 0;
+                    do_detect = 0;
+                    p->preprocessors = 0;
+
+                    p->preprocessors |= PP_PORTSCAN;
+                    p->preprocessors |= PP_STREAM4;
+                }
+            }
+        } 
+    }
+
+    #ifdef DEBUG
+    if (do_detect) 
+    {
+        DEBUG_WRAP(DebugMessage(DEBUG_OUTQUICK, "outquick: guess it was ok... (server port = %d)\n", server_port););
+    }
+    #endif
+
+    return;
+}
--- src/preprocessors/spp_outquick.h	1969-12-31 19:00:00.000000000 -0500
+++ src/preprocessors/spp_outquick.h	2003-05-04 22:31:13.000000000 -0400
@@ -0,0 +1,27 @@
+/* $Id$ */
+
+/*
+** Copyright (C) 2003 Brian Caswell <bmc at ...835...>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __SPP_OUTQUICK_H__
+#define __SPP_OUTQUICK_H__
+
+void SetupOutQuick();
+
+#endif 
--- src/preprocessors/spp_stream4.c	2003-04-17 08:38:47.000000000 -0400
+++ src/preprocessors/spp_stream4.c	2003-05-04 18:55:37.000000000 -0400
@@ -1522,9 +1522,11 @@
     if((stream->bytes_tracked - sub) > stream->bytes_tracked)
     {
         stream->bytes_tracked = 0;
+        stream->outquick_bytes = 0;
     }
     else
     {
+        stream->outquick_bytes -= sub;
         stream->bytes_tracked -= sub;
     }
 
@@ -1555,6 +1557,8 @@
     }
     else
     {
+        stream->outquick_bytes += add;
+
         stream->bytes_tracked += add;
         stream->bytes_sent += add;
         stream->pkts_sent++;


More information about the Snort-devel mailing list