Cisco ASA Deny Access-List

Does the Cisco ASA send a reset when a packet is denied by configured access-list ?

This depends on the configuration of the access-list – is it applied for inbound or outbound traffic on an interface & if there is any “service reset” command as specified here:

service resetinbound:
Sends TCP resets for all inbound TCP sessions that attempt to transit the adaptive security appliance and are denied by the adaptive security appliance based on access lists or AAA settings.

service resetoutbound: (Default)
Sends TCP resets for all outbound TCP sessions that attempt to transit the adaptive security appliance and are denied by the adaptive security appliance based on access lists or AAA settings.

service resetoutside:
Enables resets for TCP packets that terminate at the least secure interface and are denied by the adaptive security appliance based on access lists or AAA settings.

resetinbound ----> Send reset to a denied inbound TCP packet
resetoutbound ----> Send reset to a denied outbound TCP packet
resetoutside ----> Send reset to a denied TCP packet to outside interface

By default (service resetoutbound), Cisco ASA sends an explicit TCP reset for connections terminating at the Cisco ASA Firewall, if it is denied by access-list that is configured to block outbound connections like this:

access-list OUT line 1 extended deny ip host 1.1.1.1 host 2.2.2.2
access-group OUT out interface outside

For the same access-list, if it is configured for inbound access-list, the connection will be dropped without any discard being sent out:

access-list OUT line 1 extended deny ip host 1.1.1.1 host 2.2.2.2
access-group OUT in interface outside

Reference:

Service Reset – Cisco ASA

F5 iRule – User Agent


when HTTP_REQUEST {
set HOST [string tolower [HTTP::host]]

if { ($HOST eq "domain.com" || $HOST eq "www.domain.com" ) and 
         ([HTTP::header User-Agent] contains "Chrome/33.0.175") and
            ([HTTP::header User-Agent] contains "(X11; Linux x86_64)") } {
                reject
               }
}

The above iRule will enable the F5 to send a TCP RST (reset) to the client for a specific domain and specific User-Agent information within the incoming HTTP Request.

F5 Monitor Status Code

F5 performs health-checks or monitors by utilizing the status code or the content in the response from the servers to mark the server as UP or DOWN.

It is relatively easy to mark the server UP/DOWN by using a single status code in the “Receive String” attribute within the Monitor:

200 OK

If you want to mark a server up for multiple status code like using 200-209, you can use this:

HTTP/1.[01] [2]0[0-9]

In order to mark the server UP for status code 200-209 or 401

HTTP/1.[01] ([2]0[0-9]|401)

F5_Monitor_Status

 

F5 iRule – URI Encoded


when HTTP_REQUEST {

if { [active_members [LB::server pool]] < 1 } {

set STATIC_SORRY [URI::decode "%3C!DOCTYPE%20HTML%3E%0A%3Chtml%3E%0A%3Chead%3E%0A%3Cmeta%20charset%3D%22UTF-8%22%3E%0A%3Ctitle%3EOops!%20We%27ll%20be%20back%20shortly%3C%2Ftitle%3E%0A%3Cstyle%3E%0A*%20%7B%09margin%3A0%3Bpadding%3A%200%3B%7D%0Ahtml%2C%20body%7B%20height%3A100%25%3B%20color%3A%20%23333%3B%20font-family%3AHelvetica%2C%20Arial%2C%20sans-serif%3B%7D%0A.wrapper%20%7Bmax-width%3A%20960px%3Bwidth%3A100%25%3Bmargin%3A0%20auto%3Bdisplay%3Atable%3Bheight%3A100%25%3B%7D%0A.container%20%7Bdisplay%3A%20table-cell%3Bvertical-align%3A%20middle%3Btext-align%3Acenter%3B%7D%0Ah1%20%7Bfont-size%3A60px%3B%7D%0Ah2%20%7Bfont-weight%3Anormal%3Bfont-size%3A60px%3Bmargin-bottom%3A0.36em%3B%7D%0Ap%20%7Bline-height%3A1.4em%3Bmargin%3A0%200%201.3em%200%3B%7D%0A%3C%2Fstyle%3E%0A%3C%2Fhead%3E%0A%3Cbody%3E%0A%3Cdiv%20class%3D%22wrapper%22%3E%0A%3Cdiv%20class%3D%22container%22%3E%0A%3Ch1%3EOops!%3C%2Fh1%3E%0A%3Ch2%3EWe%27ll%20be%20back%20shortly.%3C%2Fh2%3E%0A%3Cp%3ESorry%20for%20the%20inconvnience%2C%20please%20try%20again%20in%20a%20few%20minutes%3C%2Fp%3E%0A%3C%2Fdiv%3E%0A%3C%2Fdiv%3E%0A%3C%2Fbody%3E%0A%3C%2Fhtml%3E"]

HTTP::respond 200 content $STATIC_SORRY
}
}

