Watcher

Watcher是用于linux系统的,通常你只需要在命令行后台运行它就可以了,它的参数如下:

Usage: watcher [参数]

  -d device       将'device'设定为当前的网卡,默认为第一个non-loopback的interface
  -f flood        设定接收到多少不完全的连接后才认为是flood的攻击
  -h              帮助信息
  -i icmplimit    设定接收到多少icmp echo replies就认为是smurf攻击
  -m level        可以设定监控的机器,比如subnet为子域中的机器,或者all为所有
  -p portlimit    在timeout的限制时间内有多少端口接收到信息包算是一次端口扫描
  -r reporttype   如果reporttype设为dos,那么只有拒绝服务攻击会被记录,如果是scan
                  的话,只有扫描行为会被记录,默认则记录所有东西
  -t timeout      每隔timeout的时间就记录信息包并打印出潜在的攻击行为
  -w webcount     设定我们从80口接收到多少信息包才算是一次端口扫描(cgi)

希望这个小玩意能使你的系统稍微安全一些,但是得警告你的是,系统安全是多方面的,别
指望一个应用程序或者什么东西能使你绝对安全——如果你不信,迟早都得重装系统的;)

<++> EX/Watcher.c
/*********************************************************************
Program: watcher

A network level monitoring tool to detect incoming packets indicative of
potential attacks.

This software detects low level packet scanners and several DOS attacks.
Its primary use is to detect low level packet scans, since these are usually
done first to identify active systems and services to mount further attacks.

The package assumes every incoming packet is potentially hostile.  Some checks
are done to minimize false positives, but on occasion a site may be falsely
identified as having performed a packet scan or SYNFLOOD attack.  This usually
occurs if a large number of connections are done in a brief time right before
the reporting timeout period (i.e. when browsing a WWW site with lots of
little GIF's, each requiring a connection to download).  You can also get false
positives if you scan another site, since the targets responses will be viewed
as a potential scan of your system.

By default, alerts are printed to SYSLOG every 10 seconds.
***********************************************************************/

#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <malloc.h>
#include <netinet/tcp.h>
#include <netinet/in_systm.h>
#include <net/if_arp.h>
#include <net/if.h>
#include <netinet/udp.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <linux/if_ether.h>
#include <syslog.h>

#define PKTLEN 96    /* Should be enough for what we want */
#ifndef IP_MF
#define IP_MF    0x2000
#endif
/***** WATCH LEVELS ******/

#define MYSELFONLY    1
#define MYSUBNET    2
#define HUMANITARIAN    3

/***** REPORT LEVELS *****/

#define REPORTALL    1
#define REPORTDOS    2
#define REPORTSCAN    3

struct floodinfo
{
    u_short sport;
    struct floodinfo *next;
};

struct addrlist
{
    u_long saddr;
    int cnt;
    int wwwcnt;
    struct addrlist *next;
};

struct atk
{
    u_long saddr;
    u_char eaddr[ETH_ALEN];
    time_t atktime;
};

struct pktin
{
    u_long saddr;
    u_short sport;
    u_short dport;
    time_t timein;
    u_char eaddr[ETH_ALEN];
    struct floodinfo *fi;
    struct pktin *next;
};

struct scaninfo
{
    u_long addr;
    struct atk teardrop;
    struct atk land;
    struct atk icmpfrag;
    struct pktin *tcpin;
    struct pktin *udpin;
    struct scaninfo *next;
    u_long icmpcnt;
} ;

struct scaninfo *Gsilist = NULL, *Gsi;

u_long Gmaddr;
time_t Gtimer = 10, Gtimein;
int Gportlimit = 7;
int Gsynflood = 8;
int Gwebcount = 40;
int Gicmplimit = 5;
int Gwatchlevel = MYSELFONLY;
int Greportlevel = REPORTALL;
char *Gprogramname, *Gdevice = "eth0";

/******** IP packet info ********/

u_long Gsaddr, Gdaddr;
int Giplen, Gisfrag, Gid;

/****** Externals *************/

extern int errno;
extern char *optarg;
extern int optind, opterr;

void do_tcp(), do_udp(), do_icmp(), print_info(), process_packet();
void addtcp(), addudp(), clear_pktin(), buildnet();
void doargs(), usage(), addfloodinfo(), rmfloodinfo();
struct scaninfo *doicare(), *addtarget();
char *anetaddr(), *ether_ntoa();
u_char *readdevice();

main(argc, argv)
int argc;
char *argv[];
{
    int pktlen = 0, i, netfd;
    u_char *pkt;
    char hostname[32];
    struct hostent *hp;
    time_t t;

    doargs(argc, argv);
    openlog("WATCHER", 0, LOG_DAEMON);
    if(gethostname(hostname, sizeof(hostname)) < 0)
    {
        perror("gethostname");
        exit(-1);
    }
    if((hp = gethostbyname(hostname)) == NULL)
    {
        fprintf(stderr, "Cannot find own address/n");
        exit(-1);
    }
    memcpy((char *)&Gmaddr, hp->h_addr, hp->h_length);
    buildnet();
    if((netfd = initdevice(O_RDWR, 0)) < 0)
    exit(-1);

    /* Now read packets forever and process them. */

    t = time((time_t *)0);
    while(pkt = readdevice(netfd, &pktlen))
    {
        process_packet(pkt, pktlen);
        if(time((time_t *)0) - t > Gtimer)
        {
                 /* Times up.  Print what we found and clean out old stuff. */
       
                for(Gsi = Gsilist, i = 0; Gsi; Gsi = Gsi->next, i++)
                {
                        clear_pktin(Gsi);
                        print_info();
                        Gsi->icmpcnt = 0;
                }
                t = time((time_t *)0);
        }
    }
    /**********************************************************************
    Function: doargs

    Purpose:  sets values from environment or command line arguments.
    **********************************************************************/
    void doargs(argc, argv)
        int argc;
        char **argv;
    {
            char c;
       
            Gprogramname = argv[0];
            while((c = getopt(argc,argv,"d:f:hi:m:p:r:t:w:")) != EOF)
            {
                switch(c)
                {
                case 'd':
                Gdevice = optarg;
                break;
                    case 'f':
                        Gsynflood = atoi(optarg);
                        break;
                case 'h':
                usage();
                exit(0);
                case 'i':
                Gicmplimit = atoi(optarg);
                break;
                case 'm':
                if(strcmp(optarg, "all") == 0)
                    Gwatchlevel = HUMANITARIAN;
                else if(strcmp(optarg, "subnet") == 0)
                    Gwatchlevel = MYSUBNET;
                else
                {
                    usage();
                    exit(-1);
                }
                break;
                case 'p':
                Gportlimit = atoi(optarg);
                break;
                case 'r':
                if(strcmp(optarg, "dos") == 0)
                    Greportlevel = REPORTDOS;
                else if(strcmp(optarg, "scan") == 0)
                    Greportlevel = REPORTSCAN;
                else
                {
                    exit(-1);
                }
                break;
                case 't':
                        Gtimer = atoi(optarg);
                        break;
                case 'w':
                Gwebcount = atoi(optarg);
                break;
                default:
                        usage();
                        exit(-1);
                }
            }
        }
        /**********************************************************************
        Function: usage

        Purpose:  Display the usage of the program
        **********************************************************************/
        void usage()
        {
                printf("Usage: %s [options]/n", Gprogramname);
                printf("  -d device       Use 'device' as the network interface device/n");
                printf("                  The first non-loopback interface is the default/n");
                printf("  -f flood        Assume a synflood attack occurred if more than/n");
                printf("                  'flood' uncompleted connections are received/n");
                printf("  -h              A little help here/n");
                printf("  -i icmplimit    Assume we may be part of a smurf attack if more/n");
                printf("                  than icmplimit ICMP ECHO REPLIES are seen/n");
                printf("  -m level        Monitor more than just our own host./n");
                printf("                  A level of 'subnet' watches all addresses in our/n");
                printf("                  subnet and 'all' watches all addresses/n");
                printf("  -p portlimit    Logs a portscan alert if packets are received for/n");
                printf("                  more than portlimit ports in the timeout period./n");
                printf("  -r reporttype   If reporttype is dos, only Denial Of Service/n");
                printf("                  attacks are reported.  If reporttype is scan/n");
                printf("                  then only scanners are reported.  Everything is/n");
                printf("                  reported by default./n");
                printf("  -t timeout      Count packets and print potential attacks every/n");
                printf("                  timeout seconds/n");
                printf("  -w webcount     Assume we are being portscanned if more than/n");
                printf("                  webcount packets are received from port 80/n");
        }

        /**********************************************************************
        Function: buildnet

        Purpose:  Setup for monitoring of our host or entire subnet.
        **********************************************************************/
        void buildnet()
        {
            u_long addr;
            u_char *p;
            int i;
       
            if(Gwatchlevel == MYSELFONLY)        /* Just care about me */
            {
            (void) addtarget(Gmaddr);
            }
            else if(Gwatchlevel == MYSUBNET)        /* Friends and neighbors */
            {
            addr = htonl(Gmaddr);
            addr = addr & 0xffffff00;
            for(i = 0; i < 256; i++)
                (void) addtarget(ntohl(addr + i));
            }
        }
        /**********************************************************************
        Function: doicare

        Purpose:  See if we monitor this address
        **********************************************************************/
        struct scaninfo *doicare(addr)
        u_long addr;
        {
            struct scaninfo *si;
            int i;
       
            for(si = Gsilist; si; si = si->next)
            {
            if(si->addr == addr)
                return(si);
            }
            if(Gwatchlevel == HUMANITARIAN)    /* Add a new address, we always care */
            {
            si = addtarget(addr);
            return(si);
            }
            return(NULL);
        }
        /**********************************************************************
        Function: addtarget

        Purpose:  Adds a new IP address to the list of hosts to watch.
        **********************************************************************/
        struct scaninfo *addtarget(addr)
        u_long addr;
        {
            struct scaninfo *si;
       
            if((si = (struct scaninfo *)malloc(sizeof(struct scaninfo))) == NULL)
            {
            perror("malloc scaninfo");
            exit(-1);
            }
            memset(si, 0, sizeof(struct scaninfo));
            si->addr = addr;
            si->next = Gsilist;
            Gsilist = si;
            return(si);
        }
        /**********************************************************************
        Function: process_packet
       
        Purpose:  Process raw packet and figure out what we need to to with it.
       
        Pulls the packet apart and stores key data in global areas for reference
        by other functions.
        **********************************************************************/
        void process_packet(pkt, pktlen)
        u_char *pkt;
        int pktlen;
        {
            struct ethhdr *ep;
            struct iphdr *ip;
            static struct align { struct iphdr ip; char buf[PKTLEN]; } a1;
            u_short off;
       
            Gtimein = time((time_t *)0);
            ep = (struct ethhdr *) pkt;
            if(ntohs(ep->h_proto) != ETH_P_IP)
            return;
       
            pkt += sizeof(struct ethhdr);
            pktlen -= sizeof(struct ethhdr);
            memcpy(&a1, pkt, pktlen);
            ip = &a1.ip;
            Gsaddr = ip->saddr;
            Gdaddr = ip->daddr;
       
            if((Gsi = doicare(Gdaddr)) == NULL)
            return;
       
            off = ntohs(ip->frag_off);
            Gisfrag = (off & IP_MF);    /* Set if packet is fragmented */
            Giplen = ntohs(ip->tot_len);
            Gid = ntohs(ip->id);
            pkt = (u_char *)ip + (ip->ihl << 2);
            Giplen -= (ip->ihl << 2);
            switch(ip->protocol)
            {
            case IPPROTO_TCP:
                do_tcp(ep, pkt);
                break;
            case IPPROTO_UDP:
                do_udp(ep, pkt);
                break;
            case IPPROTO_ICMP:
                do_icmp(ep, pkt);
                break;
            default:
                break;
            }
        }
        /**********************************************************************
        Function: do_tcp

        Purpose:  Process this TCP packet if it is important.
        **********************************************************************/
        void do_tcp(ep, pkt)
        struct ethhdr *ep;
        u_char *pkt;
        {
            struct tcphdr *thdr;
            u_short sport, dport;
       
            thdr = (struct tcphdr *) pkt;
            if(thdr->th_flags & TH_RST) /* RST generates no response */
            return;            /* Therefore can't be used to scan. */
            sport = ntohs(thdr->th_sport);
            dport = ntohs(thdr->th_dport);
       
            if(thdr->th_flags & TH_SYN)
            {
            if(Gsaddr == Gdaddr && sport == dport)
            {
                Gsi->land.atktime = Gtimein;
                Gsi->land.saddr = Gsaddr;
                memcpy(Gsi->land.eaddr, ep->h_source, ETH_ALEN);
            }
            }
            addtcp(sport, dport, thdr->th_flags, ep->h_source);
        }
        /**********************************************************************
        Function: addtcp

        Purpose:  Add this TCP packet to our list.
        **********************************************************************/
        void addtcp(sport, dport, flags, eaddr)
        u_short sport;
        u_short dport;
        u_char flags;
        u_char *eaddr;
        {
            struct pktin *pi, *last, *tpi;
       
            /* See if this packet relates to other packets already received. */
       
            for(pi = Gsi->tcpin; pi; pi = pi->next)
            {
            if(pi->saddr == Gsaddr && pi->dport == dport)
            {
                if(flags == TH_SYN)
                addfloodinfo(pi, sport);
                else if((flags & TH_FIN) || (flags & TH_ACK))
                rmfloodinfo(pi, sport);
                return;
            }
            last = pi;
            }
            /* Must be new entry */
       
            if((tpi = (struct pktin *)malloc(sizeof(struct pktin))) == NULL)
            {
            perror("Malloc");
            exit(-1);
            }
            memset(tpi, 0, sizeof(struct pktin));
            memcpy(tpi->eaddr, eaddr, ETH_ALEN);
            tpi->saddr = Gsaddr;
            tpi->sport = sport;
            tpi->dport = dport;
            tpi->timein = Gtimein;
            if(flags == TH_SYN)
            addfloodinfo(tpi, sport);
            if(Gsi->tcpin)
            last->next = tpi;
            else
            Gsi->tcpin = tpi;
        }
       
        /**********************************************************************
        Function: addfloodinfo

        Purpose:  Add floodinfo information
        **********************************************************************/
        void addfloodinfo(pi, sport)
        struct pktin *pi;
        u_short sport;
        {
                struct floodinfo *fi;

                fi = (struct floodinfo *)malloc(sizeof(struct floodinfo));
                if(fi == NULL)
                {
                        perror("Malloc of floodinfo");
                        exit(-1);
                }
                memset(fi, 0, sizeof(struct floodinfo));
                fi->sport = sport;
                fi->next = pi->fi;
                pi->fi = fi;
        }

        /**********************************************************************
        Function: rmfloodinfo
       
        Purpose:  Removes floodinfo information
        **********************************************************************/
        void rmfloodinfo(pi, sport)
        struct pktin *pi;
        u_short sport;
        {
            struct floodinfo *fi, *prev = NULL;
       
            for(fi = pi->fi; fi; fi = fi->next)
            {
                    if(fi->sport == sport)
                        break;
                    prev = fi;
            }
            if(fi == NULL)
                 return;
            if(prev == NULL)    /* First element */
                pi->fi = fi->next;
            else
                prev->next = fi->next;
            free(fi);
        }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值