Snort mailing list archives

[Snort-devel] Call for Bugs -> icmpscaner


From: Serge Droz <serge.droz () psi ch>
Date: Fri, 06 Jul 2001 16:53:04 +0200

I've appended out diff implementing out ICMP scan detector. It has been
working here quite well for a while now.

Maybe people find it usefull

Serge


-- 
Serge Droz
Paul Scherrer Institut                mailto:serge.droz () psi ch
CH-5232 Villigen PSI                   Phone: ++41 56 310 3637
                                         Fax: ++41 56 310 3649
--- snort.orig/snort.conf       Thu Jul  5 07:17:17 2001
+++ snort/snort.conf    Fri Jul  6 16:42:01 2001
@@ -228,6 +228,21 @@
 #
 #preprocessor portscan-ignorehosts: $DNS_SERVERS
 
+# icmpscan: detect icmp (ping scans) 
+# __________________________________
+#
+# Format 
+# preprocessor icmpscan:  n t1 t2 log
+# if there are more than n icmp packets from teh same source in t1 seconds
+# the scan starts. It ends after there has been no icmp traffic for t2 seconds.
+#
+#
+
+#var ICMP_SCAN_IGNORE [129.129.110.10/32] 
+#preprocessor ignore-icmpscan: $ICMP_SCAN_IGNORE
+#preprocessor icmpscan:  12 15 15 icmpscan.log
+
+
 # Spade: the Statistical Packet Anomaly Detection Engine
 #-------------------------------------------------------
 # READ the README.Spade file before using this plugin!
