📄 spp_frag3.c
字号:
/* $Id$ *//** * @file spp_frag3.c * @author Martin Roesch <roesch@sourcefire.com> * @date Thu Sep 30 14:12:37 EDT 2004 * * @brief Frag3: IP defragmentation preprocessor for Snort. *//* ** Copyright (C) 2004 Sourcefire Inc. ** ** 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. *//* * Notes: * Frag3 sports the following improvements over frag2: * - Target-based IP defragmentation, harder to evade * - 8 Anomaly detection event types * - Two separate memory management strategies to tailor * performance for specific environments * - Up to 250% faster than frag2. * * The mechanism for processing frags is based on the Linux IP stack * implementation of IP defragmentation with proper amounts of paranoia * and an IDS perspective applied. Some of this code was derived from * frag2 originally, but it's basically unrecognizeable if you compare * it to frag2 IMO. * * I switched from using the UBI libs to using sfxhash and linked lists for * fragment management because I suspected that the management code was * the cause of performance issues that we were observing at Sourcefire * in certain customer situations. Splay trees are cool and really hard * to screw with from an attack perspective, but they also incur a lot * of overhead for managing the tree and lose the order of the fragments in * the FragTracker's fraglist, so I dropped them. Originally the * frag3 code was just supposed to migrate away from the splay tree system * that I was using in frag2, but I figured since I was doing the work to * pull out the splay trees I may as well solve some of the other problems * we were seeing. * * Initial performance testing that I've done shows that frag3 can be as much * as 250% faster than frag2, but we still need to do more testing and * optimization, we may be able to squeeze out some more performance. * * Frag3 is also capable of performing "Target-based" IP defragmentation. * What this means practically is that frag3 can model the IP stack of a * target on the network to avoid Ptacek-Newsham evasions of the IDS through * sensor/target desynchronization. In terms of implentation, this is * reflected by passing a "context" into the defragmentation engine that has * a specific configuration for a specific target type. Windows can put * fragments back together differently than Linux/BSD/etc, so we model that * inside frag3 so we can't be evaded. * * Configuration of frag3 is pretty straight forward, there's a global config * that contains data about how the hash tables will be structured, what type * of memory management to use and whether or not to generate alerts, then * specific target-contexts are setup and bound to IP address sets. Check * the README file for specifics! *//* I N C L U D E S ************************************************/#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <sys/types.h>#include <stdlib.h>#include <ctype.h>#include <rpc/types.h>#include "bounds.h"#include "generators.h"#include "log.h"#include "detect.h"#include "decode.h"#include "event.h"#include "util.h"#include "debug.h"#include "plugbase.h"#include "parser.h"#include "mstring.h"#include "checksum.h"#include "perf.h"#include "event_queue.h"#include "timersub.h"#include "fpcreate.h"#include "sfutil/sflsq.h"#include "sfutil/sfxhash.h"#include "snort.h"extern OptTreeNode *otn_tmp;/* D E F I N E S **************************************************//* flags for the FragTracker->frag_flags field */#define FRAG_GOT_FIRST 0x00000001#define FRAG_GOT_LAST 0x00000002#define FRAG_REBUILT 0x00000004#define FRAG_BAD 0x00000008#define FRAG_PRUNE_QUANTA 60 /* default frag timeout, 90-120 might * be better values, can we do * target-based quanta? */#define FRAG_MEMCAP 4194304 /* default 4MB memcap */#define FRAG3_TTL_LIMIT 5 /* default TTL, unnecessary in * tgt-based systems? */#define FRAG3_MIN_TTL 1 /* min acceptable ttl (should be 1?) *//* target-based defragmentation policy enums */#define FRAG_POLICY_FIRST 1#define FRAG_POLICY_LINUX 2#define FRAG_POLICY_BSD 3#define FRAG_POLICY_BSD_RIGHT 4#define FRAG_POLICY_LAST 5#define FRAG_POLICY_WINDOWS 6 /* Combo of FIRST & LAST, depending on * overlap situation. */#define FRAG_POLICY_SOLARIS 7 /* Combo of FIRST & LAST, depending on * overlap situation. *//* the twiddle is needed for architectures that force word-aligned memory * access */#if defined (SOLARIS) || defined (SUNOS) || defined (__sparc__) || defined(__sparc64__) || defined (HPUX)#define SPARC_TWIDDLE 2#else#define SPARC_TWIDDLE 0#endif/* max packet size */#define DATASIZE (ETHERNET_HEADER_LEN+IP_MAXPACKET)/* max frags in a single frag tracker */#define DEFAULT_MAX_FRAGS 8192/* return values for CheckTimeout() */#define FRAG_TIME_OK 0#define FRAG_TIMEOUT 1/* return values for Frag3Insert() */#define FRAG_INSERT_OK 0#define FRAG_INSERT_FAILED 1#define FRAG_INSERT_REJECTED 2#define FRAG_INSERT_TIMEOUT 3#define FRAG_INSERT_ATTACK 4#define FRAG_INSERT_ANOMALY 5#define FRAG_INSERT_TTL 6/* return values for Frag3CheckFirstLast() */#define FRAG_FIRSTLAST_OK 0#define FRAG_LAST_DUPLICATE 1/* return values for Frag3Expire() */#define FRAG_OK 0#define FRAG_TRACKER_TIMEOUT 1#define FRAG_LAST_OFFSET_ADJUST 2/* flag for detecting attacks/alerting */#define FRAG3_DETECT_ANOMALIES 0x01/* D A T A S T R U C T U R E S **********************************//* global configuration data struct for this preprocessor */typedef struct { u_int32_t max_frags; /* max frags to track */ u_int32_t memcap; /* memcap for frag3 */ u_int32_t static_frags; /* static frag nodes to keep around */ u_int8_t use_prealloc; /* flag to indicate prealloc nodes in use */} Frag3GlobalConfig;/* runtime context for a specific instance of an engine */typedef struct _Frag3Context{ u_int16_t frag_policy; /* policy to use for target-based reassembly */ int32_t frag_timeout; /* timeout for frags in this policy */ u_int8_t min_ttl; /* Minimum TTL to accept */ u_int8_t ttl_limit; /* Size of ttls to avoid detection on */ char frag3_alerts; /* Whether or not frag3 alerts are enabled */ IpAddrSet *bound_addrs; /* addresses bound to this context */} Frag3Context;/* struct to manage an individual fragment */typedef struct _Frag3Frag{ u_int8_t *data; /* ptr to adjusted start position */ u_int16_t size; /* adjusted frag size */ u_int16_t offset; /* adjusted offset position */ u_int8_t *fptr; /* free pointer */ u_int16_t flen; /* free len, unneeded? */ struct _Frag3Frag *prev; struct _Frag3Frag *next; int ord; char last;} Frag3Frag;/* key struct for the sfxhash */typedef struct _fragkey{ u_int32_t sip; /* src IP */ u_int32_t dip; /* dst IP */ u_int16_t id; /* IP ID */ u_int8_t proto; /* IP protocol */} FRAGKEY;/* Only track a certain number of alerts per session */#define MAX_FRAG_ALERTS 8/* tracker for a fragmented packet set */typedef struct _FragTracker{ u_int32_t sip; /* src IP */ u_int32_t dip; /* dst IP */ u_int16_t id; /* IP ID */ u_int8_t protocol; /* IP protocol */ u_int8_t ttl; /* ttl used to detect evasions */ u_int8_t alerted; u_int32_t frag_flags; /* bit field */ u_int32_t frag_bytes; /* number of fragment bytes stored, based * on aligned fragment offsets/sizes */ u_int32_t calculated_size; /* calculated size of reassembled pkt, based on * last frag offset */ u_int32_t frag_pkts; /* nummber of frag pkts stored under this tracker */ struct timeval frag_time; /* time we started tracking this frag */ Frag3Frag *fraglist; /* list of fragments */ Frag3Frag *fraglist_tail; /* tail ptr for easy appending */ int fraglist_count; /* handy dandy counter */ u_int32_t alert_gid[MAX_FRAG_ALERTS]; /* flag alerts seen in a frag list */ u_int32_t alert_sid[MAX_FRAG_ALERTS]; /* flag alerts seen in a frag list */ u_int8_t alert_count; /* count alerts seen in a frag list */ u_int32_t ip_options_len; /* length of ip options for this set of frags */ u_int32_t ip_option_count; /* number of ip options for this set of frags */ u_int8_t *ip_options_data; /* ip options from offset 0 packet */ u_int32_t copied_ip_options_len; /* length of 'copied' ip options */ u_int32_t copied_ip_option_count; /* number of 'copied' ip options */ Frag3Context *context; int ordinal;} FragTracker;/* statistics tracking struct */typedef struct _Frag3Stats{ u_int32_t total; u_int32_t overlaps; u_int32_t reassembles; u_int32_t prunes; u_int32_t timeouts; u_int32_t fragtrackers_created; u_int32_t fragtrackers_released; u_int32_t fragtrackers_autoreleased; u_int32_t fragnodes_created; u_int32_t fragnodes_released; u_int32_t discards; u_int32_t anomalies; u_int32_t alerts;} Frag3Stats;/* G L O B A L S **************************************************/static Frag3GlobalConfig global_config; /* global configuration struct */static SFXHASH *f_cache; /* fragment hash table */static Frag3Frag *prealloc_frag_list; /* head for prealloc queue */static char global_init_complete; /* flag to signal f_cache initialization */ static u_int32_t mem_in_use; /* memory in use, used for self pres */static u_int32_t prealloc_nodes_in_use; /* counter for debug */static int ten_percent; /* holder for self preservation data */static Frag3Stats f3stats; /* stats struct */static u_int8_t stats_registered; /* make sure we only print stats once per run */static Packet *defrag_pkt; /* holder for prealloc'd defrag pkt *//* enum for policy names */static char *policy_names[] = { "no policy!", "FIRST", "LINUX", "BSD", "BSD_RIGHT", "LAST", "WINDOWS", "SOLARIS"};/* * external globals for startup */extern char *file_name; extern int file_line; extern u_int snaplen;extern SFPERF sfPerf;/* P R O T O T Y P E S ********************************************/static void Frag3ParseGlobalArgs(u_char *);static void Frag3ParseArgs(u_char *, Frag3Context *);static FragTracker *Frag3GetTracker(Packet *, FRAGKEY *);static int Frag3NewTracker(Packet *p, FRAGKEY *fkey, Frag3Context *);static int Frag3Insert(Packet *, FragTracker *, FRAGKEY *, Frag3Context *);static void Frag3Rebuild(FragTracker *, Packet *);static int INLINE Frag3IsComplete(FragTracker *);static int Frag3HandleIPOptions(FragTracker *, Packet *);static void Frag3InitPkt();/* deletion funcs */static int Frag3Prune(FragTracker *);static struct timeval *pkttime; /* packet timestamp */static void Frag3DeleteFrag(Frag3Frag *);static void Frag3RemoveTracker(void *, void *);static void Frag3DeleteTracker(FragTracker *);static int Frag3AutoFree(void *, void *);static int Frag3UserFree(void *, void *);/* fraglist handler funcs */static INLINE void Frag3FraglistAddNode(FragTracker *, Frag3Frag *, Frag3Frag *); static INLINE void Frag3FraglistDeleteNode(FragTracker *, Frag3Frag *);/* prealloc queue handler funcs */static INLINE Frag3Frag *Frag3PreallocPop();static INLINE void Frag3PreallocPush(Frag3Frag *);/* main preprocessor functions */void Frag3Defrag(Packet *, void *);void Frag3CleanExit(int, void *);void Frag3Restart(int, void *);void Frag3Init(u_char *);void Frag3GlobalInit(u_char *);#ifdef DEBUG_FRAG3/** * Print out a FragTracker structure * * @param ft Pointer to the FragTracker to print * * @return none */static void PrintFragTracker(FragTracker *ft){ LogMessage("FragTracker %p\n", ft); if(ft) { LogMessage(" sip: 0x%08X\n", ft->sip); LogMessage(" dip: 0x%08X\n", ft->dip); LogMessage(" id: %d\n", ft->id); LogMessage(" proto: 0x%X\n", ft->protocol); LogMessage(" ttl: %d\n", ft->ttl); LogMessage(" alerted: %d\n", ft->alerted); LogMessage(" frag_flags: 0x%X\n", ft->frag_flags); LogMessage(" frag_bytes: %d\n", ft->frag_bytes); LogMessage(" calc_size: %d\n", ft->calculated_size); LogMessage(" frag_pkts: %d\n", ft->frag_pkts); LogMessage(" frag_time: %lu %lu\n", ft->frag_time.tv_sec, ft->frag_time.tv_usec); LogMessage(" fraglist: %p\n", ft->fraglist); LogMessage(" fl_tail: %p\n", ft->fraglist_tail); LogMessage("fraglst cnt: %d\n", ft->fraglist_count); }}/** * Print out a FragKey structure * * @param fkey Pointer to the FragKey to print * * @return none */static void PrintFragKey(FRAGKEY *fkey){ LogMessage("FragKey %p\n", fkey); if(fkey) { LogMessage(" sip: 0x%08X\n", fkey->sip); LogMessage(" dip: 0x%08X\n", fkey->dip); LogMessage(" id: %d\n", fkey->id); LogMessage(" proto: 0x%X\n", fkey->proto); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -