Reverse Proxy With Basic SSO
Problem this snippet solves:
The iRule implements a authenticated HTTPS reverse proxy.
This iRule respond to a possible use of BigIP as an authenticated HTTPS reverse proxy. At this point, the iRule rewrite Host and Location in HTTP::header, support virtual multihosting and basic single sign-on.
First, declare two classes for rewrite HTTP::header Host and HTTP::header Location
How to use this snippet:
Supporting Classes
class tab_hostrewrite extern { type string filename "tab_hostrewrite.txt" } class tab_locationrewrite extern { type string filename "tab_locationrewrite.txt" }
- The 'extern' keyword is not required in 9.4.x versions when creating the class from the CLI.
- For "Host" rewriting, the file format is specific to our use (no DNS use), example: "host1.mydomain.com ws1.inet.mydomain.com 192.168.1.14 80", "host2.mydomain.com ws2.inet.mydomain.com 192.168.1.11 80",
- For "Location" rewriting, an example is: "ws2.inet.mydomain.com https://host2.mydomain.com",
Code :
# rule ReverseProxy ########################################################################### ## IRule Reverse Proxy (c)05 F.NOEL - No warranty, feel free to use ## v0.01: F.NOEL - create irules with basic Host and Location rewrite ## 0.02: F.NOEL - add Single Sign ON (need to set :SSO to 1 in RULE_INIT) ## 0.03: F.NOEL - build cookie domain based on HTTP Header "Host" ## - if "Host" not FQDN, cookie's domain set to ::COOKIE_DEFAULT_DOMAIN ## 0.04: F.NOEL - add SSO cookie encryption (AES) ## ########################################################################### when RULE_INIT { set ::DEBUG 0 set ::RP_PRIVIP "192.168.1.254" set ::SSO 1 set ::COOKIE_DEFAULT_DOMAIN ".mydomain.com" set ::COOKIE_NAME "WSSOMYDOMAIN" set ::COOKIE_ENCRYPT 1 set ::AES_KEY [AES::key 256] if { $::DEBUG } { log local0.debug "Initialyze random AES_KEY='$::AES_KEY' " } } when HTTP_REQUEST { set header_auth "" set header_host [HTTP::host] set hostrewrite [findclass $header_host $::tab_hostrewrite " "] if { $hostrewrite ne "" } { set destnodeaddr [getfield $hostrewrite " " 2] set destnodeport [getfield $hostrewrite " " 3] set hostrewrite [getfield $hostrewrite " " 1] HTTP::header replace "Host" $hostrewrite if { $::DEBUG } { log local0.debug "Header Host '$header_host' found -> rewrite with '$hostrewrite'" } snat $::RP_PRIVIP node $destnodeaddr $destnodeport } else { if { $::DEBUG } { log local0.debug "$header_host not found -> respond with 403..." } HTTP::respond 403 content "HTTP Error 403 - Forbidden" } if { $::SSO } { set header_auth [HTTP::header "Authorization"] if { $::DEBUG } { log local0.debug "REQ header_auth -> '$header_auth'" } if { [HTTP::cookie exists $::COOKIE_NAME] } { set SSO_DO_SET_COOKIE 0 HTTP::cookie remove $::COOKIE_NAME if { $::DEBUG } { log local0.debug "REQ cookie_sso exist -> set SSO_DO_SET_COOKIE=0 and remove cookie" } } else { if { $header_auth ne "" } { set SSO_DO_SET_COOKIE 1 if { $::DEBUG } { log local0.debug "REQ cookie_sso not exist -> set SSO_DO_SET_COOKIE=1" } } } } } when HTTP_RESPONSE { ### SSO_DO_SET_COOKIE flag on, set a cookie for support Single Sign ON if { $::SSO and $SSO_DO_SET_COOKIE } { ## extract domain name from host to set cookie domain set cookiedomain $::COOKIE_DEFAULT_DOMAIN for {set i 6} {$i > 1} {incr i -1} { set tmp [getfield $header_host "." $i] ## if Host is FQDN if { $tmp ne "" and $i > 2 } { set cookiedomain $tmp incr i -1 set cookiedomain ".[getfield $header_host "." $i].$cookiedomain" break; } } if { $::DEBUG } { log local0.debug "cookiedomain= '$cookiedomain' " } if { $::COOKIE_ENCRYPT } { set cookie_payload [b64encode [AES::encrypt $::AES_KEY $header_auth]] } else { set cookie_payload $header_auth } if { $::DEBUG } { log local0.debug "cookie_payload= '$cookie_payload' " } HTTP::cookie insert name $::COOKIE_NAME value $cookie_payload HTTP::cookie domain $::COOKIE_NAME $cookiedomain HTTP::cookie path $::COOKIE_NAME "/" set SSO_DO_SET_COOKIE 0 if { $::DEBUG } { log local0.debug "SSO_DO_SET_COOKIE=1 -> insert cookie $::COOKIE_NAME='$cookie_payload' in response..." } } if { [HTTP::status] starts_with "3" } { set location [HTTP::header "Location"] if { $location ne "" } { if { $::DEBUG } { log local0.debug "Header Location '$location' not null -> checking..." } set loc_start "" if { $location starts_with "http://" } { set loc_start "http://" } elseif { $location starts_with "https://" } { set loc_start "https://" } set loc_start_len [string length $loc_start] if { $loc_start_len eq 0 } { if { $::DEBUG } { log local0.debug "No absolute redirection! return... " } return } set loc_end [substr $location $loc_start_len] set loc_to_search [getfield $loc_end "/" 1] set locationrewrite [findclass $loc_to_search $::tab_locationrewrite " "] if { $locationrewrite ne "" } { set loc_to_search_len [string length $loc_to_search] set loc_end [substr $loc_end $loc_to_search_len] set new_loc "$locationrewrite$loc_end" HTTP::header replace "Location" $new_loc if { $::DEBUG } { log local0.debug "Rewrite Location -> $new_loc" } } else { if { $::DEBUG } { log local0.debug "Location not found in tab_locationrewrite -> return..." } } return } } else { return } } # Finally, if you want activate the support for basic single sign-on with a ldap authentication, add rule SSO_Auth_Ldap on your authentication profile # rule SSO_Auth_Ldap ########################################################################### ## IRule Reverse Proxy - AuthLdap (c)05 F.NOEL - No warranty, feel free to use ## v0.01: create irule for support Single Sign ON with LDAP authentication ## ########################################################################### when CLIENT_ACCEPTED { set tmm_auth_ldap_sid [AUTH::start pam default_ldap] } when HTTP_REQUEST { if { [HTTP::cookie exists $::COOKIE_NAME] } { set cookie_payload [HTTP::cookie value $::COOKIE_NAME] if { $::COOKIE_ENCRYPT } { set cookie_payload [AES::decrypt $::AES_KEY [b64decode $cookie_payload]] } if { $::DEBUG } { log local0.debug "cookie $::COOKIE_NAME exist -> set Authorization credential" } HTTP::header replace "Authorization" $cookie_payload } else { if { $::DEBUG } { log local0.debug "cookie $::COOKIE_NAME doesn't exist -> authenticate user" } AUTH::username_credential $tmm_auth_ldap_sid [HTTP::username] AUTH::password_credential $tmm_auth_ldap_sid [HTTP::password] AUTH::authenticate $tmm_auth_ldap_sid HTTP::collect } } when AUTH_SUCCESS { if {$tmm_auth_ldap_sid eq [AUTH::last_event_session_id]} { HTTP::release } } when AUTH_FAILURE { if {$tmm_auth_ldap_sid eq [AUTH::last_event_session_id]} { HTTP::respond 401 } } when AUTH_WANTCREDENTIAL { if {$tmm_auth_ldap_sid eq [AUTH::last_event_session_id]} { HTTP::respond 401 } } when AUTH_ERROR { if {$tmm_auth_ldap_sid eq [AUTH::last_event_session_id]} { HTTP::respond 401 } }
Published Mar 18, 2015
Version 1.0CodeCentral_194
Cirrus
Joined May 05, 2019
CodeCentral_194
Cirrus
Joined May 05, 2019
No CommentsBe the first to comment