WirelessPhreak.com

I like to travel, f*ck with technology, and partake in the occasional tropical drink.
I am also a co-host on The NBD Show podcast.
Follow Me
Showing posts with label iRule. Show all posts
Showing posts with label iRule. Show all posts
With HTML5 and other modern web technologies IE has not aged gracefully. If your client base is an enterprise many times clients are locked into an older version of IE, and aren't allowed to install an auto-updating browser like Chrome or Firefox.

This iRule is strait forward, I am redirecting clients accessing a website using an older versions of IE to a browser friendly version. This is done by evaluating the HTTP request and identifying the browsers user-agent string. As part of the redirect the F5 presents a web page that informs the users their browser is unsupported instead of blindly redirecting them. It will auto redirect after a pre determined count down, this example is set for 15 seconds.

Disclaimer Microsoft does not make this easy, Compatibility modes and Document modes in IE can send a different user-agent string.  For example IE 11 users running in Compatibility mode may still be redirected because their browser sends an MSIE 7.0 user-agent string. I am sure your could right variables that would check for compatibility in the user agent string, but iI chose not to.

Here is the iRule:

when RULE_INIT {
    set static::refresh_time 15
set static::notification_page {
        <html lang=\"en_US\">
<head><title>System Notification</title>
<meta http-equiv=\"Content-Type\" content=\"text/html; charset=us-ascii\">
<meta http-equiv=\"CACHE-CONTROL\" content=\"NO-CACHE\">
<meta http-equiv=\"PRAGMA\" content=\"NO-CACHE\">
<meta http-equiv=\"refresh\" content=\"15;URL=http://myspace.com">
</head>
<body>
<h1>System Notification</h1>
<hr>
<p>You are using an unsupported browser and will be redirected to Myspace.com</p>
<p>Wait $static::refresh_time seconds to continue, or click <a href=\"http://myspace.com\">here to continue.</a></p>
</body>
</html>
}
}
when HTTP_REQUEST {
 switch -glob [ string tolower [HTTP::header User-Agent]] {
   "*msie 10.0*" -
   "*msie 9.0*" -
   "*msie 8.0*" -
   "*msie 7.0*" -
   "*msie 6.*" {
     HTTP::respond 200 content [subst $static::notification_page] Mime-Type "text/html"
     log local0. "Client  IP:[IP::client_addr]  has been redirected with user agent :[HTTP::header User-Agent]"
   }
   default {
     # go to a default location if nothing matches
   }
 }
}
The iRule below was spawn from a request to block access to specific URIs on a website and only allow access from whitelisted IP networks and hosts. 

In my first attempt I used concatenated OR statements which worked but was less sexy and probably less efficient then the switch I ended up using. 

As for the Data List in this example it's named "AllowedIPDatalist." I created a network data list not because it was efficient, its not, I wanted to make it easier for co workers that didn't feel comfortable editing an iRule a place to enter Networks and Hosts in a format they where used to.

when HTTP_REQUEST {
  switch -glob [string tolower [HTTP::uri]] {
    "*/uri/sample1*" -
    "*/uri/sample2*" -
    "*/uri/sample3*" {
      if { !([matchclass [IP::client_addr] equals AllowedIPDatalist])} {
         reject 
         log local0. "Client IP Discard: \ [IP::client_addr]:[TCP::client_port] -> [IP::local_addr]:[TCP::local_port]"
      }
    }  
  }
}

Version 2 GeoIP and Network whitelisting iRule.  

Implementing version 1 of the iRule has highlighted a few short comings.  In version 2 I have added a stop gap measures to manually add IP space to an additional data group.  This allows time for F5's Geo-IP database update process and your companies change managment.

Prior to the deployment of version 1 we identified issues with RFC1918 IP space.  Because private IP space is not defined in the Geo-IP database the version 1 irule blocked server to virtual server communication if sourced from a private IP.  

The second short coming is frequency of Geo-IP database updates.  F5 is timely with their  Geo-IP database updates, but unless your running their Application Firewall Module updating is still a manual process. IP space is being reallocated on a daily basis which means you will always be playing catchup.  This is why I added the manual network data group.  This group can be used as a stop gap as well as letting you add any private IP space you may want to add.

