📄 detect.c
字号:
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/time.h>#include <arpa/inet.h>#include <pcap.h>/* * Ethernet header */#define ETHER_ADDR_LEN 6 /* length of ethernet address */#define ETHERTYPE_IP 0x0800 /* IP protocol */#define ETHERTYPE_8021Q 0x8100 /* IEEE 802.1Q(vlan) protocol */struct ether_header { uint8_t ether_dhost[ETHER_ADDR_LEN]; /* destination address */ uint8_t ether_shost[ETHER_ADDR_LEN]; /* source address */ uint16_t ether_type; /* ether packet type */};/* * IP header */struct ip_header { uint8_t ip_vhl; /* header length, version */#define IP_V(ip) (((ip)->ip_vhl & 0xf0) >> 4)#define IP_HL(ip) ((ip)->ip_vhl & 0x0f) uint8_t ip_tos; /* type of service */ uint16_t ip_len; /* total length */ uint16_t ip_id; /* identification */ uint16_t ip_off; /* fragment offset field */#define IP_DF 0x4000 /* dont fragment flag */#define IP_MF 0x2000 /* more fragments flag */#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ uint8_t ip_ttl; /* time to live */ uint8_t ip_p; /* protocol */ uint16_t ip_sum; /* checksum */ struct in_addr ip_src,ip_dst; /* source and dest address */};/* * monitor definition */#ifndef DEFAULT_MONITOR_INTERVAL#define DEFAULT_MONITOR_INTERVAL 3 /* default value of "-t" */#endif#ifndef DEFAULT_MONITOR_THRESHOLD#define DEFAULT_MONITOR_THRESHOLD 1000 /* default value of "-a" */#endif#define HASH_TABLE_SIZE 1000000 /* size of hash table, * it should be at least * two times of total * number of packets in * one interval to get * better performance. */#define BLACKLIST_SIZE 1000 /* size of blacklist, that * means the maximum number * of attacker in a interval. */#define HASH_SEARCH_DEPTH 2 /* hash search depth, the * larger, the more accurate, * but slower as well. */#define MAX_ACCESS 10 /* maximum number of access * for distribution analysis. */#define MSG_RECV_ADDR 0x00010000 /* message type for receiving * a new address. */#define MSG_ATTACK 0x00000001 /* message type for get an * attacker. */#define MSG_REPORT 0x00000100 /* message type for generating * report every interval. */#define MAX_COUNTDOWN 10 /* maximum number of times * of receiving address * before refreshing timer. */struct monitor;/* * The handler for processing monitor message, e.g. MSG_RECV_ADDR, MSG_ATTACK. */typedef void (*message_handler)(void *, struct monitor *, int);/* * Address node struct to store address and the number of access from it. */struct address_node { uint32_t addr; unsigned int age; unsigned int counter;};/* * Struct monitor is used to filter packets to find attacker. */struct monitor { struct address_node hash_table[HASH_TABLE_SIZE]; /* hash table. */ unsigned int access[MAX_ACCESS + 1]; /* access distribution */ unsigned int num; /* number of access in one * interval. */ time_t age; /* timer. */ unsigned int interval; /* interval, that is "-t". */ unsigned int threshold; /* threshold, that is "-a". */ unsigned int countdown; /* see MAX_COUNTDOWN. */ struct address_node *blacklist[BLACKLIST_SIZE]; /* attackers in one interval. */ unsigned int n_blacklist; /* number of attackers. */ uint32_t addr; /* most recently received * address. */ message_handler msghnd; /* the function to process * messages of monitor. */ void *msghnd_data; /* payload data for msghnd. */};/* * Make monitor to enter next interval. */time_t monitor_set_age(struct monitor *mon, time_t age);/* * Check whether next interval comes. */time_t monitor_is_new_age(struct monitor *mon);/* * Initialize monitor. */void monitor_init(struct monitor *mon);/* * Receive an address. */unsigned int monitor_recv_ip(struct monitor *mon, uint32_t addr);/* * Receive a packet. */void monitor_recv_packet(struct monitor *mon, const struct pcap_pkthdr *pkthdr, const u_char *packet);/* * session definition *//* Convert numeric address to xxx.xxx.xxx.xxx form. */#define INET_NTOA_HELPER(addr) inet_ntoa(*((struct in_addr *)(&(addr)))) /* * Struct session is used to control the process of detecting attacker. */struct session { char *dev; /* name of network interface to detect. */ pcap_t *handle; /* pcap handle. */ char *filter_str; /* filter string to build pcap filter. */ struct monitor mon; /* monitor. */ int verbose; /* verbose mode. */ int count; /* the number of packet received before exit*/};/* * Parse parameter. */int session_parse(struct session *s, int argc, char **argv);/* * Initialize session. */void session_init(struct session *s);/* * Callback funtion for receiving monitor message. */void session_recv_message(struct session *s, struct monitor *mon, int type);/* * Start detect. */int session_start(struct session *s);#ifdef DEBUG /* decide if show verbose ip information */#ifndef IPPROTO_ICMP#define IPPROTO_ICMP 1 /* control message protocol */#endif#ifndef IPPROTO_TCP#define IPPROTO_TCP 6 /* tcp */#endif#ifndef IPPROTO_UDP#define IPPROTO_UDP 17 /* user datagram protocol */#endif/* * UDP header */struct udp_header { uint16_t uh_sport; /* source port */ uint16_t uh_dport; /* destination port */ uint16_t uh_ulen; /* udp length */ uint16_t uh_sum; /* udp checksum */};/* * Show somewhat detailed information of ip packet * * Parameters: * iphdr pointer of head of ip packet. */void show_ip_info(const struct ip_header *iphdr) { char *p; char buf[10]; /* probe protocol. */ switch (iphdr->ip_p) { case IPPROTO_ICMP: p = "icmp"; break; case IPPROTO_TCP: p = "tcp"; break; case IPPROTO_UDP: p = "udp"; break; default: p = buf; sprintf(p, "ip:%d", iphdr->ip_p); break; } printf("%s src=%s", p, INET_NTOA_HELPER(iphdr->ip_src.s_addr)); if (p == "udp" || p == "tcp") { printf(":%d", ntohs(((struct udp_header *)(iphdr + 1))->uh_sport)); } printf(" dst=%s", INET_NTOA_HELPER(iphdr->ip_dst.s_addr)); if (p == "udp" || p == "tcp") { printf(":%d", ntohs(((struct udp_header *)(iphdr + 1))->uh_dport)); } fputc('\n', stdout);}#endif/* * Get ip header from packet captured by pcap. * * Parameter: * packet packet captured by pcap. * caplen length of captured part. * * Return: * pointer to ip head. */struct ip_header *get_ip_header(const char *packet, bpf_u_int32 caplen) { recurse: /* check if ip_header had been completely captured. */ if (caplen < sizeof(struct ether_header) + sizeof(struct ip_header)) { return NULL; } switch (ntohs(((struct ether_header *)packet)->ether_type)) { case ETHERTYPE_IP: /* common ip packet of ethernet. */ return (struct ip_header *)((struct ether_header *)packet + 1); case ETHERTYPE_8021Q: /* virtual lan packet of ethernet. */ caplen -= 4; packet += 4; goto recurse; default: /* unknown ethernet protocol. */ return NULL; }}/* * Make monitor to enter next interval. * * Parameter: * monitor monitor to process. * age the age of new interval. * * Return: * the old age. */time_t monitor_set_age(struct monitor *mon, time_t age) { time_t tmp = mon->age; memset(mon->access, 0, sizeof(mon->access)); mon->age = age; /* set new age. */ mon->num = 0; /* reset number of accesses. */ mon->n_blacklist = 0; /* reset blacklist. */ return tmp;}/* * Check system time to find if next interval comes. * * Parameter: * mon monitor * * Return: * 0, if next interval does not come. * age of next interval, if next interval comes. */time_t monitor_is_new_age(struct monitor *mon){ time_t age; /* since fetching system time is time costly operation, so we do nothing * before "countdown" times of probing. */ if (mon->countdown != 0) { mon->countdown--; return 0; } mon->countdown = (MAX_COUNTDOWN > mon->threshold) ? mon->threshold : MAX_COUNTDOWN; mon->countdown--; age = time(NULL) / mon->interval; return (mon->age != age) ? age : 0;}/* * Initialize monitor. * * Parameter: * mon monitor */void monitor_init(struct monitor *mon){ memset(mon->hash_table, 0, sizeof(mon->hash_table)); monitor_set_age(mon, 0); mon->countdown = 0; mon->interval = DEFAULT_MONITOR_INTERVAL; mon->threshold = DEFAULT_MONITOR_THRESHOLD;}/* * Receive an address. * * Parameter: * mon monitor * addr address * * Return: * number of accesses of this address in current interval.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -