⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flow-dscan.c

📁 netflow,抓包
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 2001 Mark Fullmer and The Ohio State University * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *      $Id: flow-dscan.c,v 1.25 2003/04/02 18:03:01 maf Exp $ */#include "ftconfig.h"#include <ftlib.h>#include <sys/time.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/uio.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <time.h>#include <fcntl.h>#include <signal.h>#include <syslog.h>#if HAVE_STRINGS_H #include <strings.h>#endif#if HAVE_STRING_H  #include <string.h>#endif#include "ftbuild.h"#include "flow-dscan.h"/* * Detect network scan's *//* XXX TODO * * trigger alarm on # of flows/second * * need to max out on # of records allocated.  If hit, then run the ager * more often/more agressive timeout. * * FUTURE: *  take advantage of need to only allocate strcuture of the same *  size by having malloc allocate chunks at a time and maintaining *  a freelist. *  *  most of the dst ports are 53 and 80.  Could save a bunch of memory *  by only allocating a bit1024 struct when it's not a list of well *  known ports -- tradoff for a few cpu cycles.. * *  possibly trigger the ager with an alarm instead of by flow traffic * *  if the dst ip list gets too long convert to a hash? */int debug;int sig_hup, sig_usr1;int load_state(struct dscan_state *ds);void flow_dump(struct fts3rec_gen *rec);void clear_suppress(struct dscan_state *ds, int sd);int load_suppress(struct dscan_state *ds, int sd);void ager(struct dscan_state *ds, u_int32 total_flows32);void sig_hup_handler(int sig);void sig_usr1_handler(int sig);void usage(void);int dump_state(struct dscan_state *ds);int main(int argc, char **argv){  struct ftio ftio;  struct ftprof ftp;  struct fts3rec_gen *rec;  struct fttime ftt;  int i, match, k, no_detach;  u_int64 total_flows;  u_int32 total_flows32;  struct dscan_state ds;  struct dscan_rec *drp;  struct dscan_dst *ddp, *ddp2;  struct dscan_sup *dsp_src, *dsp_dst;  u_long hash;  char fmt_buf1[64], fmt_buf2[64], fmt_buf3[64], fmt_buf4[54];  int do_dump, do_load;  int filter_www, filter_mcast, filter_input, filter_output;  char in_tbl[65536], out_tbl[65536];  u_int32 trigger_time, trigger_packets, trigger_octets;  pid_t pid;  struct tm *tm;  total_flows = total_flows32 = 0;  bzero(&ds, sizeof ds);  ds.ager_timeout = DSCAN_AGER_TIMEOUT;  ds.statefile = DSCAN_STATEFILE;  ds.supfile = DSCAN_SUP_FILE;  ds.dscan_ip_depth = DSCAN_IP_DEPTH;  ds.dscan_port_trigger = DSCAN_PORT_TRIGGER;  sig_hup = 0;  sig_usr1 = 0;  do_dump = 0;  do_load = 0;  filter_www = filter_mcast = filter_input = filter_output = 0;  trigger_time = trigger_octets = trigger_packets = 0;  no_detach = 0;  /* init fterr */  fterr_setid(argv[0]);  while ((i = getopt(argc, argv, "d:i:I:D:h?lmps:t:wL:O:P:S:T:bBW")) != -1)    switch (i) {    case 'd': /* debug */      debug = atoi(optarg);      break;    case 'i': /* input filter interface list */      if (load_lookup(optarg, 65536, in_tbl))        fterr_errx(1, "load_lookup(): failed");      filter_input = 1;      break;    case 'l': /* load state */      do_load = 1;      break;    case 'm': /* multicast filter */      filter_mcast = 1;      break;    case 'I': /* output filter interface list */      if (load_lookup(optarg, 65536, out_tbl))        fterr_errx(1, "load_lookup(): failed");      filter_output = 1;      break;    case 'p': /* dump state on exit */      do_dump = 1;      break;    case 's': /* statefile */      ds.statefile = optarg;      break;    case 't': /* ager timeout */      sscanf(optarg, "%u", &ds.ager_timeout);      break;    case 'w': /* filter www inbound (replies) */      filter_www = 1;      break;    case 'b': /* no detach */      no_detach = 1;      break;    case 'B': /* no detach, use syslog */      no_detach = 2;      break;    case 'D':      sscanf(optarg, "%u", &ds.dscan_ip_depth);      break;    case 'L': /* suppress file */      ds.supfile = optarg;      break;    case 'O': /* excessive octets trigger */      sscanf(optarg, "%u", (unsigned int*)&trigger_octets);      break;    case 'P': /* excessive packets trigger */      sscanf(optarg, "%u", (unsigned int*)&trigger_packets);      break;    case 'S': /* port scan trigger */      sscanf(optarg, "%u", &ds.dscan_port_trigger);      break;    case 'T': /* excessive flow time trigger */      sscanf(optarg, "%u", (unsigned int*)&trigger_time);      break;    case 'W': /* filter www outbound */      filter_www = 2;      break;    case 'h': /* help */    case '?':     default:      usage();      exit (1);      break;    } /* switch */  if (argc - optind)    fterr_errx(1, "Extra arguments starting with %s.", argv[optind]);  /* daemonize */  if (!no_detach) {    if ((pid = fork()) == -1) {      fterr_err(1, "fork()");    } else if (pid)      exit (0); /* parent */    umask(0022);    setsid();    for (i = 1; i < 16; ++i) /* XXX dynamically get NOFILE */      close (i);    /* enable syslog */    fterr_setsyslog(1, LOG_PID|LOG_NDELAY, LOG_LOCAL6);      /* disable stderr */    fterr_setfile(0, (void*)0L);  } else {    if (no_detach == 2) {      /* enable syslog */      fterr_setsyslog(1, LOG_PID|LOG_NDELAY, LOG_LOCAL6);        /* disable stderr */      fterr_setfile(0, (void*)0L);    }  }  /* profile */  ftprof_start (&ftp);  /* configure handlers */  if (mysignal(SIGHUP, sig_hup_handler) == SIG_ERR)    fterr_err(1, "signal(SIGHUP)");  if (mysignal(SIGUSR1, sig_usr1_handler) == SIG_ERR)    fterr_err(1, "signal(SIGUSR1)");  /* initialize scanner hash table */  for (i = 0; i < DSCAN_HASHSIZE; ++i) {    FT_SLIST_INIT(&ds.hash_scan[i]);  }  /* initialize suppress hash table */  for (i = 0; i < DSCAN_HASHSIZE; ++i) {    FT_SLIST_INIT(&ds.hash_sup_src[i]);  }  for (i = 0; i < DSCAN_HASHSIZE; ++i) {    FT_SLIST_INIT(&ds.hash_sup_dst[i]);  }  /* load state file */  if (do_load) {    if (load_state(&ds))      fterr_errx(1, "load_state(): failed");#ifdef XXX    ds.statefile = "/var/tmp/ds.state2";    dump_state(&ds);    exit(0);#endif  }  if (load_suppress(&ds, 0))    fterr_errx(1, "load_suppress(0): failed");  if (load_suppress(&ds, 1))    fterr_errx(1, "load_suppress(1): failed");  /* read from stdin */  if (ftio_init(&ftio, 0, FT_IO_FLAG_READ) < 0)    fterr_errx(1, "ftio_init(): failed");  /* check for records scan can understand */  if (ftio_check_generic(&ftio) < 0)    fterr_errx(1, "Unsupported export version");  while ((rec = ftio_read(&ftio))) {    if (sig_usr1) {      if (debug)        fterr_info("signal: USR1");      dump_state(&ds);      sig_usr1 = 0;    } /* sig_usr1 */    if (sig_hup) {      if (debug)        fterr_info("signal: USR1");      clear_suppress(&ds, 0);      clear_suppress(&ds, 1);      load_suppress(&ds, 0);      load_suppress(&ds, 1);      sig_hup = 0;    } /* sig_hup */    ++total_flows;    ++total_flows32;    /* filter on input interface */    if (filter_input)       if (!in_tbl[rec->input])        goto skip2;    /* filter on output interface */    if (filter_output)      if (!out_tbl[rec->output])        goto skip2;    /* filter multicast? */    if (filter_mcast) {      if ((rec->srcaddr >= 0xe0000000) && (rec->srcaddr <= 0xefffffff))        goto skip2;      if ((rec->dstaddr >= 0xe0000000) && (rec->dstaddr <= 0xefffffff))        goto skip2;    } /* filter_mcast */    /* calculate hash based on src ip */    hash = DSCAN_HASHFUNC(rec->srcaddr);    if ((filter_www == 1) && (rec->srcport == 80) && (rec->prot == 6) &&      (rec->dstport > 1023))      goto skip2;    if ((filter_www == 2) && (rec->dstport == 80) && (rec->prot == 6) &&      (rec->srcport > 1023))      goto skip2;    /* evaluate this src ip and the suppress list */    match = 0;    FT_SLIST_FOREACH(dsp_src, &ds.hash_sup_src[hash], chain) {      if (dsp_src->ip == rec->srcaddr) {        if (!(dsp_src->flags & DSCAN_SUP_SRCPORT))          goto skipsrc;        if (dsp_src->srcport != rec->srcport)          goto sup1;skipsrc:        if (!(dsp_src->flags & DSCAN_SUP_DSTPORT))          goto skipdst;        if (dsp_src->dstport != rec->dstport)          goto sup1;skipdst:        if (!(dsp_src->flags & DSCAN_SUP_PROTOCOL))          goto skip2;        if (dsp_src->protocol != rec->prot)          goto sup1;        goto skip2;      }    }sup1:    /* evaluate this dst ip and the suppress list */    match = 0;    FT_SLIST_FOREACH(dsp_dst, &ds.hash_sup_dst[hash], chain) {      if (dsp_dst->ip == rec->dstaddr) {        if (!(dsp_dst->flags & DSCAN_SUP_SRCPORT))          goto skipsrc1;        if (dsp_dst->srcport != rec->srcport)          goto sup;skipsrc1:        if (!(dsp_dst->flags & DSCAN_SUP_DSTPORT))          goto skipdst1;        if (dsp_dst->dstport != rec->dstport)          goto sup;skipdst1:        if (!(dsp_dst->flags & DSCAN_SUP_PROTOCOL))          goto skip2;        if (dsp_dst->protocol != rec->prot)          goto sup;        goto skip2;      }    }sup:    /* evaluate the triggers */    if (trigger_octets && (rec->dOctets > trigger_octets)) {      flow_dump(rec);    }    if (trigger_packets && (rec->dPkts > trigger_packets)) {      flow_dump(rec);    }    if (trigger_time && ((rec->Last - rec->First) > trigger_time)) {      flow_dump(rec);    }    match = 0;    FT_SLIST_FOREACH(drp, &ds.hash_scan[hash], chain) {      if (drp->ip_src == rec->srcaddr) {        match = 1;        break;      }    }    if (match) { /* src ip match */      /* previous host or scan report then skip */      if (drp->flags)        goto skip2;      /* if rec exists with this dest ip */      FT_STAILQ_FOREACH(ddp, &drp->dlhead, chain) {        if (ddp->ip_dst == rec->dstaddr) {          ddp->ip_time = total_flows32;          if (rec->dstport < 1024) {            bit1024_store((int)rec->dstport, &ddp->portmap);            if ((k = bit1024_count(&ddp->portmap)) >= ds.dscan_port_trigger) {              fmt_ipv4(fmt_buf1, rec->srcaddr, FMT_JUST_LEFT);              fmt_ipv4(fmt_buf2, rec->dstaddr, FMT_JUST_LEFT);              ftt = ftltime(rec->sysUpTime, rec->unix_secs, rec->unix_nsecs,                rec->First);              tm = localtime((time_t*)&ftt.secs);              fmt_uint32(fmt_buf3, ftt.secs, FMT_JUST_LEFT);              snprintf(fmt_buf4, 64, "%-2.2d%-2.2d.%-2.2d:%-2.2d:%-2.2d.%-3lu ",                 (int)tm->tm_mon+1, (int)tm->tm_mday, (int)tm->tm_hour,                 (int)tm->tm_min, (int)tm->tm_sec, (u_long)ftt.msecs);              fterr_info("port scan: src=%s dst=%s ts=%s start=%s",                fmt_buf1, fmt_buf2, fmt_buf3, fmt_buf4);              bzero(&ddp->portmap, sizeof ddp->portmap);              drp->flags |= DSCAN_FLAGS_PORTSCAN;            }          }          goto skip2;        }      }      /* no rec exists with this dst ip */      if (drp->depth >= ds.dscan_ip_depth) {        fmt_ipv4(fmt_buf1, rec->srcaddr, FMT_JUST_LEFT);        ftt = ftltime(rec->sysUpTime, rec->unix_secs, rec->unix_nsecs,          rec->First);        tm = localtime((time_t*)&ftt.secs);        fmt_uint32(fmt_buf3, ftt.secs, FMT_JUST_LEFT);        snprintf(fmt_buf4, 64, "%-2.2d%-2.2d.%-2.2d:%-2.2d:%-2.2d.%-3lu ",         (int)tm->tm_mon+1, (int)tm->tm_mday, (int)tm->tm_hour,         (int)tm->tm_min, (int)tm->tm_sec, (u_long)ftt.msecs);        fterr_info( "host scan: ip=%s ts=%s start=%s",            fmt_buf1, fmt_buf3, fmt_buf4);        drp->depth = 0;        drp->flags |= DSCAN_FLAGS_HOSTSCAN;        ddp = drp->dlhead.stqh_first;        while (ddp != NULL) {          ddp2 = ddp->chain.stqe_next;          free(ddp);          ++ds.stat_free;          ++ds.stat_free_dst;          ddp = ddp2;        }        FT_STAILQ_INIT(&drp->dlhead);      } else {        if (!(ddp = malloc(sizeof (struct dscan_dst))))          fterr_err(1, "malloc(dscan_dst)");        bzero(ddp, sizeof (struct dscan_dst));        ds.stat_malloc++;        ds.stat_malloc_dst++;        drp->depth ++;        FT_STAILQ_INSERT_TAIL(&drp->dlhead, ddp, chain);        ddp->ip_dst = rec->dstaddr;        ddp->ip_time = total_flows32;        if (rec->dstport < 1024) {          bit1024_store((int)rec->dstport, &ddp->portmap);        }      }    } else { /* no src ip match */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -