Skip to content

Instantly share code, notes, and snippets.

@lrhazi
Created September 15, 2012 21:46
Show Gist options
  • Save lrhazi/3729931 to your computer and use it in GitHub Desktop.
Save lrhazi/3729931 to your computer and use it in GitHub Desktop.
F5 BIGIP DNS Rate Limiting iRule
when RULE_INIT {
# Max queries per second, per client ip
set static::maxconn 100
# Max identical responses per second, per client ip
set static::maxresp 15
# Number of seconds to drop traffic from infringing client ip.
set static::holdtime 15
# Maximum entries in dns_drop session table.
set static::max_drop_entries 1000000
# Maximum per client, per query, table size.
set static::max_query_entries 1000000
}
when CLIENT_DATA {
set client_ip [IP::remote_addr]
set vip [IP::local_addr]
if { [table lookup -subtable "dns_drop" $client_ip] != "" } {
drop
#log local0.debug "Dropped client: $client_ip"
return
}
}
when DNS_RESPONSE {
#log local0.debug "dns_drop: [table keys -subtable "dns_drop" -count]"
#log local0.debug "dns_queries: [table keys -subtable "dns_queries" -count]"
if { [table keys -subtable "dns_drop" -count] >= $static::max_drop_entries } {
#log local0.debug "RRL disabled! Reached max_drop_entries: $static::max_drop_entries"
return
}
if { [table keys -subtable "dns_queries" -count] >= $static::max_query_entries } {
#log local0.debug "RRL disabled! Reached max_query_entries: $static::max_query_entries"
return
}
set curtime [clock second]
set ckey [b64encode [md5 "c:$client_ip:$curtime"]]
set ccount [table incr -subtable "dns_queries" $ckey]
table lifetime -subtable "dns_queries" $ckey 2
if { $ccount > $static::maxconn } {
table add -subtable "dns_drop" $client_ip "c" indef $static::holdtime
table delete $key
log local0.debug "Excessive queries max=$static::maxconn v=$vip c=$client_ip"
drop
return
}
set answer ""
set rrs [DNS::answer]
for {set i 1} {$i<=[llength $rrs]} {incr i} {
set rr [lindex $rrs [expr {$i-1}]]
append answer [DNS::name $rr] " "
append answer [DNS::ttl $rr] " "
append answer [DNS::class $rr] " "
append answer [DNS::type $rr] " "
set rdata [DNS::rdata $rr]
append answer $rdata " "
}
set rcode [DNS::header rcode]
if { $rcode != "NOERROR" } {
set rkey [b64encode [md5 "a:$client_ip:$curtime:$rcode"]]
} else {
set rkey [b64encode [md5 "a:$client_ip:$curtime:$answer"]]
}
set rcount [table incr -subtable "dns_queries" $rkey]
table lifetime -subtable "dns_queries" $rkey 2
if { $rcount > $static::maxresp } {
table add -subtable "dns_drop" $client_ip "a" indef $static::holdtime
table delete $rkey
log local0.debug "Excessive identical responses max=$static::maxresp v=$vip c=$client_ip n=[DNS::question name] t=[DNS::question type] r=$rcode"
drop
}
}
@JoshanFan
Copy link

#43 table delete $key >> table delete $ckey

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment