Multiple bind a.com:443 b.com:443 lines Yes/No?

I read that multiple line of the same IP_address:port is “allowed but incorrect”, here in this question.

However I find no pointers to the documentations, so I’ll explain what I would like to do see how this can be best configured (I have ideas that are too inelegant* to be the right way).

Topology:

Internet
|
Firewall (1 pubilc IP address)
|
LAN switch ------- HAproxy
| … |
be_a … be_z

I already configured many subdomains a.example.comz.example.com who share the same letsencrypt certificate with ssl termination in the unique same frontend.

I need to add a new backend be_AA responding to domain AA.example.com, but I need the ssl termination to be performed on the back-end side.

I added a new front-end AA, before the existing one a-to-z:

frontend http-in-AA
          bind AA.example.com:443 
          use_backend be_AA

frontend http-in-a-to-z
        bind *:443 ssl crt /etc/haproxy/certs/ defer-accept
        acl a ....
        acl z ...

    use_backend be_a if a
    use_backend be_z if z

The syntax check says valid without warning.

Is this correct ?

If not, what would be the best way to add this new server that is an exception to an already existing long list of other servers that work fine with ssl termination in HA proxy.

I supect also I may be confusing the fqdn in the bind address with the acl domain filter:
acl host_a hdr(host) -i a.example.com

Thanks a ton !

(*) The inelegant idea I had:
is to use ssl_fc_sni like in the solution from that question:

frontend ft_test
  mode http
  bind 0.0.0.0:443 ssl crt /certs/haproxy1.pem crt /certs/haproxy2.pem 
  use_backend bk_cert1 if { ssl_fc_sni my.example.com } # content switching based on SNI
  use_backend bk_cert2 if { ssl_fc_sni my.example.org } # content switching based on SNI

The reason I find it inelegant is because I fear that I may have to break my current front-end into one front-end for each a…z.example.com that would be huge work. I might be wrong though ?

No, you cannot use ssl_fc_sni, you need to use req_ssl_sni instead, and no, you don’t have to break your ssl terminating frontend to multiple ones.

Take a look at the following post for an example (which uses abns sockets but you can just replace them with loopback ports if you want):

Wow, so insightful, thank you.

I regret I do not understand the use-case of the poster Yong, but I guess he wants to authenticate clients with ca-file and verify, whereas I just need to run ssl termination in LB for 20 domains and in the back-end for one only, although they all share the same public IP routed to the LB.

However I grasp from your solution that its key principle can also apply to my case:

“Split in front1 by request SNI domain, then route (through 2 dummy be_abns sockets) to frontA or frontB which have 2 different SSL handling configurations”

is the way I would word it in non tech language. Then have each frontA and B route to specific back-ends, be_HTTPS for one and be_HTTP for all other.

Happy also to discover the Abstract namespace sockets (abns), and understood from that article that they are more convenient but less secure than Unix domain socket files, which should be fine now as a first step.

I will try to describe the solution I think of by modifying Yong’s example, to my use case, that I try to chart first:

Internet
|
Firewall (1 pubilc IP address)
|
—[--------LAN switch-------------------] ------- HAproxy *:443 *:80
|------------------- | ------------------ |
be_a:80 … be_z:80 nodes-termination:443

defaults
# prefer to set mode tcp or http explicitly

frontend https-switch
bind *:443
mode tcp #Lukas’ fix :slight_smile:
tcp-request inspect-delay 5s
tcp-request content accept if { req_ssl_hello_type 1 }
use_backend recir_notermination if { req_ssl_sni -i www.mydomain.de }
default_backend recir_default

backend recir_notermination
server loopback-for-tls abns@haproxy-notermination send-proxy-v2

backend recir_default
server loopback-for-tls abns@haproxy-default send-proxy-v2

frontend https-notermination
bind abns@haproxy-notermination accept-proxy # — removed:
ssl crt /etc/ssl/private/mydomain.de.pem ca-file /etc/ssl/private/client-authentication.pem verify required

# HSTS (15768000 seconds = 6 months)
http-response set-header Strict-Transport-Security max-age=15768000
mode tcp
default_backend nodes-notermination

frontend https-default
bind abns@haproxy-default ssl accept-proxy crt /etc/ssl/private/all_my_domains/
# HSTS (15768000 seconds = 6 months)
http-response set-header Strict-Transport-Security max-age=15768000
mode http

# — split by http domain name
acl host_a hdr(host) -i a.mydomain.de
use_backend be_a if host_a
# — (repeat a …z)
acl host_z hdr(host) -i z.mydomain.de
use_backend be_z if host_z

backend nodes-notermination
mode http
option httpclose
option forwardfor
no log
cookie JSESSIONID prefix
server https_app_server 10.1.1.250:443 cookie A check # not sure cookie will work here in HTTPS

backend be_a
mode http
option httpclose
option forwardfor
no log
compression algo gzip
compression type text/css text/less text/plain # ( … )
compression offload
cookie JSESSIONID prefix
server http_app_server_a 10.1.1.100:80 cookie A check

backend be_z
mode http
option httpclose
option forwardfor
no log
compression algo gzip
compression type text/css text/less text/plain # ( … )
compression offload
cookie JSESSIONID prefix
server http_app_server_z 10.1.1.125:80 cookie A check

Did I reflect well the solution you thought of ? Happy to check a simpler example, this turned out more complicated than I expected.

If this principle works, the key difference I understood between terminating SSL/TLS and not terminating in haproxy are:

  1. in frontend: mentioning ssl and cert path
  2. in back_end: (port 443 plus removing all HTTPS irrelevant features like cookies and compression)

Is that all ? I will try …

The fact that it doesn’t have permission is why am suggesting it, because that is an additional headache for users, especially with chroot and privilege downgrade.

It is as insecure as a high port on a loopback.

That’s about it, yes.

The point is: not HTTP features can be accessed for section that only handle untouched TCP/TLS. For example, backend nodes-notermination needs to be in tcp mode, and no cookie or forwardfor or httpclose features can be used.