Дипломная работа: Разработка и анализ эффективности средств отражения распределенных атак
3.
НД ТЗІ
1.1-003-99. ТЕРМІНОЛОГІЯ В ГАЛУЗІ ЗАХИСТУ ІНФОРМАЦІЇ В КОМП’ЮТЕРНИХ СИСТЕМАХ
ВІД НЕСАНКЦІОНОВАНОГО ДОСТУПУ
4.
http://bezpeka.com
5.
http://www.virulist.com
6.
http://www.void.ru
7.
http://www.webinform.ru
8.
http://bugtraq.ru
9.
Приказ ДСТСЗИ СБУ
30.04.2004 N 31
10.
BSI.IT
Baseline Protection Manual. Standard Security Measures. Version: October 2000
11.
RFC793
Transmission
Control Protocol
12.
http://www.securityfocus.com/infocus/1729
13.
http://www.protocols.ru
14.
http://www.preferredtechnology.com
15.
http://www.iss.net
16.
Г.И. Ивченко.
Теория массового обслуживания, М:Высшая Школа, 1982.
17.
RFC2616. Hypertext Transfer Protocol – HTTP/1.1.
18.
Д. Камер.
Сети TCP/IP том 1, изд. дом "Вильямс"
М-Санкт-Петербург-Киев 2003
19.
http://www.internettrafficreport.com/main.htm
20.
http://securitylab.ru
21.
Г.Корн, Т.Корн
Справочник по математике для научных работников и инженеров М: "НАУКА",1968.
22.
Д.Л. Ясницкий. "Разработка методики раннего
обнаружения и отражения распределённых атак
типа "отказ в обслуживании"". Магистерская аттестационная работа. Харьков: ХНУРЭ,
2006
23.
Джей Бил и др. Snort 2.1. Обнаружение вторжений. 2-е изд.
Пер. с англ. - М.: ООО "Бином-Пресс", 2006;
24.
Медведовский
И.Д., Семьянов П.В., Платонов В.В. Атака через Internet.
25.
http://www.securityfocus.com
26.
Д.Л. Ясницкий,
В.Д. Литовский, Р.В. Олейников. Методика раннего обнаружения TCP SYN атаки. Прикладная радиоэлектроника. Т.5, Харьков:
ХНУРЭ, 2006.
27.
Snort-2.4.3
source code.
28.
http://kiev-security.org.ua
29.
http://www.sophist.demon.co.uk/ping
30.
http://www.citforum.ru
31.
www.computer.org/
32.
http://wiki.hping.org/172
33.
http://www.snort.org
34.
http://www.bsi.de/
35.
http://www.linuxsecurity.com
Приложение А
Исходный код модуля
расширение функциональности для IPS Snort_inline
// Файл tcp_syn_flood.h
#ifndef
__SP_TCP_SYN_FLOOD_H__
#define
__SP_TCP_SYN_FLOOD_H__
//
TcpSynFloodDefinitions
#define
TcpSynFloodPreventionModulePtr void*
/*** Pluging
working modes ***/
#define
TCP_SYN_FLOOD_DETECTION1
#define
TCP_SYN_FLOOD_PREVENTION2
/***
TcpSynFlood atack states ***/
#define
SYN_ATACK_IS_NOT_PRESENT 1
#define
SYN_ATACK_IS_PRESENT 2
/*** Supported
packet types ***/
#define
PACKET_TYPE_UNSUPPORTED 0
#define
PACKET_TYPE_SYN_ACK 1
#define
PACKET_TYPE_ACK 2
#define
PACKET_TYPE_RST_FROM_SERVER 3
#define
PACKET_TYPE_RST_FROM_CLIENT 4
#define
PACKET_TYPE_SYN 5
/***
Prevention module checking packet results ***/
#define
PREVENTION_PACKET_IS_OK 1
#define
PREVENTION_PACKET_IS_BAD 2
void
SetupTcpSynFlood();
#endif /*
__SP_TCP_SYN_FLOOD_H__ */
// Файл tcp_syn_flood.с
#include
<sys/types.h>
#include
<stdlib.h>
#include
<ctype.h>
#include
"rules.h"
#include
"decode.h"
#include
"plugbase.h"
#include
"parser.h"
#include
"debug.h"
#include
"util.h"
#include
"plugin_enum.h"
#include
"generators.h"
#include
"event_wrapper.h"
#ifdef
HAVE_STRINGS_H
#include
"mstring.h"
#endif
#include
"sp_tcp_syn_flood.h"
#include
"tcp_conn_est_time_checker.h"
#include
"tcp_syn_flood_prevention_stat.h"
/*
* setup any
data structs here
*/
typedef struct
_TcpSynFloodData
{
// the current
mode of the plugin
int
workingMode;
// the IP
address of the server being protected
struct in_addr
serverIP;
// tcp
connection estimate time checker
TcpConnEstTimeChecker*
timeChecker;
// prevention
module
TcpSynFloodPreventionModulePtr
preventionModule;
}
TcpSynFloodData;
/* function
prototypes go here */
static void
TcpSynFloodInit(char *, OptTreeNode *, int);
static void
TcpSynFloodRuleParseFunction(char *, OptTreeNode *);
static int
TcpSynFloodCheckFunction(Packet *, struct _OptTreeNode *, OptFpList *);
/* internal
functions prototypes */
int
ParseIntElement(char* token, char *name);
void
SetupTcpSynFlood()
{
/* map the
keyword to an initialization/processing function */
RegisterPlugin("tcp_syn_flood",
TcpSynFloodInit);
DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin:
TcpSynFlood Setup\n"););
}
static void
TcpSynFloodInit(char *data, OptTreeNode *otn, int protocol)
{
// multiple
declaration check
if(otn->ds_list[PLUGIN_TCP_SYN_FLOOD])
{
FatalError("%s(%d):
Multiple tcpsynflood options in rule\n", file_name,
file_line);
}
// allocate
the data structure and attach it to the
// rule's data
struct list
TcpSynFloodData*
tcpSynFloodData = (TcpSynFloodData*)
SnortAlloc(sizeof(TcpSynFloodData));tcpSynFloodData->workingMode = TCP_SYN_FLOOD_DETECTION;
tcpSynFloodData->preventionModule
= TcpSynFloodPreventionCreateModule();
otn->ds_list[PLUGIN_TCP_SYN_FLOOD]
= tcpSynFloodData;
TcpSynFloodRuleParseFunction(data,
otn);
// finally,
attach the option's detection function to the rule's
// detect
function pointer list
AddOptFuncToList(TcpSynFloodCheckFunction,
otn);
}
/** Expected
Rule Structure
#
tcp_syn_flood:
# [0] -
ip_server
# [1] -
server_timeout_sec
# [2] -
max_overdue_count
# [3] -
max_overdue_count_diviation
# [4] -
overdue_time_sec
# [5] -
check_period_sec
*/
static void
TcpSynFloodRuleParseFunction(
char *data,
OptTreeNode
*otn)
{
int
server_timeout_sec = 0;
int
max_overdue_count = 0;
int
max_overdue_count_diviation = 0;
int
overdue_time_sec = 0;
int
check_period_sec = 0;
TcpSynFloodData
*tcpSynFloodData;
tcpSynFloodData
= otn->ds_list[PLUGIN_TCP_SYN_FLOOD];
while(isspace((int)*data))
data++;
int numTokens;
const int
TokensCount = 6;
char **tokens
= mSplit(data, ",", TokensCount, &numTokens, 0);
printf("numtokens
%d\n", numTokens );
if(numTokens
!= TokensCount)
{
FatalError("in
TcpSynFlood rule: invalid number of init parameters\n");
}
if(inet_aton(tokens[0],
&tcpSynFloodData->serverIP) == 0)
{
FatalError("in
TcpSynFlood rule: %s is invalid ip address\n", tokens[0]);
}
server_timeout_sec
= ParseIntElement(tokens[1], "server timeout");
max_overdue_count
= ParseIntElement(tokens[2], "overdue count");
max_overdue_count_diviation
= ParseIntElement(tokens[3], "overdue count diviation");
overdue_time_sec
= ParseIntElement(tokens[4], "overdue time (in seconds)");
check_period_sec
= ParseIntElement(tokens[5], "check period (in seconds)");
// init
checker
TcpConnEstTimeChecker*
checker = (TcpConnEstTimeChecker*)SnortAlloc(sizeof(TcpConnEstTimeChecker));
InitTcpConnEstTimeChecker(checker,
overdue_time_sec,
// overdueTime
check_period_sec,
// int _checkPeriod
max_overdue_count,
// overdueUpperBound
max_overdue_count_diviation,
// overdueUpperBoundDiviation
server_timeout_sec//
serverTimeout
);
tcpSynFloodData->timeChecker
= checker;
printf("TcpSynFlood
module initialized with the following parameters:\n");
printf("\tserver
timeout %d\n", server_timeout_sec);
printf("\tmax
overdue count %d\n", max_overdue_count);
printf("\tmax
overdue count diviation %d\n", max_overdue_count_diviation);
printf("\toverdue
time %d\n", overdue_time_sec);
printf("\theck
period %d\n", check_period_sec);
// free tokens
memory
mSplitFree(&tokens,
numTokens);
}
static int
TcpSynFloodCheckFunction(
Packet *p,
struct
_OptTreeNode *otn,
OptFpList
*fp_list)
{
// Get Rule
Data
TcpSynFloodData
*tcpSynFloodData;
tcpSynFloodData
= otn->ds_list[PLUGIN_TCP_SYN_FLOOD];
int packetType
= GetPacketType(tcpSynFloodData->timeChecker, p,
tcpSynFloodData->serverIP);
if(packetType
!= PACKET_TYPE_UNSUPPORTED)
{
// process ACK
packets with prevention module
if(packetType
== PACKET_TYPE_ACK)
{
printf("Processing
ACK\n");
// check if
atack is absent
int changeStat
= (tcpSynFloodData->workingMode == TCP_SYN_FLOOD_DETECTION) ?
CHANGE_STAT_YES : CHANGE_STAT_NO;
if(changeStat
== CHANGE_STAT_YES)
{
// update
statistics for "good" client
TcpSynFloodPreventionProcessPacket(tcpSynFloodData->preventionModule,
p, changeStat);
}
} // process
SYN packet with prevetntion module
else
if(packetType == PACKET_TYPE_SYN)
{
printf("processing
SYN\n");
// check if
atack is present
if(tcpSynFloodData->workingMode
== TCP_SYN_FLOOD_PREVENTION)
{
printf("processing
SYN while attack is present\n");
// get packet
status
int
packetStatus =
TcpSynFloodPreventionProcessPacket(tcpSynFloodData->preventionModule, p,
CHANGE_STAT_NO);
if(packetStatus
== PREVENTION_PACKET_IS_BAD)
{
printf("Processing
bas SYN\n");
if(InlineMode())
{
InlineDrop();
}
// else {} //
Another type of ActiveReply should be implemented
// For example
sending RST packets to server and client
return 0;
}
}
}
// process
packet with time checker
int
checkerResult =
TcpConnEstTimeChecker_ProcessPacket(tcpSynFloodData->timeChecker, p,
packetType);
if(checkerResult
== SYN_ATACK_IS_PRESENT)
{
// Check if
atack has been started now
if(tcpSynFloodData->workingMode
== TCP_SYN_FLOOD_DETECTION)
{
// Generate
log message 'Atack Started'
GenerateSnortEvent(NULL,
GENERATOR_TCP_SYN_FLOOD, 0,0,0,3,SYNFLOOD_STARTED);
//change mode
tcpSynFloodData->workingMode
= TCP_SYN_FLOOD_PREVENTION;
}
}
else
{
// Check if
atack has been finished now
if(tcpSynFloodData->workingMode
== TCP_SYN_FLOOD_PREVENTION)
{
// Generate
event log "ATACK FINISHED"
GenerateSnortEvent(NULL,
GENERATOR_TCP_SYN_FLOOD, 0,0,0,3,SYNFLOOD_FINISHED);
//change mode
tcpSynFloodData->workingMode
= TCP_SYN_FLOOD_DETECTION;
}
}
}// PACKET IS
SUPPORTED
return
fp_list->next->OptTestFunc(p, otn, fp_list->next);
}
int
ParseIntElement(char* token, char *name)
{
char * tail;
int value =
(int) strtol(token, &tail, 10);
if(*tail)
{
FatalError("in
TcpSynFlood rule: %s is invalid %s.\n", token, name);
}
return value;
}
inline int
GetPacketType(TcpConnEstTimeChecker* checker, Packet* p, struct in_addr
ipServer)
{
// check IP
address
struct in_addr
ipSrc = p->iph->ip_src;
struct in_addr
ipDst = p->iph->ip_dst;
u_int8_t flags
= p->tcph->th_flags;
if((ipDst.s_addr
== ipServer.s_addr) && ((flags ^ R_SYN) == 0))
{
return
PACKET_TYPE_SYN;
}
if((ipSrc.s_addr
== ipServer.s_addr) && ((flags ^ R_SYN ^ R_ACK) == 0))
{
return
PACKET_TYPE_SYN_ACK;
}
else
if((ipDst.s_addr == ipServer.s_addr) && ((flags ^ R_ACK) == 0))
{
return
PACKET_TYPE_ACK;
}
else
if((ipSrc.s_addr == ipServer.s_addr) && ((flags ^ R_RST) == 0))
{
return
PACKET_TYPE_RST_FROM_SERVER;
}
else
if((ipDst.s_addr == ipServer.s_addr) && ((flags ^ R_RST) == 0))
{
return
PACKET_TYPE_RST_FROM_CLIENT;
}
return
PACKET_TYPE_UNSUPPORTED;
}
// файл tcp_conn_est_time_checker.h
#ifndef
__TCP_CONN_EST_TIME_CHECKER_H__
#define
__TCP_CONN_EST_TIME_CHECKER_H__
#include
<time.h>
#include
<sys/time.h>
#include
"config.h"
#include
"decode.h"
#include
"ubi_SplayTree.h"
typedef struct
_TcpConnEstTimeChecker
{
/*** Rule
Options ***/
// time in
seconds after which the half-open connection is overdue
long
overdueTime;
// period in
seconds to check the number of overdue half-open connections
long
checkPeriod;
// the max
allowed number of half-open connections
int
overdueUpperBound;
// the
diviation of overdueUpperBound
int
overdueUpperBoundDiviation;
/*** Internal
Data ***/
// the number
of root nodes in the array
int
rootNodesCount;
// the array
of root nodes
ubi_btRoot*
rootNodes;
// the index
of the first node, which contains overdued connections
int
firstOverduedNodeIndex;
// time when
the last shift was made
struct timeval
lastShiftTime;
// Indicates
if Syn Flood atack presents
int
atackState;
}
TcpConnEstTimeChecker;
/*** Inerface
***/
void
InitTcpConnEstTimeChecker(TcpConnEstTimeChecker* checker, long _overdueTime,
long
_checkPeriod, int _overdueUpperBound,
int
_overdueUpperBoundDiviation, long _serverTimeout);
void
DeInitTcpConnEstTimeChecker(TcpConnEstTimeChecker* checker);
int
TcpConnEstTimeChecker_ProcessPacket(TcpConnEstTimeChecker* checker, Packet* p,
int packetType);
int
ShiftRootNodes(TcpConnEstTimeChecker* checker, int GenerationCount);
#endif /*
__SP_TCP_SYN_FLOOD_H__ */
// файл tcp_conn_est_time_checker.c
#ifndef
__TCP_CONN_EST_TIME_CHECKER_H__
#include
"tcp_conn_est_time_checker.h"
#endif
#include
"sp_tcp_syn_flood.h"
#include
<memory.h>
#include
<math.h>
#include
<stdlib.h>
#include
"rules.h"
#include
"util.h"
/*********
States of Timechecker Tree Node Data ********/
#define
NODE_STATE_SYN_RECEIVED 1
#define
NODE_STATE_SYN_ACK_RECEIVED 2
typedef struct
_TimeCheckerTreeNodeData
{
ubi_trNode
Node;
// state of
the node
int NodeState;
// Sequence
number for client SYN packet
u_int32_t
ClientNumber;
// Sequence
number for server SYN+ACK packet
u_int32_t
ServerNumber;
}
TChTreeNodeData;
/***
TChTreeNodeData manipulation functions ***/
static int
TChTreeNodeDataCompareFunc(ubi_trItemPtr ItemPtr, ubi_trNodePtr NodePtr);
static void
TChTreeNodeDataDeleteNode(ubi_btNodePtr NodePtr);
/***
TcpConnEstTimeChecker manipulation functions ***/
void
InitTcpConnEstTimeChecker(TcpConnEstTimeChecker* checker, long _overdueTime,
long _checkPeriod,
int _overdueUpperBound,
int
_overdueUpperBoundDiviation, long _serverTimeout)
{
CheckInitParams(_overdueTime,
_checkPeriod, _overdueUpperBound, _overdueUpperBoundDiviation,_serverTimeout);
checker->overdueTime
= _overdueTime;
checker->checkPeriod
= _checkPeriod;
checker->overdueUpperBound
= _overdueUpperBound;
checker->overdueUpperBoundDiviation
= _overdueUpperBoundDiviation;
// Get
rootNodes count
double
serverTimeout = _serverTimeout;
int
rootNodesCount = ceil(serverTimeout / _checkPeriod);
checker->rootNodesCount
= rootNodesCount;
printf("NODES
COUNT %d\n", rootNodesCount);
// init the
array of root nodes
checker->rootNodes
= (ubi_btRoot*)SnortAlloc(sizeof(ubi_btRoot) * rootNodesCount);
// the index
of the first node with overdued connections
checker->firstOverduedNodeIndex
= checker->overdueTime / checker->checkPeriod;
int i;
for(i = 0; i
< rootNodesCount; i++)
{
ubi_trInitTree(checker->rootNodes
+ i,/* ptr to the tree head */
TChTreeNodeDataCompareFunc,
/* comparison function */
ubi_trDUPKEY);
//0); /* do
not allow nither OVERWRITE nor DUPLICATES */
}
// get current
time
struct
timezone tz;
gettimeofday(&checker->lastShiftTime,
&tz);
//time(&checker->lastShiftTime);
checker->atackState
= SYN_ATACK_IS_NOT_PRESENT;
}
void
DeInitTcpConnEstTimeChecker(TcpConnEstTimeChecker* checker)
{
int
rootNodesCount = checker->rootNodesCount;
// delete
trees
int i;
for(i = 0; i
< rootNodesCount; i++)
{
ubi_trKillTree(checker->rootNodes
+ i, TChTreeNodeDataDeleteNode);
}
// delete
array
free(checker->rootNodes);
checker->rootNodes
= NULL;
}
long
GetTimeDifference(struct timeval* time1, struct timeval* time2)
{
long secDiff
=time1->tv_sec - time2->tv_sec;
long
micSecDiff = time1->tv_usec - time2->tv_usec;
return
labs(secDiff)*1000000 + labs(micSecDiff);
}
int
TcpConnEstTimeChecker_ProcessPacket(TcpConnEstTimeChecker* checker, Packet* p,
int packetType)
{
int i;
/*
// get current
time
time_t
curTime;
time(&curTime);
//check the
time
int diff =
difftime(curTime, checker->lastShiftTime);
*/
struct timeval
currTime;
struct
timezone zone;
gettimeofday(&currTime,
&zone);
long diff =
GetTimeDifference(&currTime, &checker->lastShiftTime);
if(diff >=
checker->checkPeriod)
{
// shift trees
printf("shifting
trees\n");
int
generationsCount = ((float)diff) / checker->checkPeriod;
ShiftRootNodes(checker,
generationsCount);
}
// is used as
item to search
TChTreeNodeData*
findNodeData = NULL;
// flag which
indicates if the node is inserted successfully
ubi_trBool
insertResult;
// if Syn add
node to the tree
if(packetType
== PACKET_TYPE_SYN)
{
printf("processing
SYN packet in time checker \n");
TChTreeNodeData*
newNodeData = (TChTreeNodeData*)SnortAlloc(sizeof(TChTreeNodeData));
ubi_trNodePtr
nodePtr = &newNodeData->Node;
ubi_btInitNode(nodePtr);
// save
sequence number and set NODE_STATE_SYN_RECEIVED
newNodeData->ClientNumber
= p->tcph->th_seq;
newNodeData->NodeState
= NODE_STATE_SYN_RECEIVED;
// trying to
insert the node to the 0-th tree
insertResult =
ubi_trInsert(checker->rootNodes,
nodePtr, (ubi_trItemPtr)newNodeData, NULL);
if(insertResult
!= ubi_trTRUE)
{
printf("failed
to add SYN to the tree\n");
// there is
already the node with the same key in the tree
free(newNodeData);
}
}
// if Syn +
Ack
else
if(packetType == PACKET_TYPE_SYN_ACK)
{
printf("processing
SYN + ACK in time checker\n" );
// find the
node that is corresponded to received SYN
findNodeData =
(TChTreeNodeData*)SnortAlloc(sizeof(TChTreeNodeData));
findNodeData->NodeState
= NODE_STATE_SYN_RECEIVED;
findNodeData->ClientNumber
= p->tcph->th_ack - 1;
// run over
all trees and try to find the node
for(i = 0; i
< checker->rootNodesCount; i++)
{
TChTreeNodeData*
foundNodeData = (TChTreeNodeData*)ubi_trFind(checker->rootNodes + i,
findNodeData);
if(foundNodeData
!= NULL)
{
// remove node
from tree
ubi_trRemove(checker->rootNodes
+ i, foundNodeData);
// set
Acknowledgement number and update node state to NODE_STATE_SYN_ACK_RECEIVED
foundNodeData->NodeState
= NODE_STATE_SYN_ACK_RECEIVED;
foundNodeData->ServerNumber
= p->tcph->th_seq;
// insert node
again in the tree
insertResult =
ubi_trInsert(checker->rootNodes
+ i, foundNodeData, (ubi_trItemPtr)foundNodeData, NULL);
if(insertResult
!= ubi_trTRUE)
{
// there is
already the node with the same key in the tree
free(foundNodeData);
}
break;
}
}
free(findNodeData);
}
// if Ack or
Resets
else if
((packetType == PACKET_TYPE_ACK) ||
(packetType ==
PACKET_TYPE_RST_FROM_SERVER) ||
(packetType ==
PACKET_TYPE_SYN_ACK))
{
TChTreeNodeData*
findNodeData = (TChTreeNodeData*)SnortAlloc(sizeof(TChTreeNodeData));
switch(packetType)
{
case
PACKET_TYPE_ACK:
printf("processing
ACK packet\n");
findNodeData->NodeState
= NODE_STATE_SYN_ACK_RECEIVED;
findNodeData->ClientNumber
= p->tcph->th_seq - 1;
findNodeData->ServerNumber
= p->tcph->th_ack - 1;
break;
/*
case
PACKET_TYPE_RST_FROM_SERVER:
printf("processing
RST from server\n");
findNodeData->SeqAckNumber
= p->tcph->th_ack-1;
break;
case
PACKET_TYPE_SYN_ACK:
printf("processing
RST from client\n");
findNodeData->SeqAckNumber
= p->tcph->th_seq-1;
break;
*/
}
// run over
all trees and try to Find and Delete node with the given key
for(i = 0; i
< checker->rootNodesCount; i++)
{
ubi_trNodePtr
nodePtr = ubi_trFind(checker->rootNodes + i, findNodeData);
if(nodePtr !=
NULL)
{
// delete
ubi_trRemove(checker->rootNodes
+ i, nodePtr);
free((TChTreeNodeData*)nodePtr);
break;
}
}
free(findNodeData);
}
// check
overdue connections count
printf("chekcing\n");
return
CheckOverdueConnectionsCount(checker);
}
int
ShiftRootNodes(TcpConnEstTimeChecker* checker, int generationCount)
{
int i;
if(generationCount
> checker->rootNodesCount)
{
generationCount
= checker->rootNodesCount;
}
// free old
trees
for( i =
(checker->rootNodesCount - generationCount); i <
checker->rootNodesCount; i++ )
{
ubi_trKillTree(checker->rootNodes
+ i, TChTreeNodeDataDeleteNode);
}
// shift
memmove(checker->rootNodes
+ generationCount,
checker->rootNodes,
(checker->rootNodesCount - generationCount) * sizeof(ubi_btRoot));
// init new
trees
for(i = 0; i
< generationCount; i++)
{
ubi_trInitTree(&checker->rootNodes[i],/*
ptr to the tree head */
TChTreeNodeDataCompareFunc,
/* comparison function */
ubi_trDUPKEY);
/* allow duplicates */
}
struct
timezone zone;
gettimeofday(&checker->lastShiftTime,
&zone);
return 0;
}
int
CheckOverdueConnectionsCount(TcpConnEstTimeChecker* checker)
{
int resCount =
0;
int i;
for(i =
checker->firstOverduedNodeIndex; i < checker->rootNodesCount; i++ )
{
resCount +=
ubi_trCount(checker->rootNodes + i);
}
int
currentlyAllowedBound;
if(checker->atackState
== SYN_ATACK_IS_PRESENT)
{
// subtract
diviation from the bound
currentlyAllowedBound
= checker->overdueUpperBound - checker->overdueUpperBoundDiviation;
}
else
{
// add
diviation to the bound
currentlyAllowedBound
= checker->overdueUpperBound + checker->overdueUpperBoundDiviation;
}
// save
current atack state
checker->atackState
= (resCount > currentlyAllowedBound )? SYN_ATACK_IS_PRESENT :
SYN_ATACK_IS_NOT_PRESENT;
printf("check
overdued: %d - %d\n", currentlyAllowedBound, resCount);
return
checker->atackState;
}
void
CheckInitParams(int _overdueTime,int _checkPeriod,
int
_overdueUpperBound, int _overdueUpperBoundDiviation,
int
_serverTimeout)
{
if(_overdueTime
< 0)
{
FatalError("TcpConnectionEstimateTimeChecker::
_overdueTime must be > 0\n");
}
if(_checkPeriod
< 0)
{
FatalError("TcpConnectionEstimateTimeChecker::
_checkPeriod must be > 0\n");
}
if(_overdueUpperBound
< 0)
{
FatalError("TcpConnectionEstimateTimeChecker::
_overdueUpperBound must be > 0\n");
}
if(_overdueUpperBoundDiviation
< 0)
{
FatalError("TcpConnectionEstimateTimeChecker::
_overdueUpperBoundDiviation must be > 0\n");
}
if((_overdueUpperBound
- _overdueUpperBoundDiviation) < 0)
{
FatalError("TcpConnectionEstimateTimeChecker::
(_overdueUpperBound - _overdueUpperBoundDiviation) must be > 0\n");
}
if((_overdueUpperBound
+ _overdueUpperBoundDiviation) > _serverTimeout)
{
FatalError("TcpConnectionEstimateTimeChecker::
(_overdueUpperBound + _overdueUpperBoundDiviation) must be <
_serverTimeout\n");
}
if(_serverTimeout
< 0)
{
FatalError("TcpConnectionEstimateTimeChecker::
_serverTimeout must be > 0\n");
}
if(_overdueTime
> _serverTimeout)
{
FatalError("TcpConnectionEstimateTimeChecker::
overdue time can't be greater than server timeout\n");
}
if(_serverTimeout
<= _checkPeriod)
{
FatalError("TcpConnectionEstimateTimeChecker::
_serverTimeout must be greater than _checkPeriod\n");
}
}
/* Returns -1
if A < B
Returns 1 if A
> B
Returns 0 if A
= B
At first
Client number is checked.
Than if
neccessary Server nubmer is checked
*/
static int
TChTreeNodeDataCompareFunc(ubi_trItemPtr ItemPtr, ubi_trNodePtr NodePtr)
{
TChTreeNodeData
*A = (TChTreeNodeData *) ItemPtr;
TChTreeNodeData
*B = (TChTreeNodeData *) NodePtr;
if(A->ClientNumber
< B->ClientNumber)return -1;
if(A->ClientNumber
== B->ClientNumber)return 0;
else // check
curr node state
if(B->NodeState
== NODE_STATE_SYN_ACK_RECEIVED)
{
if(A->ServerNumber
< B->ServerNumber) return -1;
if(A->ServerNumber
== B->ServerNumber) return 0;
else return 1;
}
else // state
is NODE_STATE_SYN_RECEIVED
{
return 1;
}
}
static void
TChTreeNodeDataDeleteNode(ubi_btNodePtr NodePtr)
{
free(NodePtr);
}
// файл tcp_syn_flood_prevention_stat.h
#ifndef
_TCP_SYN_FLOOD_PREVENTION_STAT_H_
#define
_TCP_SYN_FLOOD_PREVENTION_STAT_H_
//#include
"config.h"
#include
"decode.h"
#include
"sp_tcp_syn_flood.h"
#include
"ubi_SplayTree.h"
#define
CHANGE_STAT_YES 1
#define CHANGE_STAT_NO
2
typedef struct
_TcpSynFloodPreventionModule
{
// the root of
the statistics tree
ubi_btRootPtr
rootStat;
long
totalPacketsCount;
}
TcpSynFloodPreventionModule;
// Creates and
initializes the prevention module
void*
TcpSynFloodPreventionStatCreateModule();
void
TcpSynFloodPreventionStatDeinitModule(TcpSynFloodPreventionModule*
preventionModule);
int
TcpSynFloodPreventionStatProcessPacket(TcpSynFloodPreventionModule*
preventionModule, Packet* packet, int changeStat);
// Unified Tcp
Syn Flood prevention interface
#define
TcpSynFloodPreventionProcessPacket( module, p, changeStat )
TcpSynFloodPreventionStatProcessPacket( (TcpSynFloodPreventionModule*) (module)
,(Packet*) (p), (int) (changeStat) )
#define
TcpSynFloodPreventionCreateModule TcpSynFloodPreventionStatCreateModule
#define
TcpSynFloodPreventionDeinitModule( module )
TcpSynFloodPreventionStatDeinitModule( (TcpSynFloodPreventionModule*) (module)
)
#endif
// файл tcp_syn_flood_prevention_stat.c
#ifndef
_TCP_SYN_FLOOD_PREVENTION_STAT_H_
#include
"tcp_syn_flood_prevention_stat.h"
#endif
typedef struct
_TcpSynFloodPreventionStatTreeNodeData
{
// the node in
which data is stored
ubi_trNode
Node;
// Fields to
identify from what client the packet has came
u_int8_t ttl;
struct in_addr
ipSrc;
// the number
of packets with TTL=ttl and IPSrc=ipSrc that've been processed
long counter;
}
TcpSynFloodPreventionStatTreeNodeData;
/***
TcpSynFloodPreventionStatTreeNodeData manipulation functions ***/
static int
TcpSynFloodPreventionStatTreeNodeDataCompareFunc(ubi_trItemPtr ItemPtr,
ubi_trNodePtr NodePtr);
static void
TcpSynFloodPreventionStatTreeNodeDataDeleteNode(ubi_btNodePtr NodePtr);
void*
TcpSynFloodPreventionStatCreateModule()
{
TcpSynFloodPreventionModule*
newModule = (TcpSynFloodPreventionModule*
)SnortAlloc(sizeof(TcpSynFloodPreventionModule));
newModule->totalPacketsCount
= 0l;
int* a =
(int*)SnortAlloc(10);
newModule->rootStat
= (ubi_btRootPtr)SnortAlloc(sizeof(ubi_btRoot));
ubi_trInitTree(newModule->rootStat,/*
ptr to the tree head */
TcpSynFloodPreventionStatTreeNodeDataCompareFunc,
/* comparison function */
0); /* do not
allow nither OVERWRITE nor DUPLICATES */
return
newModule;
}
void
TcpSynFloodPreventionStatDeinitModule(TcpSynFloodPreventionModule*
preventionModule)
{
// kill tree
ubi_trKillTree(preventionModule->rootStat,
TcpSynFloodPreventionStatTreeNodeDataDeleteNode);
free(preventionModule->rootStat);
free(preventionModule);
}
int
TcpSynFloodPreventionStatProcessPacket(TcpSynFloodPreventionModule* module,
Packet* packet, int changeStat)
{
// try to find
TcpSynFloodPreventionStatTreeNodeData*
findNodeData =
(TcpSynFloodPreventionStatTreeNodeData*)SnortAlloc(sizeof(TcpSynFloodPreventionStatTreeNodeData));
findNodeData->ipSrc
= packet->iph->ip_src;
findNodeData->ttl
= packet->iph->ip_ttl;
TcpSynFloodPreventionStatTreeNodeData*
currNodeData = (TcpSynFloodPreventionStatTreeNodeData*
)ubi_trFind(module->rootStat, findNodeData);
// update
statistics
if(changeStat
== CHANGE_STAT_YES)
{
if(currNodeData
== NULL)
{
// add new
node to the tree
TcpSynFloodPreventionStatTreeNodeData*
newNodeData =
(TcpSynFloodPreventionStatTreeNodeData*)SnortAlloc(sizeof(TcpSynFloodPreventionStatTreeNodeData));
newNodeData->ipSrc
= findNodeData->ipSrc;
newNodeData->ttl
= findNodeData->ttl;
ubi_trNodePtr
newNodePtr = &newNodeData->Node;
ubi_trInsert(module->rootStat,
newNodePtr, (ubi_trItemPtr)newNodeData, NULL);
currNodeData =
newNodeData;
}
module->totalPacketsCount++;
currNodeData->counter++;
printf("stats
is updated %d \n", currNodeData->counter);
}
free(findNodeData);
// Make the
decision if the packet is bad
if(currNodeData
== NULL) return PREVENTION_PACKET_IS_BAD;
double avg =
0;
double
nodesCount = ubi_trCount(module->rootStat);
if(nodesCount
!= 0)
{
avg =
module->totalPacketsCount / nodesCount;
}
if(currNodeData->counter
>= avg)
{
printf("packet
is OK\n");
return
PREVENTION_PACKET_IS_OK;
}
else
{
printf("packet
is BAD\n");
return
PREVENTION_PACKET_IS_BAD;
}
}
/* Returns -1
if A < B
Returns 1 if A
> B
Returns 0 if A
= B */
static int
TcpSynFloodPreventionStatTreeNodeDataCompareFunc(ubi_trItemPtr ItemPtr,
ubi_trNodePtr NodePtr)
{
TcpSynFloodPreventionStatTreeNodeData
*A = (TcpSynFloodPreventionStatTreeNodeData *) ItemPtr;
TcpSynFloodPreventionStatTreeNodeData
*B = (TcpSynFloodPreventionStatTreeNodeData *) NodePtr;
if((A->ipSrc.s_addr
== B->ipSrc.s_addr) && (A->ttl == B->ttl))
return 0;
else
{
if(A->ipSrc.s_addr
< B->ipSrc.s_addr)
return -1;
else
if(A->ipSrc.s_addr > B->ipSrc.s_addr)
return 1;
else
return
(A->ttl < B->ttl ) ? -1 : 1;
}
}
static void
TcpSynFloodPreventionStatTreeNodeDataDeleteNode(ubi_btNodePtr NodePtr){
free(NodePtr);
}
Приложение Б
Исходный код
вспомогательной утилиты
Утилита предназначена для:
· Извлечения из html страницы списка пингуемых хостов
· Извлечение из логов пингования
времени отклика
· Анализ распределения полученных
извлеченных значений времени
namespace
pings{
class Class1{
public static
void ExtractUrls(string FileName){
StreamReader
sr = new StreamReader(FileName);
StreamWriter
sw = new StreamWriter("run_pings.cmd");
string content
= sr.ReadToEnd();
string pattern
= @"href=.*""";
System.Text.RegularExpressions.MatchCollection
matches = Regex.Matches(content, pattern );
foreach(Match
match in matches){
string val =
match.Value;
if(val.IndexOf("viacom.local")
> -1) continue;
val =
val.Replace("href=", "");
val =
val.Replace("http://", "");
val =
val.Replace(@"""", "");
val =
val.Replace("/", "");
sw.WriteLine("ping
" + Regex.Split(val, ":")[0]);
}
sr.Close();
sw.Close();
}
public static
void ExtractPingTime(string FileName){
StreamReader
sr = new StreamReader(FileName);
StreamWriter
sw = new StreamWriter("extracted_time.txt");
string str;
int count = 0;
while((str =
sr.ReadLine()) != null){
if(str !=
string.Empty){
string []
tokens = str.Split();
foreach(string
token in tokens){
if(token.IndexOf("time=")
> -1){
count ++;
sw.WriteLine(token.Replace("time=",
"").Replace("ms", ""));
}
}
}
}
sr.Close();
sw.Close();
}
public static
void Usage(){
Console.WriteLine("pings
<option> <filename>");
Console.WriteLine("
option={url, time}");
}
[STAThread]
static void
Main(string[] args){
if(args.Length
== 2){
switch(args[0]){
case
"url":
ExtractUrls(args[1]);
break;
case
"time":
ExtractPingTime(args[1]);
break;
}
}
else{
Usage();
}
}
}
}
|