Forum Discussion

igor_'s avatar
igor_
Icon for Altocumulus rankAltocumulus
Jun 29, 2023
Solved

Migration from HAProxy to F5

Hi all,

I have a conundrum of sorts.

We are currently in the process of evaluating how to migrate from HAProxy reverse proxy and load balancer to F5.

I have a couple of questions for someone who has been in the same boat, if any 😄

1. What type of licence do we need for Reverse Proxy/Load Balancing

2) I am posting a sample config of what I need to migrate to F5

Since I have been reading about iRules and LTM Local Traffic Policy I am thinking of going the LTM route since I've read that iRules are a lot more problematic and slower to go through.

Here is the sample config. Does anyone have an idea how to implement this into F5 using LTM?

 

 

frontend web11
  mode http
  bind 10.1.1.10:80
  bind 10.1.1.10:443 ssl crt /etc/ssl/web.pem
  
  # Redirect HTTP to HTTPS
  http-request redirect scheme https code 301 unless { ssl_fc }

  # Log the session cookie if passed
  capture cookie JSESSIONID= len 32
  
  acl web_url hdr(host) -i web11.com www.web11.com
    
  acl path_cxserver path -i -m beg /Thingworx/WS
  acl path_tunnelserver path -i -m beg /Thingworx/WSTunnelServer
  acl path_tunnelclient path -i -m beg /Thingworx/WSTunnelClient
  
  # Backend logic
  use_backend cxserver if web_url path_cxserver
  use_backend tunnelserver if web_url path_tunnelserver
  use_backend tunnelclient if web_url path_tunnelclient


  
  ##### Backend section
  
backend cxserver
  mode http
  balance roundrobin
  option forwardfor

  # sticky sessions
  cookie SERVER insert indirect nocache

  http-request set-header X-Forwarded-Port %[dst_port]
  http-request add-header X-Forwarded-Proto https if { ssl_fc }

  # health check
  option httpchk GET /Thingworx/health

  
  server cxserver1 10.0.10.10:8080 check inter 1000 fastinter 1000" cookie twx1
  server cxserver2 10.0.10.11:8080 check inter 1000 fastinter 1000" cookie twx2
  
  
backend tunnelserver
  mode http
  balance source
  option forwardfor
  option httpchk GET /

  server tunnelserver1 10.0.10.20:8080 check port 9009
  server tunnelserver2 10.0.10.21:8080 check port 9009
  
backend tunnelclient
  mode http
  balance roundrobin
  option forwardfor
  option httpchk HEAD /healthcheck.html HTTP/1.1
  
  server tunnelclient1 10.0.10.30:8080 check inter 1000 fastinter 1000" cookie twx1
  server tunnelclient2 10.0.10.31:8080 check inter 1000 fastinter 1000" cookie twx2
  server tunnelclient3 10.0.10.32:8080 check inter 1000 fastinter 1000" cookie twx3
  
  
  
# Default traffic to platform
default_backend NOSRV

 

 

Thanks for any suggestions 🙂 

If you need clarification of what each line does I will be happy to break them down further if needed 🙂

  • Hi igor_ 

    I haven't used haproxy personally, but the config looks pretty self explanatory. Here's a start for some of the work to get you going. Note that the cookie names are going to be stock in this solution, the jsessionid is not handled yet, and only one of the three backends has been addressed. You can add the other two as rules to the policy once you build out the pools for them. Post back with any questions.

     

    ltm monitor http cxserver-httpchk {
        adaptive disabled
        defaults-from http
        interval 5
        ip-dscp 0
        recv none
        recv-disable none
        send "GET /Thingworx/health\r\n"
        time-until-up 0
        timeout 16
    }
    
    ltm pool cxserver-pool {
        members {
            cxserver1:8080 {
                address 10.0.10.10
            }
            cxserver2:8080 {
                address 10.0.10.11
            }
        }
        monitor cxserver-httpchk
    }
    
    ltm policy test-policy {
        controls { forwarding }
        requires { http }
        rules {
            cxserver-match {
                actions {
                    0 {
                        forward
                        select
                        pool cxserver-pool
                    }
                }
                conditions {
                    0 {
                        http-uri
                        values { /Thingworx/WS }
                    }
                }
                ordinal 1
            }
        }
        status published
        strategy first-match
    }
    
    ltm policy http-to-https {
        controls { forwarding }
        requires { http tcp }
        rules {
            redirect {
                actions {
                    0 {
                        http-reply
                        redirect
                        location tcl:https://[getfield [HTTP::host] ":" 1][HTTP::uri]
                    }
                }
                conditions {
                    0 {
                        tcp
                        port
                        values { 80 }
                    }
                }
            }
        }
        status published
        strategy first-match
    }
    
    ltm virtual testapp-vip {
        destination 10.1.1.10:80
        ip-protocol tcp
        mask 255.255.255.255
        policies {
            http-to-https { }
        }
        profiles {
            http { }
            tcp { }
        }
        serverssl-use-sni disabled
        source 0.0.0.0/0
        translate-address enabled
        translate-port enabled
    }
    ltm virtual testappssl-vip {
        destination 10.1.1.10:443
        ip-protocol tcp
        mask 255.255.255.255
        persist {
            cookie {
                default yes
            }
        }
        policies {
            test-policy { }
        }
        profiles {
            clientssl {
                context clientside
            }
            http { }
            tcp { }
        }
        serverssl-use-sni disabled
        source 0.0.0.0/0
        source-address-translation {
            type automap
        }
        translate-address enabled
        translate-port enabled
    }

     

    high level from objects perspective (and this is imperative config, I highly encouarge you taking a look at the declarative automated tool chain):

    Monitors for the pools
    Pools for each of your backend servers
    Cookie profiles if you want them to be named specifically
    SSL profile for your front-end
    LTM policy for redirecting from http->https
    LTM policy for traffic matching, forwarding, and logging 
    Virtual server for port 80
    Virtual server for port 443

10 Replies

  • Hi igor_ 

    I haven't used haproxy personally, but the config looks pretty self explanatory. Here's a start for some of the work to get you going. Note that the cookie names are going to be stock in this solution, the jsessionid is not handled yet, and only one of the three backends has been addressed. You can add the other two as rules to the policy once you build out the pools for them. Post back with any questions.

     

    ltm monitor http cxserver-httpchk {
        adaptive disabled
        defaults-from http
        interval 5
        ip-dscp 0
        recv none
        recv-disable none
        send "GET /Thingworx/health\r\n"
        time-until-up 0
        timeout 16
    }
    
    ltm pool cxserver-pool {
        members {
            cxserver1:8080 {
                address 10.0.10.10
            }
            cxserver2:8080 {
                address 10.0.10.11
            }
        }
        monitor cxserver-httpchk
    }
    
    ltm policy test-policy {
        controls { forwarding }
        requires { http }
        rules {
            cxserver-match {
                actions {
                    0 {
                        forward
                        select
                        pool cxserver-pool
                    }
                }
                conditions {
                    0 {
                        http-uri
                        values { /Thingworx/WS }
                    }
                }
                ordinal 1
            }
        }
        status published
        strategy first-match
    }
    
    ltm policy http-to-https {
        controls { forwarding }
        requires { http tcp }
        rules {
            redirect {
                actions {
                    0 {
                        http-reply
                        redirect
                        location tcl:https://[getfield [HTTP::host] ":" 1][HTTP::uri]
                    }
                }
                conditions {
                    0 {
                        tcp
                        port
                        values { 80 }
                    }
                }
            }
        }
        status published
        strategy first-match
    }
    
    ltm virtual testapp-vip {
        destination 10.1.1.10:80
        ip-protocol tcp
        mask 255.255.255.255
        policies {
            http-to-https { }
        }
        profiles {
            http { }
            tcp { }
        }
        serverssl-use-sni disabled
        source 0.0.0.0/0
        translate-address enabled
        translate-port enabled
    }
    ltm virtual testappssl-vip {
        destination 10.1.1.10:443
        ip-protocol tcp
        mask 255.255.255.255
        persist {
            cookie {
                default yes
            }
        }
        policies {
            test-policy { }
        }
        profiles {
            clientssl {
                context clientside
            }
            http { }
            tcp { }
        }
        serverssl-use-sni disabled
        source 0.0.0.0/0
        source-address-translation {
            type automap
        }
        translate-address enabled
        translate-port enabled
    }

     

    high level from objects perspective (and this is imperative config, I highly encouarge you taking a look at the declarative automated tool chain):

    Monitors for the pools
    Pools for each of your backend servers
    Cookie profiles if you want them to be named specifically
    SSL profile for your front-end
    LTM policy for redirecting from http->https
    LTM policy for traffic matching, forwarding, and logging 
    Virtual server for port 80
    Virtual server for port 443

  • Maybe you will only need an iRule to log the cookie:

     

    https://clouddocs.f5.com/api/irules/HTTP__cookie.html

    https://community.f5.com/t5/technical-articles/getting-started-with-irules-logging-comments/ta-p/290408/redirect_from_archived_page/true

     The request logging profile can also be a nice feature:

    https://my.f5.com/manage/s/article/K00847516

     

    You can send the HTTP logs directly to a syslog or SIEM without saving them locally and the irules, F5 system or the request logging profile support HSL:

     

    https://clouddocs.f5.com/api/irules/HSL.html

    https://techdocs.f5.com/kb/en-us/products/big-ip_ltm/manuals/product/bigip-external-monitoring-implementations-12-0-0/4.html

    https://my.f5.com/manage/s/article/K50040950

     

     

     

     


    when HTTP_REQUEST {
    log local0. “JSESSIONID cookie: [HTTP::cookie value "JSESSIONID"] from source IP [IP::client_addr] ”
    }

     

    Maybe also check if One Connect will be needed as this could be enabled by default for HAProxy and you will need one connect profile for F5.

    https://www.haproxy.com/blog/http-keep-alive-pipelining-multiplexing-and-connection-pooling

    https://my.f5.com/manage/s/article/K91757375

     

    For X-Forwarded options you play with the F5 HTTP profile as there is no need for irule or local traffic policies

    https://my.f5.com/manage/s/article/K43444200

    https://my.f5.com/manage/s/article/K4816

     

    • JRahm's avatar
      JRahm
      Icon for Admin rankAdmin

      Nikoolayy1   Good call on one connect, forgot that. It is considered a misconfiguration on http without it. 

      igor_ iRules are totally acceptable, but it is best to do as much as you can without them, and sometimes an apples to apples configuration might require it, whereas a review of requirements for each app you're migrating might present an opportunity to make some changes that a) keep the config and therefore all the logic in native tmm objects and b) prep the config for easy automation when ready.

  • Hi guys,

    Thanks for the proposed solutions. I will be going through them to see how to copy them into the configuration.

    One question though since I am new to F5 JRahm , the configuration you posted is that in a form which is then imported in F5 from GUI ?

    • AlexS_yb's avatar
      AlexS_yb
      Icon for Cirrocumulus rankCirrocumulus

      I went from nginx -> f5, i used linux clustering with a single floating VIP to handle failover.

       

      I would suggest just using irules.

      Unless you are hammering the system and need all the performance you can get.

      Why - well they both do about the same thing

      Irules give you more ability to do just about anything.

      For example we do stick session based upon jsessionid - which didn't fit with the persistance model built into the F5.

      Setting up irules to do what the policies do is easy.

      Also then thing about logging the request / response logging is not pretty  i wrote my own irule module to capature all of the events and record them as well as return headers from back end apps which included timing info.

      Another nice thing as well we have https backends and http backends - irules to process that

       

      Have fun

       

    • JRahm's avatar
      JRahm
      Icon for Admin rankAdmin

      the config as provided is the configuration file version. For GUI would need screenshots or video walkthrough. I can look at that for next week, but on vacation the rest of this week.

  • Guys,

    Much appreciated your answers. It gave me some directions on where to go in the first place.

    AlexS_yb The company is part of the PCI industry so every ms counts 😁 

    Some initial feedback and some questions from my side:

    I have created backend server pools.

    I have created a virtual server with private ip and NAT-ed the public ip into the private one. 

    The path looks like this:

    Internet ----> Router -----> FIrewall (NAT) ----> F5 Virtual server IP (I will call it V1)

    A question: Since the public website is https://app1.somesite.com, I have created an LTM policy using an article from this site written by Eric_Chen - SNI Routing with BIG-IP.

    Now since in the backend, I have some servers which communicate over HTTP and others over HTTPS, can I mix and match protocols? Bear in mind that on the same Windows server under IIS, I have a service using HTTP on port 555, and another service using HTTPS on port 566 for example.

    Under LTM Policy rules I have a lot of:

    If HTTP Uri path starts with : /app1 forward traffic to pool (pool1) at request

    If HTTP Uri path starts with : /app2 forward traffic to pool (pool2) at request

    Now am I using this right since the traffic is encrypted until it hits the virtual server V1. From there based on condition it should be redirected to even the same pool of servers but different ports.

    What I found out is that when setting the virtual server V1 if I select a certificate for SSL Profile (server) I can't connect pools that are running over HTTP and if I don't select SSL Profile (server) I can't communicate with backend pools over HTTPS. Can this be done automatically using one virtual server and combined LTM Policy rules? 

    Any ideas?

    Thanks,

    Igor