The above iRule can be utilized in order to serve a sorry page when all the pool members in the default pool (pool attached to the Virtual Server) are down.

The “STATIC_SORRY” is a variable that contains the URI Encoded version of the Sorry Page. Encoding the sorry page would help is the normal HTML page is not accepted by the F5. F5 can be finicky and not accept any HTML page that contains non-English characters. Hence, URI Encoded page can be of help in these cases.

This page can be utilized to encode the Sorry Page: URI Encoder/Decoder

F5 iRule – Serving Sorry Image

There are 3 steps to creating the F5 iRule to serve the image of a sorry page. Serving image of sorry page is utilized when you need to serve non-English characters which may not be compatible with F5. Of course, you can use it even for simple sorry pages with English characters.

There are 3 main steps:

  • Create a base64 image of the original Sorry Page Image
  • Create a datagroup that references the base64 Sorry Page Image
  • Create an iRule that reference the datagroup and attach this to the Virtual Server that requires the Sorry Page iRule.

 

Create a base64 image of the original Sorry Page Image:

  1. Copy the image (SORRY_IMAGE.png – this should be less than 46KB in size) onto F5’s directory /var/tmp/SORRY_IMAGE.png
  2. The following command should be copied to the F5 shell as a single line in order to create the base64 image
    echo \"SORRYIMAGE\" \:\= \"`base64 /var/tmp/SORRY_IMAGE.png | xargs echo | sed 's/ //g'`\"\, > /var/class/SORRY.class
  3. Check /var/class/SORRY.class
    [root@f5-ltm:Active] config # head /var/class/SORRY.class
    "SORRYIMAGE" := "iVBORw0KGgoAAAANSUhEUgAABAAAAAMACAMAAACNZOU/A ...... <<remaining output omitted>>

 

Create a datagroup that references the base64 Sorry Page Image via GUI:

Name: SORRY_PAGE
Partition: Common
Type: (External File)
Path / Filename: /var/class/SORRY.class
File Contents: String
Key/Value Pair Separator: :=
Access Mode: Read/Write

 

Create an iRule:

when HTTP_REQUEST {
  if { ([active_members [LB::server pool]] < 1)} {
      HTTP::respond 503 content [b64decode [class element -value 0 SORRY_PAGE]]
      event disable
     }
}

iRule references the datagroup SORRYPAGE which references the file /var/class/SORRY.class and this contains the base64 image of the sorry page. SORRY_IMAGE.png which is utilized to create the base64 image should not be more than 46KB. This is a limitation on the F5 LTM.

 

iRule – Persistence Across HTTP Method


when HTTP_REQUEST {
set HOST [string tolower [HTTP::host]]

#Persistence is enabled for specific domain
if { $HOST equals "domain.com" }{

#Persistence for GET Request
if { [HTTP::method] equals "GET" } {
set SESSIONID [findstr [HTTP::uri] "uuid=" 5 20]
set KEY [crc32 $HOST$SESSIONID]

persist hash $KEY 30

#Collect Data upto Content Length or 1048
} elseif { (([HTTP::method] equals "POST") and ([HTTP::uri] contains "/ptm/tentxml.jsp")) } {

if {[HTTP::header "Content-Length"] ne "" && [HTTP::header "Content-Length"] <= 1048 } {
HTTP::collect $CONTENT
}
}
}

}

#Persist based on information available in the POST data
when HTTP_REQUEST_DATA {
if { (([HTTP::method] equals "POST") and ([HTTP::uri] contains "/ptm/tentxml.jsp")) } {

set HOST [string tolower [HTTP::host]]
set SESSIONID [findstr [HTTP::payload] "uuid=" 5 20]
set KEY [crc32 $HOST$SESSIONID]

persist hash $KEY 30
}
}

In the above iRule, persistence is maintained across HTTP GET & POST Methods. The Session id is present within:

URI of GET Request

POST Data

Persistence key is a combination of the domain & session id – set KEY [crc32 $HOST$SESSIONID]

In order to identify the Session id within the POST data, we will be collecting the data of size defined by the “Content-Length” header or default of 1048 bytes.

The iRULE would have to be utilized within an UIE persistence profile with “Match Across Services” for persistence across HTTP & HTTPS Virtual Servers.

 

F5 Cookie Persistence

This is  a good read on how to configure Cookie Persistence on F5 LTM: Cookie Persistence – F5

Cookie Insert:

When you create a normal cookie persistence profile using GUI:

lbal4(Active)(tmos.ltm)# list persistence cookie PROF-COOKIE-INSERT

ltm persistence cookie PROF-COOKIE-INSERT {
defaults-from cookie
}

When you update the existing session cookie via GUI:

ltm persistence cookie PROF-COOKIE-INSERT {
cookie-name BIGIP-F5
defaults-from cookie
expiration 10:0
method insert
timeout 180
}

In the above example, expiration timer is set to 10 minutes. The expiration timer will refresh as long as new requests are sent to the F5 within the 10 minute interval.

The “timeout 180” is just an addition that is seen but doesn’t hold any meaning for cookie persistence (Insert, Passive & Rewrite) as outlined in this document: SOL13069

Expiration:

Specifies the cookie expiration date in the format d:h:m:s, h:m:s, m:s or seconds. Hours 0-23, minutes 0-59, seconds 0-59. The
time period must be less than 24856 days. You can use “session-cookie” (0 seconds) to indicate that the cookie expires when the
browser closes.

F5 LTM Caching 10.x Code

An overview on F5 LTM Caching for 10.x code version

 

F5 LTM Cache

  • F5 LTM RAM Cache is used to cache HTTP objects in the F5’s RAM.
  • High Demand HTTP objects / Static Content can be stored on the F5 and served till the expiration period for the object.
  • RAM Cache feature in F5 is compliant with RFC 2616.

 

F5 LTM Cache Eligibility

  • Any response with the following status code 200, 203, 206, 300, 301 and 410 to a GET request, is cached by default.
  • Any non-GET method request to URI can be cached by adding the URI to the “Include List” or “Pin List” Difference between “Include List” and “Pin List”
  • Both Lists are used to store objects that are NOT cached by default.
  • “Pin List” will store the object, ignoring the expiry information provided by the header. The object will be cached even after the expiry timer – like a permanent cache. “Include List” will store the object, honoring the Cache headers.

Exclude List

  • Any object that can be stored by the F5 LTM cache, by default (GET Request + relevant status code) can be “excluded” from being cached by adding it to this list.

If you want to enable or disable caching, use an iRULE along with     HTTP Caching profile:


     
when HTTP_REQUEST {    

                  if { [HTTP::uri] starts_with "/static" } {          

                          CACHE::disable

        }

    }

With Caching enabled on the HTTP profile, the above iRULE will cache any valid object (defined by HTTP profile) but will NOT cache requests with “/static” uri, even if they satisfy the cache requirement.

 

NOTE

When you use “CACHE::enable” for any iRule, it will cache the relevant object even if the response headers prevent it from being cached. I would recommend using reverse logic – Use “Cache::disable” for any object that should NOT be cached and any object that should be cached will be taken care by the HTTP Caching profile based on the response headers.

Cache Control Headers

HTTP headers that are given importance by F5 LTM as per RFC:

  • Expires
  • Last-Modified
  • Cache-Control

Cache-Control

HTTP 1.1 introduced a new class of headers, Cache-Control response headers, to give Web publishers more control over their content, and to address the limitations of Expires.

Useful Cache-Control response headers include:

max-age=(seconds) — specifies the maximum amount of time that an representation will be considered fresh. Similar to Expires, this directive is relative to the time of the request, rather than absolute. Seconds is the number of seconds from the time of the request you wish the representation to be fresh for.

s-maxage=(seconds) — similar to max-age, except that it only applies to shared (e.g., proxy) caches.

public — allows caches (shared and private) to store the response.

private — allows caches that are specific to one user (e.g., in a browser) to store the response; shared caches (e.g., in a proxy) may not.

no-cache — forces caches to submit the request to the origin server for validation before releasing a cached copy, every time. This is useful to assure that authentication is respected (in combination with public), or to maintain rigid freshness, without sacrificing all of the benefits of caching.

no-store — instructs caches not to keep a copy of the representation under any conditions.

must-revalidate — tells caches that they must obey any freshness information you give them about a representation. HTTP allows caches to serve stale representations under special conditions; by specifying this header, you’re telling the cache that you want it to strictly follow your rules.

proxy-revalidate — similar to must-revalidate, except that it only applies to proxy caches.

For example:

Cache-Control: max-age=3600, must-revalidate

When both Cache-Control and Expires are present, Cache-Control takes precedence.

 This is a good document about Caching – Caching Tutorial

 

F5 RAM Cache Setting

In this case, default “HTTP” profile is used as a parent profile for the “PROF_HTTP_CACHE” custom profile.

F5-LTM-Cache-2

In this example, a snapshot of F5 Cache Settings is provided:

F5-LTM-Cache-1

RAM Cache: This needs to be Enabled for Caching to be implemented.

Maximum Cache Size: Total memory that is used for caching by this profile.

Maximum Entries: Number of HTTP objects that is cached.

Maximum Age: This is the duration till which the HTTP object is cached. Regardless of this value, RAM Cache will flush any object that is considered to be “expired” based on the Cache Control Headers.

Minimum Object Size: Any object that is equal to or greater than this value can be cached, if its headers allow it to be cached.

Maximum Object Size: Any object that is equal to or lesser than this value can be cached, if its headers allow it to be cached.

Ignore Headers: These are specific Headers that are provided by the Client-side, if Client requries “fresh/non-cached” objects. By default, it is set to ignore these Client Side headers (Ignore Headers : ALL). In effect, even if the Client requires a “non-cached” object, F5 can serve a cached object, provided such an object exists in its RAM Cache. If you want F5 to obey client-side cache-control headers, set “Ignore Headers : None”.

An Example

  • HTTP Server has to be configured to serve the HTTP objects with the correct Header for caching.

This link can be used to test out the “Cacheability” of a site:

http://redbot.org/

For any cache-able resource this MUST exist in order to honor caching:

  • “Expires” or “Cache-Control” header MUST exist
  • “Last-Modified” or “ETag” header MUST exist

In the above Header list, “ETag” is not considered by F5 LTM. So, for caching on F5:

  • “Expires” or “Cache-Control”
  • “Last-Modified”

Caching will occur even without the above headers but in that case, it is tough to control the expiry time and each proxy has its own algorithm to determine the cache-ability of an object and this is not optimum. While troubleshooting, make sure that the server’s response contains the headers specified.

If you use a specific HTTP link, the response provides information on the Header:

https://redbot.org/?uri=http%3A%2F%2Fwww.yahoo.com

You can move the cursor on the specific headers to get more information on the specific headers.

Cached Header Response

In this example, the “Date” and “Age” headers were inserted by the F5 to indicate the “Date” at which the F5 received the HTTP request and the “Age” of the cached object that was served. If Client should not see these values, then you can disable it under the “Insert Age Header” variable in the F5’s HTTP profile that is used for enabling caching.

$ curl -vk http://domain.com

> GET / HTTP/1.1

> User-Agent: curl/7.18.2 (x86_64-pc-linux-gnu) libcurl/7.18.2 OpenSSL/0.9.8g        zlib/1.2.3.3 libidn/1.10

> Host: blog.corporationwiki.com

> Accept: */*

< HTTP/1.1 200 OK

< Cache-Control: max-age=3600, must-revalidate

< Content-Type: text/html; charset=UTF-8

< Last-Modified: Thu, 12 Jan 2012 20:07:56 GMT

< Vary: Accept-Encoding, User-Agent< Server: Microsoft-IIS/7.5

< X-Powered-By: PHP/5.2.17

< WP-Super-Cache: Served supercache file from PHP

< X-Powered-By: ASP.NET< Accept-Ranges: bytes

< Connection: Keep-Alive

< Date: Thu, 12 Jan 2014 21:07:01 GMT <<<—–

< Age: 289 <<<< ——

< Content-Length: 37089

Vary Header

In the above example, Vary header has the following information:

Vary: Accept-Encoding, User-Agent

This tells the cache that the cached object is specific to the “User-Agent”. If you open up a browser (say, FF) and access the URL with HTTP objects that can be cached, it will be cached by the F5 LTM. If you access the same URL, from the same User-Agent (FF), you will be served with the cached HTTP objects.

On the other hand, if you open up a browser (say, FF) and access the URL with HTTP objects that can be cached, it will be cached by the F5 LTM. Now, if you access the same URL but from a different User-Agent (say, IE), the cached object will NOT be served. The cached objects are specific to FF (User-Agent) and there is no cache object for IE, for the specific URL requested and the request will be directed to the server. Basically, the content cached by F5 is unique to each User-Agent because of the Vary Header.

NOTE: F5 LTM honors only Accept-Encoding & User-Agent as Vary Header values. Any other value will be ignored.

This is a good blog to understand Vary Header and Caching