HTTP and HTTPS on a single virtual server
Problem this snippet solves:
iRule to support a virtual server on port 0, a client SSL profile, and an HTTP pool.
The goal is to replace two separate HTTP and HTTPS virtual servers with a single virtual server.
Requests to ports defined as HTTPS will have the client SSL profile applied and traffic will be decrypted. Requests to ports defined as HTTP will be left in cleartext All other requests to undefined ports will be reset. All requests sent to the pool are in HTTP. The rule depends on having a pool of HTTP servers defined as the default pool of the virtual server.
Optionally, you can redirect all HTTP requests to the same host and URI over HTTPS by enabling static::redirect_http_to_https in the RULE_INIT event.
If you do not need either the redirection from HTTP to HTTPS or to rewrite the URI to lowercase, you can remove the code from the iRule to save resources.
The old v9 iRule version is below this one.
Code :
when RULE_INIT { # Requests to ports not defined in either the https or http ports list will be reset # Define virtual server ports that should have SSL enabled # in an integer type datagroup (example: 443, 8443, etc) # and update the name here from https_ports_dg to the data group name you create set static::vip_https_ports "https_ports_dg" # Define virtual server ports that should be answered with HTTP # in an integer type datagroup (example: 80, 8080, etc) # and update the name here from http_ports_dg to the data group name you create set static::vip_http_ports "http_ports_dg" # Set this option to 1 to redirect client requests from HTTP to HTTPS. Set to 0 to not redirect clients from HTTP to HTTPS. set static::redirect_http_to_https 0 # Set this option to 1 to log debug messages (to /var/log/ltm by default) set static::single_vs_debug 1 } when CLIENT_ACCEPTED { # Save the VIP name, client IP:port as a log prefix to make the log lines shorter set log_prefix "[IP::client_addr]:[TCP::client_port] [virtual name]" if { [matchclass [TCP::local_port] equals $static::vip_https_ports] }{ # Request was to an HTTPS port, so do nothing for the clientside connection. # The defined client and/or server SSL profiles will be applied as normal if {$static::single_vs_debug}{log local0. "$log_prefix: HTTPS request to [IP::local_addr]:[TCP::local_port]"} # log an error if the virtual server doesn't have a client SSL profile, but receives an SSL request if {[PROFILE::exists clientssl] == 0}{ if {$static::single_vs_debug}{log local0. "$log_prefix:\ Client connection received on port [TCP::local_port], but no client SSL profile is enabled on [IP::local_addr]"} reject } } elseif { [matchclass [TCP::local_port] equals $static::vip_http_ports] }{ # Request was to an HTTP port, not an HTTPS port, so disable client SSL profile if one is enabled on the VIP set vip_http_port 1 if {$static::single_vs_debug}{log local0. "$log_prefix: HTTP request to [IP::local_addr]:[TCP::local_port]"} # Check to see if there is a client SSL profile and if so, disable it if { [PROFILE::exists clientssl] == 1} { if {$static::single_vs_debug}{log local0. "$log_prefix: Client SSL profile enabled on VIP. Disabling SSL."} set disable_cmd "SSL::disable" eval $disable_cmd } } else { # Request wasn't to a defined port, so reset the TCP connection. if {$static::single_vs_debug}{log local0. "$log_prefix:\ Dropping request to undefined port [IP::local_addr]:[TCP::local_port]"} reject } } when HTTP_REQUEST { # If redirect_http_to_https is enabled and the request was made to an HTTP port, # redirect the client to the same host/URI over HTTPS if { ($static::redirect_http_to_https == 1 or ([info exists redirect_http_to_https] && $redirect_http_to_https)) && \ ([info exists vip_http_port] && $vip_http_port==1)}{ HTTP::redirect https://[getfield [HTTP::host] ":" 1][HTTP::uri] if {$static::single_vs_debug}{log local0. "$log_prefix:\ Redirecting client [IP::client_addr] to https://[getfield [HTTP::host] \":\" 1][HTTP::uri]"} } }