Forum Discussion

Rich_79422's avatar
Rich_79422
Icon for Nimbostratus rankNimbostratus
Jan 16, 2013

irule to read sidband cvs file and then drop connect based on db.

Good day, I hope someone would be able to aide me in this Irule. I'm trying to implement the following:

 

I took the Sideband irule and modified it, but I'm having an issue at the point where I want to drop the connection if the condition is met?

 

Thx

 

-Rich

 

ACL with sideband database update

 

 

v1.2 - 12/11/2012

 

 

BIG-IP version 11.1.0 HF5

 

 

Majority of code received from devcentral.f5.com

 

 

Purpose:

 

This rule was created for Access Control to VS. It should be updated for the specific virtual server.

 

You will be required to update the RULE_INIT section to the specific db server you will want to connect to.

 

Logging is eanbled by default, please turn off after the iRule has been verified to work.

 

 

when RULE_INIT {

 

 

HTTP server holding the CSV-formatted database

 

set static::rmp01_db_host xspl10c153a.x.x.x

 

HTTP path for the CSV-formatted database

 

set static::rmp01_db_path "/lists.csv"

 

 

CSV database line delimiter: CR = \r, LF = \n, CR+LF = \r\n

 

set static::rmp01_db_line_delimiter "\n"

 

DNS server if using DNS resolution (optional)

 

set static::rmp01_dns_server 1.1.1.1

 

Timeout for database cached in a table

 

set static::rmp01_db_cache_timeout 10

 

 

Drop unknown source IP addresses? 0 = no, 1 = yes

 

set static::rmp01_drop_unknown_sources 1

 

 

Log accepted requests? 0 = no, 1 = yes

 

set static::rmp01_log_accepted_requests 1

 

Log accepted requests? 0 = no, 1 = yes

 

set static::rmp01_log_dropped_requests 1

 

Log accepted requests? 0 = no, 1 = yes

 

set static::rmp01_acl_log_accepted_requests 1

 

Log accepted requests? 0 = no, 1 = yes

 

set static::rmp01_acl_log_dropped_requests 1

 

 

}

 

