HAProxy con SNI e diverse impostazioni SSL


9

Ho HAProxy per i miei due siti, uno pubblico e uno privato.

www.mysite.com private.mysite.com

Atm, sto usando haproxy in questo modo:

frontend mysite_https
  bind *.443 ssl crt /etc/mycert.pem ca-file /etc/myca.pem verify optional no-sslv3
  mode http
  acl domain_www     hdr_beg(host) -i www.
  acl domain_private hdr_beg(host) -i private.
  acl path_ghost     path_beg         /ghost/
  acl clientcert     ssl_c_used

  redirect location https://www.example.com if path_ghost !clientcert
  redirect location https://www.example.com if !domain_www !clientcert

  use_backend bknd_private if domain_private
  use_backend bknd_www     if domain_www

  default_backend bknd_www

Quello che dovrebbe fare è chiedere un certificato client (opzionale) e procedere. Se il dominio non è www.example.com e il visitatore non può fornire il certificato giusto o il percorso è / ghost / e il visitatore non può fornire il certificato giusto, deve essere reindirizzato a https://www.example.com

Finora funziona bene. Tuttavia, ho ricevuto lamentele da parte degli utenti Mac che navigano nel mio sito con Safari che continuano a ricevere il certificato quando navigano su https://www.example.com/ mentre ad esempio Firefox chiede solo quando navigano su https: //private.example .com / o https://www.example.com/ghost/ .

Apparentemente è così che funziona Safari, quindi non posso risolverlo. La mia idea era di usare SNI per dividere tra frontend diversi

frontend mysite_https
  bind *.443 ssl crt /etc/mycert.pem no-sslv3

frontend private_https
  bind *.443 ssl crt /etc/mycert.pem ca-file /etc/myca.pem verify optional no-sslv3

Certo che non funziona perché

un. Non posso avere due frontend in ascolto sulla porta 443 con un solo IP pubblico b. Non ho ancora trovato un modo per dire "use_frontend if domain_www" o qualcosa del genere. (Solo use_backend o use-server)

Ho anche provato a farlo con tre server haproxy

frontend haproxy-sni
bind *:443 ssl crt /etc/mycert.pem no-sslv3
mode tcp

tcp-request inspect-delay 5s
tcp-request content accept if { req.ssl_hello_type 1 }

acl domain_www ssl_fc_sni_end -i www.example.com

use-server server1 haproxy-private.lan  if !domain_www
use-server server2 haproxy-public.lan   if domain_www

Funziona, il problema qui è che haproxy-private richiede il certificato client, ma la richiesta non raggiunge il browser. In qualche modo haproxy-sni elimina la richiesta.

Inoltre, ora ho tre server haproxy che non sono desiderabili (anche se un'opzione possibile se non trovo una soluzione migliore).

Preferibilmente vorrei qualcosa del genere (inventato .. non conosco le opzioni reali)

frontend mysite_https
  bind *.443 ssl crt /etc/mycert.pem no-sslv3
  mode http

  acl domain_www     hdr_beg(host) -i www.
  acl domain_private hdr_beg(host) -i private.
  acl path_ghost     path_beg         /ghost/

  ssl_options ca-file /etc/myca.pem verify optional if !www_domain          # made up!
  ssl_options ca-file /etc/myca.pem verify optional if !path_ghost          # made up!

  acl clientcert     ssl_c_used

  redirect location https://www.example.com if path_ghost !clientcert
  redirect location https://www.example.com if !domain_www !clientcert
  ...

Spero che qualcuno mi possa aiutare con questo...

Risposte:


13

Ho trovato una soluzione a questo problema, che non richiede server o servizi aggiuntivi. Non sono del tutto sicuro che ciò non generi nuovi problemi. Per me sembra funzionare proprio ora.

Il modo in cui l'ho fatto è stato quello di creare un frontend per ogni dominio che richiedeva impostazioni ssl diverse. Ho quindi impostato l'opzione di associazione di quei frontend su porte alte (non sono raggiungibili dal pubblico!).

Ho creato un altro frontend in ascolto sulla porta: 443 per dividere il traffico basato su SNI e ho impostato i server back-end su 127.0.0.1:high-port.

In questo modo, ho creato una specie di loop in haproxy

[incoming]->[haproxy:443]->[haproxy:7000]->[www.intern.lan]
[incoming]->[haproxy:443]->[haproxy:8000]->[private.intern.lan]

Ecco la parte di configurazione.

frontend frnd_snipt                                             # Frontend_SNI-PassThrough (snipt)
  bind *:443                                                    # Do not use bind *:8443 ssl crt etc....!
  option tcplog
  mode tcp 

  tcp-request inspect-delay 5s
  tcp-request content accept if { req_ssl_hello_type 1 } 

  acl subdomain_is_www   req_ssl_sni -i www.example.com
  acl subdomain_is_www   req_ssl_sni -i example.com
  acl subdomain_is_private req_ssl_sni -i private.example.com

  use_backend bknd_snipt_private if subdomain_is_private
  use_backend bknd_snipt_www  if subdomain_is_www

backend bknd_snipt_www
  mode tcp                                              # tcp mode must match the frontend mode - already set as default in [global]
  server snipt-www 127.0.0.1:7000                       # run without "check", otherwise haproxy checks itself all the time!

backend bknd_snipt_private
  mode tcp     
  server snipt-private 127.0.0.1:8000                   # also, don't add "ssl" when in tcp mode. "ssl" is an http mode option (result in "NO-SRV" when set in tcp)

##### NORMAL HAPROXY PART #####
frontend www_example_com                                # this frontend can be in tcp or http mode...
  bind *:7000 ssl crt /etc/mycert.pem no-sslv3          # www. frontend with normal https
  mode http
  option httplog


frontend private_example_com
  bind *:8000 ssl crt /etc/mycert.pem ca-file /etc/myca.pem verify optional no-sslv3        # private. frontend with client certificate request.
  mode http
  option httplog
  ... # whatever you have in your frontend

Se qualcuno ha pensieri su questo, o qualche idea sul perché questa potrebbe essere una cattiva idea, per favore fatemelo sapere. Funziona, ma mi chiedo perché use_frontend non sia un'opzione. Forse perché è qualcosa che non dovrebbe essere fatto per qualsiasi motivo.


Buona idea. Non sono riuscito a trovare documentazione nemmeno su questa configurazione. Le prestazioni sono simili con questo loop HAProxy?
JB. Con Monica.

Sry, non so quanto sia performante perché A: non lo ha usato a lungo (a causa dei filtri IP di origine), B: non ha un sito di traffico elevato, dove l'ottimizzazione delle prestazioni sarebbe più interessante ...
Mohrphium,

Ho appena messo apache2 davanti a haproxy, che funziona ma è un po 'stupido perché un singolo punto di errore davanti al cluster hapexy e (penso) un collo di bottiglia delle prestazioni (penso che hap sia più veloce di ap2, non ho dati reali su quello però.)
mohrphium il

3

le versioni recenti di haproxy supportano un'impostazione chiamata crt-listche consente di specificare diverse impostazioni TLS in base al certificato corrispondente

puoi usarlo in questo modo:

haproxy.conf:

frontend https
    mode http
    bind *:443 ssl crt-list /etc/haproxy/crt-list.conf ca-file ca.pem

    use_backend test if { ssl_fc_sni -i test.area.example.org }
    use_backend private if { ssl_fc_sni -i private.example.org }
    default_backend www

CRT-list.conf:

www.pem [verify none]
www.pem [verify required] *.area.example.org
private.pem [verify required]

maggiori informazioni: https://cbonte.github.io/haproxy-dconv/1.9/configuration.html#5.1-crt-list

nota sulla sicurezza: abbina sempre i tuoi nomi host (sensibili) a SNI ssl_fc_sni, non il nome host HTTP. Altrimenti, un utente malintenzionato potrebbe aggirare l'autenticazione del client inviando l'SNI TLS di www.example.orgma impostando il nome host HTTP su private.example.org!


OP utilizza lo stesso certificato per entrambi. La domanda riguardava più le diverse ca-fileimpostazioni.
gre_gor,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.