Forum Discussion

Tyler_Hardison_'s avatar
Tyler_Hardison_
Icon for Nimbostratus rankNimbostratus
Jan 24, 2014

Sideband for connections that are not going to a pool?

Hi There!

I'm trying to inject a sideband check that queries an internal server for dns blacklisting on the source IP addresses. Because I'm not using pools (low traffic legacy websites) I'm trying to wrap my head around how to inject sideband into this iRule.

Example:

when HTTP_REQUEST {
        switch [HTTP::host] {
                "foo.bar.tld" {
                                node 192.168.100.100 80
                }
                "baz.bar.tld" {
                                node 192.168.100.101 80
                }
                default {
                                HTTP::redirect "http://www.bar.tld/404.html"
                }
        }
}
  • I would use a datagroup for the URL lookup instead of statically modifying the iRule every time you need to make a change. You could do the side band connection in client_accepted like kevin states, then you don't have to continue processing for blacklisted IPs.

    when CLIENT_ACCEPTED {
        set clientAddress [IP::client_addr]
    
         Do sideband connection like described here
        https://devcentral.f5.com/wiki/irules.sideband-connection-http-example.ashx
    
        if { sideband tells us this is a bad IP address } {
             Drop it on the floor.
            drop
        }
    
         If it's not a blacklisted IP we let it continue
    
    }
    when HTTP_REQUEST {
        class match here for destination IP based on [HTTP::host]
        https://devcentral.f5.com/wiki/irules.class.ashx
    }
    

    Here's a more elaborate access control iRule which uses data groups instead of a sideband connection

    https://devcentral.f5.com/wiki/iRules.AccessControlBasedOnNetworkOrHost.ashx

  • A few things:

     

    1. What protocol would you be using to query the internal blacklist server? How is the data stored? LDAP/DB/REST call/DNS?

       

    2. Making a sideband call in each HTTP request would potentially add significant overhead. At the very least I would do it in the CLIENT_ACCEPTED event.

       

  • The backend will be a REST service that does several different checks. The URL looks like:

     

    http://thisserver.local/ipcheck?address=1.1.1.1

     

    It returns:

     

    Things are OK. { ip: "1.1.1.1", status: "no" }

     

    Things are not OK. { ip: "1.1.1.1", status: "some long string, but not no"}

     

    If necessary, I could (in theory) make it not HTTP. But the server for checking stores most transactions in memory. Also, performance is not a top priority as much as security is.

     

  • Aaron_Forster_3's avatar
    Aaron_Forster_3
    Historic F5 Account

    I would use a datagroup for the URL lookup instead of statically modifying the iRule every time you need to make a change. You could do the side band connection in client_accepted like kevin states, then you don't have to continue processing for blacklisted IPs.

    when CLIENT_ACCEPTED {
        set clientAddress [IP::client_addr]
    
         Do sideband connection like described here
        https://devcentral.f5.com/wiki/irules.sideband-connection-http-example.ashx
    
        if { sideband tells us this is a bad IP address } {
             Drop it on the floor.
            drop
        }
    
         If it's not a blacklisted IP we let it continue
    
    }
    when HTTP_REQUEST {
        class match here for destination IP based on [HTTP::host]
        https://devcentral.f5.com/wiki/irules.class.ashx
    }
    

    Here's a more elaborate access control iRule which uses data groups instead of a sideband connection

    https://devcentral.f5.com/wiki/iRules.AccessControlBasedOnNetworkOrHost.ashx

  • Sort of ironically I was working on a sideband call iRule today, so here's the meat of the sideband function. Modify as required.

    when CLIENT_ACCEPTED {
    
         set name of virtual server that blackhole server is behind (load balanced)
        set SB_VIP "sideband-vs"
    
         set client IP address
        set clientip [IP::client_addr]
    
         set sideband URI
        set SB_URI "/ipcheck?address=$clientip"
    
         start the sideband fun
        set conn [connect -timeout 6000 -idle 60 -status conn_status $static::IDP_VS]
    
        if { $conn eq "" } {
            if { $static::DEBUG } { log local0. "Sideband IdP connection could not be established" }
                return
            }       
    
             create the data to send to the IdP
            set data "GET $SB_URI HTTP/1.1\r\nHost: localhost\r\n\r\n"
    
             send the sideband call
            set send_info [send -timeout 6000 -status send_status $conn $data]
    
             receive the IdP response (via data "peek")
            set start [clock clicks -milliseconds]
            for {set i 0} {$i <= 40} {incr i} {
                set recv_data [recv -peek -status peek_status -timeout 40 $conn]
                if { [string match "HTTP/*\r\n\r\n*" $recv_data] } {
                    if { [string match -nocase "*Content-Length: *" $recv_data] }{
                        set header_length [expr {[string first "\r\n\r\n" $recv_data] + 4}]
                        set payload_length [findstr [string tolower $recv_data] "content-length: " 16 "\r"]
                        if { $payload_length ne "" and $payload_length > 0 } {
                            set recv_data [recv -peek -timeout 6000 -status recv_status [expr {$header_length + $payload_length}] $conn]
                            break
                        } else {
                            break
                        }
                    } else {
                        break
                    }
                }
            }
    
             close the connection
            close $conn
    
             if the sideband call returns with data ($recv_data), it'll be the entire HTTP response, so you'll need to parse out what you need
    
             ...process your other logic here
    
        }
    }