• BIGIP F5 iRule — Server Selection based on Client Source Address and Port

    A interesting request came up today regarding a Web Service we provide to multiple clients, all of whom have peering points connecting their IP network to ours using private address. The request was to have certain clients hit a particular Web box in a Server Pool, while others hitting the other. At the same time only for certain ports. Some of our web applications use a variety of ports because of the proprietary application running. Ports include, all TCP, 80, 443, 5555, 6050.  So I set off to create an iRule to handle this and have it log to show how everything is being mapped, start to finish for each connection.

    A Service little info:

    • Client PAT = 10.99.29.10
    • PrimaryWebCluster = 10.43.1.6
    • Web01 = 10.43.4.231
    • Web02 = 10.43.4.232
    • Ports = 80, 443, 5555, 6050

    iRule: irule_SrvSelection_byClientSrcAndPort

    when CLIENT_ACCEPTED {    
         if { [TCP::local_port] == 80 } {  
            if { [IP::addr [IP::client_addr] equals 10.99.29.10] } {        
            pool pool_ct_primarywebcluster_80 member 10.43.4.231 80
            log local0. "[IP::client_addr] is Web01"            
            } else {        
             pool pool_ct_primarywebcluster_80 member 10.43.4.232 80    
            log local0. "[IP::client_addr] is Web02"          
            }
        }
        if { [TCP::local_port] == 443 } {
            if { [IP::addr [IP::client_addr] equals 10.99.29.10] } {        
            pool pool_ct_primarywebcluster_443 member 10.43.4.231 443
            log local0. "[IP::client_addr] is Web01"            
            } else {        
             pool pool_ct_primarywebcluster_443 member 10.43.4.232 443
            log local0. "[IP::client_addr] is Web02"  
            }
        }
    if { [TCP::local_port] == 5555 } {
            if { [IP::addr [IP::client_addr] equals 10.99.29.10] } {        
            pool pool_ct_primarywebcluster_5022 member 10.43.4.231 5022
            log local0. "[IP::client_addr] is Web01"   
            } else {        
             pool pool_ct_primarywebcluster_5022 member 10.43.4.232 5022
            log local0. "[IP::client_addr] is Web02"  
            }
        }
    }
    
    if { [TCP::local_port] == 6050 } {
            if { [IP::addr [IP::client_addr] equals 10.99.29.10] } {        
            pool pool_ct_primarywebcluster_5022 member 10.43.4.231 5022
            log local0. "[IP::client_addr] is Web01"   
            } else {        
             pool pool_ct_primarywebcluster_5022 member 10.43.4.232 5022
            log local0. "[IP::client_addr] is Web02"  
            }
        }
    }
    when SERVER_CONNECTED {
      log local0. "Connection from [IP::client_addr]:[TCP::client_port]. \
        Mapped to F5 Floating IP [serverside {IP::local_addr}]:[serverside {TCP::local_port}] \
        -->> [IP::server_addr]:[serverside {TCP::remote_port}]"
    }

    And to check, SSH into the Primary F5 in the pair and type bash to give you shell access. (BIGIP v11.5+),

    tailf /var/log/ltm
    
     tmm3[14225]: Rule /Common/irule_SrvSelection_byClientSrcAndPort : 10.99.29.10 is Web02
     tmm3[14225]: Rule /Common/irule_SrvSelection_byClientSrcAndPort : Connection from 10.99.29.10:22524. to VIP 10.43.1.6  -->> 10.43.4.232:443
     tmm3[14225]: Rule /Common/irule_SrvSelection_byClientSrcAndPort : 10.99.29.10 is Web02
     tmm3[14225]: Rule /Common/irule_SrvSelection_byClientSrcAndPort : Connection from 10.99.29.10:10972. to VIP 10.43.1.6  -->> 10.43.4.232:443
     tmm[14225]: Rule /Common/irule_SrvSelection_byClientSrcAndPort : 10.99.29.10 is Web02
     tmm[14225]: Rule /Common/irule_SrvSelection_byClientSrcAndPort : Connection from 10.99.29.10:53187. to VIP 10.43.1.6  -->> 10.43.4.232:443
     tmm2[14225]: Rule /Common/irule_SrvSelection_byClientSrcAndPort : 10.99.29.10 is Web02
     tmm2[14225]: Rule /Common/irule_SrvSelection_byClientSrcAndPort : Connection from 10.99.29.10:15709. to VIP 10.43.1.6  -->> 10.43.4.232:443
     tmm3[14225]: Rule /Common/irule_SrvSelection_byClientSrcAndPort : 10.99.29.10 is Web02
     tmm3[14225]: Rule /Common/irule_SrvSelection_byClientSrcAndPort : Connection from 10.99.29.10:62364. to VIP 10.43.1.6  -->> 10.43.4.232:443
     tmm3[14225]: Rule /Common/irule_SrvSelection_byClientSrcAndPort : 10.99.29.10 is Web02
     tmm3[14225]: Rule /Common/irule_SrvSelection_byClientSrcAndPort : Connection from 10.99.29.10:62496. to VIP 10.43.1.6  -->> 10.43.4.232:443
     tmm[14225]: Rule /Common/irule_SrvSelection_byClientSrcAndPort : 10.99.29.10 is Web02
     tmm[14225]: Rule /Common/irule_SrvSelection_byClientSrcAndPort : Connection from 10.99.29.10:42691. to VIP 10.43.1.6  -->> 10.43.4.232:443
     tmm1[14225]: Rule /Common/irule_SrvSelection_byClientSrcAndPort : 10.99.29.10 is Web02
     tmm1[14225]: Rule /Common/irule_SrvSelection_byClientSrcAndPort : Connection from 10.99.29.10:28510. to VIP 10.43.1.6  -->> 10.43.4.232:443
     tmm3[14225]: Rule /Common/irule_SrvSelection_byClientSrcAndPort : 10.99.29.10 is Web02
     tmm3[14225]: Rule /Common/irule_SrvSelection_byClientSrcAndPort : Connection from 10.99.29.10:40464. to VIP 10.43.1.6  -->> 10.43.4.232:443
     tmm1[14225]: Rule /Common/irule_SrvSelection_byClientSrcAndPort : 10.99.29.10 is Web02
     tmm1[14225]: Rule /Common/irule_SrvSelection_byClientSrcAndPort : Connection from 10.99.29.10:4082. to VIP 10.43.1.6  -->> 10.43.4.232:443
     tmm[14225]: Rule /Common/irule_SrvSelection_byClientSrcAndPort : 10.99.29.10 is Web02
    

    Nice!!

     

  • BIGIP F5 iRule — Block URI for external Client’s only

    So, I had a cool question asked to me today regarding an F5 VIP used by a web application.
    “Can we block a certain URI from external client’s but allow internal client’s to visit it?”

    Of course there is!! Now there are probably a billion different ways to do this, but this is what I came up with. First the condition, we want only 10.0.0.0/8 hosts to be able to access this restricted URI. Anyone else should be dropped. I say dropped and not denied, because that way if a user tries to navigate to the URI that shouldn’t it just timesout, and doesn’t give them any more information then they need. Second, I want to log blocks, so I can see it working and get an idea of how many times it gets hit. Lastly we need to know the Virtual server to apply the iRule to.

    Here is the finished iRule, hope it helps!

    when RULE_INIT {
    	set static::drop_notallowed 0
    
    }
    
    when CLIENT_ACCEPTED {
    	if {not [IP::addr [IP::client_addr] equals 10.0.0.0/8]} {
                    log local0. "[IP::client_addr] does not match 10.0.0.0/8 AND access URI = /restricted-URI/"
    		set static::drop_notallowed 1
    	}
    }
    
    when HTTP_REQUEST {
    	if { [string tolower [HTTP::uri]] starts_with "/restricted-URI" }{
    		if {$static::drop_notallowed==1}{
    			drop
    		}
    	}
    
    }

     

    [Read More…]

  • BIGIP F5 iRule — Return Splash Page When No Members Are Available

    I wrote a iRule post located here, where I describe the essentials behind how beneficial iRules can be and the many use cases they have. I stumbled across a situation the other day for a client. This client had an F5 VIP load balancing 2 web servers of theirs. Now if those web servers for some reason are not available due to their healthcheck monitor failing, the users of that web site will receive a white page as the F5 will not proxy the traffic because there are no available pool members. I thought what if this was a big site, should users be left in the dark about a web site they use frequently when it’s not available? Then the idea of having the F5 LTM bounce back a well-formed splash page. This splash page would inform the user that the web site temporarily down, and if they believe this result is in error to contact their helpdesk.

    This situation can be remedied with a couple of lines in an iRule.

    when HTTP_REQUEST {
        #check if no members available
        if { [active_members [LB::server pool]] == 0 } {
           #create data variables with HTML content to send to client
           set httphost [string tolower [HTTP::host]]
           set data "

    $httphost

    NOTICE: Site Unavailable.

    If you believe you are receiving this message in error, contact your site administrator.

    " #send string HTTP::respond 200 content $data } #unset variables unset $httphost unset $data }

     

    Or:

    when HTTP_REQUEST {
       #check if no members available
       if { [active_members [LB::server pool]] == 0 } {
          HTTP::respond 200 content {
          
          Unavailable
          
          

    If you believe you are receiving this message in error, contact your site administrator.

    } #end of content block }

     
    This iRule uses the when HTTP_REQUEST event, and the HTTP::respond function. You could also use the HTTP::redirect function, however for something as small as a few lines, might as well have the F5 handle it directly.

    You could easily use links from other sources to make a more authentic looking page for your users.

  • BIGIP F5 iRules — What are they?

    What is an iRule? What are iRules? What can I do with iRules? What is an iRule example?

    One of the most advantageous features that an BIG IP F5 Local Traffic Manager brings is it’s iRule feature. This feature allows the F5 to manipulate and perform event driven functions to the application traffic as it passes through the F5 LTM. This is very useful and has many use cases. For example, a common iRule is as follows. Let’s say you have a typical load balancing setup, with 5 web servers being balanced in a round robin fashion. The traffic that passes through is HTTP. For security purposes only HTTP-SSL is allowed to this site, however you don’t want users to have to remember to put https:// rather than http:// in their internet browser’s address bar. Instead of putting a redirect page on the port 80(insecure) instance on each of the 5 web servers, a simple iRule will take care of that!

    Example HTTP to HTTPS redirect iRule:

    #my first iRule
    when HTTP_REQUEST {
        HTTP::redirect "https://[HTTP::host][HTTP::uri]"
    }

     

    When we look at this iRule we see a few things. We see an event that must be triggered in order to for the iRule to execute, “when HTTP_REQUEST“. Next we see a HTTP redirect function being performed with a few parameters. HTTP::redirect is the function and the target URL string “https://[HTTP::host][HTTP::uri]”. Let’s break this statement down as it is the meat and potatoes of the iRule.

    https:// is what protocol to send the users browser when it performs the redirect.

    [HTTP::host] which is derived from the clients host-header as it comes across to the F5 LTM. The host header is set when you open a new browser and type the domain/host you are requesting to go to. For example, if you type http://www.google.com in your browser, when you hit enter in the HTTP stream the host-header is set to www.google.com. This is essential when using SSL, but more on that in another post.

    [HTTP::uri] the last part is the URI the user is trying to GET. If this is a standalone site such as www.mysite.com, usually users will hit that first and be redirect already via our iRule before they browse to any URIs. However, perhaps a user tries to go to http://yousite.com/URI, they are not coming across HTTPS so the iRule will intercept it and redirect them to https://yoursite.com, but wait we don’t want them to get kicked back to the root of the site, so the [HTTP::uri] is appended to the redirect target string.

    URIs vs URLs:
    You will see people use these interchangeably, or used in-properly. Even Wikipedia’s article on them is confusing. Since I’ve been an IT engineer working in web-centric environments a URI is what is appended at the end of the host or FQDN, and a URL is the whole thing.

    So,
    http://en.wikipedia.org/wiki/Computer

    FQDN = en.wikipedia.org
    URI = wiki/Computer
    URL = http://en.wikipedia.org/wiki/Computer

↓