Here is the rule:
# Geo-IP_Network_Whitelist_acl_rule
#
# v2.0 - May 9 2014
#
# BIG-IP versions 11.x (tested on 11.3.8)
#
# Purpose:
#   This rule should be added to a network virtual server to catch all requests
#   which  don't match an allowed GeoIP country code or IP network/host.  This
#   creates a white list of networks and hosts that are allowed to connect to
#   the virtual server. By default, log entries are written to /var/log/ltm.
#
#   The rule expects the following two data groups to define which allowed country
#   codes (example: ca, us), or defined allowed networks (example: 10.0.0.0/8)
#   are allowed to connect to the virtual server.
#
#   Clients that match on either the Network or GeoIP data group will be allowed
#   to connect to the default pool. Clients that do not match will be rejected and
#   see a web page not available.
#
#   The data group names should be:
#
#   geo_allowed_country (string Data Group List)
#   geo_allowed_network (network Data Group List)
#
#
#
#
# This event is triggered when a client - BIG-IP TCP connection is established
when CLIENT_ACCEPTED {
 if { [class match [whereis [IP::client_addr] country] equals geo_allowed_country] } {
    # do nothing
         log local0. "Geo-IP Code accepted from client: \
         [IP::client_addr]:[TCP::client_port] -> [IP::local_addr]:[TCP::local_port]"
 } elseif { [class match [IP::client_addr] equals geo_allowed_network] } {
    # do nothing
         log local0. "Network accepted from client: \
         [IP::client_addr]:[TCP::client_port] -> [IP::local_addr]:[TCP::local_port]"
  } else {
  reject
  log local0. "Client request rejected: \
         [IP::client_addr]:[TCP::client_port] -> [IP::local_addr]:[TCP::local_port]"
 }
}


Enjoy!





I came across an iRule that identifies multiple connection attempts from an IP address and throttle their connection. Because it is an iRule you can completely configure both the connection limit, timeouts, and even the message your F5 will send the user.


when RULE_INIT {
# This is the max requests allowed during "interval" specified below.
set static::maxRate 125;
# Below is the lifetime of the subtable record in seconds.
# This defines the interval during which requests are tallied. Example: Rate=10 and Timeout=3, allows 10 requests in 3 seconds
# Note: do not use very high timeout because it increases memory utilization especially under high load.
# Note: A rate of 100 in 50 seconds is the same is a rate of 20 in 1 second. But 1 second is a lot easier on memory,
# Because the records expire more quickly and the table does become too large.
set static::timeout 3;}
when HTTP_REQUEST {
set getCount [table lookup -notouch -subtable requests [IP::client_addr]]
    if { $getCount equals "" } {
       # log local0. "New one:  getCount=$getCount [IP::client_addr] [clock seconds]"
       table set -subtable requests [IP::client_addr] "1" $static::timeout $static::timeout
       } else {
    if { $getCount < $static::maxRate } {
       table incr -notouch -subtable requests [IP::client_addr]
       } else {
    if {$getCount == $static::maxRate } {
       log local0. "User @ [IP::client_addr] [clock seconds] has reached $getCount requests in $static::timeout seconds."
       table incr -notouch -subtable requests [IP::client_addr]
       }
   HTTP::respond 501 content "We apologize but your request/sec limit has exceeded the set threshold.  Please wait 30 seconds and refresh the page."
   #drop
   #return

Update coming soon a more advanced irule that accounts for rfc1918 ip space as well as data groups that allow multiple geoip country codes.

This iRule will allow you to block requests to your website from IP address that are not from the US. GeoIP blocking is flexible and a way of white listing traffic to your servers.  It does have it's limitations though.

GeoIP Databases change all the time.  To keep the F5   GeoIP database up to date wouldn't be practical.

Some may consider this a security measure. But to limit IP traffic from a limited geographic area is not an affective security measure. Real bad guys will proxy or use un willing victims to carry out their attacks.

when CLIENT_ACCEPTED {
if {not ([whereis [IP::client_addr] country] eq "US")}{
reject
}
}

The following is a list of Country Codes you can test with.