Yes, this can be done on premise, as we are doing.
Say you have 3 servers for Rancher: 10.0.1.11, 12, and 13.
You also have 3 servers for your load balancers, 10.0.1.21, 22, and 23.
You run Keepalived on the load balancers, and configure it to serve the VIP of 10.0.1.31. This is what you point your DNS entry for the Rancher UI to. The 3 load balancers will talk to each other, and one of them will assume the VIP address. If that LB node dies or reboots, the other two will decide which one will take the IP, and it will then assume that IP.
Each of the LB nodes will also run HAproxy/Nginx and be configured to listen on IP 10.0.1.31 and port 443. The “backend” will be the 3 IP addresses for your Rancher servers. The Nginx frontend should be configured as a TCP frontend, not HTTP, so that the SSL certs will be provided by Rancher, and not Nginx.
You will also need to enable non_local bind on the load balancers, so that Nginx won’t complain when it tries to bind to an IP that it doesn’t own (for the two servers that do NOT own the VIP).