Ssl – Pass-through SSL with HAProxy and vhosts on same IP

haproxyssl

Can i pass-through SSL with HAProxy to a vhost that shares ip with other vhosts?

I try

frontend https
bind *:443 #ssl
mode tcp
default_backend port_443

backend port_443
mode tcp
server web42 www.example.com

But i see the default webserver, not www.example.com

I could do SNI on frontend, but how to say to backend – this is for domain www.example.com?

server web1 www.example.com:443 sni str(www.example.com) verify none

doesn't work either.

To make it clear, webserver www.default.com, www.example.com, www.example.net all have same IP and Port, e.g. 10.0.1.10:443
Apache/ngix chooses the right vhost with SNI.

Problem is still not solved. Here some graphic

                                   --------------------
                                  |(All 10.0.1.10:443)
www2.example.com:443 -> HaProxy ->|www.default.com <- Apache vhost default
                                  |www.example.com
                                  |www.example.net 
                                   --------------------

I would like to reach www.example.com (with mode tcp)

If i have private keys of www.example.com and www.example.net. Can i reach www.example.net (when user input is www.example.com) without security problems?

Best Answer

You can pass connections to whatever backend server/port you want.

But I see there is a bunch of stuff missing from your setup.

So this is from my own HAProxy setup, with which I forward https connections that must share a global IPv4 address, to backend servers which all have unique global IPv6 (and unique private IPv4).

frontend https
    bind :443
    mode tcp
    option tcplog
    tcp-request inspect-delay 5s
    tcp-request content accept if { req.ssl_hello_type 1 }

    use_backend goren_example_com if { req_ssl_sni -i awx.example.com }
    use_backend goren_example_com if { req_ssl_sni -i goren.example.com }
    use_backend goren_example_com if { req_ssl_sni -i tower.example.com }

backend goren_example_com
    server goren 192.168.101.182:443 send-proxy-v2

Note that I am doing SNI inspection here, and matching on the SNI hostname to determine which backend to send the connection to.

Then I use send-proxy-v2 which enables the PROXY protocol on the backend connection. This will let me tell the backend the IP address where the connection originated. We use this protocol because X-Forwarded-For is not possible in this setup.

But the PROXY protocol does require the backend server to be aware of it. To make that happen required a small change in my nginx setup, to wit:

listen 443 ssl http2 proxy_protocol;
listen [::]:443 ssl http2;
set_real_ip_from 192.168.101.1;
real_ip_header proxy_protocol;

By specifying proxy_protocol in listen and real_ip_header, nginx now knows to get the real IP address of the client via PROXY protocol. (And notice that I do not use it on the IPv6 listener, because I only proxy IPv4 connections via haproxy. IPv6 connections come in directly, and a proxy is not required. This is one big advantage of IPv6.)

Finally, older versions of nginx spoke version 1 of the PROXY protocol, so if send-proxy-v2 in haproxy.cfg doesn't work, you'll need to change it to send-proxy.

(And if you're one of the people still using Apache, set RemoteIPProxyProtocol on.)