📄 flowps.c
字号:
/* $Id: *//**************************************************************************** * * Copyright (C) 2003-2008 Sourcefire, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License Version 2 as * published by the Free Software Foundation. You may not use, modify or * distribute this program under any other version of the GNU General * Public License. * * 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. * ****************************************************************************/ #ifdef HAVE_CONFIG_H#include "config.h"#endif#include "flowps.h"#include "scoreboard.h"#include "unique_tracker.h"#include "server_stats.h"#include "packet_time.h"#include "util_net.h"/* local copy of these tcp flags */#ifndef TH_FIN#define TH_FIN 0x01#define TH_SYN 0x02#define TH_RST 0x04#define TH_PUSH 0x08#define TH_ACK 0x10#define TH_URG 0x20#define TH_RES2 0x40#define TH_RES1 0x80#endif /* TH_FIN */#define FLOWPS_NC 1000000 /* number of rows to use for each scan table */static int s_debug = 0;static int s_enabled = 0;/** * Setup a SCORE_THRESHOLD object. * * This contains the limits and window sizes that will be used each * time we evaluate a SCORE_ENTRY from one of the scoreboards. * * @param thr pointer to the threshold to initialize * @param fixed_size the time window for fixed scale * @param fixed_limit the score limit to alert on * @param sliding_size the sliding time window initial size * @param sliding_limit score limit to alert on * @param window_scale what to multiple the sliding size on each "hit" * * @return FLOW_SUCCESS on success */int flowps_mkthreshold(SCORE_THRESHOLD *thr, int fixed_size, u_int32_t fixed_limit, int sliding_size, u_int32_t sliding_limit, float window_scale){ if(!thr) return FLOW_ENULL; if(fixed_size < 0) fixed_size = 0; if(sliding_size < 0) sliding_size = 0; thr->fixed_size = fixed_size; thr->sliding_size = sliding_size; thr->window_scale = window_scale; thr->fixed = fixed_limit; thr->sliding = sliding_limit; return FLOW_SUCCESS;}/** * Initialize the configuration structure and set everything to 0 * * @param configp config to set * * @return FLOW_SUCCESS on success */int flowps_mkconfig(PS_CONFIG *configp, int sb_memcap_talker, int sb_rows_talker, int sb_memcap_scanner, int sb_rows_scanner, int ut_memcap, int ut_rows, int server_memcap, int server_rows, int server_learning_time, int tcp_penalties, u_int32_t server_ignore_limit, u_int32_t server_scanner_limit, int base_score, int alert_once, FLOWPS_OUTPUT output_mode){ if(!configp) return FLOW_ENULL; memset(configp, 0, sizeof(PS_CONFIG)); configp->sb_memcap_total = sb_memcap_scanner + sb_memcap_talker; configp->sb_memcap_scanner = sb_memcap_scanner; configp->sb_memcap_talker = sb_memcap_talker; configp->sb_rows_talker = sb_rows_talker; configp->sb_rows_scanner = sb_rows_scanner; configp->tcp_penalties = tcp_penalties; configp->ut_memcap = ut_memcap; configp->ut_rows = ut_rows; configp->server_memcap = server_memcap; configp->server_rows = server_rows; configp->server_learning_time = server_learning_time; configp->server_ignore_limit = server_ignore_limit; configp->server_scanner_limit = server_scanner_limit; configp->base_score = base_score; configp->alert_once = alert_once; configp->output_mode = output_mode; configp->dumpall = 0; return FLOW_SUCCESS;}/** * Determine if the server stats feature is enabled * * @param trackerp portscan tracker * * @return FLOW_SUCCESS if server_stats is enabled */int flowps_server_stats_enabled(PS_TRACKER *trackerp){ if(trackerp->config.server_watchnet_ipv4) return FLOW_SUCCESS; return FLOW_DISABLED;}/** * Determine if server stats is enabled for this particular IP * address. * * @param trackerp portscan tracker to inquire * * @return FLOW_SUCCESS if the server watchnet stuff is enabled */int flowps_server_watch(PS_TRACKER *trackerp, u_int32_t address){ FLOWASSERT(trackerp != NULL); if (trackerp == NULL) return FLOW_DISABLED; if(trackerp->config.server_watchnet_ipv4 == NULL) return FLOW_DISABLED; if(server_stats_contains(&trackerp->server_stats,address) == FLOW_SUCCESS) return FLOW_SUCCESS; /* finally fail */ return FLOW_DISABLED;}/** * initialize the Portscan Tracker. * * This takes several arguments, all, on the PS_CONFIG structure. * * @param trackerp tracker object to initialize * @param configp well-formed configuration to initialize this object * * @return FLOW_SUCCESS on success */int flowps_init(PS_TRACKER *trackerp, PS_CONFIG *configp){ int ret; if(!trackerp || !configp) return FLOW_ENULL; /* we should validate this threshold object somewhat */ memcpy(&trackerp->config, configp, sizeof(PS_CONFIG)); ret = scoreboard_init(&trackerp->table_active, /* table */ "Active Talkers", /* description */ TRACKER_ACTIVE, /* position */ trackerp->config.sb_rows_talker, /* node count */ trackerp->config.sb_memcap_talker); /* memcap */ if(ret != FLOW_SUCCESS) { return ret; } ret = scoreboard_init(&trackerp->table_scanner, /* table */ "Portscanners", /* description */ TRACKER_SCANNER, /* position */ trackerp->config.sb_rows_scanner, /* node count */ trackerp->config.sb_memcap_scanner); /* memcap */ if(ret != FLOW_SUCCESS) { scoreboard_destroy(&trackerp->table_active); return ret; } /* setup the unique talkers table */ ret = ut_init(&trackerp->unique_tracker,trackerp->config.ut_rows, trackerp->config.ut_memcap); if(ret != FLOW_SUCCESS) { scoreboard_destroy(&trackerp->table_active); scoreboard_destroy(&trackerp->table_scanner); return ret; } /* the watchnet stuff is optional */ if(flowps_server_stats_enabled(trackerp) == FLOW_SUCCESS) { ret = server_stats_init(&trackerp->server_stats, trackerp->config.server_watchnet_ipv4, trackerp->config.server_rows, trackerp->config.server_memcap); if(ret != FLOW_SUCCESS) { scoreboard_destroy(&trackerp->table_active); scoreboard_destroy(&trackerp->table_scanner); ut_destroy(&trackerp->unique_tracker); return ret; } } s_enabled = 1; return FLOW_SUCCESS;}int flowps_destroy(PS_TRACKER *trackerp){ if(!trackerp) return FLOW_ENULL; scoreboard_destroy(&trackerp->table_scanner); scoreboard_destroy(&trackerp->table_active); ut_destroy(&trackerp->unique_tracker); return FLOW_SUCCESS;}/** * Reset a single flag in the alert_flags entry if the score is 0 * * @param type flag to reset * @param alert_flags flag entry * @param score score to reset */static INLINE void flowps_reset_alert_flags(u_int32_t type, u_int32_t *alert_flags, u_int32_t *score){ if(((*alert_flags) & type)) { *alert_flags &= ~type; *score = 0; }}/** * Evaluate the score on an entry, generating alerts if needed. * * @param pstp portscan tracker * @param sep score entry * @param score score determined for this flow * @param tr_pos what type of connection the current one is * @param alert_once alert only on the first one we find * @param alert_flags what type of alerts should we generate * * @return FLOW_SUCCESS on success */int flowps_score_entry(PS_TRACKER *pstp, SCORE_ENTRY *sep, int score, TRACKER_POSITION tr_pos, int alert_once, u_int32_t *alert_flags){ /* @todo - evaluate the score for the node before we evaluate the expiration on a sliding time window */ if(!pstp || !sep || !alert_flags) { return FLOW_ENULL; } *alert_flags = 0; if(alert_once == 0) { /* if our score entry flags ever get set to 0, reset the alert * flags */ flowps_reset_alert_flags(ALERT_FIXED_TALKER, &sep->flags, &sep->fixed_talker.score); flowps_reset_alert_flags(ALERT_SLIDING_TALKER, &sep->flags, &sep->sliding_talker.score); flowps_reset_alert_flags(ALERT_FIXED_SCANNER, &sep->flags, &sep->fixed_scanner.score); flowps_reset_alert_flags(ALERT_SLIDING_SCANNER, &sep->flags, &sep->sliding_scanner.score); } FLOWASSERT((tr_pos == TRACKER_SCANNER) || (tr_pos == TRACKER_ACTIVE)); switch(tr_pos) { case TRACKER_SCANNER: sep->fixed_scanner.score += score; sep->sliding_scanner.score += score; /* talking thresholds increment even if this is a "scanner" * connection */ break; case TRACKER_ACTIVE: sep->fixed_talker.score += score; sep->sliding_talker.score += score; break; } /* done resetting the scores, now check the thresholds */ if(pstp->config.limit_talker.fixed && pstp->config.limit_talker.fixed <= sep->fixed_talker.score) { *alert_flags |= ALERT_FIXED_TALKER; } if(pstp->config.limit_talker.sliding && pstp->config.limit_talker.sliding <= sep->sliding_talker.score) { *alert_flags |= ALERT_SLIDING_TALKER; } if(pstp->config.limit_scanner.fixed && pstp->config.limit_scanner.fixed <= sep->fixed_scanner.score) { *alert_flags |= ALERT_FIXED_SCANNER; } if(pstp->config.limit_scanner.sliding && pstp->config.limit_scanner.sliding <= sep->sliding_scanner.score) { *alert_flags |= ALERT_SLIDING_SCANNER; } /* ** This logic will only give us alerts for the ones that have not ** already gone off for this score entry. */ if(alert_once) { *alert_flags &= ~sep->flags; } return FLOW_SUCCESS; }/** * find the trackers in the table * * Currently, it first looks it up in the active table and then the * scanner table * * @param trackerp tracker to search * @param address key to search for * @param sepp where to place the results * * @return FLOW_SUCCESS on sucess and sets sepp */int flowps_find_entry(PS_TRACKER *trackerp, u_int32_t *address, SCORE_ENTRY **sepp){ int ret; if(!trackerp || !sepp || !address) { return FLOW_ENULL; } ret = scoreboard_find(&trackerp->table_active, address, sepp); if(ret == FLOW_NOTFOUND) { // flow_printf(stdout, "address was not found :("); /* the find failed -- look it up in the * scanner table */ ret = scoreboard_find(&trackerp->table_scanner, address, sepp); } return ret;}/** * Register a new node in the portscan tracker. * * This does not enforce that a node can only be in one table at a * time to avoid the 2 extra searching operations. All uses of this * should be done after performing a find to make sure the trackers * do not already exist. * * @param trackerp portscan tracker * @param position where to place this node * @param address the address for the key * @param sepp score entry return information * * @return FLOW_SUCCESS on success * * @retval FLOW_ENULL null arguments passed * @retval FLOW_SUCESS sucessfull added * @retval FLOW_EINVALID already in table * @retval FLOW_ENOMEM out of memory */int flowps_add_entry(PS_TRACKER *trackerp, TRACKER_POSITION position, u_int32_t *address, SCORE_ENTRY **sepp){ int ret; if(position == TRACKER_ACTIVE) { ret = scoreboard_add(&trackerp->table_active, address, sepp); } else { ret = scoreboard_add(&trackerp->table_scanner, address, sepp); } if(ret == FLOW_SUCCESS) { (*sepp)->position = position; } return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -