Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctime>
- #include <errno.h>
- #include <arpa/inet.h>
- //номер версии программы
- #define VERS_PROG 21
- /*даты изменения
- 6 авг 2010
- 17 авг 2010
- 1 сент 2010
- 9 сент 2010
- 25 нояб 2010 - calcPopr
- */
- //максимальное количество строк считывемое из лог файла
- #define MAX_STR_LOG 130000
- //максисальная длина подстроки на которые разбивается строка запроса, если больше то обрезаем
- #define MAX_LEN_SUBSTR 200
- //максимальное количество различных вариантов запроса, если больше, то сообщается о ошибке
- #define MAX_REQWEST_COUNT 90000
- //максимальная сохраняемая длина строки запроса, если больше то обрезается
- #define MAX_LEN_REQWEST 100
- //максимально количество разных реферреров, если больше, то сообщается о ошибке
- #define MAX_REFERRER_COUNT 30000
- //максимальная длина строки реферрера, если больше то обрезается
- #define MAX_REFERRER_LEN 150
- //максимально количество разных юзер ангетов, если больше, то сообщается о ошибке
- #define MAX_USER_AGENT_COUNT 25000
- //максимальная длина строки юзер агента, если больше то обрезается
- #define MAX_USER_AGENT_LEN 200
- //максимальная длина строки анализируемая в лог файле, если больше, то сообщается о ошибке
- #define MAX_LEN_STR 19000
- //максимальное количество коннектов анализируемое в команде netstat
- #define MAX_LEN_NETSTAT 10000
- //максимальное количество строк в стоп листе
- #define MAX_COUNT_BAD_STR 100
- //максимальная длина строки в стоп листе
- #define MAX_LEN_BAD_STR 30
- //максимальное количество строк считываемое из файла белых подсетей по ключу w
- #define MAX_COUNT_WHITE_IP 6000
- //////////////////
- struct oneHeat{ //инфорсация о одной строке из лог файла
- int ip; //IP адрес
- time_t t; //UNIX время в секундах этой троки запроса
- int num_r; //номер строки запроса из таблицы запросов
- int num_ua; //номер строки юзер агента таблицы юзер агентов
- int num_ref;//номер строки реферрера таблицы реферреров
- int c_double;//количество повторений, будет расчитанно
- int len_str;//длина исходной строки запроса
- int code_otv;//код ответа веб сервера
- int cookie;//
- };
- //////
- struct command{
- char command;
- int par[4];
- };
- //////
- struct netstat_t{ //статистика одного IP адреса в выдаче команды netstat
- // int ip_loc;
- int ip_for;
- // int port_loc;
- // int state;
- int count;
- int c_SYN_RECV;
- int c_ESTABLISHED;
- int c_TIME_WAIT;
- int c_SYN_SENT;
- int c_FIN_WAIT1;
- int c_FIN_WAIT2;
- int c_CLOSING;
- int c_CLOSE_WAIT;
- int c_LAST_ACK;
- };
- ////////////////////////////////////////////////////////////////
- //разбивает строку s на подстроки по разделителю - пробел
- //возвращает количество подстрок
- //то что заключено в кавычки - на подстроки не разбиваеься, даже если в кавычках есть пробелы
- //результирующие подстроки помещабтся в массив m[20][MAX_LEN_REQWEST] 20 сток длиной MAX_LEN_REQWEST символов
- ////////////////////////////////////////////////////////////////
- int strBreak(
- const char *s,
- char m[20][MAX_LEN_SUBSTR],
- int allow_z){
- const int maxx=MAX_LEN_SUBSTR-1; //максимальная длина одной подстроки, Если длинее, то обрезается
- const int maxy=19; //Максимальное количество подстрок. Если больше, то не учитываются.
- int x=0,y=0;
- int isQ, isSlash=0;
- isQ=0;
- while (*s)
- {
- if ((*s=='"') && !isSlash) //если кавычка, то ждем закрывающую
- isQ=!isQ;
- else if ((*s==' ') && !isQ)
- { m[y][x]=0;
- if (allow_z || (x>0))
- {
- if (y>=maxy-1)
- return y+1;
- y++;
- x=0;
- }
- }else
- { if (x<maxx)
- { m[y][x]=*s;
- x++;
- }
- else
- m[y][x]=0; //если текущая подстрока длинее maxx, то ее обрезаем
- }
- if (*s=='\\')
- isSlash=1;
- else
- isSlash=0;
- s++;
- }
- m[y][x]=0;
- return y+1;
- }
- ///////////////////////////////////////////////////
- //разбивает строку s на подстроки по разделителю - / и :
- //возвращает количество подстрок
- //////////////////////////////////////////////////
- int strBreak2(const char *s, char m[11][8]){
- const int maxx=6; //максимальная длина одной подстроки, Если длинее, то обрезается
- const int maxy=10; //Максимальное количество подстрок. Если больше, то не учитываются.
- int x=0,y=0 ,nn=0;
- while (*s)
- {
- if (*s=='[')// пропускаем этот символ
- nn=0;
- else if ((*s=='/') || (*s==':'))
- { m[y][x]=0;
- if (x>0)
- {
- if (y>=maxy-1)
- return y+1;
- y++;
- x=0;
- }
- }else
- { if (x<maxx)
- { m[y][x]=*s;
- x++;
- }
- else
- m[y][x]=0; //если текущая подстрока длинее maxx, то ее обрезаем
- }
- s++;
- }
- m[y][x]=0;
- return y+1;
- }
- // элемент массива для сортировки.
- //sort_data -хранится номер элемента
- //sort_key - поле по которому происзодит сортировка
- struct sort_item{
- int sort_data;
- int sort_key;
- };
- ////////////
- int sort_2(struct sort_item *m){//сортировка массива ровно из 2-х элементов
- struct sort_item t;
- if (m->sort_key < (m+1)->sort_key)
- { t=*m;
- *m=*(m+1);
- *(m+1)=t;
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////////
- // сортировка Хоара для массива элементов на первый элемент которого указывает p
- // n - длина массива
- // исползование индексной адресации и указателей
- // память под временные массивы выделяется динамически
- ///////////////////////////////////////////////////////////////////////////////////////
- void hoar_sort(int n, struct sort_item *p){
- //printf("\nСортировка Хоара n=%d\n",n);
- int i,k,k1,k2,kr, //счетчики
- key; //Ключ первого элемента
- struct sort_item //Указатели для прбегания по массивам
- *lp, // Указатель для пробегания по исходному массиву
- *lp1, // Указатель для пробегания по массиву меньших элементов
- *lp2, // Указатель для пробегания по массиву больших элементов
- *lpr; // Указатель для пробегания по массиву равных элементов
- struct sort_item *mr, //указатель на массив для хранния элементов равных первому
- *m1, //указатель на массив для хранния элементов меньше первого
- *m2; //указатель на массив для хранния элементов больше первого
- //динамическре выделение памяти
- mr=(struct sort_item *)malloc(n*sizeof(sort_item));if (!mr) exit(1);
- m1=(struct sort_item *)malloc((n-1)*sizeof(sort_item));if (!m1) exit(1);
- m2=(struct sort_item *)malloc((n-1)*sizeof(sort_item));if (!m2) exit(1);
- key=p->sort_key; //записываем значение ключа первого элемента
- kr=1;k1=0;k2=0; //счетчики для временных массивов
- lp=p; // Указатель для пробегания по исходному массиву ставим на 0-й элемент
- lp1=m1; // Указатель для пробегания по массиву меньших элементов ставим на начало выделенной области
- lp2=m2; // Указатель для пробегания по массиву больших элементов ставим на начало выделенной области
- lpr=mr; // Указатель для пробегания по массиву равных элементов ставим на начало выделенной области
- *lpr++=*lp++; //записываем значение первого элемента в массив равных
- for(k=1;k<n;k++)//все элементы (кроме 1-го) исходного массива сравниваем с первым элементом
- {
- if (key > lp->sort_key )
- { *lp1++=*lp;//те которые меньше записываем во временный массив m1 и передвигаем указатель
- k1++; //увеличиваем счетчик элемнтов в этом массиве
- }else if (key < lp->sort_key)
- { *lp2++=*lp;//те которые больше записываем во временный массив m2 и передвигаем указатель
- k2++; //увеличиваем счетчик элемнтов в этом массиве
- }else
- { *lpr++=*lp;//те которые равны записываем во временный массив mr и передвигаем указатель
- kr++; //увеличиваем счетчик элемнтов в этом массиве
- }
- lp++;
- }
- if (k1==2) //если временный массив содержит ровно 2 элемента,
- sort_2(m1); //то вызываем быструю функцию сортировки для двух элементов
- else if (k1>2) //если временные массивы содержат более 2 элементов, то сортируем их рекурсивным вызовом
- hoar_sort(k1,m1);
- if (k2==2) //если временный массив содержит ровно 2 элемента,
- sort_2(m2);//то вызываем быструю функцию сортировки для двух элесентов
- else if (k2>2) //если временные массивы содержат более 2 элементов, то сортируем их рекурсивным вызовом
- hoar_sort(k2,m2);
- k=0; lp=p; //в начало исходного массива
- lp1=m1; lp2=m2; lpr=mr;
- for(i=0;i<k2;i++)//в исходный массив записываем отсортированный массив больших элементов,
- *lp++ = *lp2++;
- for(i=0;i<kr;i++)//в исходный массив записываем отсортированный массив равных элементов,
- *lp++ = *lpr++;
- for(i=0;i<k1;i++)//в исходный массив записываем отсортированный массив меньших элементов,
- *lp++ = *lp1++;
- free(mr);//освобождаем память
- free(m1);
- free(m2);
- }
- //преобразовать названия месяца в номер. Для анализа даты из лог файла.
- int monToi(char *m){
- if (!strcmp(m,"Jan")) return 0;
- else if (!strcmp(m,"Feb")) return 1;
- else if (!strcmp(m,"Mar")) return 2;
- else if (!strcmp(m,"Apr")) return 3;
- else if (!strcmp(m,"May")) return 4;
- else if (!strcmp(m,"Jun")) return 5;
- else if (!strcmp(m,"Jul")) return 6;
- else if (!strcmp(m,"Aug")) return 7;
- else if (!strcmp(m,"Sep")) return 8;
- else if (!strcmp(m,"Oct")) return 9;
- else if (!strcmp(m,"Nov")) return 10;
- else if (!strcmp(m,"Dec")) return 11;
- else return 11;
- }
- /////////////////////////////////////////////////////////////////
- // преобразует строковый формат даты в количество сикунд от 1970
- // Если преобразовать не удалось, то возвращает -1
- ////////////////////////////////////////////////////////////////
- int strToTime(char *s){
- tm tt;
- int t;
- char m[11][8];
- t=strBreak2(s,m);
- if (t!=6)
- {
- // printf ("t=%d\n",t);
- return -1;
- }
- //for (int i=0;i<t;i++)
- // printf("%s ",m[i]);
- //printf ("\n--------\n");
- time_t v;
- tt.tm_sec=atoi(m[5]);
- tt.tm_min=atoi(m[4]);
- tt.tm_hour=atoi(m[3]);
- tt.tm_mday=atoi(m[0]);
- tt.tm_mon=monToi(m[1]);
- tt.tm_year=atoi(m[2]) - 1900;
- v=mktime(&tt);
- return v;
- }
- /////////////////////////////
- // проверить есть ли значение val в массиве целых чисел ar
- /////////////////////////////
- int inArray(
- int ar_c, //количество элементов в массиве ar
- int *ar, //массив целых чисел в котором ищем
- int val){ //целое число, которое ищем
- int n;
- for (n=0;n<ar_c;n++)
- if (ar[n]==val)
- return 1;
- return 0;
- }
- /////////////////////////////////////////////////////////////////////////
- // проверить есть ли значение val в массиве целых чисел ar, массив ar заканчивается нулеаым элементом
- ////////////////////////////////////////////////////////////////////////
- int inArray_z(int *ar,int val){
- while (*ar)
- if (*ar++==val)
- return 1;
- return 0;
- }
- int inArray_m(int *ar,int val){
- while ( (*ar)!=-1 )
- if (*ar++==val)
- return 1;
- return 0;
- }
- /////////////////////////
- //отличается от предыдущих тем что сравнение происходит по маске
- /////////////////////////
- int inArray_ip_mask(
- int *ar_ip, //массив ip адресов, заканчивается нулевым элементом
- int *ar_mask, //массив масок для каждого ip
- int ip){ //ip который ищется
- while (*ar_ip)
- if (*ar_ip++ == (ip & *ar_mask++) )
- return 1;
- return 0;
- }
- ///////
- int myTimeToStr(time_t *t, char *s){
- tm *e;
- e = localtime(t);
- sprintf(s,"%d.%d.%d %d:%02d:%02d",e->tm_mday,e->tm_mon+1,e->tm_year+1900,e->tm_hour,e->tm_min,e->tm_sec);
- //s= asctime(e_tm);
- }
- //////////////////////////////////////////////////////////////////////////////////
- //вывести на экран содержимое структуры с информацией о одной строке лог файла //
- //////////////////////////////////////////////////////////////////////////////////
- int showOneHeat(
- int logLen,
- struct oneHeat *oh,
- char (*reqwest) [MAX_REQWEST_COUNT][MAX_LEN_REQWEST],
- int one_ip,
- int c_print
- ){
- int n,counter=0;
- in_addr ad;
- char *ipstr, timeStr[20];
- printf(" *** Log *** ");
- if (one_ip)
- { ad.s_addr=one_ip;
- ipstr = inet_ntoa(ad);
- printf("One IP=%s",ipstr);
- }
- printf("\n");
- for (n=0;n<logLen;n++)
- if (one_ip && (one_ip == oh[n].ip) || !one_ip)
- {
- if (counter>=c_print)
- { printf("%d of %d\n",counter,logLen);
- return 1;
- }
- counter++;
- ad.s_addr=oh[n].ip;
- ipstr = inet_ntoa(ad);
- myTimeToStr(&oh[n].t,timeStr);
- printf("%-15s %-19s %d %s %d %d\n",
- ipstr,
- timeStr,
- oh[n].num_r,
- (*reqwest)[ oh[n].num_r ],
- oh[n].code_otv,
- oh[n].cookie
- );
- }
- }
- /***********************************************************
- создает массив структур ipInfo для дальнейшей сортировки
- Возврящает количество элементов в созданном массиве
- ************************************************************/
- int makeIpInfo(
- int logLen, //количество элементов в исходном лог массиве
- struct oneHeat *log,//указатель на исходный лог в массиве
- struct sort_item *ipInfo){//будет создан массив структур
- int c_ip=0, //счетчик разных IP
- n, //счетчик цикла
- k,
- isi;//был ли данный IP ранее
- for (n=0;n<logLen; n++) //пробегаем по всем элементам исходного лог файла
- { // printf("i=%d\n",log[n].ip);
- isi=0;
- for (k=0;k<c_ip; k++) //проверяем все ранее добавленные IP
- if (ipInfo[k].sort_data == log[n].ip )
- { ipInfo[k].sort_key++; //если такой IP уже был добавлен, то увеличиваем его количество
- isi=1;
- break;
- }
- if (!isi)//если IP нет, то его добавляем
- { ipInfo[c_ip].sort_data =log[n].ip;
- ipInfo[c_ip].sort_key=1;
- c_ip++;
- }
- }
- return c_ip;
- }
- /***********************************************************
- создает массив структур codeInfo для дальнейшей сортировки
- Возврящает количество элементов в созданном массиве
- ************************************************************/
- int makeCodeInfo(
- int logLen, //количество элементов в исходном лог массиве
- struct oneHeat *log,//указатель на исходный лог в массиве
- struct sort_item *codeInfo){//будет создан массив структур
- int c_code=0, //счетчик разных IP
- n, //счетчик цикла
- k, //счетчик вложенного цикла
- is_code; //был ли данный код ранее
- for (n=0;n<logLen; n++) //пробегаем по всем элементам исходного лог файла
- { // printf("i=%d\n",log[n].ip);
- is_code=0;
- for (k=0;k<c_code; k++) //проверяем все ранее добавленные коды
- if (codeInfo[k].sort_data == log[n].code_otv )
- { codeInfo[k].sort_key++; //если такой код уже был добавлен, то увеличиваем его количество
- is_code=1;
- break;
- }
- if (!is_code)//если IP нет, то его добавляем
- { codeInfo[c_code].sort_data =log[n].code_otv;
- codeInfo[c_code].sort_key=1;
- c_code++;
- }
- }
- return c_code;
- }
- /****************************************************************
- посчитать количество уникальных URL для одного IP
- *****************************************************************/
- int calcUniqUrlForIP(
- int logLen, //количество элементов в массиве log
- struct oneHeat *log, //массив типа oneHeat с информацией о одной строке лог файла
- int ip //IP для которого считаем количество
- ){
- int count_r=0, //счетчик количества найденных запросов для этого IP
- n, //счетчик цикла
- ar_r[MAX_REQWEST_COUNT];
- for(n=0;n<logLen;n++) //пробегаем по всем строкам лог файла
- if (log[n].ip == ip) //если в лог файле нашли запрос с нужным IP
- if (!inArray(count_r, ar_r, log[n].num_r ))
- ar_r[count_r++]=log[n].num_r;
- return count_r;
- }
- /**************************************************************************************
- вычислить коэффициент (в процентах) на который умножаются лимиты, когда лог файл длинный по времени.
- То есть ддос атаки скорее всего нет
- **************************************************************************************/
- int calcPopr(int len_time_sec){
- const int leng=7;//длина лог файла в минутах, когда начинает использоваться поправочный коэфициент
- if (len_time_sec >60*leng)
- // return leng * len_time_sec/60;
- return (len_time_sec*10) / (leng*6);
- else
- return 100;
- }
- /*******************************************************
- найти ip адреса по критерию превышение количества повторов
- забанить ip адреса удовлетоворяющие всем 3 условиям
- 1) болше limit повторов в логе (limit_white - для белого списка)
- 2) у IP процент уникальных URL менее procent_uniq
- 3) таких IP найдено более 3
- ********************************************************/
- void findIPbyLimit (
- int logLen, //количество элементов в массиве log
- struct oneHeat *log, //массив типа oneHeat с информацией о одной строке лог файла
- int countIpInfo, //количество элементов в массиве ipInfo
- struct sort_item *ipInfo, //указатель на массив структур с информацией о одном ip
- int limit, //лимит на количество повторений одного ip адреса
- int limit_white, //лимит на количество повторений одного ip адреса для IP из белого списка
- int procent_uniq, //процент уникальных кликов для одного IP, если процент ниже этого значения, то это бот
- int count_ban, //сколько должно быть найдено IP , что бы они забанились
- int countClickLastMinute,
- int koef,
- int len_time_sec, //длина лога в секундах
- int *ar_res_ip, //массив забаненных, сюда же добавляем найденных ботов
- int &c_ddos_ip, //количество элементов массива ar_res_ip
- int *ar_white_ip, //белый список IP
- int *ar_white_mask //маска для белого списка
- ){
- int n, numUniqUrlForIP, p, ip_val, ip_count,
- ar_ip[2000], //не более 2000 ip удовлетворяющих условиям
- ar_c[2000],
- ar_u[2000],
- count_ar=0,
- white_ip;
- in_addr ad;
- char *ipstr;
- if (koef)
- { limit=limit*koef/100;
- limit_white=limit_white*koef/100;
- }
- limit= limit * calcPopr(len_time_sec) / 100;
- limit_white= limit_white * calcPopr(len_time_sec) / 100;
- time_t timer1;
- char str_time[30];
- for(n=0;n<countIpInfo;n++)// проходим по всем уникальным IP
- {
- ip_count=ipInfo[n].sort_key;
- if (ip_count>=limit)// если один IP повторялся в логе более limit раз
- {
- ip_val=ipInfo[n].sort_data;
- if (inArray_ip_mask( ar_white_ip, ar_white_mask, ip_val ) )
- white_ip=1; //если это IP из белого списка
- else
- white_ip=0;
- if (!white_ip || (ip_count>=limit_white) )
- {
- //найти количество уникальных URL для этого IP
- numUniqUrlForIP=calcUniqUrlForIP(logLen,log, ip_val);
- p=100 * numUniqUrlForIP / ip_count;
- if (p<procent_uniq)
- {
- // ad.s_addr=ip_val;//преобразуем ip адрес из типа int в строку
- // ipstr = inet_ntoa(ad);
- // printf("ip=%s, c=%d, url=%d, p=%d\n",
- // ipstr,
- // ipInfo[n].sort_key,
- // numUniqUrlForIP,
- // p);
- ar_ip[count_ar]=ip_val;
- ar_c[count_ar]=ip_count;
- ar_u[count_ar]=numUniqUrlForIP;
- count_ar++;
- }
- }
- }
- }
- //printf("count_ar=%d\n",count_ar);
- //printf("count_ban=%d\n",count_ban);
- if (count_ar>=count_ban)
- {
- time(&timer1);
- myTimeToStr(&timer1,str_time);
- for(n=0;n<count_ar;n++)
- {
- if (!inArray(c_ddos_ip, ar_res_ip, ar_ip[n] ) )
- {
- ar_res_ip[c_ddos_ip++]=ar_ip[n];
- ad.s_addr=ar_ip[n];//преобразуем ip адрес из типа int в строку
- ipstr = inet_ntoa(ad);
- if (koef)
- printf("k=%d,",koef);
- if (white_ip)
- printf("-mW %d,",
- limit_white);
- else
- printf("-m %d,",
- limit);
- printf("%d,%d.",procent_uniq,count_ban);
- printf("ip=%s,c=%d,u=%d,Cm=%d,t=%s,",
- ipstr,
- ar_c[n],
- ar_u[n],
- countClickLastMinute,
- str_time
- );
- if (len_time_sec<400)
- printf("Tl=%ds\n",len_time_sec);
- else if (len_time_sec<7200)
- printf("Tl=%dm\n",len_time_sec/60);
- else
- printf("Tl=%dh\n,",len_time_sec/3600);
- }
- }
- }
- }
- /***********************************************************************************
- подсчитать количество разных запросов и юзерагентов для заданногго IP
- ***********************************************************************************/
- void calcCountForIP(
- int logLen, //количество элементов в массиве log
- struct oneHeat *log, //массив типа oneHeat с информацией о одной строке лог файла
- int ip, //IP для которого считаем количество
- int &count_r, //счетчик количества найденных запросов для этого IP
- int &last_code,
- int &count_ref,
- int &count_ua, //счетчик количества найденных юзер агентов для этого IP
- int &last_url,
- int &last_ua
- ){
- int n, //счетчик цикла
- ar_r[MAX_REQWEST_COUNT],
- ar_ref[MAX_REFERRER_COUNT],
- ar_u[MAX_USER_AGENT_COUNT];
- count_r=0;
- count_ref=0;
- count_ua=0;
- for(n=0;n<logLen;n++) //пробегаем по всем строкам лог файла
- if (log[n].ip == ip) //если в лог файле нашли запрос с нужным IP
- {
- last_url=log[n].num_r;
- last_code=log[n].code_otv;
- last_ua=log[n].num_ua;
- if (!inArray(count_r, ar_r, log[n].num_r ))
- ar_r[count_r++]=log[n].num_r;
- if (!inArray(count_ref, ar_ref, log[n].num_ref ))
- ar_ref[count_ref++]=log[n].num_ref;
- if (!inArray(count_ua, ar_u, log[n].num_ua ))
- ar_u[count_ua++]=log[n].num_ua;
- }
- }
- /***********************************************************************************
- подсчитать количество разных ip и юзерагентов для заданной страницы
- ***********************************************************************************/
- void calcCountForReqwest(
- int logLen, //количество элементов в массиве log
- struct oneHeat *log, //массив типа oneHeat с информацией о одной строке лог файла
- int num_r, //запрос для которого считаем количество
- int &count_ip,
- int &count_ref,
- int &count_ua,
- int &exemple_code
- ){
- int n, //счетчик цикла
- ar_ip[MAX_STR_LOG],
- ar_ref[MAX_REFERRER_COUNT],
- ar_u[MAX_USER_AGENT_COUNT];
- count_ip=0;
- count_ref=0;
- count_ua=0;
- for(n=0;n<logLen;n++) //пробегаем по всем строкам лог файла
- if (log[n].num_r == num_r) //если в лог файле нашли запрос с нужным IP
- {
- if (!inArray(count_ip, ar_ip, log[n].ip ))
- ar_ip[count_ip++]=log[n].ip;
- if (!inArray(count_ref, ar_ref, log[n].num_ref ))
- ar_ref[count_ref++]=log[n].num_ref;
- if (!inArray(count_ua, ar_u, log[n].num_ua ))
- ar_u[count_ua++]=log[n].num_ua;
- exemple_code=log[n].code_otv;
- }
- }
- /***********************************************************************************
- ***********************************************************************************/
- void calcCountForCode(
- int logLen, //количество элементов в массиве log
- struct oneHeat *log, //массив типа oneHeat с информацией о одной строке лог файла
- int code_otv, //
- int &count_ip,
- int &count_r,
- int &count_ua,
- int &exemple_ip,
- int &exemple_r
- ){
- int n, //счетчик цикла
- ar_ip[MAX_STR_LOG],
- ar_r[MAX_REQWEST_COUNT],
- ar_u[MAX_USER_AGENT_COUNT];
- count_ip=0;
- count_r=0;
- count_ua=0;
- for(n=0;n<logLen;n++) //пробегаем по всем строкам лог файла
- if (log[n].code_otv == code_otv) //если в лог файле нашли запрос с нужным IP
- {
- if (!inArray(count_ip, ar_ip, log[n].ip ))
- { ar_ip[count_ip++]=log[n].ip;
- exemple_ip=log[n].ip;
- }
- if (!inArray(count_r, ar_r, log[n].num_r ))
- { ar_r[count_r++]=log[n].num_r;
- exemple_r=log[n].num_r;
- }
- if (!inArray(count_ua, ar_u, log[n].num_ua ))
- ar_u[count_ua++]=log[n].num_ua;
- }
- }
- /***********************************************
- Функция используется для создания отчета -I
- Подсчитать сколько максимум кликов делается за период времени per.
- Подсчет идет по режиму mode
- ************************************************/
- int findDDOS_one_ip(
- int one_ip,
- int logLen,
- struct oneHeat *log,
- // int limit_d, //сколько раз за периуд времени должен повторится запрос, что бы считать его ддосом
- int per, //период времени в течении которгго производится подсчет повторов
- int mode
- ){
- int n,n2, max_c_double;
- for (n=0;n<logLen;n++)//пробегаеся по всему логу
- { log[n].c_double=1;
- if (log[n].ip==one_ip)
- {
- if ( (mode==4) && (log[n].code_otv!=404) )
- continue;
- n2=n+1; //пробегаем по оставшейся части лога после этого клика на период времени per
- while ((n2<logLen) && (log[n2].t - log[n].t <per) )//пробегаем пока либо не достигнем конца лога либо время время не достигнет per
- { if (log[n].ip==log[n2].ip)
- { if (mode==1)
- { if ((log[n].num_r==log[n2].num_r) )
- log[n].c_double++;
- else
- { log[n].c_double=0;
- break;
- }
- }
- else
- if (mode==2)
- { if ((log[n].num_r==log[n2].num_r) )
- log[n].c_double++;
- }
- else
- if (mode==3)
- log[n].c_double++;
- else
- if (mode==4)
- { if (log[n2].code_otv==404)
- log[n].c_double++;
- else
- {
- log[n].c_double=0;
- break;
- }
- }
- }
- n2++;
- }
- }
- }
- max_c_double = 1;
- for (n=0;n<logLen;n++)
- if ( (log[n].ip == one_ip) && (log[n].c_double > max_c_double) )
- max_c_double = log[n].c_double;
- return max_c_double;
- }
- /////////////////////////
- int calcCookie(
- int logLen, //количество элементов в массиве log
- struct oneHeat *log, //исходный лог
- int ip){
- int n,res=0;
- for (n=0;n<logLen;n++)
- {
- // printf("q\n");
- if (log[n].ip==ip)
- if (log[n].cookie>0)
- res++;
- }
- return res;
- }
- /******************************
- Вывести топ IP
- ******************************/
- void showIpInfo(int countIpInfo, //количество элементов в массиве ipInfo
- struct sort_item *ipInfo,//указатель на массив структур с информацией о каждом ip
- int logLen, //количество элементов в массиве log
- struct oneHeat *log, //исходный лог
- char (*reqwest) [MAX_REQWEST_COUNT][MAX_LEN_REQWEST], //массив строк запроса
- char (*user_agent) [MAX_USER_AGENT_COUNT][MAX_USER_AGENT_LEN], //
- int verbose, //для каждого выводимого ip подсчитывать количество разных запросов и печатать
- int c_print, //сколько строк выводить
- int show_d
- ){
- //int ar[MAX_STR_LOG],//массив для хранения разных варимантов запроса для каждого ip
- // //варианты запроса хранятся по номерам из строк массива reqwest
- // c_reqv, //счетчик для количества элементов массива ar
- int last_url, //номер первого запроса для ip
- last_ua,n;
- int count_r,
- count_ref,
- count_ua,
- exemple_code ,
- ccookie;
- in_addr ad;
- char *ipstr;
- char str[3000], str1[200];
- if (verbose)
- { printf(" * Top IP=%d *\n",countIpInfo);
- if (show_d)
- printf(" ip c d1 d2 d3 url co ref ua last_url last ua\n");
- else
- printf(" ip c/c60 url co ref ua last_url last_ua\n");
- // printf(" ip c/coo/c60 url co ref ua last_url last_ua\n");
- }
- for (n=0;n<countIpInfo; n++) //пробегаем по всем элементам массива ipInfo
- {
- if (n>=c_print) //если превышен лимит на количество выводимых строк то выходим
- { if (verbose)
- printf("%d of %d\n",n,countIpInfo);//вывести количество напечатанных строк
- return;
- }
- ad.s_addr=ipInfo[n].sort_data;//преобразуем ip адрес из типа int в строку
- ipstr = inet_ntoa(ad);
- if (verbose)
- {
- calcCountForIP(
- logLen, //количество элементов в массиве log
- log, //массив типа oneHeat с информацией о одной строке лог файла
- ipInfo[n].sort_data, //IP для которого считаем количество
- count_r, //счетчик количества найденных запросов для этого IP
- exemple_code,
- count_ref,
- count_ua, //счетчик количества найденных юзер агентов для этого IP
- last_url,
- last_ua
- );
- if (show_d)
- {
- printf("%-16s %3d ",
- ipstr,
- ipInfo[n].sort_key);
- sprintf(str1,"%d/%d/%d",
- findDDOS_one_ip(ipInfo[n].sort_data,logLen,log,60,1),
- findDDOS_one_ip(ipInfo[n].sort_data,logLen,log,120,1),
- findDDOS_one_ip(ipInfo[n].sort_data,logLen,log,180,1));
- printf("%9s ",str1);
- sprintf(str1,"%d/%d/%d",
- findDDOS_one_ip(ipInfo[n].sort_data,logLen,log,60,2),
- findDDOS_one_ip(ipInfo[n].sort_data,logLen,log,120,2),
- findDDOS_one_ip(ipInfo[n].sort_data,logLen,log,180,2));
- printf("%9s ",str1);
- sprintf(str1,"%d/%d/%d",
- findDDOS_one_ip(ipInfo[n].sort_data,logLen,log,60,3),
- findDDOS_one_ip(ipInfo[n].sort_data,logLen,log,120,3),
- findDDOS_one_ip(ipInfo[n].sort_data,logLen,log,180,3));
- printf("%11s ",str1);
- if (ipInfo[n].sort_key == count_r)
- printf(" ");
- else
- printf("%-4d ",count_r);
- printf("%-4d %-4d %-4d ",
- exemple_code,
- count_ref,
- count_ua);
- strcpy(str, (*reqwest)[last_url]);
- str[30]=0;
- printf("%-31s ",str);
- strcpy(str, (*user_agent)[last_ua]);
- str[19]=0;
- printf("%s\n",str);
- }else
- {
- ccookie=calcCookie(
- logLen, //количество элементов в массиве log
- log, //исходный лог);
- ipInfo[n].sort_data);
- printf("%-16s %4d/%-3d ",
- ipstr,
- ipInfo[n].sort_key,
- // ccookie,
- findDDOS_one_ip(
- ipInfo[n].sort_data,
- logLen,log,
- 60,3)
- );
- if (ipInfo[n].sort_key == count_r)
- printf(" ");
- else
- printf("%-4d ",count_r);
- strcpy(str, (*reqwest)[last_url]);
- str[44]=0;
- printf("%-4d %-4d %-4d %-45s ",
- exemple_code,
- count_ref,
- count_ua,
- str);
- strcpy(str, (*user_agent)[last_ua]);
- str[31]=0;
- printf("%s\n",str);
- }
- }
- else
- printf("%s\n",ipstr);
- }
- }
- /******************************
- Вывести топ кодов ответа
- ******************************/
- void showCodeInfo(int countCodeInfo, //количество элементов в массиве CodeInfo
- struct sort_item *codeInfo,//указатель на массив структур с информацией о одном Code
- int logLen, //количество элементов в массиве log
- struct oneHeat *log, //исходный лог
- char (*reqwest) [MAX_REQWEST_COUNT][MAX_LEN_REQWEST], //массив строк запроса
- int c_print //сколько строк выводить
- ){
- int n,
- count_ip,
- count_r,
- count_ua,
- exemple_ip,
- exemple_r;
- in_addr ad;
- char *ipstr;
- printf(" * TOP response code=%d *\n",countCodeInfo);
- printf("code c ip url ua last_ip last_url\n");
- for (n=0;n<countCodeInfo; n++) //пробегаем по всем элементам массива ipInfo
- {
- if (n>=c_print) //если превышен лимит на количество выводимых строк то выходим
- {
- printf("%d of %d\n",n,countCodeInfo);//вывести количество напечатанных строк
- return;
- }
- calcCountForCode(
- logLen, //количество элементов в массиве log
- log, //массив типа oneHeat с информацией о одной строке лог файла
- codeInfo[n].sort_data, //запрос для которого считаем количество
- count_ip,
- count_r,
- count_ua,
- exemple_ip,
- exemple_r
- );
- ad.s_addr=exemple_ip;//преобразуем ip адрес из типа int в строку
- ipstr = inet_ntoa(ad);
- printf("%-4d %-6d %-4d %-6d %-4d %-16s %s\n",
- codeInfo[n].sort_data,
- codeInfo[n].sort_key,
- count_ip,
- count_r,
- count_ua,
- ipstr,
- (*reqwest)[exemple_r]
- );
- }
- }
- /****************************
- Вывести топ запросов
- *****************************/
- int printReqvInfo(
- int logLen, //количество элементов в массиве log
- struct oneHeat *log, //массив типа oneHeat с информацией о одной строке лог файла
- int count , //количество элементов в массиве reqv_info
- struct sort_item * reqv_info,//отсортированный массив с указанием на запрос и количеством(отсортирован по количеству)
- char (*reqwest) [MAX_REQWEST_COUNT][MAX_LEN_REQWEST], //текст самих запросов(не повторяются)
- int c_print //сколько строк выводить на экран
- ){
- int n,
- count_ip,
- count_ref,
- count_ua,
- exemple_code;
- printf(" * TOP urls=%d *\n",count);
- printf("c ip co ref ua url\n");
- for (n=0; n<count; n++)
- { if (n>=c_print)
- { printf("%d of %d\n",n,count);
- return 1;
- }
- calcCountForReqwest(
- logLen, //количество элементов в массиве log
- log, //массив типа oneHeat с информацией о одной строке лог файла
- reqv_info[n].sort_data, //запрос для которого считаем количество
- count_ip,
- count_ref,
- count_ua,
- exemple_code);
- printf("%-4d %-4d %-4d %-4d %-4d %s\n",
- reqv_info[n].sort_key,
- count_ip,
- exemple_code,
- count_ref,
- count_ua,
- (*reqwest) [ reqv_info[n].sort_data ]
- );
- }
- }
- //////////////
- void printDdos(
- int ip,time_t t,
- char * reqw_str,
- int verbose){
- in_addr ad;
- char *ipstr, timeStr[20];
- ad.s_addr=ip;
- ipstr = inet_ntoa(ad);
- if (verbose)
- {
- myTimeToStr(&t,timeStr);
- printf("ip=%s %s %s\n",ipstr, timeStr, reqw_str);
- }
- else
- printf("%s\n",ipstr);
- }
- /////////////////////////
- /*
- int ipUseURLs( int ip,
- struct oneHeat *log,
- int *ar_ddos_url,
- int count_ddos_url){
- struct oneHeat *p;
- p=log;
- while(p->ip)
- {
- if (p->ip==ip)
- if (inArray(count_ddos_url,ar_ddos_url, p->num_r))
- return 1;
- p++;
- }
- return 0;
- }
- */
- /***********************************************
- проверить были ли обращения с одного ip к URL НЕ из списка ar_ddos_url
- ***********************************************/
- int ipUseOtherURLs( int ip, //анализируемый ip
- struct oneHeat *log, //исходный лог
- int *ar_ddos_url, //список url которе ддосят
- int count_ddos_url, //количество элементов в массиве ar_ddos_url
- int &count_ref//заодно расчитываем и возвращаем количество уникальных url для этого ip
- ){
- int ar_ref[MAX_REFERRER_COUNT];//массив для хранения уникальных url этого ip
- count_ref=0;
- int url;
- struct oneHeat *p;//указатель на структуру с информацией о одной строке лога
- p=log; //присваиваем указателю адрес первого элемента в логе
- while(p->ip) //пробегаемся по всему логу
- { //значение IP после последнего в логе рпавно 0
- if (p->ip==ip)//если эта строка лога сделана анализируемым ip
- {
- if (!inArray(count_ref, ar_ref, p->num_r ))//если это новый уникальный url для этого ip
- ar_ref[count_ref++]= p->num_r ;
- if (!inArray (count_ddos_url,ar_ddos_url, p->num_r))//если url этой строки не входит в список ar_ddos_url
- return 1;
- }
- p++;
- }
- return 0;
- }
- ///////////
- void findGroupURL(
- int logLen, //количество элементов в массиве log
- struct oneHeat *log, //массив типа oneHeat с информацией о каждой строке лог файла
- int count_reqv , //количество элементов в массиве reqv_info
- struct sort_item * reqv_info, //отсортированный массив с указанием на запрос и количеством(отсортирован по количеству)
- char (*reqwest) [MAX_REQWEST_COUNT][MAX_LEN_REQWEST], //текст самих запросов(не повторяются)
- int limit_r, //находит URL с количеством обращений со всех IP больше этого значения
- int limit_2, //находит IP, которые сделали больше этого чисоа кликов и клики были только к URL найденным ранее
- int countClickLastMinute,
- int len_time_sec,
- int koef,
- int *ar_res_ip, //указатель на масив найденных IP
- int &c_ddos_ip, //количество найденных IP
- int *ar_white_ip, //
- int *ar_white_mask //
- ){
- int n,n2, countIpInfo, count_ip, count_ref, count_ua, exemple_code, ip_val, count_ddos_url=0,
- isZag=0, numUniqUrl,
- ar_ddos_url[2000];//сюда будем добавлять найденные номера запросов, которые превысили лимит на количество кликов
- if (koef)
- limit_r=limit_r*koef/100;
- limit_r= limit_r * calcPopr(len_time_sec) / 100;
- time_t timer1;
- char str_time[30];
- time(&timer1);
- myTimeToStr(&timer1,str_time);
- struct sort_item ipInfo[MAX_STR_LOG];
- in_addr ad;
- char *ipstr;
- for (n=0; n<count_reqv; n++) //пробегаем по всем вариантам запросов
- if (reqv_info[n].sort_key>=limit_r) //если какой то запрос был сделан более лимита
- {
- calcCountForReqwest(
- logLen, //количество элементов в массиве log
- log, //массив типа oneHeat с информацией о одной строке лог файла
- reqv_info[n].sort_data, //номер запроса для которого считаем количество
- count_ip,
- count_ref,
- count_ua,
- exemple_code);
- ar_ddos_url[count_ddos_url++]=reqv_info[n].sort_data;//добавляем найденный номер запроса в список
- if (!isZag)
- {
- printf("-x %d %d,",limit_r,limit_2);
- if (koef)
- printf("k=%d,",koef);
- printf("Rd=%d,Cm=%d,",logLen,countClickLastMinute);
- if (len_time_sec<400)
- printf("Tl=%ds",len_time_sec);
- else if (len_time_sec<7200)
- printf("Tl=%dm",len_time_sec/60);
- else
- printf("Tl=%dh",len_time_sec/3600);
- printf(",%s\n",str_time);
- isZag=1;
- }
- printf("c=%d,ip=%d,ref=%d,ua=%d,co=%d %s\n",
- reqv_info[n].sort_key,
- count_ip,
- count_ref,
- count_ua,
- exemple_code,
- (*reqwest) [ reqv_info[n].sort_data ]
- );
- }
- //printf("count_ddos_url=%d\n",count_ddos_url);
- if (!count_ddos_url)//если нет ни одного запроса превысевшего количество кликов
- return;
- //создаем массив ipInfo с информацией о количестве кликов каждого IP
- //это нужно, что бы получить список уникальных IP
- //что бы перебирать именно уникальные IP без повторов
- countIpInfo= //количество разных ip(длина мкассива ipInfo)
- makeIpInfo( //создание массива ipInfo
- logLen, //количество элементов в массиве log
- log, //массив типа oneHeat с информацией о одной строке лог файла
- ipInfo);//указатель на массив элементов типа sort_item,
- for (n=0; n<countIpInfo; n++)//перебераем все варианты IP (не повторяются)
- {
- /* if ( ipUseURLs(//если IP обращается к URL из списка ддос урлов
- ipInfo[n].sort_data,
- log,
- ar_ddos_url,
- count_ddos_url) )*/
- if (ipInfo[n].sort_key >= limit_2 )//если количество кликов с этого IP больше лимита
- if (! ipUseOtherURLs(//если IP не обращается к URL не из списка ддос урлов
- ipInfo[n].sort_data, //анализипуемый IP
- log, //исходный массив лога
- ar_ddos_url, //массив номеров атакуемых URL
- count_ddos_url, //количество URL под атакой
- numUniqUrl) ) //заодно расчитываем количестов уникальных URL для этого ip
- {
- ip_val=ipInfo[n].sort_data;//значение IP
- if (!inArray(c_ddos_ip,ar_res_ip,ip_val))//если IP еще нет в списке ar_res_ip
- {
- if (!inArray_ip_mask(ar_white_ip,ar_white_mask,ip_val) )//если IP нет в белом спаске ar_white_ip
- {
- ar_res_ip[c_ddos_ip++]=ip_val;
- ad.s_addr=ip_val;
- ipstr = inet_ntoa(ad);
- printf("x: %d,u=%d - %s\n",
- ipInfo[n].sort_key,
- numUniqUrl,
- ipstr);
- }
- }
- }
- }
- ar_res_ip[c_ddos_ip]=0;
- }
- //подсчитать сколько разных IP используют данный юзерагент
- int calcIPbyUA(
- int id_user_agent,
- int logLen, //длина лога
- struct oneHeat *log){
- int n, ar_ip[MAX_STR_LOG], count_ip=0;
- for(n=0;n<logLen;n++) //пробегаем по всем строкам лог файла
- if (log[n].num_ua == id_user_agent) //если в лог файле нашли запрос с нужным юзер агентом
- if (!inArray(count_ip, ar_ip, log[n].ip )) //если запроса с этим ip еще не было
- ar_ip[count_ip++]=log[n].ip; //то добавляем этот запрос в массив ar_int и увеличиваем количество элементов в массиве
- return count_ip;
- }
- //подсчитать сколько разных IP используют данный реферрер
- int calcIPbyRef(
- int id_referer,
- int logLen, //длина лога
- struct oneHeat *log){
- int n, ar_ip[MAX_STR_LOG], count_ip=0;
- for(n=0;n<logLen;n++) //пробегаем по всем строкам лог файла
- if (log[n].num_ref == id_referer) //если в лог файле нашли запрос с нужным юзер агентом
- if (!inArray(count_ip, ar_ip, log[n].ip )) //если запроса с этим ip еще не было
- ar_ip[count_ip++]=log[n].ip; //то добавляем этот запрос в массив ar_int и увеличиваем количество элементов в массиве
- return count_ip;
- }
- int banAllLastM(
- int logLen,
- struct oneHeat *log,
- int *ar_res_ip,
- int &c_ddos_ip,
- int *ar_white_ip,
- int *ar_white_mask
- ){
- int n, t2=0, c=0, ip;
- time_t last_time;
- in_addr ad;
- char *ipstr;
- if (logLen<3)
- return 0;
- last_time=log[logLen-1].t;
- for(n=logLen-2;n>=0;n--)
- {
- t2=last_time-log[n].t;
- if (t2>60)
- break;
- ip=log[n].ip;
- if (!inArray_ip_mask( ar_white_ip, ar_white_mask, ip) )
- if (! inArray(c_ddos_ip , ar_res_ip ,ip) )
- {
- ar_res_ip[ c_ddos_ip++ ]= ip;
- ad.s_addr=ip;
- ipstr = inet_ntoa(ad);
- printf("-A:%s\n",ipstr);
- }
- }
- return c;
- }
- /**************************************************************
- подсчитать количество не забаненных кликов в последнюю минуту
- ***************************************************************/
- int calcNumNotBanLastM(
- int logLen, //количество элементов массива log
- struct oneHeat *log, //массив элементов лога
- int *ban_ip, //массив забаненных IP
- int &numIPlastM){ //заодно расчитываем и возвращаем количество уникальных IP за последнюю минуту
- int n,
- t2=0,
- c=0,
- ip,
- ar_ip[MAX_STR_LOG];//массив используется для подсчета количества уникальных IP
- time_t last_time;
- numIPlastM=0;
- if (logLen<3)
- return 0;
- last_time=log[logLen-1].t;//время последнего клика
- for(n=logLen-2;n>=0;n--) //пробегаем по логу начиная с последнего элемента и до тех пор пока не закончится минута
- { t2=last_time-log[n].t;
- if (t2>60)
- break;
- ip=log[n].ip;
- if (!inArray_z(ban_ip,ip) )//если клик сделан с не забаненного IP то увеличиваем счетчик не забаненых кликов
- c++;
- if (!inArray(numIPlastM, ar_ip, ip) ) //если такого ip еще нет в массиве ar_ip то добавояем его в
- ar_ip[numIPlastM++]=ip; //ar_ip и увеличиваем счетчик уникальных IP
- }
- return c;
- }
- /***********************
- алгоритм банит всех кто зашел в последнюю минуту в случае выполнения всех 4 условий
- 1) количество забаненных IP предыдущими алгоритмами в этом вызове программы менее 10
- 2) количество кликов в последнюю минуту больше или равно limit_lastm
- 3) количестово уникальных IP в последнюю минуту больше или равно limit_countIP
- 4) процент не забаненных кликов в последнюю минуту болше или равен limit_proc_ban
- ***********************/
- void armagedon(
- int logLen, //количество элементов в логе (в массиве log)
- struct oneHeat *log, //массив элементов исходного лога
- int limit_lastm, //лимит на количество кликов в роследнюю минуту
- int limit_countIP, //лимит на количество IP в последнюю минуту
- int limit_proc_ban, //лимит на процент не забаненных кликов в последнюю минуту
- int countClickLastMinute,//количестово кликов за последнюю минуту
- int countIpInfo, //количество уникальных IP в логе
- //это число может быть вычислено предыдущими алгоритмами
- //Если оно вычислено, то оно используется для сравнения с limit_countIP
- //и может предотвратить лишние расчеты.
- //если это значение предыдущими алгоритмами не вычеслено, то его значение должно быть 0
- int len_time_sec, //длина лога в секундах
- // int koef, //???????
- int *ar_res_ip, //массив забаненных IP, сюда добавляем обнаруженных ботов
- int &c_ddos_ip, //уоличество элементов в массиве ar_res_ip
- int *ar_white_ip, //белый список IP
- int *ar_white_mask //маска белого списка
- ){
- int numNotBanLastM,proc_not_ban,numIPlastM;
- struct sort_item ipInfo[MAX_STR_LOG];
- time_t timer1;
- char str_time[30];
- //printf("armagedon\n");
- //printf("countClickLastMinute=%d\n",countClickLastMinute);
- //printf("limit_countIP=%d\n",limit_countIP);
- //printf("countIpInfo=%d\n",countIpInfo);
- //printf("limit_lastm=%d\n",limit_lastm);
- //printf("limit_proc_ban=%d\n",limit_proc_ban);
- //printf("c_ddos_ip=%d\n",c_ddos_ip);
- if ( (c_ddos_ip<10) && (countClickLastMinute>2) && (countClickLastMinute >= limit_lastm ) )
- {
- if ( !countIpInfo || (countIpInfo >= limit_countIP ) )
- {
- ar_res_ip[c_ddos_ip]=0;
- //подсчитать количество не забаненных кликов в последнюю минуту
- numNotBanLastM=calcNumNotBanLastM(
- logLen,
- log,
- ar_res_ip,
- numIPlastM);//заодно расчитываем и возвращаем количество уникальных IP за последнюю минуту
- proc_not_ban=100 * numNotBanLastM/countClickLastMinute;// находим процент не забаненных кликов
- // printf("numNotBanLastM=%d\n",numNotBanLastM);
- // printf("proc_not_ban=%d\n",proc_not_ban);
- // printf("numIPlastM=%d\n",numIPlastM);
- if (( numIPlastM >= limit_countIP) && ( proc_not_ban >= limit_proc_ban ) )
- {
- time(&timer1);
- myTimeToStr(&timer1,str_time);
- printf("-A %d %d %d, Cm=%d,IpM=%d,Pn=%d %s\n",
- limit_lastm,
- limit_countIP,
- limit_proc_ban,
- countClickLastMinute,
- numIPlastM,
- proc_not_ban,
- str_time
- );
- banAllLastM(
- logLen,
- log,
- ar_res_ip,
- c_ddos_ip,
- ar_white_ip,
- ar_white_mask);
- }
- }
- }
- }
- /*************************
- какой длины limit_len должна быть строка и сколько раз она должна повториться limit_d за период времени per
- Что бы считать этот ддосом
- ***************************/
- void findLongStr(
- int logLen,
- struct oneHeat *log,
- char (*reqwest) [MAX_REQWEST_COUNT][MAX_LEN_REQWEST],
- int limit_d, //сколько раз за периуд времени должен повторится запрос, что бы считать его ддосом
- int per, //периуд времени в течении которгго производится подсчет повторов
- int limit_len,
- int verbose,
- int c_print,
- int *ar_res_ip,
- int &c_ddos_ip
- ){
- int n,n2, max_c_double;
- //printf("-s limit_d=%d , per=%d , limit_len=%d\n",limit_d,per,limit_len);
- for (n=0;n<logLen;n++)
- { if (log[n].len_str > limit_len)
- { log[n].c_double=1;
- n2=n+1;
- while ((n2<logLen) && (log[n2].t - log[n].t <per) )
- {
- if (log[n].ip==log[n2].ip)
- if (log[n2].len_str > limit_len)
- log[n].c_double++;
- n2++;
- }
- }else
- log[n].c_double=0;
- };
- for (n=0;n<logLen;n++)
- if (log[n].c_double>=limit_d)
- if (!inArray(c_ddos_ip, ar_res_ip,log[n].ip) )
- { max_c_double = log[n].c_double;
- for (n2=n;n2<logLen;n2++)
- if ( (log[n].ip == log[n2].ip) && (log[n2].c_double > max_c_double) )
- max_c_double = log[n2].c_double;
- ar_res_ip[c_ddos_ip]=log[n].ip;
- c_ddos_ip++;
- printf("-s %d %d %d:L=%d,c=%d,", limit_d,per, limit_len, log[n].len_str, max_c_double);
- printDdos(
- log[n].ip,
- log[n].t,
- (*reqwest)[ log[n].num_r ],
- verbose);
- /* if (c_ddos_ip>=c_print)
- { ar_res_ip[c_ddos_ip]=0;
- if (verbose)
- printf("Первые %d. Не все.\n",c_ddos_ip);
- return;
- }*/
- }
- ar_res_ip[c_ddos_ip]=0;
- }
- //////////
- /*************************
- какой длины limit_len должна быть строка и сколько раз она должна повториться limit_d за период времени per
- Что бы считать этот ддосом
- ***************************/
- void findDirki(
- int logLen,
- struct oneHeat *log,
- char (*reqwest) [MAX_REQWEST_COUNT][MAX_LEN_REQWEST],
- int per1, //сколько раз за периуд времени должен повторится запрос, что бы считать его ддосом
- int per2, //периуд времени в течении которгго производится подсчет повторов
- int verbose,
- int c_print,
- int *ar_res_ip,
- int &c_ddos_ip,
- int *ar_white_ip,
- int *ar_white_mask
- ){
- int n,n2, t_old , d ,maxd;
- //printf("-z per1=%d , per2=%d\n",per1,per2);
- for (n=0;n<logLen;n++)
- {
- // printf("n=%d\n",n);
- if (inArray_ip_mask(ar_white_ip,ar_white_mask,log[n].ip) )
- {
- log[n].c_double=per2;
- continue;
- }
- maxd=0; t_old=log[n].t; n2=n+1;
- while ((n2<logLen) && (log[n2].t - log[n].t <per2) )
- {
- if (log[n].ip==log[n2].ip)
- {
- d=log[n2].t - t_old;
- t_old=log[n2].t;
- if (d>maxd)
- {
- maxd=d;
- if (maxd>per1)
- break;
- }
- // printf("n2=%d d=%d, ",n2,d);
- }
- n2++;
- }
- d= log[n].t + per2 - t_old;
- if (d>maxd)
- maxd=d;
- // printf("n=%d maxd=%d\n",n,maxd);
- log[n].c_double=maxd;
- };
- for (n=0;n<logLen;n++)
- if (log[n].c_double<per1)
- if (!inArray(c_ddos_ip, ar_res_ip,log[n].ip) )
- { maxd = log[n].c_double;
- // printf("rrr n=%d maxd=%d\n",n,maxd);
- // for (n2=n;n2<logLen;n2++)
- // if ( (log[n].ip == log[n2].ip) && (log[n2].c_double > maxd) )
- // maxd = log[n2].c_double;
- ar_res_ip[c_ddos_ip]=log[n].ip;
- c_ddos_ip++;
- printf("-z %d %d: c=%d ", per1, per2, maxd);
- printDdos(
- log[n].ip,
- log[n].t,
- (*reqwest) [ log[n].num_r ],
- verbose);
- }
- ar_res_ip[c_ddos_ip]=0;
- }
- ////////
- void printHelp(){
- printf(" *** Поиск DDOS в лог файле web сервера ***\n");
- printf("\n");
- }
- ////////
- int strIPportToIP(char *s){
- in_addr ad; //структура для хранения IP адреса
- int razdc=0;
- char *n;
- n=s;
- while(*n)
- {
- if ((*n=='.') || (*n==':') )
- {
- if (razdc>=3)
- {
- *n=0;
- break;
- }else
- razdc++;
- }
- n++;
- }
- //printf("s=%s\n",s);
- if (inet_aton(s,&ad) ==0) //преобразуем строковый вормат IP адреса в 4-х байтовое целое
- return -1; // если формат не верный выходим
- return ad.s_addr;
- }
- ////////////
- void printNetstat(
- int count,
- netstat_t *netstat,
- int sockCount,
- int koef,
- sort_item *order,
- int max_row,
- int *ar_res_ip,
- struct netstat_t netstat_limit,
- char *comment_str
- ){
- int n,num, print_counter=0;
- in_addr ad;
- char *ipstr;
- time_t timer1;
- char str_time[30];
- time(&timer1);
- myTimeToStr(&timer1,str_time);
- if (koef)
- {
- netstat_limit.count = netstat_limit.count *koef/100;
- netstat_limit.c_SYN_RECV = netstat_limit.c_SYN_RECV *koef/100;
- netstat_limit.c_SYN_SENT = netstat_limit.c_SYN_SENT *koef/100;
- netstat_limit.c_ESTABLISHED = netstat_limit.c_ESTABLISHED *koef/100;
- netstat_limit.c_TIME_WAIT = netstat_limit.c_TIME_WAIT *koef/100;
- netstat_limit.c_FIN_WAIT1 = netstat_limit.c_FIN_WAIT1 *koef/100;
- netstat_limit.c_FIN_WAIT2 = netstat_limit.c_FIN_WAIT2 *koef/100;
- netstat_limit.c_CLOSING = netstat_limit.c_CLOSING *koef/100;
- netstat_limit.c_CLOSE_WAIT = netstat_limit.c_CLOSE_WAIT *koef/100;
- netstat_limit.c_LAST_ACK = netstat_limit.c_LAST_ACK *koef/100;
- }
- for (n=0;n<count;n++)
- { if (print_counter>=max_row)
- { printf("%d of %d\n",print_counter,count);
- ar_res_ip[print_counter]=0;
- return;
- }
- num=order[n].sort_data;
- if (
- (netstat[num].count >= netstat_limit.count ) && netstat_limit.count ||
- (netstat[num].c_SYN_RECV >= netstat_limit.c_SYN_RECV) && netstat_limit.c_SYN_RECV ||
- (netstat[num].c_SYN_SENT >= netstat_limit.c_SYN_SENT ) && netstat_limit.c_SYN_SENT ||
- (netstat[num].c_ESTABLISHED >= netstat_limit.c_ESTABLISHED )&& netstat_limit.c_ESTABLISHED ||
- (netstat[num].c_TIME_WAIT >= netstat_limit.c_TIME_WAIT ) && netstat_limit.c_TIME_WAIT ||
- (netstat[num].c_FIN_WAIT1 >= netstat_limit.c_FIN_WAIT1 ) && netstat_limit.c_FIN_WAIT1 ||
- (netstat[num].c_FIN_WAIT2 >= netstat_limit.c_FIN_WAIT2 ) && netstat_limit.c_FIN_WAIT2 ||
- (netstat[num].c_CLOSING >= netstat_limit.c_CLOSING ) && netstat_limit.c_CLOSING ||
- (netstat[num].c_CLOSE_WAIT >= netstat_limit.c_CLOSE_WAIT ) && netstat_limit.c_CLOSE_WAIT ||
- (netstat[num].c_LAST_ACK >= netstat_limit.c_LAST_ACK ) && netstat_limit.c_LAST_ACK
- )
- {
- if (comment_str)
- printf("%s ",comment_str);
- if (koef)
- printf("k=%d,",koef);
- printf("s=%d,%s ",sockCount,str_time);
- ad.s_addr=netstat[num].ip_for;
- ipstr = inet_ntoa(ad);
- printf("%-3d %-17s",netstat[num].count ,ipstr);
- if (netstat[num].c_SYN_RECV) printf(" sr=%d",netstat[num].c_SYN_RECV);
- if (netstat[num].c_SYN_SENT) printf(" ss=%d",netstat[num].c_SYN_SENT);
- if (netstat[num].c_ESTABLISHED) printf(" est=%d",netstat[num].c_ESTABLISHED);
- if (netstat[num].c_TIME_WAIT) printf(" tw=%d",netstat[num].c_TIME_WAIT);
- if (netstat[num].c_FIN_WAIT1) printf(" fw1=%d",netstat[num].c_FIN_WAIT1);
- if (netstat[num].c_FIN_WAIT2) printf(" fw2=%d",netstat[num].c_FIN_WAIT2);
- if (netstat[num].c_CLOSING) printf(" clo=%d",netstat[num].c_CLOSING);
- if (netstat[num].c_CLOSE_WAIT) printf(" clw=%d",netstat[num].c_CLOSE_WAIT);
- if (netstat[num].c_LAST_ACK) printf(" la=%d",netstat[num].c_LAST_ACK);
- printf("\n");
- ar_res_ip[print_counter]=netstat[num].ip_for;
- print_counter++;
- }
- }
- ar_res_ip[print_counter]=0;
- };
- ///////
- int chekState(char *s, struct netstat_t *netstat){
- //printf("chekState %s\n",s);
- if (strcmp(s,"SYN_RECV")==0) netstat->c_SYN_RECV++;
- else if (strcmp(s,"SYN_SENT")==0) netstat->c_SYN_SENT++;
- else if (strcmp(s,"ESTABLISHED")==0) netstat->c_ESTABLISHED++;
- else if (strcmp(s,"TIME_WAIT")==0) netstat->c_TIME_WAIT++;
- else if (strcmp(s,"FIN_WAIT1")==0) netstat->c_FIN_WAIT1++;
- else if (strcmp(s,"FIN_WAIT2")==0) netstat->c_FIN_WAIT2++;
- else if (strcmp(s,"CLOSING")==0) netstat->c_CLOSING++;
- else if (strcmp(s,"CLOSE_WAIT")==0) netstat->c_CLOSE_WAIT++;
- else if (strcmp(s,"LAST_ACK")==0) netstat->c_LAST_ACK++;
- // for freeBSD
- // В freeBSD состояния сокета называются по другиму
- else if (strcmp(s,"CLOSED")==0) netstat->c_CLOSING++; // CLOSING или CLOSE_WAIT ? Не известно чему соответсвует.
- else if (strcmp(s,"SYN_RCVD")==0) netstat->c_SYN_RECV++;
- else if (strcmp(s,"FIN_WAIT_1")==0) netstat->c_FIN_WAIT1++;
- else if (strcmp(s,"FIN_WAIT_2")==0) netstat->c_FIN_WAIT2++;
- else
- printf("no: %s\n",s);
- }
- ///////
- void set_all_netstat(netstat_t &n, int v){
- n.count=v;
- n.c_SYN_RECV=v;
- n.c_ESTABLISHED=v;
- n.c_TIME_WAIT=v;
- n.c_SYN_SENT=v;
- n.c_FIN_WAIT1=v;
- n.c_FIN_WAIT2=v;
- n.c_CLOSING=v;
- n.c_CLOSE_WAIT=v;
- n.c_LAST_ACK=v;
- }
- /////////
- //////
- int strToNetstat(
- char *s,
- int logLen,
- struct netstat_t *netstat,
- int *ar_banned_ip,
- int *ar_white_ip,
- int *ar_white_mask
- ){
- //printf("strToNetstat logLen=%d\n",logLen);
- char m[20][MAX_LEN_SUBSTR]; //массив для хранения 20 подстрок длиной MAX_LEN_SUBSTR разбитых по пробелу
- int k,ip;
- k=strBreak(s,m,0);//разбиваем строку по разделителю пробел
- if ((k!=7)&&(k!=6))
- return -1;
- ip=strIPportToIP(m[4]);
- if (ip==-1)
- return -1;
- if (inArray_z(ar_banned_ip, ip))
- return -2;
- if (inArray_ip_mask(
- ar_white_ip,
- ar_white_mask,
- ip) )
- return -2;
- ////////////////////
- for(k=0; k<logLen;k++)
- if (netstat[k].ip_for==ip)
- {
- netstat[k].count++;
- chekState(m[5],&netstat[k]);
- return 1;
- }
- netstat[logLen].ip_for=ip;
- set_all_netstat(netstat[logLen], 0);
- netstat[logLen].count=1;
- chekState(m[5],&netstat[logLen]);
- return 0;
- };
- /********************************************
- прочитать из файла logFileName статистику команды netstat
- ********************************************/
- int readNetstat(
- char *logFileName,
- netstat_t *netstat, //указатель на массив элеменов, каждый элемент содержит информацию о одном IP
- //IP не повторяются
- int &readCount, //сюда заносим количество строк в считываемом файле(количестов коннектов)
- sort_item *IPinfo, //массив для сортировки ip адресов по количеству повторений
- //каждый элемент содержит IP и количество повторений
- int *ar_banned_ip, //не считывем
- int showHeader,
- int *ar_white_ip, //эти ip не считываем по маске
- int *ar_white_mask, //
- char *comment_str //
- ){
- FILE *fp;
- char s[200],c,*ps;
- int IPcount=0,
- logError=0,
- strLoss=0,
- res,
- n=0,
- IPalreadyBanned=0;
- readCount=0;//общее количество коннектов или количество прочитанных строк
- if( (fp= fopen(logFileName,"r") ) ==NULL)
- { printf("Error %d: %s : %s\n",errno, logFileName, strerror(errno));
- return 0;
- }
- n=0; ps=s;
- while (!feof(fp))
- { c=fgetc(fp);
- if (c!=EOF)
- {
- if (c=='\n')
- {
- *ps=0;
- if (IPcount < MAX_LEN_NETSTAT)
- {
- // printf("%s\n",s);
- res=strToNetstat(
- s, //добавляемая строка
- IPcount, //количество уже добавленных IP
- netstat, //указатель на массив информации о статистике IP
- ar_banned_ip, //массив IP которые не читаем
- ar_white_ip, //массив IP которые не читаем по маске
- ar_white_mask
- );
- if (res==-1)//не верный формат строки лог файла
- { logError++;
- // if (logError<3)
- printf("ERR: %s\n",s);
- }
- else if (res==0)//формат верный и IP добавлен
- {
- readCount++;
- IPcount++;
- }
- else if (res==1)//формат верный, но IP уже был
- {
- readCount++;
- }
- else if (res==-2)
- {
- IPalreadyBanned++;
- }
- }else
- {
- strLoss=1; //Прочитанны не все строки, так как много строк
- break;
- }
- n=0; ps=s;
- }else
- {
- if (n<200)
- *ps++=c;
- n++;
- }
- }
- }
- fclose(fp);
- //////
- //заполняем массив IPinfo. Количество элементов в нем равно количеству элементов массива netstat
- //
- for (n=0;n<IPcount;n++)
- {
- IPinfo[n].sort_key=netstat[n].count;
- IPinfo[n].sort_data=n;
- }
- if (showHeader)
- {
- if (comment_str)
- printf("%s ",comment_str);
- printf("ReadCount:%d, IPcount=%d",readCount,IPcount);
- if (IPalreadyBanned)
- printf(",AllreadyBanAndWhite:%d",IPalreadyBanned);
- if (strLoss)
- printf("(Не все)");
- if (logError)
- printf("(Не распознанно=%d)",logError);
- printf("\n");
- }
- return IPcount;
- }
- int calc_hash(char *s){
- int res=0;
- int c=0;
- int i;
- while (*s)
- {
- i=(*s) -32 ;
- res+=i + c*128 ;
- s++;
- if (c>100)
- break;
- c++;
- }
- return res;
- }
- //////////////////////////////////////////////////
- /********************************************************
- разбирает одну строку лог файла и выделяет из нее данные
- если формат верный, то возвращает 0, если не верный -1.
- Если собираем лишь 1 IP адрес, формат строки верный, но это не тот IP адрес, то возвращаем -2
- Если превышен лимит количества возможных вариантов запроса MAX_REQWEST_COUNT, то возвращаем -3
- Данные помещаются
- в структуру oneHeat: ip, t-время, num_r - номер строки в таблице запросов
- добавляется строка в таблицуу запросов reqwest и reqv_info, если ее не было( при этом увеличиваем reqwest_c)
- *********************************************************/
- int strToOneHeat(
- char *s,
- struct oneHeat *oh,
- char (*reqwest) [MAX_REQWEST_COUNT][MAX_LEN_REQWEST], //массив вариантов запросов
- int reqwest_hash[MAX_REQWEST_COUNT],
- int referrer_hash[MAX_REFERRER_COUNT],
- int user_agent_hash[MAX_USER_AGENT_COUNT],
- struct sort_item reqv_info[], //массив с информацией о количестве каждого запроса
- int &reqwest_c, //количество элементов в таблице reqwest и reqv_info
- char (*referrer) [MAX_REFERRER_COUNT][MAX_REFERRER_LEN] ,//массив строк, в каждой строке один вариант реферрера(не повторяются)
- struct sort_item referrer_info[], //массив структур. номер строки из таблицы referrer и количетво повторов
- int &referrer_c, //количество строк в таблице referrer и referrer_info
- char (*user_agent) [MAX_USER_AGENT_COUNT][MAX_USER_AGENT_LEN] , //массив строк, в каждой строке один вариант юзер агента(юзер агенты не повторяются)
- struct sort_item user_agent_info[], //массив структур. номер строки из таблицы reqwest и количетво повторов
- int &user_agent_c, //количество строк в таблице user_agent
- int *ar_banned_ip, //массив ip которые считывать не нужно, заканчивается нулевым элементом
- int *ar_mask,
- int one_ip, //если собираем лишь 1 IP адрес, иначе 0
- int need_reqwest_info//заполняем таблицу reqwest
- ){
- //printf("s=%s\n",s);
- char m[20][MAX_LEN_SUBSTR]; //массив для хранения 20 подстрок длиной MAX_LEN_SUBSTR разбитых по пробелу
- int k;
- int new_hash;
- int str_is;//был ли этот запрос ранее
- in_addr ad; //структура для хранения IP адреса
- k=strBreak(s,m,1);//разбиваем строку по разделителю пробел
- if (k<10) //Не верный формат строки лог файла.
- {
- // printf("k=%d\n",k);
- return -1;
- }
- //printf("k=%d\n",k);
- if (inet_aton(m[0],&ad) ==0) //преобразуем строковый вормат IP адреса в 4-х байтовое целое
- {
- return -1; // если формат не верный выходим
- }
- oh->ip=ad.s_addr;
- if (inArray_ip_mask(ar_banned_ip,ar_mask, ad.s_addr))//если этот ip в списке уже забаненных
- return -2;
- if (one_ip && (one_ip != oh->ip) )//если мы собираем лишь 1 IP адрес и это не тот адрес
- return -2;
- if ((oh->t=strToTime(m[3])) ==-1)//преобразуем время из строки в число секунд начиная с 1970
- {
- return -1;
- }
- //if ( ( *m[5]=='-' ) && ( * (m[5] + 1)==0 ) ){
- // printf("408\n");
- // printf("%s\n",s);
- // return -408;
- //}
- if (!need_reqwest_info)//если ускоренный вариант, то не заполняем таблицу reqwest,referrer и user_agent
- {
- // oh->num_r=0;
- return 0;
- }
- oh->code_otv=atoi(m[6]);
- if (k==11)
- oh->cookie=atoi(m[10]);
- else
- oh->cookie=0;
- //printf("%s\n",m[9]);
- //уменьшаем длину строки запроса
- m[5][MAX_LEN_REQWEST-1]=0;
- //уменьшаем длину строки реферрера
- m[8][MAX_REFERRER_LEN-1]=0;
- //уменьшаем длину строки юзер агкента
- m[9][MAX_USER_AGENT_LEN-1]=0;
- str_is=0;
- new_hash=calc_hash(m[5]);
- for (k=0; k < reqwest_c; k++) //Ищем запрос в таблице запросов
- if (reqwest_hash[k] == new_hash)
- if ( !strcmp (m[5] , (*reqwest)[k] ) ) //если находим, то
- { oh->num_r=k; //записываем номер строки в таблице запросов
- reqv_info[k].sort_key++; //увеличиваем счеттчик количества таких запросов
- str_is=1;
- break;
- }
- if (!str_is)//если этого запроса еще не было то добавляем его
- {
- if (reqwest_c >= MAX_REQWEST_COUNT-1)
- return -1;
- reqv_info[reqwest_c].sort_key=1; //если в таблице запросов, такого нет, до добавляем его
- reqv_info[reqwest_c].sort_data=reqwest_c;
- strcpy((* reqwest)[reqwest_c], m[5]);
- reqwest_hash[reqwest_c]=new_hash;
- oh->num_r=reqwest_c;
- reqwest_c++;
- }
- //////////////////////////////
- str_is=0;
- new_hash=calc_hash(m[8]);
- for (k=0; k < referrer_c; k++) //Ищем referrer в таблице referrer
- if (referrer_hash[k] == new_hash)
- if ( !strcmp (m[8] , (*referrer)[k] ) ) //если находим, то
- { oh->num_ref=k; //записываем номер строки в таблице
- referrer_info[k].sort_key++; //увеличиваем счеттчик количества
- str_is=1;
- break;
- }
- if (!str_is)//если этого реферрера еще не было то добавляем его
- {
- if (referrer_c >= MAX_REFERRER_COUNT-1)
- return -1;
- referrer_info[referrer_c].sort_key=1; //если в таблице, такого нет, до добавляем его
- referrer_info[referrer_c].sort_data=referrer_c;
- strcpy((*referrer)[referrer_c], m[8]);
- referrer_hash[referrer_c]=new_hash;
- oh->num_ref=referrer_c;
- referrer_c++;
- }
- ////////////
- str_is=0;
- new_hash=calc_hash(m[9]);
- for (k=0; k < user_agent_c; k++) //Ищем юзер агент в таблице юзер агентов
- if (user_agent_hash[k] == new_hash)
- if ( !strcmp (m[9] , (*user_agent)[k] ) ) //если находим, то
- { oh->num_ua=k; //записываем номер строки в таблице юзер агентов
- user_agent_info[k].sort_key++; //увеличиваем счеттчик количества таких юзер агентов
- str_is=1;
- break;
- }
- if (!str_is)//если этого юзер агента еще не было то добавляем его
- {
- if (user_agent_c >= MAX_USER_AGENT_COUNT-1)
- return -1;
- user_agent_info[user_agent_c].sort_key=1; //если в таблице юзер агентов, такого нет, до добавляем его
- user_agent_info[user_agent_c].sort_data=user_agent_c;
- strcpy((*user_agent)[user_agent_c], m[9]);
- user_agent_hash[user_agent_c]=new_hash;
- oh->num_ua=user_agent_c;
- user_agent_c++;
- }
- return 0;
- }
- int calcClickLastMinute(
- int logLen,
- struct oneHeat *log){
- int n, t2=0, c=1;
- time_t last_time;
- if (logLen<3)
- return 0;
- //printf("logLen=%d\n",logLen);
- last_time=log[logLen-1].t;
- for(n=logLen-2;n>=0;n--)
- { t2=last_time-log[n].t;
- if (t2>60)
- break;
- c++;
- // printf("%d %d %d\n", n,log[n].code_otv, t2);
- }
- return c;
- }
- /*************************************************************************
- считываем лог файл
- **************************************************************************/
- int readLogFile(
- //входные данные
- char *logFileName, //имя лог файла
- //выходные данные
- struct oneHeat *log, //указатель на массив структур с информацией о каждой строке лог файла
- char (*reqwest) [MAX_REQWEST_COUNT][MAX_LEN_REQWEST],//таблица вариантов запросов, запросы не повторяются
- struct sort_item reqv_info[], //массив структур. номер строки из таблицы reqwest и количетво повторов
- int &reqwest_c, //количество строк в таблице reqwest, равное количеству элементов в массиве reqv_info
- int &countClickLastMinute,
- char (*referrer) [MAX_REFERRER_COUNT][MAX_REFERRER_LEN] , //массив строк, в каждой строке один вариант реферрера(реферреры не повторяются)
- struct sort_item referrer_info[], //массив структур. номер строки из таблицы referrer и количетво повторов
- int &referrer_c, //количество строк в таблице referrer
- char (*user_agent) [MAX_USER_AGENT_COUNT][MAX_USER_AGENT_LEN] , //массив строк, в каждой строке один вариант юзер агента(юзер агенты не повторяются)
- struct sort_item user_agent_info[], //массив структур. номер строки из таблицы reqwest и количетво повторов, этот массив заполняется при рпаботе этой функции
- int &user_agent_c, //количество строк в таблице user_agent
- int &len_time_sec, //длина лога в секундах
- //входные данные
- int *ar_banned_ip, //массив ip которые считывать не нужно, заканчивается нулевым элементом
- int *ar_mask, //массив масок для каждого IP из массива ar_banned_ip
- int one_ip, //если собираем лишь 1 IP адрес, иначе 0
- int verbose, //
- int showHeader, //
- int need_reqwest_info//заполняем таблицу reqwest и user_agent
- ){
- in_addr ad;
- char *ipstr;
- int reqwest_hash[MAX_REQWEST_COUNT];
- int referrer_hash[MAX_REFERRER_COUNT];
- int user_agent_hash[MAX_USER_AGENT_COUNT];
- int logLen=0, logError=0,strLoss=0, n=0, res , err_408=0;
- char s[MAX_LEN_STR+1],c,*ps;
- FILE *fp;
- if( (fp= fopen(logFileName,"r") ) ==NULL)
- {
- printf("Error %d: %s : %s\n",errno, logFileName, strerror(errno));
- return 0;
- }
- n=0; ps=s;
- while (!feof(fp))
- { c=fgetc(fp);
- if (c!=EOF)
- {
- if (c=='\n')
- {
- *ps=0;
- if (logLen < MAX_STR_LOG)
- {
- res=strToOneHeat( //функция для добавления одной строки из лог файла в массивы
- s, //добавляемая строка лог файла
- &log[logLen],
- reqwest, //массив вариантов запросов
- reqwest_hash, //
- referrer_hash,
- user_agent_hash,
- reqv_info, //массив с информацией о количестве каждого запроса
- reqwest_c, //Количество элементов в таблице reqwest и reqv_info
- // количество элементов массива reqv_info, равно количеству элементов массива reqwest
- referrer , //массив строк, в каждой строке один вариант реферрера(не повторяются)
- referrer_info,
- referrer_c, //количество строк в таблице referrer и referrer_info
- user_agent , //массив строк, в каждой строке один вариант юзер агента(юзер агенты не повторяются)
- user_agent_info,
- user_agent_c, //количество строк в таблице user_agent и user_agent_info
- ar_banned_ip,//массив ip которые считывать не нужно, заканчивается нулевым элементом
- ar_mask,
- one_ip, //если собираем лишь 1 IP адрес, иначе 0
- need_reqwest_info//заполняем таблицу reqwest
- );
- if (res==-1)//не верный формат строки лог файла
- { logError++;
- if (logError<3)
- printf("ERR: %s\n",s);
- }
- else if (res==-408)
- err_408++;
- else if (res==0)//формат верный и строка добавлена
- {
- log[logLen].len_str=strlen(s);
- logLen++;
- }
- }else
- {
- strLoss=1; //Прочитанны не все строки, так как много строк
- break;
- }
- n=0; ps=s;
- }else
- {
- if (n<MAX_LEN_STR)
- *ps++=c;
- n++;
- }
- }
- }
- fclose(fp);
- (*reqwest)[reqwest_c][0]=0;
- log[logLen].ip=0;
- if (logLen>2)
- len_time_sec=log[logLen-1].t-log[0].t;
- else
- len_time_sec=1;
- countClickLastMinute=calcClickLastMinute(logLen,log);
- if (verbose && showHeader)
- {
- printf("Read:%d,Cm=%d,urls:%d,ref=%d,ua=%d,",logLen,countClickLastMinute, reqwest_c,referrer_c,user_agent_c);
- if (one_ip)
- { ad.s_addr=one_ip;
- ipstr = inet_ntoa(ad);
- printf(" Один IP=%s",ipstr);
- }
- if (strLoss)
- printf("(Не все)");
- if (logError)
- printf("(Не распознанно=%d)",logError);
- if (err_408)
- printf("ERR408=%d,",err_408);
- char timeStr[20];
- myTimeToStr(&log[0].t, timeStr);
- printf(" t:%s",timeStr);
- if (logLen>2)
- {
- if (len_time_sec>3600*3)
- printf("-(%d h) ", (int ) len_time_sec/3600);
- else if (len_time_sec>60*3)
- printf("-(%d m) ", (int ) len_time_sec/60);
- else
- printf("-(%d s) ", (int ) len_time_sec);
- }
- printf("\n");
- // for (int k=0;k<30;k++)
- // printf("%d ",reqwest_hash[k]);
- }
- return logLen;
- }
- ///////////
- int readBadStrs(char *fileBadStrs,char bad_strs[][MAX_LEN_BAD_STR]){
- //printf("readBadStrs %s\n",fileBadStrs);
- char s[MAX_LEN_BAD_STR],c,*ps;
- int c_str=0,n;
- FILE *fp;
- if( (fp= fopen(fileBadStrs,"r") ) ==NULL)
- { printf("Error %d: %s : %s\n",errno, fileBadStrs, strerror(errno));
- return -1;
- }
- ps=s;
- while (!feof(fp))
- { c=fgetc(fp);
- if (c!=EOF)
- {
- if (c=='\n')
- {
- *ps=0;
- // printf("s=%s\n",s);
- if (c_str<MAX_COUNT_BAD_STR)
- strcpy(bad_strs[c_str++],s);
- n=0; ps=s;
- }else
- {
- if (n<MAX_LEN_BAD_STR)
- *ps++=c;
- n++;
- }
- }
- }
- fclose(fp);
- bad_strs[c_str][0]=0;
- return c_str;
- }
- /**************************************
- преобразование IP адреса с маской в тестовом формате в числовой
- возвращаем
- 1 - все нормально
- 0 - ошибка в ip адресе
- 2 - это строка слишком короткая, считаем комментарием
- ***************************************/
- int str2ip_mask(char *s,int &ip,int &mask){
- in_addr ad;
- char *p;
- mask=32;
- int lenStr=0;
- p=s;
- while(*p)//обрезаем комментарий по символу '#' или ' ', заменяея его на 0
- { lenStr++;
- if ( (*p=='#') || (*p==' '))
- { *p=0;
- break;
- }
- p++;
- }
- if (lenStr<5)//если строка слишком корроткая, то это строка комментаий
- return 2;
- p=s;
- while(*p)
- {
- if (*p=='/')
- {
- *p=0;
- p++;
- mask=atoi(p);
- if (mask>32)
- return 0;
- break;
- }
- p++;
- }
- //printf("%s \n",s);printf("%s \n",p);
- if (inet_aton(s,&ad) )
- { ip=ad.s_addr;
- return 1;
- }
- else
- return 0;
- }
- //////////////////////////////////////////////////////////////////////////
- //преобразует маску из числового формата в битовый формат //
- // /24 => 11111111.11111111.11111111.00000000 //
- //результат возвращается в сетевом порядке байт //
- //////////////////////////////////////////////////////////////////////////
- int maskNumToMaskNet(int mask){
- int t,k;
- t=0;
- mask=32-mask;
- for(k=0;k<mask;k++)
- { t=t<<1;
- t=t|1;
- }
- t=~htonl(t);
- return t;
- }
- /////////
- int readIPmask(
- char *file_name,
- int *ar_ip,
- int *ar_mask,
- int max_num_read
- ){
- char s[100],c,*ps;
- int c_ip=0,n=0,ip,mask, res;
- FILE *fp;
- if( (fp= fopen(file_name,"r") ) ==NULL)
- { printf("Error %d: %s : %s\n",errno, file_name, strerror(errno));
- return -1;
- }
- //printf("readBannedIP = %s\n",file_name);
- //in_addr ad;
- //char *ipstr;
- ps=s;
- while (!feof(fp))
- { c=fgetc(fp);
- if (c!=EOF)
- { if (c=='\n')
- { *ps=0;//поставить завершающий ноль в строку
- // printf("s=%s\n",s);
- res=str2ip_mask(s,ip,mask);
- if (res==1)
- { mask=maskNumToMaskNet(mask);
- ar_mask[c_ip]=mask;
- ar_ip[c_ip]=ip&mask;
- c_ip++;
- if (c_ip>= max_num_read)
- { printf("too many ip/mask\n");
- ar_ip[c_ip]=0;ar_mask[c_ip]=0;
- return c_ip;
- }
- }
- else if (res==0)
- printf("Error ip/mask: %s\n",s);
- n=0; ps=s;
- }else
- { if (n<100)
- *ps++=c;
- n++;
- }
- }
- }
- fclose(fp);
- *ps=0;//поставить завершающий ноль в строку
- //printf("last s=%s\n",s);
- res=str2ip_mask(s,ip,mask);
- if (res==1)
- { mask=maskNumToMaskNet(mask);
- ar_mask[c_ip]=mask;
- ar_ip[c_ip]=ip&mask;
- c_ip++;
- }
- ar_ip[c_ip]=0;ar_mask[c_ip]=0;
- return c_ip;
- }
- ///////////
- /*
- int readBannedIP(
- char *file_banned_ip,
- int *ar_banned_ip
- ){
- char s[100],c,*ps;
- int c_banned_ip=0, Error=0,n=0,ip;
- in_addr ad;
- FILE *fp;
- if( (fp= fopen(file_banned_ip,"r") ) ==NULL)
- { printf("Error %d: %s : %s\n",errno, file_banned_ip, strerror(errno));
- return -1;
- }
- //printf("readBannedIP = %s\n",file_banned_ip);
- ps=s;
- while (!feof(fp))
- { c=fgetc(fp);
- if (c!=EOF)
- {
- if (c=='\n')
- {
- *ps=0;
- // printf("s=%s\n",s);
- if (inet_aton(s,&ad) ) //преобразуем строковый вормат IP адреса в 4-х байтовое целое
- ar_banned_ip[c_banned_ip++]=ad.s_addr;
- n=0; ps=s;
- }else
- {
- if (n<100)
- *ps++=c;
- n++;
- }
- }
- }
- fclose(fp);
- ar_banned_ip[c_banned_ip]=0;
- return c_banned_ip;
- }
- */
- //////////////
- void print_ar(int *ar){
- in_addr ad;
- char *ipstr;
- while(*ar)
- {
- ad.s_addr=*ar++;
- ipstr = inet_ntoa(ad);
- printf("%s\n",ipstr);
- }
- }
- //////////////
- void print_ar_ar(int *ar,int *ar2){
- in_addr ad;
- char *ipstr;
- while(*ar)
- {
- ad.s_addr=*ar++;
- ipstr = inet_ntoa(ad);
- printf("%s",ipstr);
- ad.s_addr=*ar2++;
- ipstr = inet_ntoa(ad);
- printf("/%s",ipstr);
- printf("\n");
- }
- }
- void print_ar_to_file(int count, int *ar, char *file_name){
- in_addr ad;
- char *ipstr;
- FILE *fp;
- if( (fp= fopen(file_name,"w") ) ==NULL)
- { printf("Error %d: %s : %s\n",errno,file_name, strerror(errno));
- return ;
- }
- //printf("count2=%d\n",count);
- while (*ar)
- {
- ad.s_addr=*ar++;
- ipstr = inet_ntoa(ad);
- fputs(ipstr,fp);
- /*
- if (count>2000)
- fputs("/16",fp);
- else if (count>1000)
- fputs("/24",fp);
- */
- fputc('\n',fp);
- }
- fclose(fp);
- }
- int findBad_str(
- char (*reqwest) [MAX_REQWEST_COUNT][MAX_LEN_REQWEST],
- char bad_strs[][MAX_LEN_BAD_STR],
- struct oneHeat *log,
- int *ar_res_ip,
- int &c_ddos_ip,
- int *ar_white_ip,
- int *ar_white_mask
- ){
- int n,n2,n3;
- in_addr ad;
- char *ipstr, timeStr[20];
- //printf("findBad_str limit_count=%d\n",limit_count);
- n=0;
- while( (*reqwest) [n] [0] )//перебераем все строки вариантов запроса
- {
- n2=0;
- while(bad_strs[n2] [0])//перебераем весь черный список
- {
- if (strcasestr( (*reqwest)[n] , bad_strs[n2]))//если строка из черного списка совподает с одной из строк запроса
- if (!strcasestr((*reqwest)[n] , "?find=" ) )//если в строке запроса нет подстроки
- {
- n3=0;
- while(log[n3].ip)//перебераем весь исходный лог в поисках строк с этим запросом
- {
- if (log[n3].num_r==n)//если нашли строку с плохим запросом
- if (!inArray_ip_mask( ar_white_ip, ar_white_mask, log[n3].ip) )
- if (!inArray(c_ddos_ip, ar_res_ip,log[n3].ip) )
- {
- ad.s_addr=log[n3].ip;
- ipstr = inet_ntoa(ad);
- myTimeToStr(&log[n3].t,timeStr);
- printf("BadStr:%s,%s %s %s\n",bad_strs[n2],ipstr, timeStr, (*reqwest)[n]);
- ar_res_ip[c_ddos_ip++]=log[n3].ip;
- }
- n3++;
- }
- }
- n2++;
- }
- n++;
- }
- ar_res_ip[c_ddos_ip]=0;
- return 0;
- }
- //////////
- int read_one_netstat_limit(char *s, netstat_t &netstat_limit){
- //printf("read_one_netstat_limit:%s\n",s);
- int n=0,n_val=0,v;
- char com[10],val[10];
- while(s[n] && (s[n]!='=') )
- { com[n]=s[n]; n++;
- }
- com[n]=0;
- n++;//пропуск =
- while(s[n] )
- { val[n_val]=s[n]; n_val++; n++;
- }
- val[n_val]=0;
- v=atoi(val);
- if (v<=0)
- return 0;
- if (strcmp(com,"all")==0)
- set_all_netstat(netstat_limit,v);
- else if (strcmp(com,"c")==0)
- netstat_limit.count=v;
- else if (strcmp(com,"sr")==0)
- netstat_limit.c_SYN_RECV=v;
- else if (strcmp(com,"est")==0)
- netstat_limit.c_ESTABLISHED=v;
- else if (strcmp(com,"tw")==0)
- netstat_limit.c_TIME_WAIT=v;
- else if (strcmp(com,"ss")==0)
- netstat_limit.c_SYN_SENT=v;
- else if (strcmp(com,"fw1")==0)
- netstat_limit.c_FIN_WAIT1=v;
- else if (strcmp(com,"fw2")==0)
- netstat_limit.c_FIN_WAIT2=v;
- else if (strcmp(com,"clo")==0)
- netstat_limit.c_CLOSING=v;
- else if (strcmp(com,"clw")==0)
- netstat_limit.c_CLOSE_WAIT=v;
- else if (strcmp(com,"la")==0)
- netstat_limit.c_LAST_ACK=v;
- else
- return 0;
- return 1;
- }
- //////////
- void printNS(struct netstat_t n){
- printf("count=%d\n",n.count);
- printf("c_SYN_RECV=%d\n",n.c_SYN_RECV);
- printf("c_ESTABLISHED=%d\n",n.c_ESTABLISHED);
- printf("c_TIME_WAIT=%d\n",n.c_TIME_WAIT);
- printf("c_SYN_SENT=%d\n",n.c_SYN_SENT);
- printf("c_FIN_WAIT1=%d\n",n.c_FIN_WAIT1);
- printf("c_FIN_WAIT2=%d\n",n.c_FIN_WAIT2);
- printf("c_CLOSING=%d\n",n.c_CLOSING);
- printf("c_CLOSE_WAIT=%d\n",n.c_CLOSE_WAIT);
- printf("c_LAST_ACK=%d\n",n.c_LAST_ACK);
- }
- //////////
- /////////
- int read_netstat_limit(char *s,netstat_t &netstat_limit){
- char *first,*f2;
- char *sub_string,*s2;
- set_all_netstat(netstat_limit,0);
- //printf("read_netstat_limit:%s\n",s);
- first=strtok(s,",");
- if (!read_one_netstat_limit(first, netstat_limit))
- return 0;
- //printf("first:%s\n",first);
- while ( (sub_string=strtok(NULL, ",")) != NULL)
- if (!read_one_netstat_limit(sub_string, netstat_limit))
- return 0;
- return 1;
- }
- int read_par_int(
- int n,
- char *argv[],
- int argc,
- char command,
- int num_par,
- struct command ar_command[],
- int &c_command){
- int i;
- /*printf("n=%d\n",n);
- printf("argc=%d\n",argc);
- printf("command=%c\n",command);
- printf("num_par=%d\n",num_par);
- printf("c_command=%d\n",c_command);
- printf("argc-n-2=%d\n",argc-n-2);*/
- ar_command[c_command].command=command;
- if (argc-n-2<num_par)
- {
- printf("Мало параметров у команды %c(%d) Должно быть=%d. argc=%d\n",command,n,num_par,argc);
- return 1;
- }
- for (i=0;i<num_par;i++)
- {
- // printf("i=%d\n, n+i+1=%d \n",i, n+i+1);
- if (*(argv[n+i+1])=='-')
- {
- printf("Мало параметров (-) у команды %c(%d) Должно быть=%d. argc=%d\n",command,n,num_par,argc);
- return 1;
- }
- ar_command[c_command].par[i]=atoi(argv[n+i+1]);
- if (!ar_command[c_command].par[i])
- {
- printf("Не удалось преобразовать параметр %s в целое число у команды %c(%d) Должно быть=%d. argc=%d\n",
- argv[n+i+1],command,n,num_par,argc);
- return 1;
- }
- }
- c_command++;
- return 0;
- }
- /***********************************************************************************
- подсчитать количество разных ip адресов и разных запросов для юзерагента номер id_user_agent
- ***********************************************************************************/
- int calcCountForUA(
- int logLen, //количество элементов в массиве log
- struct oneHeat *log, //массив типа oneHeat с информацией о одной строке лог файла
- int id_user_agent, //номер юзер агента для которого считаем количество ip
- int &count_ip, //счетчик количества найденных ip для этого юзер агента
- int &count_r, //счетчик количества найденных запросов для этого юзер агента
- int &count_ref
- ){
- int n, //счетчик цикла
- ar_ip[MAX_STR_LOG], //массив уже найденных ip для юзер агента
- ar_r[MAX_REQWEST_COUNT], //массив уже найденных запросов для юзер агента
- ar_ref[MAX_REFERRER_COUNT];
- count_ip=0;count_r=0;count_ref=0;
- for(n=0;n<logLen;n++) //пробегаем по всем строкам лог файла
- if (log[n].num_ua == id_user_agent) //если в лог файле нашли запрос с нужным юзер агентом
- {
- if (!inArray(count_ip, ar_ip, log[n].ip )) //если запроса с этим ip еще не было
- ar_ip[count_ip++]=log[n].ip; //то добавляем этот запрос в массив ar_int и увеличиваем количество элементов в массиве
- if (!inArray(count_r, ar_r, log[n].num_r )) //если запроса этого еще не было
- ar_r[count_r++]=log[n].num_r; //то добавляем этот запрос в массив ar_int и увеличиваем количество элементов в массиве
- if (!inArray(count_ref, ar_ref, log[n].num_ref )) //
- ar_ref[count_ref++]=log[n].num_ref; //
- }
- }
- /***********************************************************************************
- подсчитать количество разных ip адресов,разных запросов и юзер агентов для реферрера
- ***********************************************************************************/
- int calcCountForRef(
- int logLen, //количество элементов в массиве log
- struct oneHeat *log, //массив типа oneHeat с информацией о одной строке лог файла
- int id_referrer, //номер юзер агента для которого считаем количество ip
- int &count_ip, //счетчик количества найденных ip для этого юзер агента
- int &count_r, //счетчик количества найденных запросов для этого юзер агента
- int &count_ua
- ){
- int n, //счетчик цикла
- ar_ip[MAX_STR_LOG], //массив уже найденных ip для referrer
- ar_r[MAX_REQWEST_COUNT], //массив уже найденных запросов для referrer
- ar_ua[MAX_USER_AGENT_COUNT];
- count_ip=0;
- count_r=0;
- count_ua=0;
- for(n=0;n<logLen;n++) //пробегаем по всем строкам лог файла
- if (log[n].num_ref == id_referrer) //если в лог файле нашли запрос с нужным referrer
- {
- if (!inArray(count_ip, ar_ip, log[n].ip )) //если запроса с этим ip еще не было
- ar_ip[count_ip++]=log[n].ip; //то добавляем этот запрос в массив ar_int и увеличиваем количество элементов в массиве
- if (!inArray(count_r, ar_r, log[n].num_r )) //если запроса этого еще не было
- ar_r[count_r++]=log[n].num_r; //то добавляем этот запрос в массив ar_int и увеличиваем количество элементов в массиве
- if (!inArray(count_ua, ar_ua, log[n].num_ua )) //если запроса этого еще не было
- ar_ua[count_ua++]=log[n].num_ua; //то добавляем этот запрос в массив ar_int и увеличиваем количество элементов в массиве
- }
- }
- ///////////////////////
- void printUserAgent(
- int logLen, //количество элементов в массиве log
- struct oneHeat *log,//массив типа oneHeat с информацией о одной строке лог файла
- char (*user_agent) [MAX_USER_AGENT_COUNT][MAX_USER_AGENT_LEN],
- struct sort_item user_agent_info[],
- int user_agent_c,
- int c_print
- ){
- printf(" * TOP useragents=%d *\n",user_agent_c);
- printf("c ip url ref ua\n");
- int n,count_ip,count_r,count_ref;
- for(n=0;n<user_agent_c;n++)
- {
- if (n>=c_print)
- {
- printf("%d of %d\n",c_print,user_agent_c);
- return;
- }
- calcCountForUA(
- logLen,log,
- user_agent_info[n].sort_data,
- count_ip,
- count_r,
- count_ref);
- printf("%-4d %-3d %-4d %-4d %s\n",
- user_agent_info[n].sort_key,
- count_ip,
- count_r,
- count_ref,
- (*user_agent) [ user_agent_info[n].sort_data ]);
- }
- }
- ////////////////////////////////////
- void printReferrer(
- int logLen, //количество элементов в массиве log
- struct oneHeat *log,//массив типа oneHeat с информацией о одной строке лог файла
- char (*referrer) [MAX_REFERRER_COUNT][MAX_REFERRER_LEN],
- struct sort_item referrer_info[],
- int referrer_c,
- int c_print
- ){
- printf(" * TOP referrer=%d *\n",referrer_c);
- printf("c ip url ua ref\n");
- int n,count_ip,count_r, count_ua;
- for(n=0;n<referrer_c;n++)
- {
- if (n>=c_print)
- {
- printf("%d of %d\n",c_print,referrer_c);
- return;
- }
- calcCountForRef(
- logLen,log,
- referrer_info[n].sort_data,
- count_ip,
- count_r,
- count_ua);
- printf("%-4d %-3d %-4d %-4d %s\n",
- referrer_info[n].sort_key,
- count_ip,
- count_r,
- count_ua,
- (*referrer)[ referrer_info[n].sort_data ]);
- }
- }
- int calcPopravku(
- int countClickLastMinute,
- int c_click,
- int koef,
- int mode,
- char *comment_str
- ){
- time_t timer1;
- char str_time[30];
- if (mode==2)
- { if (countClickLastMinute> c_click)
- {
- time(&timer1);
- myTimeToStr(&timer1,str_time);
- if (comment_str)
- printf("%s ",comment_str);
- printf("Get lim %d (%d)-%s\n", c_click, countClickLastMinute, str_time);
- return koef;
- }
- else
- return 0;
- }else{
- if (countClickLastMinute< c_click)
- return koef;
- else
- return 0;
- }
- }
- void make_file_next_count(
- int logLen,
- int len_time_sec,
- int need_len_time_sec,
- int min_logLen,
- char *file_name){
- /*
- printf("logLen=%d\n",logLen);
- printf("len_time_sec=%d\n",len_time_sec);
- printf("need_len_time_sec=%d\n",need_len_time_sec);
- printf("min_logLen=%d\n",min_logLen);
- printf("file_name=%s\n",file_name);
- */
- FILE *fp;
- char str[40];
- int res;
- if( (fp= fopen(file_name,"w") ) ==NULL)
- { printf("Error %d: %s : %s\n",errno,file_name, strerror(errno));
- return ;
- }
- if (len_time_sec <=0 )
- len_time_sec=1;
- res=need_len_time_sec*logLen / len_time_sec;
- if (res<min_logLen)
- res=min_logLen;
- if (res>50000)
- res=50000;
- sprintf(str,"%d",res);
- fputs(str,fp);
- //fputc('\n',fp);
- fclose(fp);
- }
- //////////////////////////////////////////////////////////////////////////////////////////
- // Cтартовая функция main //
- //////////////////////////////////////////////////////////////////////////////////////////
- int main(int argc,char *argv[]){
- time_t time_start=0,time_finish;
- //time(&time_start);
- int one_ip=0;
- struct command ar_command[100];
- int c_command=0;
- char
- *file_banned_ip=0,
- *file_white_ip=0,
- *file_ip_res=0,
- *file_next_count=0;
- char *comment_str=0;
- char bad_strs[MAX_COUNT_BAD_STR][MAX_LEN_BAD_STR];
- *bad_strs[0]=0;
- int show_banned_ip;
- int c_banned_ip=0, c_white_ipm=0;
- int koef=0;
- int countClickLastMinute;
- int ar_white_ip [MAX_COUNT_WHITE_IP];
- int ar_white_mask[MAX_COUNT_WHITE_IP];
- int ar_int[MAX_STR_LOG+1], //в нем сначала хранится список уже забаненных ip, потом туда добавляются найденные IP для бана
- ar_mask[MAX_STR_LOG+1],
- c_ddos_ip=0;
- int verbose=1, showHeader=1,
- do_netstat=0;
- struct oneHeat *log;
- struct netstat_t *netstat;
- struct netstat_t netstat_limit;
- int need_reqwest_info=0;//нужна ли таблица reqwest
- int len_time_sec;//длина лога в секундах
- int err=0;//наличие ошибки
- int c_print=35;//сколько строк результата выводить на экран
- int logLen, n;
- //Количество элементов в таблице reqwest и reqv_info
- // количество элементов массива reqv_info, равно количеству элементов массива reqwest
- char (*reqwest) [MAX_REQWEST_COUNT][MAX_LEN_REQWEST];//массив строк для хранения вариантов запросов
- char (*referrer) [MAX_REFERRER_COUNT][MAX_REFERRER_LEN]; //массив строк для хранения вариантов реффереров
- int referrer_c=0;
- char (*user_agent) [MAX_USER_AGENT_COUNT][MAX_USER_AGENT_LEN]; //массив строк для хранения вариантов юзер агентов
- int user_agent_c=0;
- //char reqwest [MAX_REQWEST_COUNT+1][MAX_LEN_REQWEST];
- //массив элементов с информацией о количесве повторов каждого варианта запроса
- int reqwest_c=0;
- // reqv_info[].sort_data; номер элемента в таблице reqwest
- // reqv_info[].sort_key; количество запросов
- struct sort_item *reqv_info;
- struct sort_item *ipInfo;
- struct sort_item *user_agent_info;
- struct sort_item *referrer_info;
- int countIpInfo=0;
- //printf("argc=%d\n",argc);
- if ((argc==2) && (*(argv[1])=='-' ) && (*(argv[1]+1)=='v' ) )
- { printf("%d\n", VERS_PROG);
- // return 0;
- exit(0);
- }
- if (argc<=2)
- { printf("Too few params=%d\n",argc);
- exit(1);
- }
- //////////
- for(n=1;n<argc-1;n++)
- {
- if (*argv[n]=='-')
- {
- switch(*(argv[n]+1) ){
- case 'i': //топ IP
- ar_command[c_command++].command='i';
- need_reqwest_info=1;
- break;
- case 'I': //топ IP
- ar_command[c_command++].command='I';
- need_reqwest_info=1;
- break;
- case 'h': //
- need_reqwest_info=1;
- err=read_par_int(n,argv,argc,'h', 3,ar_command,c_command);
- break;
- case 'y'://статистика по кодам ответа
- ar_command[c_command++].command='y';
- need_reqwest_info=1;
- break;
- case 'm'://найти ip адреса превышающие количество повторов
- err=read_par_int(n,argv,argc,'m', 4,ar_command,c_command);
- need_reqwest_info=1;
- break;
- case 'c'://комментарий
- if ( (argc-n-2>=1) &&
- (*(argv[n+1])!='-')
- )
- comment_str=argv[n+1];
- else
- err=1;
- break;
- case 'n':
- do_netstat=1;
- if ( (argc-n-2>=1) &&
- (*(argv[n+1])!='-')
- )
- {
- if (!read_netstat_limit(argv[n+1], netstat_limit))
- err=1;
- }else
- err=1;
- break;
- case 'g':
- time_start=1;
- break;
- case 'a'://все отчеты
- need_reqwest_info=1;
- ar_command[c_command++].command='i';
- ar_command[c_command++].command='u';
- ar_command[c_command++].command='y';
- ar_command[c_command++].command='e';
- ar_command[c_command++].command='U';
- c_print=20;
- break;
- case 'x':
- need_reqwest_info=1;
- err=read_par_int(n,argv,argc,'x', 2,ar_command,c_command);
- break;
- case 'A'://
- need_reqwest_info=1;
- err=read_par_int(n,argv,argc,'A', 3,ar_command,c_command);
- break;
- case 'r'://
- need_reqwest_info=1;
- err=read_par_int(n,argv,argc,'r', 2,ar_command,c_command);
- break;
- case 'R'://
- need_reqwest_info=1;
- err=read_par_int(n,argv,argc,'R', 4,ar_command,c_command);
- break;
- case 'u'://топ запросов
- need_reqwest_info=1;
- ar_command[c_command++].command='u';
- break;
- case 'U'://топ по user agent
- need_reqwest_info=1;
- ar_command[c_command++].command='U';
- break;
- case 'e'://статистика по реферрерам
- need_reqwest_info=1;
- ar_command[c_command++].command='e';
- break;
- case 's'://длинные запросы
- need_reqwest_info=1;
- err=read_par_int(n,argv,argc,'s', 3,ar_command,c_command);
- break;
- case 'z'://поиск ботов работающих без пауз
- need_reqwest_info=1;
- err=read_par_int(n,argv,argc,'z', 2,ar_command,c_command);
- break;
- case 'l'://показать исходный лог
- need_reqwest_info=1;
- ar_command[c_command++].command='l';break;
- case 't'://плохие слова в запросе
- need_reqwest_info=1;
- ar_command[c_command].command='t';
- if ( (argc-n-2>=1) &&
- (*(argv[n+1])!='-')
- )
- readBadStrs(argv[n+1],bad_strs);
- else
- err=1;
- c_command++;
- break;
- case 'j'://вычислить количество строк лог файла для следующего анализа
- if ( (argc-n-2>=3) && (*(argv[n+3])!='-') ){
- file_next_count=argv[n+3];
- err=read_par_int(n,argv,argc,'j', 2,ar_command,c_command);
- }
- else
- err=1;
- break;
- case 'f'://сохранение в файл
- if ( (argc-n-2>=1) && (*(argv[n+1])!='-') )
- file_ip_res=argv[n+1];
- else
- err=1;
- break;
- case 'b'://список уже забаненных
- if ( (argc-n-2>=1) && (*(argv[n+1])!='-') )
- file_banned_ip=argv[n+1];
- else
- err=1;
- show_banned_ip=0;
- break;
- case 'w'://список белых IP и подсетей
- if ( (argc-n-2>=1) && (*(argv[n+1])!='-') )
- file_white_ip=argv[n+1];
- else
- err=1;
- break;
- case 'B'://список уже забаненных
- if ( (argc-n-2>=1) && (*(argv[n+1])!='-') )
- file_banned_ip=argv[n+1];
- else
- err=1;
- show_banned_ip=1;
- break;
- case 'o'://один IP
- need_reqwest_info=1;
- if ( (argc-n-2>=1) && (*(argv[n+1])!='-') )
- {
- in_addr ad; //структура для хранения IP адреса
- if (inet_aton(argv[n+1],&ad) ==0) //преобразуем строковый вормат IP адреса в 4-х байтовое целое
- { err=1; // если формат IP не верный
- printf("Не верный IP адрес %s\n\n",argv[n+1]);
- }
- one_ip=ad.s_addr;
- }
- else
- err=1;
- break;
- case 'q': verbose=0; break;
- case 'k': showHeader=0; break;
- case 'p':
- if ( (argc-n-2>=1) && (*(argv[n+1])!='-') )
- c_print=atoi(argv[n+1]);
- else
- err=1;
- if (!c_print)
- err=1;
- break;
- default: printHelp();return 0;
- }
- }
- }
- ar_command[c_command].command=0;//поставить 0 после последней комманды
- if (time_start==1)
- time(&time_start);
- if ( err ||
- !c_command ||
- (*(argv[ argc -1 ]) == '-')
- )
- {
- printf("Error.\n");
- //printHelp();
- exit(1);
- }
- if (file_banned_ip)
- {
- c_banned_ip=readIPmask(
- file_banned_ip,
- ar_int,
- ar_mask,
- 100000);
- if (c_banned_ip== -1)
- return 0;
- if (showHeader)
- printf("B:%d.",c_banned_ip);
- if (show_banned_ip)
- {
- printf("\n");
- print_ar_ar(ar_int,ar_mask);
- }
- }
- ar_white_ip[0]=0;
- ar_white_mask[0]=0;
- if (file_white_ip)
- {
- c_white_ipm=readIPmask(
- file_white_ip,
- ar_white_ip,
- ar_white_mask,
- MAX_COUNT_WHITE_IP);
- // printf("white ip\n");
- // print_ar(ar_white_ip);
- // printf("white mask\n");
- // print_ar(ar_white_mask);
- }
- ///////////
- if (do_netstat)
- {
- netstat= (netstat_t *) malloc(MAX_LEN_NETSTAT * sizeof(netstat_t) );
- if (!netstat) { printf("Память не выделена. 1\n\n\n");exit(1);}
- ipInfo = (sort_item *) malloc((MAX_LEN_NETSTAT+1)* sizeof(sort_item) ) ;
- if (!ipInfo) {printf("Память не выделена. 2\n\n\n");free(netstat);exit(1);}
- logLen=readNetstat(
- argv[ argc -1 ],
- netstat,
- countClickLastMinute, //сюда заносим количество строк в считываемом файле(количестов коннектов)
- ipInfo, //массив для сортировки ip адресов по количеству повторений
- ar_int,//массив ранее забаненных IP
- showHeader,
- ar_white_ip,
- ar_white_mask,
- comment_str);
- }
- else
- {
- log= (oneHeat *) malloc((MAX_STR_LOG+1)* sizeof(oneHeat) );
- if (!log)
- { printf("Память для log выделена.\n\n\n");
- exit(1);
- }
- reqwest= (char (*) [MAX_REQWEST_COUNT][MAX_LEN_REQWEST] ) malloc( sizeof( char [MAX_REQWEST_COUNT][MAX_LEN_REQWEST] ) );
- if (!reqwest)
- { printf("Память для reqwest выделена.\n\n\n");
- free(log);
- exit(1);
- }
- referrer= (char (*) [MAX_REFERRER_COUNT][MAX_REFERRER_LEN] ) malloc( sizeof( char [MAX_REFERRER_COUNT][MAX_REFERRER_LEN] ) );
- if (!reqwest)
- { printf("Память для referrer выделена.\n\n\n");
- free(log);
- free(reqwest);
- exit(1);
- }
- user_agent= (char (*) [MAX_USER_AGENT_COUNT][MAX_USER_AGENT_LEN] ) malloc( sizeof( char [MAX_USER_AGENT_COUNT][MAX_USER_AGENT_LEN] ) );
- if (!reqwest)
- { printf("Память для user_agent выделена.\n\n\n");
- free(log);
- free(reqwest);
- free(referrer);
- exit(1);
- }
- ipInfo = (sort_item *) malloc((MAX_STR_LOG+1)* sizeof(sort_item) ) ;
- if (!ipInfo)
- { printf("Память не выделена. 4\n\n\n");
- free(log);
- free(reqwest);
- free(referrer);
- free(user_agent);
- exit(1);
- }
- reqv_info = (sort_item *) malloc((MAX_REQWEST_COUNT+1)* sizeof(sort_item) ) ;
- if (!reqv_info)
- { printf("Память не выделена. 2\n\n\n");
- free(log);
- free(reqwest);
- free(referrer);
- free(user_agent);
- free(ipInfo);
- exit(1);
- }
- referrer_info = (sort_item *) malloc((MAX_REFERRER_COUNT+1)* sizeof(sort_item) ) ;
- if (!referrer_info)
- { printf("Память не выделена. 3\n\n\n");
- free(log);
- free(reqwest);
- free(referrer);
- free(user_agent);
- free(ipInfo);
- free(reqv_info);
- exit(1);
- }
- user_agent_info = (sort_item *) malloc((MAX_USER_AGENT_COUNT+1)* sizeof(sort_item) ) ;
- if (!user_agent_info)
- { printf("Память не выделена. 3\n\n\n");
- free(log);
- free(reqwest);
- free(referrer);
- free(user_agent);
- free(ipInfo);
- free(reqv_info);
- free(referrer_info);
- exit(1);
- }
- if (time_start)
- {
- time(&time_finish);
- unsigned int time_work=time_finish - time_start;
- printf("Начало рабты =%d сек.\n", time_work);
- }
- logLen=readLogFile(
- argv[ argc -1 ],//имя читаемого лог файла
- log, //массив структур куда сохраняем прочитанную информацию о каждой строке запроса
- reqwest, //массив строк, в каждой строке один вариант запроса(запросы не повторяются)
- reqv_info, //массив структур. в каждой структуре номер запроса из таблицы reqwest и количество повторов
- //нужно для дальнейшей сортировки по количеству повторов
- reqwest_c, //количество строк в таблице reqwest, равное количеству строк в таблие reqv_info
- countClickLastMinute,
- referrer, //массив строк, в каждой строке один вариант реферрера(не повторяются)
- referrer_info, //массив структур. в каждой структуре номер запроса из таблицы referrer и количество повторов
- //нужно для дальнейшей сортировки по количеству повторов реферрера
- referrer_c, //количество строк в таблице referrer и referrer_info
- //этот массив заполняется при рпаботе этой функции
- user_agent, //массив строк, в каждой строке один вариант юзер агента(юзер агенты не повторяются)
- user_agent_info,//массив структур. в каждой структуре номер запроса из таблицы user_agent и количество повторов
- //нужно для дальнейшей сортировки по количеству повторов юзер агентов
- // этот массив заполняется при рпаботе этой функции
- user_agent_c, //количество строк в таблице user_agent и user_agent_info
- len_time_sec, //длина лога в секундах
- ar_int, //массив уже забаненных ip, заканчивающийся нулевым элементом. Их не считываем.
- ar_mask, //массив масок для каждого IP из массива ar_int
- one_ip, //если считываем только 1 ip, иначе 0
- verbose, //
- showHeader,
- need_reqwest_info//заполняем таблицу reqwest
- );
- }
- if (time_start)
- {
- time(&time_finish);
- unsigned int time_work=time_finish - time_start;
- printf("Построены индексы=%d сек.\n", time_work);
- }
- ar_int[0]=0;//обнулить массив, так как до этого в нем был список уже забаненных, а теперь будет список новых забаненных
- if ( (logLen>2) || ((logLen>0) && do_netstat) )
- {
- // printf("c_command=%d\n",c_command);
- for (int num_command=0;num_command<c_command;num_command++)
- switch (ar_command[num_command].command){
- case 'i':
- if (do_netstat)
- {
- hoar_sort(logLen,ipInfo);
- printNetstat(
- logLen, //количество разных IP в команде netstat
- netstat, //статистика по каждому IP
- countClickLastMinute,//количество строк прочитанное из файла(количество сокетов)
- koef,
- ipInfo, //отсортированный по количеству массив ip адресов
- c_print, //сколько IP выводим на экран
- ar_int, //массив найденных IP заканчиваюзиеся нулевым элементом
- netstat_limit,//структура с информацией по лимитам на каждое состояние
- comment_str);//
- // printNS(netstat_limit);
- }else
- {
- countIpInfo= //количество разных ip(длина мкассива ipInfo)
- makeIpInfo( //создание массива ipInfo
- logLen, //количество элементов в массиве log
- log, //массив типа oneHeat с информацией о одной строке лог файла
- ipInfo);//указатель на массив элементов типа sort_item, для дальнейшей сортировки IP по количеству повторений
- hoar_sort(countIpInfo,ipInfo);//сортировка массива ipInfo по количеству повторений ip
- showIpInfo( //
- countIpInfo,//
- ipInfo, //
- logLen, //
- log, //
- reqwest, //
- user_agent, //
- verbose, //
- c_print,
- 0); //
- };
- break;
- case 'I':
- countIpInfo= //количество разных ip(длина мкассива ipInfo)
- makeIpInfo( //создание массива ipInfo
- logLen, //количество элементов в массиве log
- log, //массив типа oneHeat с информацией о одной строке лог файла
- ipInfo);//указатель на массив элементов типа sort_item, для дальнейшей сортировки IP по количеству повторений
- hoar_sort(countIpInfo,ipInfo);//сортировка массива ipInfo по количеству повторений ip
- showIpInfo( //
- countIpInfo,//
- ipInfo, //
- logLen, //
- log, //
- reqwest, //
- user_agent, //
- verbose, //
- c_print,
- 1); //
- break;
- case 'y':
- countIpInfo= //количество разных ip(длина мкассива ipInfo)
- makeCodeInfo( //создание массива ipInfo
- logLen, //количество элементов в массиве log
- log, //массив типа oneHeat с информацией о одной строке лог файла
- ipInfo);//указатель на массив типа sort_item, для дальнейшей сортировки IP по количеству повторений
- hoar_sort(countIpInfo,ipInfo);//сортировка массива ipInfo по количеству повторений ip
- showCodeInfo( //
- countIpInfo,//
- ipInfo, //
- logLen, //
- log, //
- reqwest, //
- c_print); //
- break;
- case 'j':
- make_file_next_count(
- logLen,
- len_time_sec,
- ar_command[num_command].par[0],
- ar_command[num_command].par[1],
- file_next_count);
- break;
- case 'U':
- hoar_sort(user_agent_c,user_agent_info);//сортировка массива user_agent_info по количеству повторений
- printUserAgent(
- logLen, //количество элементов в массиве log
- log, //массив типа oneHeat с информацией о одной строке лог файла
- user_agent,
- user_agent_info,
- user_agent_c,
- c_print
- );
- break;
- case 'e':
- hoar_sort(referrer_c,referrer_info);//сортировка массива referrer_info по количеству повторений
- printReferrer(
- logLen, //количество элементов в массиве log
- log, //массив типа oneHeat с информацией о одной строке лог файла
- referrer,
- referrer_info,
- referrer_c,
- c_print
- );
- break;
- case 'l':
- showOneHeat(logLen, log, reqwest, one_ip, c_print);break;
- case 'x':
- findGroupURL(
- logLen, //количество элементов в массиве log
- log, //массив типа oneHeat с информацией о одной строке лог файла
- reqwest_c,
- reqv_info,
- reqwest,
- ar_command[num_command].par[0],
- ar_command[num_command].par[1],
- countClickLastMinute,
- len_time_sec,
- koef,
- ar_int,
- c_ddos_ip,
- ar_white_ip,
- ar_white_mask
- );
- break;
- case 'u':
- hoar_sort(reqwest_c,reqv_info);
- printReqvInfo(
- logLen, //количество элементов в массиве log
- log, //массив типа oneHeat с информацией о одной строке лог файла
- reqwest_c,
- reqv_info,
- reqwest,
- c_print); break;
- case 'm':
- countIpInfo= //количество разных ip(длина массива ipInfo)
- makeIpInfo( //создание массива ipInfo
- logLen, //количество элементов в массиве log
- log, //массив типа oneHeat с информацией о одной строке лог файла
- ipInfo);//указатель на массив типа sort_item, с информацией о количестве кликов каждого IP
- hoar_sort(countIpInfo,ipInfo);
- findIPbyLimit (
- logLen, //количество элементов в массиве log
- log, //массив типа oneHeat с информацией о одной строке лог файла
- countIpInfo,//количество разных ip в логе
- ipInfo,
- ar_command[num_command].par[0],
- ar_command[num_command].par[1],
- ar_command[num_command].par[2],
- ar_command[num_command].par[3],
- countClickLastMinute,//количество кликов за последню минуту
- koef,
- len_time_sec, //длина лога в секндах
- ar_int, //массив уже забаненных, сюда же добавляем найденных ботов
- c_ddos_ip, //количество строк массива ar_int
- ar_white_ip, //массив белого списка IP и подсетей
- ar_white_mask //маска для массива белого списка
- );
- break;
- case 'h':
- if (!koef)
- koef=calcPopravku(
- countClickLastMinute,
- ar_command[num_command].par[0],
- ar_command[num_command].par[1],
- ar_command[num_command].par[2],
- comment_str);
- break;
- case 'A'://
- armagedon(
- logLen,
- log,
- ar_command[num_command].par[0],
- ar_command[num_command].par[1],
- ar_command[num_command].par[2],
- countClickLastMinute,
- countIpInfo,
- len_time_sec,
- // koef,
- ar_int,
- c_ddos_ip,
- ar_white_ip,
- ar_white_mask
- );
- break;
- case 't':
- findBad_str(
- reqwest,
- bad_strs,
- log,
- ar_int,
- c_ddos_ip,
- ar_white_ip,
- ar_white_mask
- );
- break;
- case 's':
- findLongStr(
- logLen,
- log,
- reqwest,
- ar_command[num_command].par[0],
- ar_command[num_command].par[1],
- ar_command[num_command].par[2],
- verbose,
- c_print,
- ar_int,
- c_ddos_ip
- );
- break;
- case 'z':
- findDirki(
- logLen,
- log,
- reqwest,
- ar_command[num_command].par[0],
- ar_command[num_command].par[1],
- verbose,
- c_print,
- ar_int,
- c_ddos_ip,
- ar_white_ip,
- ar_white_mask
- );
- break;
- }
- }
- if (file_ip_res)
- {
- // printf("c_ddos_ip=%d\n",c_ddos_ip);
- // printf("c_banned_ip=%d\n",c_banned_ip);
- print_ar_to_file(
- c_ddos_ip + c_banned_ip ,
- ar_int,
- file_ip_res );
- }
- if (do_netstat)
- {
- free(netstat);
- free(ipInfo);
- }
- else
- {
- free(log);
- free(reqwest);
- free(referrer);
- free(user_agent);
- free(ipInfo);
- free(reqv_info);
- free(referrer_info);
- free(user_agent_info);
- }
- if (time_start)
- {
- time(&time_finish);
- unsigned int time_work=time_finish - time_start;
- printf("Время рабты=%d сек.\n", time_work);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement