Showing results for 
Search instead for 
Did you mean: 

redirect http to https


I want to redirect Http to Https, for now I have created 2 VS one with port 443 and port 80 and I have used _sys_https_redirect  

rule ( provided by waf) in VS port 80.. so is there any alternative way instated of creating 2 virtuals?


Hi  , yes you can achieve it using single virtual server. For this, you can use port list option where you can add multiple services in a single port list group. In your case, it would be 80 and 443. And This port list group will be mapped on the vServer. With this, single virtual server will listen on multiple ports. Once it is done, with the help of irule, you can manage redirections when request is coming on port 80.


Hope it helps!

Alternatively you can use a virtual server with port 0.

The wildcard of 0 lets the virtual listen on all ports.

Now you need to differentiate the handling depending on the service port.

This might be done via LTM policy or by iRule as the following one:

when CLIENT_ACCEPTED { switch [LB::server port] { 80 { SSL::disable return } 443 { # some other iRule logic on tcp protocol level } default { reject } } } when HTTP_REQUEST { if { [LB::server port] == 80 } { HTTP::respond 301 \ noserver \ Server "redirector" \ Location https://[getfield [HTTP::host] ":" 1][HTTP::uri] \ Date [clock format [clock seconds] -format {%a, %b %d %Y %H:%M:%S GMT} -gmt 1] \ Connection Close } else { # some other iRule logic on http protocol level } }


F5 Employee
F5 Employee

In general, for security purposes, a virtual server's listening scope, as derived by its destination IP address and port combination (among other things), should be kept as narrow as possible to avoid the possibility of it picking up traffic it is not intended to process.


Two separate virtual servers, one listening on port 80 and the other listening on port 443, make life easier as only the port 80 virtual needs an iRule or local traffic policy to unconditionally do the redirect. (Local traffic policies generally perform better.) For example, below are my two virtual server definitions, the default pool for the port 443 virtual, and the local traffic policy on the port 80 virtual server. Notice the HTTP virtual server has no default pool (doesn't need one as any traffic to this virtual will be unconditionally redirected by the local traffic policy. Notice the HTTPS virtual server does have a default pool. You don't need a client-ssl and server-ssl profile on the HTTPS virtual server if you don't have any processing that requires visibility into the unencrypted layer 7 payload, such as might be required if using an F5 Advanced WAF application security policy or other iRule or local traffic policy:

******* VIRTUAL SERVER LISTENING ON PORT 80 ******* ltm virtual http_vs_103 { creation-time 2021-08-05:13:11:58 destination ip-protocol tcp last-modified-time 2021-08-05:13:11:58 mask policies { devcentral_test_http_redirect { } } profiles { http { } tcp { } } serverssl-use-sni disabled source translate-address enabled translate-port enabled vs-index 8 }   ******* LOCAL TRAFFIC POLICY FOR PORT 80 VIRTUAL ******** ltm policy devcentral_test_http_redirect { controls { forwarding } last-modified 2021-08-05:13:11:19 requires { http } rules { perform_redirect { actions { 0 { http-reply redirect location "tcl: https://[getfield [HTTP::host] : 1][HTTP::uri]" } } } } status published strategy first-match }   ******* VIRTUAL SERVER LISTENING ON PORT 443 ******* ltm virtual https_vs_103 { creation-time 2021-08-05:13:12:28 destination ip-protocol tcp last-modified-time 2021-08-05:13:12:28 mask pool https_pool profiles { clientssl { context clientside } serverssl { context serverside } tcp { } } serverssl-use-sni disabled source translate-address enabled translate-port enabled vs-index 9 }   ******* LOAD BALANCING POOL FOR PORT 443 VIRTUAL ******* ltm pool https_pool { members { { address } { address } { address } } }

Mayur's suggestion is good if you want to combine the two ports - 80 (HTTP) and 443 (HTTPS) on one virtual server using a port list that contains two ports: 80 and 443. (Port lists are defined under "Shared Objects" in the BIG-IP system's GUI, also known as the Configuration utility.) But it does make things a little more complex as you will also have to conditionally disable SSL on the connection if it is over port 80. An iRule works better for this. For example:

***** IRULE ON SINGLE VIRTUAL LISTENING FOR BOTH 443 AND *) ******* when CLIENT_ACCEPTED { set ssl_on true SSL::enable if { [TCP::local_port] equals 80 } { set ssl_on false } }   when HTTP_REQUEST { if { !$ssl_on } { HTTP::respond 301 -version 1.1 Location "https://[HTTP::host][HTTP::uri]" Connection "close" } }   ******* VIRTUAL SERVER LISTENING ON BOTH 443 AND 80 ******* ltm virtual http_and_https_vs { creation-time 2021-08-05:12:12:31 ip-protocol tcp last-modified-time 2021-08-05:12:29:52 pool https_pool profiles { clientssl { context clientside } http { } serverssl { context serverside } tcp { } } rules { devcentral_test_http_redirect } serverssl-use-sni disabled traffic-matching-criteria http_and_https_vs_VS_TMC_OBJ translate-address enabled translate-port enabled vs-index 7 }   ******* TRAFFIC MATCHING CRITERIA FOR SINGLE VIRTUAL SERVER ******* ltm traffic-matching-criteria http_and_https_vs_VS_TMC_OBJ { destination-address-inline destination-port-list http_and_https protocol tcp source-address-inline }   ******* PORT LIST DEFINITION ******* net port-list /Common/http_and_https { ports { 80 { } 443 { } } }

Finally, in Stephan's suggestion, note that load balancing information, such as LB::server port, is not always available yet at the CLIENT_ACCEPTED and HTTP_REQUEST events, assuming an HTTP-type profile is also assigned to the virtual server. When an HTTP profile is assigned, TCP connection setup on the server-side is delayed until after the first HTTP request is received and whatever conditional logic you have defined for the HTTP_REQUEST event (such as in an iRule or local traffic policy) have run. This allows an iRule or local traffic policy to be involved in selecting the pool, pool member, or node to used during a subsequent load balancing decision. You would also want to check the destination port sent by the client (TCP::local_port) not the destination port of the pool member selected by load balancing (LB::server port), as the latter can be different from the former. For example, the client might connect to the virtual server on port 443 (standard browser behavior when using "https://") but the pool members could be configured with alternate non-standard secure ports, such as 8443 (or whatever the server admin's chose).


One final note, if you are sure your client's never connect to the virtual server using a URL that directly specifies the port (for example, you can change the redirects to just "https://[HTTP::host][HTTP::uri]" and ditch the getfield command parts, which causes additional overhead.