when CLIENT_ACCEPTED {

 

table to cacha CSV-formatted database

 

set rmp01_db_cache_table "rmp01_db_cache_[virtual]"

 

table to track when to refresh the database's contents

 

set rmp01_db_cache_state_table "rmp01_db_cache_timeout_[virtual]"

 

 

set rmp01_last_refresh [table lookup -subtable $rmp01_db_cache_state_table rmp01_last_refresh]

 

if { $rmp01_last_refresh eq "" } { set rmp01_last_refresh 0 }

 

if { [expr [clock seconds]-$rmp01_last_refresh] > $static::rmp01_db_cache_timeout } {

 

set rmp01_db_ip [lindex [RESOLV::lookup @$static::rmp01_dns_server -a $static::rmp01_db_host] 0]

 

 

if { $rmp01_db_ip ne "" } {

 

if { [table lookup -subtable $rmp01_db_cache_state_table lock] != 1 } {

 

lock table modifications so that multiple instances don't attempt to update the table

 

table set -subtable $rmp01_db_cache_state_table lock 1 $static::rmp01_db_cache_timeout $static::rmp01_db_cache_timeout

 

 

log local0. "Locking table"

 

 

establish connection to server

 

set conn [connect -timeout 1000 -idle 30 $rmp01_db_ip:80]

 

 

build request to send to HTTP server hosting DB

 

set request "GET $static::rmp01_db_path HTTP/1.1\r\nHost: $static::rmp01_db_host\r\n\r\n"

 

 

send request to server

 

send -timeout 1000 -status send_status $conn $request

 

 

receive response and place in variable

 

set rmp01_db_contents [getfield [recv -timeout 1000 -status recv_info $conn] "\r\n\r\n" 2]

 

 

if { $rmp01_db_contents ne "" } {

 

update last refresh time in timeout table

 

table set -subtable $rmp01_db_cache_state_table rmp01_last_refresh [clock seconds] indef indef

 

 

grab a list of old keys so we can remove them from cache if not in new DB copy

 

set rmp01_old_keys [table keys -subtable $rmp01_db_cache_table]

 

 

foreach field [split [string map [list $static::rmp01_db_line_delimiter \uffff] $rmp01_db_contents] \uffff] {

 

if { ($field contains ",") && !($field starts_with "") } {

 

set rmp01_sep_offset [string first "," $field]

 

 

set rmp01_key [string range $field 0 [expr $rmp01_sep_offset - 1]]

 

set rmp01_value [string range $field [expr $rmp01_sep_offset + 1] end]

 

lappend rmp01_new_keys $rmp01_key

 

 

add key/value pairs to DB cache table

 

table set -subtable $rmp01_db_cache_table $rmp01_key $rmp01_value indef indef

 

 

if { [lsearch $rmp01_old_keys $key] >= 0 } {

 

log local0. "Updating \"$rmp01_key\" = \"$rmp01_value\" in DB cache table"

 

} else {

 

log local0. "Adding \"$rmp01_key\" = \"$rmp01_value\" to DB cache table"

 

}

 

}

 

}

 

 

foreach rmp01_old_key $rmp01_old_keys {

 

if { [lsearch $rmp01_new_keys $rmp01_old_key] < 0 } {

 

remove any keys which don't exist in new DB copy

 

table delete -subtable $rmp01_db_cache_table $rmp01_old_key

 

 

log local0. "Deleting \"$rmp01_old_key\" from DB cache table, key doesn't exist in new DB copy"

 

}

 

}

 

 

set rmp01_deny [table lookup -subtable $rmp01_db_contents [IP::client_addr]]

 

log local0. "client ip = [IP::client_addr]"

 

log local0. "db address = $rmp01_db_contents"

 

if { [IP::client_addr] == $rmp01_db_contents } {

 

if {$static::rmp01_acl_log_accepted_requests == 1 } {

 

log local0. "the following client was dropped: [IP::client_addr] "

 

}

 

log local0. "client is dropped"

 

drop }

 

 

} else {

 

 

if {$static::rmp01_acl_log_dropped_requests == 1 } {

 

log local0. "the following client was allowed: [IP::client_addr] "

 

}

 

 

 

}

 

 

close $conn

 

 

table delete -subtable $rmp01_db_cache_state_table lock

 

 

}

 

} else {

 

 

log local0. "Could not get valid IP for the DB server. Check the hostname and nameserver settings."

 

 

}

 

}

 

 

}

 

5 Replies

  • I'd love to say I understand everything in this rule but there's no chance. Regardless, I can answer your question; to drop the connection simply use either the 'drop' or 'reject' commands. 'drop' just silently drops the traffic (and removes any connection table entries), 'reject' also sends a TCP RST to the client.

     

  • Thanks for the reply, but that's not the issue I'm having. What it looks like to me is that whole section is not getting executed.

     

     

    Thx

     

    -Rich

     

  • Knew it was too easy and have now spotted the drop in your code

     

     

    So the CLIENT_ACCEPTED event is not being triggered?
  • Sorry, I should have been more clear.

     

    The irule works right up to this line

     

    log local0. "db address = $rmp01_db_contents"

     

    I receive no errors or anything. So it like the next if statment is not being execuited.

     

     

    Thx

     

    -Rich

     

  • Ah OK. So, could you try with this somewhat tidied up code, also I'm sure there is an unnecessary bracket in there but can't be 100% as it's hard to keep all those ifs in my head at one time;

     

    
     set rmp01_deny [table lookup -subtable $rmp01_db_contents [IP::client_addr]]
         log local0. "client ip = [IP::client_addr], db address = $rmp01_db_contents"
         if { [IP::client_addr] == $rmp01_db_contents } {
           if {$static::rmp01_acl_log_accepted_requests == 1 } {
           log local0. "the following client was dropped: [IP::client_addr]"
           drop
           return
           }
           log local0. "client is dropped"
           drop
           return
         }
         } << Is this required
         elseif { $static::rmp01_acl_log_dropped_requests == 1 } {
           log local0. "the following client was allowed: [IP::client_addr] "
           }