--- snort.orig/spp_icmpscan.c   Fri Jul  6 16:36:58 2001
+++ snort/spp_icmpscan.c        Fri Jul  6 16:22:14 2001
@@ -0,0 +1,535 @@
+/*
+** Copyright (C) 2001 Serge Droz <serge.droz () psi ch>
+**
+** 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.
+*//* $Id$ */
+/* Snort IcmpScan preprocessor Plugin
+   by Serge Droz <serge.droz () psi ch>
+   Version 0.1*/
+
+/* spp_icmpscan
+ * 
+ * Purpose: Detect and report icmp (ping) scans
+ *
+ *
+ * Arguments:  numhosts timeinterval timeout [icmplogFile]
+ *  
+ *
+ * A scans starts when there are icmp packets to more than numhosts hosts in timeinterval
+ * seconds. It stops if no packets have been seen in timeout seconds.
+ *
+ * Effect:
+ *  
+ * Issue an alert if an ICMP Scan is detected. Log the targets into an optional log file.
+ *
+ */
+
+/* preprocessor header file goes here */
+#include "spp_icmpscan.h"
+#include <stdio.h>
+#include <string.h>
+#include <arpa/inet.h> 
+#include "rules.h"
+#include "log.h"
+
+#define pTime(p) (p->pkth->ts.tv_sec) 
+#define MaxIgnore 32 /* Maximum number of hosts/subnets which can be ignored */
+
+/* external globals from rules.c */
+
+
+extern char *file_name;
+extern int file_line;
+extern u_int32_t event_id;
+
+typedef struct _target {
+          long int  time;
+         struct in_addr myaddr;
+         u_int8_t type;
+         u_int8_t code;
+         u_int8_t ttl;
+} target;
+
+/* Things we need to know about a scaner */              
+
+typedef struct _scaner {
+          struct in_addr source; 
+          struct _scaner *next,*prev;
+         u_int32_t event_id;
+         long int  start;
+         long int  last;
+         int top; 
+         unsigned long   count;
+         int scan_detected;
+         target targets[0];
+} scaner;
+
+/* Hosts and subnets we should ignore */
+typedef struct _ignorius {
+   unsigned long network;
+   unsigned long netmask;
+} ignorius;
+                 
+/* Some Prototypes */
+int IgnorePacket(Packet *p);
+
+
+/* Globals */
+static int threshTargets;              
+static int threshSecs;
+static int finSecs;
+static FILE *icmplogFile = NULL;
+static scaner *FirstScaner;
+static ignorius *Ignore;
+static int NumIgnore = 0;
+
+/* Some stuff to do diagnostics. This is not needed for normal operation */ 
+void print_all_sources () {
+  scaner *s = FirstScaner;
+  printf("------------------------\n");
+  while ( s ) {
+    printf("Scanner: %s\n",inet_ntoa(s->source));
+    s = s->next;
+  }
+  printf("------------------------\n");
+}
+
+void print_all_targets (scaner *s) {
+int i;  
+  printf("------ Targets -------\n");
+  printf("Scanner: %s\n",inet_ntoa(s->source));
+  for (i=0; i < s->top; i++)   printf("target: %s\n",inet_ntoa(s->targets[i].myaddr));
+  printf("------------------------\n");
+}
+
+/*
+ * Function: SetupIcmpScan()
+ *
+ * Purpose: Registers the preprocessor keyword and initialization 
+ *          function into the preprocessor list.  This is the function that
+ *          gets called from InitPreprocessors() in plugbase.c.
+ *
+ * Arguments: None.
+ *
+ * Returns: void function
+ *
+ */
+void SetupIcmpScan()
+{
+    /* link the preprocessor keyword to the init function in 
+       the preproc list */
+    RegisterPreprocessor("icmpscan", IcmpScanInit);
+
+#ifdef DEBUG
+    printf("Preprocessor: IcmpScan is setup...\n");
+#endif
+}
+
+
+/*
+ * Function: IcmpScanInit(u_char *)
+ *
+ * Purpose: Calls the argument parsing function, performs final setup on data
+ *          structs, links the preproc function into the function list.
+ *
+ * Arguments: args => ptr to argument string
+ *
+ * Returns: void function
+ *
+ */
+void  IcmpScanInit(u_char *args)
+{
+#ifdef DEBUG
+    printf("Preprocessor: IcmpScan Initialized\n");
+#endif
+
+    /* parse the argument list from the rules file */
+    ParseIcmpScanArgs(args);
+
+    /* Set the preprocessor function into the function list */
+    AddFuncToPreprocList(PreprocIcmpScanFunction);
+    AddFuncToCleanExitList(ExitIcmpScanFunction,NULL);
+}
+
+
+
+/*
+ * Function: ParseIcmpScanArgs(char *)
+ *
+ * Purpose: Process the preprocessor arguements from the rules file and 
+ *          initialize the preprocessor's data struct.  This function doesn't
+ *          have to exist if it makes sense to parse the args in the init 
+ *          function.
+ *
+ * Arguments: args => argument list
+ *
+ * Returns: void function
+ *
+ * Remark: This is shamelessly stoplen from spp_portscan.c
+ */
+void ParseIcmpScanArgs(char *args)
+{
+  char **toks;
+  int  numToks;
+
+  char *icmplogFileName;
+
+
+
+  if (!args)  FatalError("icmpscan" ": ERROR: %s (%d) => icmpscan configuration format:  hosts seconds 
seconds[icmplogFile]\n", file_name, file_line);;
+  toks = mSplit(args, " ", 4, &numToks, '\\');
+
+  if((numToks < 3) || (numToks > 4))  FatalError("icmpscan" ": ERROR: %s (%d) => icmpscan configuration format:  hosts 
seconds seconds[icmplogFile]\n", file_name, file_line);;
+  threshTargets = atoi(toks[0]);
+  threshSecs    = atoi(toks[1]);
+  finSecs       = atoi(toks[2]);
+  FirstScaner   = NULL;
+  if(numToks == 4)
+    {
+        if(pv.log_dir && (*toks[3] != '/'))
+        {
+            if(*(pv.log_dir + strlen(pv.log_dir) - 1) != '/')
+            {
+                icmplogFileName = chrootdir == NULL ?
+                    (char *) calloc(strlen(pv.log_dir) + strlen(toks[3]) + 1 + 1, 1) :
+                    (char *) calloc(strlen(pv.log_dir) + strlen(toks[3]) + strlen(chrootdir) + 1 + 1, 1);
+
+                if(chrootdir)
+                    strncpy(icmplogFileName, chrootdir, strlen(chrootdir) + 1);
+                strncat(icmplogFileName, pv.log_dir, strlen(pv.log_dir) + 1);
+                strncat(icmplogFileName, "/", 1);
+                strncat(icmplogFileName, toks[3], strlen(toks[3]));
+            }
+            else
+            {
+                icmplogFileName = chrootdir == NULL ?
+                    (char *) calloc(strlen(pv.log_dir) + strlen(toks[3]) + 1, 1) :
+                    (char *) calloc(strlen(pv.log_dir) + strlen(toks[3]) + strlen(chrootdir) + 1, 1);
+                if(chrootdir)
+                    strncpy(icmplogFileName, chrootdir, strlen(chrootdir) + 1);
+                strncat(icmplogFileName, pv.log_dir, strlen(pv.log_dir) + 1);
+                strncat(icmplogFileName, toks[3], strlen(toks[3]));
+            }
+        }
+        else
+        {
+            icmplogFileName = chrootdir == NULL ?
+                (char *) calloc(strlen(toks[3]) + 1, 1) :
+                (char *) calloc(strlen(toks[3]) + strlen(chrootdir) + 1, 1);
+            if(chrootdir)
+                strncpy(icmplogFileName, chrootdir, strlen(chrootdir) + 1);
+            strncat(icmplogFileName, toks[3], strlen(toks[3]) + 1);
+        }
+
+#ifdef DEBUG
+        printf("icmpscan" ": icmplogFileName = %s\n", icmplogFileName);
+#endif
+
+        icmplogFile = fopen(icmplogFileName, "a+");
+        if(!icmplogFile)
+        {
+            perror("fopen");
+            FatalError("icmpscan" ": icmplogFile open error (%s)\n", icmplogFileName);
+        }
+
+   }
+ }
+/*
+ * Function RemoveScaner(scaner **)
+ *
+ * Purpose: Removes a system from the list of scanners
+ *
+ * Arguments: s pointer to the addres of the scaner struct 
+ *
+ * Returns: void function
+ *
+ */
+void RemoveScaner(scaner **s) {
+  scaner *temp;
+  char AlertLine[256];
+  Event event;
+  
+  temp = *s;
+  
+  if ( (temp)->prev ) (temp)->prev->next = (temp)->next; else FirstScaner = (temp)->next;
+  if ( (temp)->next ) (temp)->next->prev = (temp)->prev;
+  *s = temp->next;
+  /* Log this */
+  if ( temp->scan_detected ) {
+    sprintf(AlertLine,"spp_icmpscan: End of icmpscan from %s %ld packets 
recieved",inet_ntoa(temp->source),temp->count);
+    SetEvent(&event, GENERATOR_SPP_ICMPSCAN, ICMPSCAN_SCAN_END, 1, 0, 0,temp->event_id);
+       CallAlertFuncs(NULL,AlertLine,NULL,&event);
+  }
+  free(temp);
+#ifdef DEBUG
+  printf("Remove: %s\n",inet_ntoa(temp->source));
+#endif
+}
+
+/*
+ * Function NewScaner(Packet *)
+ *
+ * Purpose: Inserts a new source into the list of potential 
+ *          icmp scaners.
+ *
+ * Arguments: p => pointer to the current packet data struct 
+ *
+ * Returns: void function
+ *
+ */
+ void NewScaner(Packet *p) {
+   scaner *news;
+   news = (scaner *)malloc(sizeof(scaner) + (threshTargets+1)*sizeof(target));
+   news->last = news->start = pTime(p);
+   news->source.s_addr = p->iph->ip_src.s_addr;
+   news->count = 1;
+   memset(news->targets+1,0,threshTargets*sizeof(target));
+   news->targets[0].time = news->start;
+   news->targets[0].myaddr = p->iph->ip_dst;
+   news->targets[0].ttl = p->iph->ip_ttl;
+   news->targets[0].type = p->icmph->type;
+   news->targets[0].code = p->icmph->code;
+   news->top=1;
+   news->scan_detected=0;
+   if ( FirstScaner ) {
+     FirstScaner->prev = news;
+   }
+   news->next = FirstScaner;
+   news->prev = NULL;
+   FirstScaner = news;  
+#ifdef DEBUG
+   printf("New src: %s\n",inet_ntoa(p->iph->ip_src));
+#endif   
+ }  
+
+/*
+ * Function LogTarget(char *src, target *t)
+ *
+ * Purpose: Log a target into the icmplogFile
+ *
+ * Arguments: src => string containing the source, t => pointer to the target 
+ *
+ * Returns: void function
+ *
+ */
+
+void LogTarget(char *src, target *t) {
+  struct tm *time;
+  char month[][4] = { "Jan","Feb","Mar","Apr","Mai","Jun","Jul","Aug","Sep","Oct","Nov","Dec" };
+  time = localtime((time_t *) & t->time);
+
+  fprintf(icmplogFile,"%s %2d %.2d:%.2d:%.2d %s -> %s Type: %2d Code: %2d TTL: %3d\n",
+          month[time->tm_mon ], time->tm_mday,time->tm_hour, time->tm_min, time->tm_sec,
+          src,inet_ntoa(t->myaddr),t->type, t->code,t->ttl);
+}
+/*
+ * Function UpdateScaner(scaner *, Packet *)
+ *
+ * Purpose: Updates the info on a given scaner.
+ *
+ * Arguments: s => poninter to a scaner, p => pointer to the current packet data struct 
+ *
+ * Returns: void function
+ * This function updates the list of recent targets. 
+ * It manipulates a cronologically orderd stack of targets. If we ht the top,
+ then we deal with a scan and report. 
+ * 
+ */
+void UpdateScaner(scaner *s, Packet *p) {
+   char srcn[17];
+   char AlertLine[256];
+   Event event;
+   int i,j=-1;
+   /* Insert the new entry on the top */
+#ifdef DEBUG
+   print_all_targets(s);
+#endif   
+   /* First remove the entries which are too old to be kept */
+   for (i=0; s->targets[i].time < pTime(p) - threshSecs && i < s->top; i++) {}
+   /* Now either update the new target (it it exists) or append on the top */
+   for (j=i ; j < s->top; j++ ) if ( s->targets[j].myaddr.s_addr == p->iph->ip_dst.s_addr ) break;
+   /* We're above the limit, so we have to throw an 'active' target out  */
+   if (j == threshTargets ) {
+      s->top++;
+      if (! i ) i=1;
+   }
+   /* Now move the stuff down the stack, kicking the 'expired' stuff out */
+   memmove(s->targets,s->targets+i,(j-i)*sizeof(target));
+   if (j != s->top) memmove(s->targets+j-i,s->targets+j+1,(s->top-j-1)*sizeof(target));
+   else s->top++;
+   /* And finally add the new target, which always goes to the top */
+   s->top-=i;
+   s->targets[s->top-1].time = pTime(p);
+   s->last = pTime(p) ;
+   s->targets[s->top-1].myaddr = p->iph->ip_dst;
+   s->targets[s->top-1].ttl = p->iph->ip_ttl;
+   s->targets[s->top-1].type = p->icmph->type;
+   s->targets[s->top-1].code = p->icmph->code;
+   s->count++;
+   
+   /*Logit*/
+
+   strcpy(srcn,inet_ntoa(p->iph->ip_src));
+   if ( s->scan_detected ) {
+     if ( icmplogFile ) LogTarget(srcn,&s->targets[s->top-1]);
+     if ( s->count % 100 == 0 ) {
+       sprintf(AlertLine,"spp_icmpscan: ICMPSCAN status from %s: %d packets",inet_ntoa(p->iph->ip_src),s->count);
+       SetEvent(&event, GENERATOR_SPP_ICMPSCAN, ICMPSCAN_INTER_INFO , 1, 0, 0,s->event_id);
+        CallAlertFuncs(NULL,AlertLine,NULL,&event);
+     }
+   } else if (  s->top == threshTargets ) {
+     s->scan_detected = 1 ;
+     sprintf(AlertLine,"spp_icmpscan: ICMPSCAN DETECTED from %s",inet_ntoa(p->iph->ip_src));
+     SetEvent(&event, GENERATOR_SPP_ICMPSCAN, ICMPSCAN_SCAN_DETECT, 1, 0, 0,0);
+        CallAlertFuncs(NULL,AlertLine,NULL,&event);
+        s->event_id = event_id;
+     if ( icmplogFile ) for (i=0; i< s->top; i++ ) LogTarget(srcn,&s->targets[i]);
+   }
+}
+   
+/*
+ * Function: PreprocFunction(Packet *)
+ *
+ * Purpose: This is the mainloop. First check if it's an icmp packet,
+ *          the if we ignore it, and if not, do the fun stuff.
+ *
+ * Arguments: p => pointer to the current packet data struct 
+ *
+ * Returns: void function
+ *
+ */
+void PreprocIcmpScanFunction(Packet *p) {
+ 
+    scaner *currentScaner;
+       int Exists = 0;
+    /* We only do IP */
+       if ( p->iph == NULL )  {
+         return;
+       }
+       
+       
+       /* In fact, we only do ICMP */
+       
+       if ( p->icmph == NULL ) {
+         return ;
+       }
+       if ( IgnorePacket( p ) ){
+         return ;
+       }
+       currentScaner = FirstScaner;
+       
+       /* Now we loop over all scaners.
+          If we find the curent source we update.
+          Then we check if there are expired sources and delete them.
+          Finally if the scanner wasn't in the list we insert it. */
+       
+       while ( currentScaner ) {
+#ifdef DEBUG
+           print_all_sources();
+#endif
+          if ( currentScaner->source.s_addr == p->iph->ip_src.s_addr  ) { /* Found em */
+                UpdateScaner(currentScaner, p);
+                Exists = 1;
+                currentScaner = currentScaner->next;
+          } else if  (pTime(p) >  currentScaner->last + finSecs ) {
+            RemoveScaner(&currentScaner);
+          } else { 
+            currentScaner = currentScaner->next;
+          }
+    }
+    if ( ! Exists ) NewScaner(p);
+}      
+
+void ExitIcmpScanFunction(int signal,void *arg)
+{
+   /* clean exit code goes here */
+   scaner *s = FirstScaner;
+   
+   if ( icmplogFile ) fclose(icmplogFile);
+
+   while ( s ) RemoveScaner(&s);
+
+}
+
+void RestartIcmpScanFunction(int signal)
+{
+       /* restart code goes here */
+}
+
+/*****************************************************************
+  Here the Ignore hosts stuff follows !
+ *****************************************************************/
+void SetupIgnoreIcmpScan()
+{
+    /* link the preprocessor keyword to the init function in 
+       the preproc list */
+    RegisterPreprocessor("ignore-icmpscan", IgnoreIcmpScanInit);
+
+#ifdef DEBUG
+    printf("Preprocessor: IcmpScan is setup...\n");
+#endif
+}
+
+
+void  IgnoreIcmpScanInit(u_char *args)
+{
+    int i;
+    char *myargs,*t;
+    char **toks;
+    unsigned long a,b,c,d,e;
+#ifdef DEBUG
+    printf("Preprocessor: IgnoreIcmpScan Initialized\n");
+#endif
+    Ignore = (ignorius *)malloc(MaxIgnore*sizeof(ignorius));
+    /* parse the argument list from the rules file */
+    myargs = strchr(args,'[');
+    if (! myargs ) FatalError("icmpscanIgnore" ": ERROR: %s (%d) => Ignore icmpscan configuration format:  
[addr/mask,...]\n", file_name, file_line);;
+    t = strchr(myargs,']');
+    t = NULL;
+    toks = mSplit(myargs+1, ",", 32, &NumIgnore, '\\');
+    for (i=0; i<NumIgnore; i++) {
+       if ( 5 != sscanf(toks[i],"%lu.%lu.%lu.%lu/%lu",&a,&b,&c,&d,&e)) {
+           FatalError("icmpscanIgnore" ": ERROR: %s (%d) => Adressformat: a.b.c.d/mask\n", file_name, file_line);;
+       }  
+       Ignore[i].netmask = 0xffffffff >> (32-e);
+       Ignore[i].network = ( a + (b << 8)  + (c << 16) +  (d << 24)) &  ( Ignore[i].netmask ) ;
+    }
+    /* Set the preprocessor function into the function list */
+    AddFuncToCleanExitList(ExitIgnoreIcmpScanFunction,NULL);
+}
+
+
+ 
+void ExitIgnoreIcmpScanFunction(int signal,void *arg)
+{
+   /* clean exit code goes here */
+   free(Ignore);
+}
+
+/*****************************************************************
+ *
+ * Function: Igonre Packet
+ * Checks if a certain packet should be ignored.
+ * Argument: p => Pointer to pacet struct
+ * Return value: 1 if the packet should be ignored, 0 otherwise.
+ *****************************************************************/
+int IgnorePacket(Packet *p) {
+  int i;
+  for (i=0; i< NumIgnore; i++) {
+     if ( (p->iph->ip_src.s_addr & Ignore[i].netmask) == Ignore[i].network ) return 1;
+  }
+  return 0; 
+}
+     
--- snort.orig/spp_icmpscan.h   Fri Jul  6 16:37:00 2001
+++ snort/spp_icmpscan.h        Fri Jul  6 16:10:09 2001
@@ -0,0 +1,29 @@
+/* $Id: spp_template.h,v 1.2 2000/11/13 06:01:25 roesch Exp $ */
+/* Snort Preprocessor Plugin Header File Template */
+
+/* This file gets included in plugbase.h when it is integrated into the rest 
+ * of the program.  Sometime in The Future, I'll whip up a bad ass Perl script
+ * to handle automatically loading all the required info into the plugbase.*
+ * files.
+ */
+#include "snort.h"
+
+#ifndef __SPP_ICMPSCAN_H__
+#define __SPP_ICMPSCAN_H__
+
+/* typedef struct _TemplateData
+{
+    
+} TemplateData; */
+
+/* list of function prototypes for this preprocessor */
+void SetupIcmpScan();
+void IcmpScanInit(u_char *);
+void ParseIcmpScanArgs(char *);
+void PreprocIcmpScanFunction(Packet *);
+void ExitIcmpScanFunction(int,void *);
+
+void SetupIgnoreIcmpScan();
+void ExitIgnoreIcmpScanFunction(int signal,void *arg);
+void IgnoreIcmpScanInit(u_char *args);
+#endif  /* __SPP_ICMPSCAN_H__ */
--- snort.orig/plugbase.c       Fri Jun 22 00:22:19 2001
+++ snort/plugbase.c    Fri Jul  6 16:08:28 2001
@@ -75,6 +75,8 @@
     SetupHttpDecode();
     SetupPortscan();
     SetupPortscanIgnoreHosts();
+    SetupIcmpScan();
+    SetupIgnoreIcmpScan();
     SetupDefrag();
     SetupTcpStream2();
     SetupSpade();
--- snort.orig/plugbase.h       Fri Jun 22 00:22:19 2001
+++ snort/plugbase.h    Fri Jul  6 16:06:13 2001
@@ -52,6 +52,7 @@
 
 #include "spp_http_decode.h"
 #include "spp_portscan.h"
+#include "spp_icmpscan.h"
 #include "spp_defrag.h"
 #include "spp_tcp_stream2.h"
 #include "spp_anomsensor.h"
--- snort.orig/generators.h     Tue Jul  3 02:43:02 2001
+++ snort/generators.h  Fri Jul  6 16:13:04 2001
@@ -72,5 +72,8 @@
 #define     STREAM4_STEALTH_NMAP_FINGERPRINT    12
 #define     STREAM4_STEALTH_SYN_FIN_SCAN        13
 
-
+#define GENERATOR_SPP_ICMPSCAN      112
+#define     ICMPSCAN_SCAN_DETECT        1
+#define     ICMPSCAN_INTER_INFO         2
+#define     ICMPSCAN_SCAN_END           3
 #endif /* __GENERATORS_H__ */
--- snort.orig/Makefile.am      Tue Jun 26 04:49:30 2001
+++ snort/Makefile.am   Fri Jul  6 16:07:18 2001
@@ -31,7 +31,7 @@
 sp_ip_same_check.h sp_priority.c sp_priority.h sp_ip_proto.c          \
 sp_ip_proto.h ubi_BinTree.c ubi_BinTree.h ubi_SplayTree.c \
 spo_unified.c spo_unified.h generators.h spp_stream4.h spp_stream4.c  \
-ubi_SplayTree.h sys_include.h
+ubi_SplayTree.h sys_include.h spp_icmpscan.h spp_icmpscan.c
 
 EXTRA_DIST = BUGS RULES.SAMPLE CREDITS snort.conf USAGE backdoor.rules \
 info.rules smtp.rules ddos.rules local.rules telnet.rules dns.rules   \

Current thread: