Migrate iRules to Avi
Migrate Your iRules to a Modern ADC Platform
Nathan McMahon, Avi Networks
nathan@avinetworks.com
www.avinetworks.com
Dataplane scripting – Powerful but brittle
foreach header {"Location" "Content-Location" "URI"} {
set protocol [URI::protocol [HTTP::header $header]]
if { $static::ProxyPassDebug > 1 } {
log local0. "$log_prefix: Checking $header=[HTTP::header $header], $protocol=$protocol"
}
if {$protocol ne ""} {
set server_path [findstr [HTTP::header $header] $host_serverside [string length $host_serverside]]
if {$server_path starts_with $path_serverside} {
if { $static::ProxyPassDebug } {
log local0. "$log_prefix: Changing response header $header: [HTTP::header $header] with $protocol://$host_clientside$path_clientside[substr $server_path [string length $path_serverside]]"
}
HTTP::header replace $header $protocol://$host_clientside$path_clientside[substr $server_path [string length $path_serverside]]
}
}
}
# Rewrite any domains/paths in Set-Cookie headers
if {[HTTP::header exists "Set-Cookie"]}{
array unset cookielist
foreach cookievalue [HTTP::header values "Set-Cookie"] {
set cookiename [getfield $cookievalue "=" 1]
set namevalue ""
set newcookievalue ""
foreach element [split $cookievalue ";"] {
set element [string trim $element]
if {$namevalue equals ""} {
set namevalue $element
} else {
if {$element contains "="} {
set elementname [getfield $element "=" 1]
set elementvalue [getfield $element "=" 2]
if {[string tolower $elementname] eq "domain"} {
set elementvalue [string trimright $elementvalue "."]
if {$host_serverside ends_with $elementvalue} {
if {$static::ProxyPassDebug > 1} {
log local0. "$log_prefix: Modifying cookie $cookiename domain from $elementvalue to $host_clientside"
}
set elementvalue $host_clientside
}
append elementvalue "."
}
if {[string tolower $elementname] eq "path"} {
if {$elementvalue starts_with $path_serverside} {
if {$static::ProxyPassDebug > 1} {
log local0. "$log_prefix: Modifying cookie $cookiename path from $elementvalue to $path_clientside[substr $elementvalue [string length $path_serverside]]"
}
set elementvalue $path_clientside[substr $elementvalue [string length $path_serverside]]
}
}
append newcookievalue "; $elementname=$elementvalue"
} else {
append newcookievalue "; $element"
}
}
}
set cookielist($cookiename) "$namevalue$newcookievalue"
}
HTTP::header remove "Set-Cookie"
foreach cookiename [array names cookielist] {
HTTP::header insert "Set-Cookie" $cookielist($cookiename)
if {$static::ProxyPassDebug > 1} {
log local0. "$log_prefix: Inserting cookie: $cookielist($cookiename)"
}
}
}
}
when SERVER_CONNECTED {
if {$bypass} {
return
}
set class_exists_cmd "class exists ProxyPassSSLProfiles"
if {! [eval $class_exists_cmd]} {
return
}
set pool [LB::server pool]
set profilename [findclass $pool ProxyPassSSLProfiles " "]
if {$profilename eq ""} {
if { [PROFILE::exists serverssl] == 1} {
# Hide this command from the iRule parser (in case no serverssl profile is applied)
set disable "SSL::disable serverside"
catch {eval $disable}
}
return
}
if { $static::ProxyPassDebug > 0 } {
log local0. "$log_prefix: ServerSSL profile $profilename assigned for pool $pool"
}
if { [PROFILE::exists serverssl] == 1} {
# Hide these commands from the iRule parser (in case no serverssl profile is applied)
set profile "SSL::profile $profilename"
catch {eval $profile}
set enable "SSL::enable serverside"
catch {eval $enable}
} else {
iRule
DataScript
Migration of iRules to Avi
when HTTP_REQUEST {
HTTP::redirect “https://site.com”
}
Feature
Policy
Very easy to use
Minimal flexibility
Easy to use
Some flexibility
More effort
Most flexible
AviF5
iRule
DataScript
HTTP to HTTPS Redirect
when HTTP_REQUEST {
HTTP::redirect “https://site.com”
}
-- HTTP Request Event
avi.http.redirect(“https://site.com”)
Feature
Policy
AviF5
Survey Question!
How many iRules do you have deployed in your organization?
N / A
0 - 9
10 - 99
100+
BARE METAL VIRTUALIZED CONTAINERSON PREMISES PUBLIC CLOUDVIRTUALIZED CONTAINERS
Scalable Architecture
Scale up and scale out data plane resources to handle complex rule logic
CONTROLLERS
SERVICE ENGINES
Content Switch
• Use Case: Assign content to specified pools, such as images sent to caches
when HTTP_REQUEST {
if {[HTTP::uri] starts_with "/development" } {
pool pool_development
} elseif {[HTTP::uri] starts_with "/marketing" } {
pool pool_marketing
} elseif {[HTTP::uri] starts_with "/support" } {
pool pool_support
}
else {
discard
}
}
Example Use Cases
HTTP to HTTPS redirect
HTTP content switch
1. HTTP Request throttle
2. Persist on a session ID
3. Trace a user session
4. Insert client SSL cert into header
5. ProxyPass
6. HTTP server reselect
7. Maintenance page
8. Load balancing URIs
9. A/B server testing
10.DNS domain name switch
HTTP Request Throttle
• Use Case: Limit the number of HTTP requests from a client over a period of time
• Identify Client: IP address, username, session ID, or custom identifier
• Throttle Action: Throttle the number of requests per time period, return a custom page, custom
response code, or redirect to an alternate location
when RULE_INIT {
array set ::active_clients { }
}
when CLIENT_ACCEPTED {
set client_ip [IP::remote_addr]
if { [info exists ::active_clients($client_ip)] } {
if {$::active_clients($client_ip) > 10 } {
log "Client $client_ip has too many connections" reject return }
else {
log local0. "$::active_clients($client_ip)“
incr ::active_clients($client_ip) }
}
else { set ::active_clients($client_ip) 1 }
}
when CLIENT_CLOSED { if { [info exists ::active_clients($client_ip)] } {
incr ::active_clients($client_ip) -1
if { $::active_clients($client_ip) <= 0 } {
unset ::active_clients($client_ip) }
}
}
Persist on a Session ID
• Use Case: Leverage a server’s existing session cookies to identify and persist clients
• Pick Persist > App Cookie method and type in the name of the session ID
• Avi will inspect both the headers and cookies for the session ID
when HTTP_REQUEST {
If {[HTTP::cookie exists “JSessionID”] } {
persist uie [HTTP::cookie “JSessionID”]
} else {
set jsessionid [findstr [HTTP::uri] “JSessionID” 17
“;”]
if { $jsessionid != “” } {
persist uie $jsessionid
}
}
}
when HTTP_RESPONSE {
if {[HTTP::cookie exists “JSessionID”] } {
persist add uie [ HTTP::cookie “JSessionID”]
}
}
Trace a User Session
• Use Case: Log, filter, and search for a complete user session
• Avi can log every connection or request, or log only sessions of interest
• Search through logs via IP address, session ID, or user ID
when CLIENT_ACCEPTED {
set info "client { [IP::client_addr]:[TCP::client_port] -> [IP::local_addr]:[TCP::local_port] }"
append info " ethernet { [string range [LINK::lasthop] 0 16] -> [string range [LINK::nexthop] 0 16] tag [LINK::vlan_id] qos [LINK::qos] }"
log local0. $info
}
when LB_SELECTED {
set info "client { [IP::client_addr]:[TCP::client_port] -> [clientside {IP::local_addr}]:[clientside {TCP::local_port}] }"
catch { append info " server { [IP::local_addr]:[TCP::local_port] -> [IP::server_addr]:[TCP::server_port] }" }
append info " ethernet { [string range [LINK::lasthop] 0 16] -> [string range [LINK::nexthop] 0 16] tag [LINK::vlan_id] qos [LINK::qos] }"
log local0. $info
}
when SERVER_CONNECTED {
set info "client { [IP::client_addr]:[TCP::client_port] -> [clientside {IP::local_addr}]:[clientside {TCP::local_port}] }"
append info " server { [IP::local_addr]:[TCP::local_port] -> [IP::server_addr]:[TCP::server_port] }"
append info " ethernet { [string range [LINK::lasthop] 0 16] -> [string range [LINK::nexthop] 0 16] tag [LINK::vlan_id] qos [LINK::qos] }"
log local0. $info
}
when HTTP_REQUEST {
set info "client { [IP::client_addr]:[TCP::client_port] -> [clientside {IP::local_addr}]:[clientside {TCP::local_port}] }"
catch { append info " server { [serverside {IP::local_addr}]:[serverside {TCP::local_port}] -> [IP::server_addr]:[TCP::server_port] }" }
append info " ethernet { [string range [LINK::lasthop] 0 16] -> [string range [LINK::nexthop] 0 16] tag [LINK::vlan_id] qos [LINK::qos] }"
append info " - [HTTP::method] [HTTP::uri] [HTTP::version]"
append info " *TCP MSS [TCP::mss], BW [TCP::bandwidth], RTT [TCP::rtt], OFFSET [TCP::offset]"
append info " *IP TOS [IP::tos], HOPS [IP::hops], TTL [IP::ttl], PKTS_IN [IP::stats pkts in], PKTS_OUT [IP::stats pkts out], BYTES_IN [IP::stats bytes in], BYTES_OUT [IP::stats bytes out]"
append info " *HTTP HOST [HTTP::host], KEEPALIVE [HTTP::is_keepalive], REQ_NUM [HTTP::request_num]"
append info " *HTTP PATH [HTTP::path], QUERY [HTTP::query]"
log local0. $info
}
when HTTP_RESPONSE {
set info "client { [IP::client_addr]:[TCP::client_port] -> [clientside {IP::local_addr}]:[clientside {TCP::local_port}] }"
append info " server { [IP::local_addr]:[TCP::local_port] -> [IP::server_addr]:[TCP::server_port] }"
append info " ethernet { [string range [LINK::lasthop] 0 16] -> [string range [LINK::nexthop] 0 16] tag [LINK::vlan_id] qos [LINK::qos] }"
append info " - [HTTP::status] [HTTP::version] - REDIR [HTTP::is_redirect], Content-Length [HTTP::header Content-Length], Transfer-Encoding [HTTP::header Transfer-Encoding]"
Insert Client SSL Cert into Header
• Use Case: Insert the client’s SSL certificate into request headers sent to server
• Avi can authenticates clients via their client SSL certificates
• Any component or the entire client cert may be insert into a header
class secure_uri {
/humanresources
/confidential
/private
}
when CLIENTSSL_CLIENTCERT {
HTTP::release
if { [SSL::cert count] < 1 } {
reject
} }
when HTTP_REQUEST {
if { [matchclass [HTTP::uri] starts_with ::secure_uri] } {
if { [SSL::cert count] <= 0 } {
HTTP::collect
SSL::authenticate always
SSL::authenticate depth 9
SSL::cert mode require
SSL::renegotiate
} } }
when HTTP_REQUEST_SEND {
clientside {
if { [SSL::cert count] > 0 } {
HTTP::header insert "X-SSL-Session-ID" [SSL::sessionid]
HTTP::header insert "X-SSL-Client-Cert-Status” [X509::verify_cert_error_string [SSL::verify_result]]
HTTP::header insert "X-SSL-Client-Cert-Subject“ [X509::subject [SSL::cert 0]]
HTTP::header insert "X-SSL-Client-Cert-Issuer“ [X509::issuer [SSL::cert 0]]
} } }
if {[regexp -nocase $regex "$orig_host$orig_uri" 0 1 2 3 4 5 6 7 8 9]}{
# The clientside becomes the matched string and the serverside the substitution
set clientside $0
set serverside [eval set X $rewrite]
} else {
pool $default_pool
return
}
}
if {$clientside starts_with "/"} {
# No virtual hostname specified, so use the Host header instead
set host_clientside $orig_host
set path_clientside $clientside
} else {
# Virtual host specified in entry, split the host and path
set host_clientside [getfield $clientside "/" 1]
set path_clientside [substr $clientside [string length $host_clientside]]
}
# At this point $host_clientside is the client hostname, and $path_clientside
# is the client-side path as specified in the data group
set host_serverside [getfield $serverside "/" 1]
set path_serverside [substr $serverside [string length $host_serverside]]
ProxyPass
• Use Case: Translate between the external and internal site names
• Rewrite client requests, such as their URI and hostnames to something the server is
expecting. Then reverse the process with the response traffic
• Avi automatically handles rewriting server redirects to the name used by the client. Throw in
a policy or two for more robust cookie name or HTML content rewrite
www.oldsite.com www.newsite.com
HTTP Server Reselect
• Use Case: Don’t let an errant server error be sent to a client
• If a server sends out an error, such as 503 (server busy),
Avi will retry the request with another server in the pool
when HTTP_REQUEST {
set my_url [HTTP::host][HTTP::uri]
if { [HTTP::cookie BIGIP] contains "Redirect" } {
set count [findstr [HTTP::cookie BIGIP] "Redirect_" 9 1]
} else {
set count 0
}
}
when HTTP_RESPONSE {
if { [HTTP::status] == 500 && $count < 4 } {
incr count
HTTP::respond 302 Location "http://$my_url" Set-Cookie “self=Redirect_$count"
Connection "Close"
} elseif { [HTTP::status] == 500 && $count == 4 } {
set count 0
HTTP::respond 404 Set-Cookie "BIGIP=Not_Found" Connection "Close"
}
}
}
Maintenance Page
• Use Case: Display a friendly error page when a site is down for maintenance
• Upload a custom web page within the HTTP policies
• Disable the policy after the maintenance period is over
when HTTP_REQUEST {
set my_url [HTTP::host][HTTP::uri]
if { [HTTP::cookie BIGIP] contains "Redirect" } {
set count [findstr [HTTP::cookie BIGIP] "Redirect_" 9 1]
} else {
set count 0
}
}
when HTTP_RESPONSE {
if { [HTTP::status] == 500 && $count < 4 } {
incr count
HTTP::respond 302 Location "http://$my_url" Set-Cookie “self=Redirect_$count"
Connection "Close"
} elseif { [HTTP::status] == 500 && $count == 4 } {
set count 0
HTTP::respond 404 Set-Cookie "BIGIP=Not_Found" Connection "Close"
}
}
}
Load Balance URIs
• Use Case: Distribute and persist requests across servers based on URI
• Clients requests can be load balanced based on criteria such as requested URI
– Select Pool > Load Balance algorithm > Consistent Hash > URI
– F5 has an equivalent feature, but it only works when paired with an iRule
– Avi provides the most common values as sub-options for the LB method.
when HTTP_REQUEST {
set Highest_Score 0
set Node_Picked ""
foreach check_addr $::carp_list {
log local0. "Node: $check_addr Score: [expr [crc32 $check_addr[HTTP::host][HTTP::uri]] % 1000]"
if { [expr [crc32 $check_addr[HTTP::host][HTTP::uri]] % 1000] > $Highest_Score } {
# Highest score so far, store new high score and record node
set Highest_Score [expr [crc32 $check_addr[HTTP::host][HTTP::uri]] % 1000]
set Node_Picked $check_addr
}
}
if {[string length $Node_Picked] > 0} {
log local0. "Picked Node: [substr $Node_Picked 0 "/"] URI: [HTTP::uri] Highest Score: $Highest_Score"
node [substr $Node_Picked 0 "/"]
}
}
A/B Server Testing
• Use Case: Send a small percentage of traffic to servers running new code version
• Using a pool group, distribute traffic between the version 1 pool and version 2 pool
• Compare the end user experience between the two pools
DNS Domain Name Switching
• Use Case: Send to specified pools based on DNS query parameters
• Similar to HTTP content switching, Avi can modify or direct requests for DNS
Migration to Avi
• F5 to Avi
– Configuration is automatically imported via Avi’s config converter tool
• iRules to Avi
– Over 75% of iRules can be handled via native Avi functionality - no scripting required
– Remaining iRules may need to be converted to Avi’s DataScript
– Avi consulting services are available to assist with rule conversions
Thank You!
Nathan McMahon, Avi Networks
nathan@avinetworks.com
avinetworks.com

Top 10 F5 iRules to migrate to a modern load balancing platform

  • 1.
    Migrate iRules toAvi Migrate Your iRules to a Modern ADC Platform Nathan McMahon, Avi Networks nathan@avinetworks.com www.avinetworks.com
  • 2.
    Dataplane scripting –Powerful but brittle foreach header {"Location" "Content-Location" "URI"} { set protocol [URI::protocol [HTTP::header $header]] if { $static::ProxyPassDebug > 1 } { log local0. "$log_prefix: Checking $header=[HTTP::header $header], $protocol=$protocol" } if {$protocol ne ""} { set server_path [findstr [HTTP::header $header] $host_serverside [string length $host_serverside]] if {$server_path starts_with $path_serverside} { if { $static::ProxyPassDebug } { log local0. "$log_prefix: Changing response header $header: [HTTP::header $header] with $protocol://$host_clientside$path_clientside[substr $server_path [string length $path_serverside]]" } HTTP::header replace $header $protocol://$host_clientside$path_clientside[substr $server_path [string length $path_serverside]] } } } # Rewrite any domains/paths in Set-Cookie headers if {[HTTP::header exists "Set-Cookie"]}{ array unset cookielist foreach cookievalue [HTTP::header values "Set-Cookie"] { set cookiename [getfield $cookievalue "=" 1] set namevalue "" set newcookievalue "" foreach element [split $cookievalue ";"] { set element [string trim $element] if {$namevalue equals ""} { set namevalue $element } else { if {$element contains "="} { set elementname [getfield $element "=" 1] set elementvalue [getfield $element "=" 2] if {[string tolower $elementname] eq "domain"} { set elementvalue [string trimright $elementvalue "."] if {$host_serverside ends_with $elementvalue} { if {$static::ProxyPassDebug > 1} { log local0. "$log_prefix: Modifying cookie $cookiename domain from $elementvalue to $host_clientside" } set elementvalue $host_clientside } append elementvalue "." } if {[string tolower $elementname] eq "path"} { if {$elementvalue starts_with $path_serverside} { if {$static::ProxyPassDebug > 1} { log local0. "$log_prefix: Modifying cookie $cookiename path from $elementvalue to $path_clientside[substr $elementvalue [string length $path_serverside]]" } set elementvalue $path_clientside[substr $elementvalue [string length $path_serverside]] } } append newcookievalue "; $elementname=$elementvalue" } else { append newcookievalue "; $element" } } } set cookielist($cookiename) "$namevalue$newcookievalue" } HTTP::header remove "Set-Cookie" foreach cookiename [array names cookielist] { HTTP::header insert "Set-Cookie" $cookielist($cookiename) if {$static::ProxyPassDebug > 1} { log local0. "$log_prefix: Inserting cookie: $cookielist($cookiename)" } } } } when SERVER_CONNECTED { if {$bypass} { return } set class_exists_cmd "class exists ProxyPassSSLProfiles" if {! [eval $class_exists_cmd]} { return } set pool [LB::server pool] set profilename [findclass $pool ProxyPassSSLProfiles " "] if {$profilename eq ""} { if { [PROFILE::exists serverssl] == 1} { # Hide this command from the iRule parser (in case no serverssl profile is applied) set disable "SSL::disable serverside" catch {eval $disable} } return } if { $static::ProxyPassDebug > 0 } { log local0. "$log_prefix: ServerSSL profile $profilename assigned for pool $pool" } if { [PROFILE::exists serverssl] == 1} { # Hide these commands from the iRule parser (in case no serverssl profile is applied) set profile "SSL::profile $profilename" catch {eval $profile} set enable "SSL::enable serverside" catch {eval $enable} } else {
  • 3.
    iRule DataScript Migration of iRulesto Avi when HTTP_REQUEST { HTTP::redirect “https://site.com” } Feature Policy Very easy to use Minimal flexibility Easy to use Some flexibility More effort Most flexible AviF5
  • 4.
    iRule DataScript HTTP to HTTPSRedirect when HTTP_REQUEST { HTTP::redirect “https://site.com” } -- HTTP Request Event avi.http.redirect(“https://site.com”) Feature Policy AviF5
  • 5.
    Survey Question! How manyiRules do you have deployed in your organization? N / A 0 - 9 10 - 99 100+
  • 6.
    BARE METAL VIRTUALIZEDCONTAINERSON PREMISES PUBLIC CLOUDVIRTUALIZED CONTAINERS Scalable Architecture Scale up and scale out data plane resources to handle complex rule logic CONTROLLERS SERVICE ENGINES
  • 7.
    Content Switch • UseCase: Assign content to specified pools, such as images sent to caches when HTTP_REQUEST { if {[HTTP::uri] starts_with "/development" } { pool pool_development } elseif {[HTTP::uri] starts_with "/marketing" } { pool pool_marketing } elseif {[HTTP::uri] starts_with "/support" } { pool pool_support } else { discard } }
  • 8.
    Example Use Cases HTTPto HTTPS redirect HTTP content switch 1. HTTP Request throttle 2. Persist on a session ID 3. Trace a user session 4. Insert client SSL cert into header 5. ProxyPass 6. HTTP server reselect 7. Maintenance page 8. Load balancing URIs 9. A/B server testing 10.DNS domain name switch
  • 9.
    HTTP Request Throttle •Use Case: Limit the number of HTTP requests from a client over a period of time • Identify Client: IP address, username, session ID, or custom identifier • Throttle Action: Throttle the number of requests per time period, return a custom page, custom response code, or redirect to an alternate location when RULE_INIT { array set ::active_clients { } } when CLIENT_ACCEPTED { set client_ip [IP::remote_addr] if { [info exists ::active_clients($client_ip)] } { if {$::active_clients($client_ip) > 10 } { log "Client $client_ip has too many connections" reject return } else { log local0. "$::active_clients($client_ip)“ incr ::active_clients($client_ip) } } else { set ::active_clients($client_ip) 1 } } when CLIENT_CLOSED { if { [info exists ::active_clients($client_ip)] } { incr ::active_clients($client_ip) -1 if { $::active_clients($client_ip) <= 0 } { unset ::active_clients($client_ip) } } }
  • 10.
    Persist on aSession ID • Use Case: Leverage a server’s existing session cookies to identify and persist clients • Pick Persist > App Cookie method and type in the name of the session ID • Avi will inspect both the headers and cookies for the session ID when HTTP_REQUEST { If {[HTTP::cookie exists “JSessionID”] } { persist uie [HTTP::cookie “JSessionID”] } else { set jsessionid [findstr [HTTP::uri] “JSessionID” 17 “;”] if { $jsessionid != “” } { persist uie $jsessionid } } } when HTTP_RESPONSE { if {[HTTP::cookie exists “JSessionID”] } { persist add uie [ HTTP::cookie “JSessionID”] } }
  • 11.
    Trace a UserSession • Use Case: Log, filter, and search for a complete user session • Avi can log every connection or request, or log only sessions of interest • Search through logs via IP address, session ID, or user ID when CLIENT_ACCEPTED { set info "client { [IP::client_addr]:[TCP::client_port] -> [IP::local_addr]:[TCP::local_port] }" append info " ethernet { [string range [LINK::lasthop] 0 16] -> [string range [LINK::nexthop] 0 16] tag [LINK::vlan_id] qos [LINK::qos] }" log local0. $info } when LB_SELECTED { set info "client { [IP::client_addr]:[TCP::client_port] -> [clientside {IP::local_addr}]:[clientside {TCP::local_port}] }" catch { append info " server { [IP::local_addr]:[TCP::local_port] -> [IP::server_addr]:[TCP::server_port] }" } append info " ethernet { [string range [LINK::lasthop] 0 16] -> [string range [LINK::nexthop] 0 16] tag [LINK::vlan_id] qos [LINK::qos] }" log local0. $info } when SERVER_CONNECTED { set info "client { [IP::client_addr]:[TCP::client_port] -> [clientside {IP::local_addr}]:[clientside {TCP::local_port}] }" append info " server { [IP::local_addr]:[TCP::local_port] -> [IP::server_addr]:[TCP::server_port] }" append info " ethernet { [string range [LINK::lasthop] 0 16] -> [string range [LINK::nexthop] 0 16] tag [LINK::vlan_id] qos [LINK::qos] }" log local0. $info } when HTTP_REQUEST { set info "client { [IP::client_addr]:[TCP::client_port] -> [clientside {IP::local_addr}]:[clientside {TCP::local_port}] }" catch { append info " server { [serverside {IP::local_addr}]:[serverside {TCP::local_port}] -> [IP::server_addr]:[TCP::server_port] }" } append info " ethernet { [string range [LINK::lasthop] 0 16] -> [string range [LINK::nexthop] 0 16] tag [LINK::vlan_id] qos [LINK::qos] }" append info " - [HTTP::method] [HTTP::uri] [HTTP::version]" append info " *TCP MSS [TCP::mss], BW [TCP::bandwidth], RTT [TCP::rtt], OFFSET [TCP::offset]" append info " *IP TOS [IP::tos], HOPS [IP::hops], TTL [IP::ttl], PKTS_IN [IP::stats pkts in], PKTS_OUT [IP::stats pkts out], BYTES_IN [IP::stats bytes in], BYTES_OUT [IP::stats bytes out]" append info " *HTTP HOST [HTTP::host], KEEPALIVE [HTTP::is_keepalive], REQ_NUM [HTTP::request_num]" append info " *HTTP PATH [HTTP::path], QUERY [HTTP::query]" log local0. $info } when HTTP_RESPONSE { set info "client { [IP::client_addr]:[TCP::client_port] -> [clientside {IP::local_addr}]:[clientside {TCP::local_port}] }" append info " server { [IP::local_addr]:[TCP::local_port] -> [IP::server_addr]:[TCP::server_port] }" append info " ethernet { [string range [LINK::lasthop] 0 16] -> [string range [LINK::nexthop] 0 16] tag [LINK::vlan_id] qos [LINK::qos] }" append info " - [HTTP::status] [HTTP::version] - REDIR [HTTP::is_redirect], Content-Length [HTTP::header Content-Length], Transfer-Encoding [HTTP::header Transfer-Encoding]"
  • 12.
    Insert Client SSLCert into Header • Use Case: Insert the client’s SSL certificate into request headers sent to server • Avi can authenticates clients via their client SSL certificates • Any component or the entire client cert may be insert into a header class secure_uri { /humanresources /confidential /private } when CLIENTSSL_CLIENTCERT { HTTP::release if { [SSL::cert count] < 1 } { reject } } when HTTP_REQUEST { if { [matchclass [HTTP::uri] starts_with ::secure_uri] } { if { [SSL::cert count] <= 0 } { HTTP::collect SSL::authenticate always SSL::authenticate depth 9 SSL::cert mode require SSL::renegotiate } } } when HTTP_REQUEST_SEND { clientside { if { [SSL::cert count] > 0 } { HTTP::header insert "X-SSL-Session-ID" [SSL::sessionid] HTTP::header insert "X-SSL-Client-Cert-Status” [X509::verify_cert_error_string [SSL::verify_result]] HTTP::header insert "X-SSL-Client-Cert-Subject“ [X509::subject [SSL::cert 0]] HTTP::header insert "X-SSL-Client-Cert-Issuer“ [X509::issuer [SSL::cert 0]] } } }
  • 13.
    if {[regexp -nocase$regex "$orig_host$orig_uri" 0 1 2 3 4 5 6 7 8 9]}{ # The clientside becomes the matched string and the serverside the substitution set clientside $0 set serverside [eval set X $rewrite] } else { pool $default_pool return } } if {$clientside starts_with "/"} { # No virtual hostname specified, so use the Host header instead set host_clientside $orig_host set path_clientside $clientside } else { # Virtual host specified in entry, split the host and path set host_clientside [getfield $clientside "/" 1] set path_clientside [substr $clientside [string length $host_clientside]] } # At this point $host_clientside is the client hostname, and $path_clientside # is the client-side path as specified in the data group set host_serverside [getfield $serverside "/" 1] set path_serverside [substr $serverside [string length $host_serverside]] ProxyPass • Use Case: Translate between the external and internal site names • Rewrite client requests, such as their URI and hostnames to something the server is expecting. Then reverse the process with the response traffic • Avi automatically handles rewriting server redirects to the name used by the client. Throw in a policy or two for more robust cookie name or HTML content rewrite www.oldsite.com www.newsite.com
  • 14.
    HTTP Server Reselect •Use Case: Don’t let an errant server error be sent to a client • If a server sends out an error, such as 503 (server busy), Avi will retry the request with another server in the pool when HTTP_REQUEST { set my_url [HTTP::host][HTTP::uri] if { [HTTP::cookie BIGIP] contains "Redirect" } { set count [findstr [HTTP::cookie BIGIP] "Redirect_" 9 1] } else { set count 0 } } when HTTP_RESPONSE { if { [HTTP::status] == 500 && $count < 4 } { incr count HTTP::respond 302 Location "http://$my_url" Set-Cookie “self=Redirect_$count" Connection "Close" } elseif { [HTTP::status] == 500 && $count == 4 } { set count 0 HTTP::respond 404 Set-Cookie "BIGIP=Not_Found" Connection "Close" } } }
  • 15.
    Maintenance Page • UseCase: Display a friendly error page when a site is down for maintenance • Upload a custom web page within the HTTP policies • Disable the policy after the maintenance period is over when HTTP_REQUEST { set my_url [HTTP::host][HTTP::uri] if { [HTTP::cookie BIGIP] contains "Redirect" } { set count [findstr [HTTP::cookie BIGIP] "Redirect_" 9 1] } else { set count 0 } } when HTTP_RESPONSE { if { [HTTP::status] == 500 && $count < 4 } { incr count HTTP::respond 302 Location "http://$my_url" Set-Cookie “self=Redirect_$count" Connection "Close" } elseif { [HTTP::status] == 500 && $count == 4 } { set count 0 HTTP::respond 404 Set-Cookie "BIGIP=Not_Found" Connection "Close" } } }
  • 16.
    Load Balance URIs •Use Case: Distribute and persist requests across servers based on URI • Clients requests can be load balanced based on criteria such as requested URI – Select Pool > Load Balance algorithm > Consistent Hash > URI – F5 has an equivalent feature, but it only works when paired with an iRule – Avi provides the most common values as sub-options for the LB method. when HTTP_REQUEST { set Highest_Score 0 set Node_Picked "" foreach check_addr $::carp_list { log local0. "Node: $check_addr Score: [expr [crc32 $check_addr[HTTP::host][HTTP::uri]] % 1000]" if { [expr [crc32 $check_addr[HTTP::host][HTTP::uri]] % 1000] > $Highest_Score } { # Highest score so far, store new high score and record node set Highest_Score [expr [crc32 $check_addr[HTTP::host][HTTP::uri]] % 1000] set Node_Picked $check_addr } } if {[string length $Node_Picked] > 0} { log local0. "Picked Node: [substr $Node_Picked 0 "/"] URI: [HTTP::uri] Highest Score: $Highest_Score" node [substr $Node_Picked 0 "/"] } }
  • 17.
    A/B Server Testing •Use Case: Send a small percentage of traffic to servers running new code version • Using a pool group, distribute traffic between the version 1 pool and version 2 pool • Compare the end user experience between the two pools
  • 18.
    DNS Domain NameSwitching • Use Case: Send to specified pools based on DNS query parameters • Similar to HTTP content switching, Avi can modify or direct requests for DNS
  • 19.
    Migration to Avi •F5 to Avi – Configuration is automatically imported via Avi’s config converter tool • iRules to Avi – Over 75% of iRules can be handled via native Avi functionality - no scripting required – Remaining iRules may need to be converted to Avi’s DataScript – Avi consulting services are available to assist with rule conversions
  • 20.
    Thank You! Nathan McMahon,Avi Networks nathan@avinetworks.com avinetworks.com

Editor's Notes

  • #7 3. Multi-cloud: SEs can be deployed across heterogeneous environment – x86 bare metal servers, in virtualized environments or along side containers in both on-prem data centers, private clouds and public clouds. Multi-cloud is important not only due to the flexibility and freedom it allows but also reduces your risk of being forced to put all your eggs in one basket. CSP 2100 NFV appliance ESXi and vCenter Docker, Kubernetes and OpenShift for containerized environments On-prem and clouds (AWS, Azure, GCP public clouds and OpenStack private clouds)