在NS2-3.34中添加黑洞攻擊的過程還是比較簡單的,具體過程大緻如下描述:
1. 首先我們在aodv/aodv.h中的AODV類中添加一個标志該Agent(該節點是blackhole的标志)
class AODV: public Agent {
int blackhole; //是否是攻擊節點
}
2.修改aodv/aodv.cc以實作blackhole 攻擊
首先是在command 中定義相應的TCL “blackhole”
if (strcmp(argv[1], "blackhole") == 0) {
printf("exsits blackhole/n");
blackhole = 1;
return TCL_OK;
}
接下來根據AODV協定和blackhole attack 的特點,我們實作blackhole attack的攻擊過程(具體的攻擊手段就是
在接收到某個節點發來的路由請求後,黑洞攻擊節點不是檢視路由表是否由到達目的節點的路由,進而轉發或回複一個RREP。
取而代之的是,在它接收到一個RREQ後,立即回複一個RREP路由回複包,說他有到達目的節點的最優路徑。而且當黑洞攻擊節點
接收到資料包時,全部丢掉,進而形成一個像黑洞一樣的攻擊,資料包隻進不出。具體詳細關于黑洞攻擊請google了解):
修改aodv.cc 中的recvRequest(Packet *p)函數:
void
AODV::recvRequest(Packet *p) {
if(debug>1) printf("recvRequest/n");
struct hdr_ip *ih = HDR_IP(p);
struct hdr_aodv_request *rq = HDR_AODV_REQUEST(p);
aodv_rt_entry *rt;
/*
* Drop if:
* - I'm the source
* - I recently heard this request.
*/
if (rq->rq_src == index) {
#ifdef DEBUG
//fprintf(stderr, "%s: got my own REQUEST/n", __FUNCTION__);
#endif // DEBUG
Packet::free(p); //如果是自己發出來的就直接丢棄
return;
}
if (id_lookup(rq->rq_src, rq->rq_bcast_id)) {
#ifdef DEBUG
//fprintf(stderr, "%s: discarding request/n", __FUNCTION__);
#endif // DEBUG
// printf("我之前已經接收到了這個分組!and my id is %d /n", index);
Packet::free(p); //這個分組已經收到過
return;
}
/*
* Cache the broadcast ID
*/
id_insert(rq->rq_src, rq->rq_bcast_id);
/*
* We are either going to forward the REQUEST or generate a
* REPLY. Before we do anything, we make sure that the REVERSE
* route is in the route table.
*/
aodv_rt_entry *rt0; // rt0 is the reverse route
rt0 = rtable.rt_lookup(rq->rq_src);
if (rt0 == 0) { /* if not in the route table */
// create an entry for the reverse route.
rt0 = rtable.rt_add(rq->rq_src);
}
rt0->rt_expire = max(rt0->rt_expire, (CURRENT_TIME + REV_ROUTE_LIFE));
if ( (rq->rq_src_seqno > rt0->rt_seqno ) ||
((rq->rq_src_seqno == rt0->rt_seqno) &&
(rq->rq_hop_count < rt0->rt_hops)) ) {
// If we have a fresher seq no. or lesser #hops for the
// same seq no., update the rt entry. Else don't bother.
rt_update(rt0, rq->rq_src_seqno, rq->rq_hop_count, ih->saddr(),
max(rt0->rt_expire, (CURRENT_TIME + REV_ROUTE_LIFE)) );
if (rt0->rt_req_timeout > 0.0) {
// Reset the soft state and
// Set expiry time to CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT
// This is because route is used in the forward direction,
// but only sources get benefited by this change
rt0->rt_req_cnt = 0;
rt0->rt_req_timeout = 0.0;
rt0->rt_req_last_ttl = rq->rq_hop_count;
rt0->rt_expire = CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT;
}
/* Find out whether any buffered packet can benefit from the
* reverse route.
* May need some change in the following code - Mahesh 09/11/99
*/
assert (rt0->rt_flags == RTF_UP);
Packet *buffered_pkt;
while ((buffered_pkt = rqueue.deque(rt0->rt_dst))) {
if (rt0 && (rt0->rt_flags == RTF_UP)) {
assert(rt0->rt_hops != INFINITY2);
forward(rt0, buffered_pkt, NO_DELAY);
}
}
}
// End for putting reverse route in rt table
/*
* We have taken care of the reverse route stuff.
* Now see whether we can send a route reply.
*/
rt = rtable.rt_lookup(rq->rq_dst);
// First check if I am the destination ..
if (rq->rq_dst == index) {
#ifdef DEBUG
fprintf(stderr, "%d - %s: destination sending reply/n",
index, __FUNCTION__);
#endif // DEBUG
//printf("I am the desitination and my ip address is %d/n", index);
// Just to be safe, I use the max. Somebody may have
// incremented the dst seqno.
seqno = max(seqno, rq->rq_dst_seqno) + 1;
if (seqno % 2) seqno++;
sendReply(rq->rq_src, // IP Destination
1, // Hop Count
index, // Dest IP Address
seqno, // Dest Sequence Num
rq->rq_src,
MY_ROUTE_TIMEOUT, // Lifetime
rq->rq_timestamp); // timestamp
Packet::free(p);
}
// I am not the destination, but I may have a fresh enough route.
//Start balckhole Code
//a Blackhole attacker always say that have the route to be a sink.
else if ((rt && blackhole == 1)) {
assert(rq->rq_dst == rt->rt_dst);
//printf("I am the blackhole node and blackhole = %d/n", index);
sendReply(rq->rq_src,
1,
//rt->rt_hops, //Blackhole gravity.
rq->rq_dst,
//rt->rt_seqno + 10, //Blackhole gravity.
4294967295,
rq->rq_src,
(u_int32_t) (rt->rt_expire - CURRENT_TIME),
rq->rq_timestamp);
rt->pc_insert(rt0->rt_nexthop); // nexthop to RREQ source
rt0->pc_insert(rt->rt_nexthop); // nexthop to RREQ destination
//printf("node ip = %d,rt->rt_hops = %d, rt->rt_seqno = %d/n",index,rt->rt_hops, rt->rt_seqno);
#ifdef RREQ_GRAT_RREP
sendReply(rq->rq_dst,
rq->rq_hop_count,
rq->rq_src,
rq->rq_src_seqno,
rq->rq_src,
(u_int32_t) (rt->rt_expire - CURRENT_TIME),
rq->rq_timestamp);
printf("ifndef RREQ_GRAT_RREP....../n");
#endif
Packet::free(p);
}
//End balckhole Code
/*Sniffer IDS 假設中間節點是不能回複RREP的,但是黑洞攻擊節點卻必須可疑回複,其實這種做法明顯是存在很大的缺陷的。
這樣即使可以有效隔離黑洞攻擊節點,但是這隻能說是路由協定的一種特殊條件的下的檢測方法。
後面我希望在此基礎上做進一步的改進,可以把這種攻擊手段擴大化,也就是更加普遍話。适應各種路由情況,而不僅限于某種特殊情況
*/
} else if ((rt && (rt->rt_hops != INFINITY2) &&
(rt->rt_seqno >= rq->rq_dst_seqno) )) {
//printf("I am not the desitination, but is may have a fresh enough route/n");
//assert (rt->rt_flags == RTF_UP);
assert(rq->rq_dst == rt->rt_dst);
//assert ((rt->rt_seqno%2) == 0); // is the seqno even?
sendReply(rq->rq_src,
rt->rt_hops + 1,
rq->rq_dst,
rt->rt_seqno,
rq->rq_src,
(u_int32_t) (rt->rt_expire - CURRENT_TIME),
// rt->rt_expire - CURRENT_TIME,
rq->rq_timestamp);
// Insert nexthops to RREQ source and RREQ destination in the
// precursor lists of destination and source respectively
rt->pc_insert(rt0->rt_nexthop); // nexthop to RREQ source
rt0->pc_insert(rt->rt_nexthop); // nexthop to RREQ destination
#ifdef RREQ_GRAT_RREP
sendReply(rq->rq_dst,
rq->rq_hop_count,
rq->rq_src,
rq->rq_src_seqno,
rq->rq_src,
(u_int32_t) (rt->rt_expire - CURRENT_TIME),
// rt->rt_expire - CURRENT_TIME,
rq->rq_timestamp);
printf("I am not the desitination, but is may have a fresh enough route , RREQ_GRAT_RREP/n");
#endif
// TODO: send grat RREP to dst if G flag set in RREQ using rq->rq_src_seqno, rq->rq_hop_counT
// DONE: Included gratuitous replies to be sent as per IETF aodv draft specification. As of now, G flag has not been dynamically used and is always set or reset in aodv-packet.h --- Anant Utgikar, 09/16/02.
Packet::free(p);
}
/*
* Can't reply. So forward the Route Request
*/
else {
//Start Blackhole Code
if(blackhole == 1) //是黑洞攻擊節點
{
//printf("%d can't replay, but %d is a attacker, so i will replay the RREP packets/n", index, index);
sendReply(rq->rq_src, // IP Destination
1, // Hop Count
rq->rq_dst, // Dest IP Address
4294967295, // Highest Dest Sequence Num that is largest 32-bit integers from -2147483647 to +2147483647
rq->rq_src,
//rt->rt_seqno + 10,
MY_ROUTE_TIMEOUT, // Lifetime
rq->rq_timestamp); // timestamp
Packet::free(p);
}//End Blackhole Code
else
{
ih->saddr() = index;
ih->daddr() = IP_BROADCAST;
rq->rq_hop_count += 1;
// Maximum sequence number seen en route
if (rt) rq->rq_dst_seqno = max(rt->rt_seqno, rq->rq_dst_seqno);
forward((aodv_rt_entry*) 0, p, DELA
這裡面的sendReply我是修改過了的,就是添加一個字段。這個和實作黑洞攻擊沒有關系。可以忽略!
然後實作所有的黑洞攻擊節點在接收到資料包時(自己不是目的節點),把所有接收到的資料包直接丢掉
在AODV::rt_resolve(Packet *p) 函數中添加:
//if (rt->rt_flags == RTF_UP){
if ((rt->rt_flags == RTF_UP) &&
//Start Watchdog Code
(blackhole != 1)) {
//End Watchdog Code
assert(rt->rt_hops != INFINITY2);
forward(rt, p, NO_DELAY);
// printf("%f forward this packet by not need the REQUEST, dst = %d/n and next_hop = %d/n", Scheduler::instance().clock(),ih->daddr(), rt->rt_nexthop);
}
//Start Watchdog Code
else if(blackhole == 1 && ih->daddr() != index){ //黑洞節點并且我不是目的節點
if(blackholed == 0 && packets_dropped >= PACKETS_TO_CONSIDER_AN_ATTACK){
blackholed=1;
printAttackMessage(p);
}
packets_dropped++;
drop(p, DROP_IFQ_FILTER);
return;
}
//End Watchdog Code
3.最後我們還需要在tcl/lib/ns-mobilenode.tcl中添加
#Blackhole
Node/MobileNode instproc set_Blackhole {} {
$self instvar ragent_
puts "Installing new blackhole...................."
return $ragent_
}
4.這樣我們可以直接在tcl腳本中使用黑洞攻擊節點了:
set n3 [$ns node]
$n3 set X_ 372
$n3 set Y_ 400
$n3 set Z_ 0.0
$ns initial_node_pos $n3 20
$ns at 0.01 "[$n3 set ragent_] blackhole"
$ns at 0.01 "$n3 label /"blackhole node/" "
這裡就是把節點3定義為一個黑洞攻擊節點。
注:在協定中添加攻擊行為還可以使用另外一種方法進行添加,就是像建立一種新的協定過程一樣,比如說建立一種叫做blackholeAODV
整個協定的建立過程跟很多樹上描述的建立一個新的MyPing協定過程一樣。這裡面的blackholeAODV協定建立過程按照AODV協定建立過程,然後修改AODV協定,使得這個協定能夠實作黑洞攻擊。最後在tcl腳本中使用是,和使用AODV協定配置一樣。比如說你協定的定義的TCL為blackholeAODV,則可以這樣子調用:
set val(brp) blackholeAODV ;# blackhole attack in AODV
$ns node-config -adhocRouting $val(brp)
set n3 [$ns node]
$n3 set X_ 372
$n3 set Y_ 400
$n3 set Z_ 0.0
$ns initial_node_pos $n3 20
這樣同樣可以實作上面的黑洞攻擊的功能。