J'ai Haproxy pour mes deux sites, l'un d'eux public et un privé.
www.mysite.com privé.mysite.com
ATM, j'utilise haproxy comme ceci:
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
Ce que cela devrait faire est de demander un certificat client (éventuellement) et de continuer. Si le domaine n'est pas www.example.com et que le visiteur ne peut pas fournir le bon certificat ni le chemin est/Ghost/et le visiteur ne peut pas fournir le bon certificat, il devrait être redirigé vers HTTPS: //www.example .com
Jusqu'à présent, cela fonctionne bien. Cependant, j'ai eu des plaintes par les utilisateurs de Mac parcourant mon site avec Safari qu'ils continuent à demander le certificat lorsqu'il navigue sur https://www.example.com/ tandis que, par exemple, Firefox ne demande que lors de la navigation. https://private.example.com/ ou https://www.example.com/ghost/ .
Il s'agit de ce que Safari fonctionne donc donc je ne peux pas résoudre ce problème. Mon idée était d'utiliser SNI pour diviser entre différentes fronçons
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
Bien sûr que cela ne fonctionne pas parce que
une. Je ne peux pas avoir deux frontes à écouter sur le port 443 avec une seule pivité publique b. Je n'ai pas encore trouvé de chemin à dire "use_frontend si domain_www" ou quelque chose comme ça. (Seulement utiliser_backend ou use-serveur)
J'ai aussi essayé de le faire avec trois serveurs 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
Cela fonctionne, cependant, le problème est que Haproxy-Private demande le certificat client, mais la demande n'atteint pas le navigateur. D'une manière ou d'une autre haproxy-sni abandonne la demande.
De plus, je dispose maintenant de trois serveurs haproxy qui n'est pas souhaitable (bien qu'une possible option si je ne trouve pas de meilleure solution).
De préférence, je voudrais quelque chose comme ça (maquillé .. ne connaissez pas les véritables options)
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
...
J'espère que quelqu'un peut me aider...
J'ai trouvé une solution à ce problème, cela ne nécessite pas de serveurs ou de services supplémentaires. Je ne suis pas totalement sûr que cela n'accorde pas de nouveaux problèmes cependant. Pour moi, il semble fonctionner en ce moment.
La façon dont je l'ai fait, était de créer un frontend pour chaque domaine nécessitant différents paramètres SSL. J'ai ensuite défini l'option Bind de ces fronctions à des ports élevés (ceux-ci ne sont pas accessibles de public!).
J'ai créé une autre écoute de frontend sur le port: 443 pour diviser le trafic basé sur SNI et définir les serveurs de backend au 127.0.0.1:High-port.
De cette façon, j'ai créé une sorte de boucle dans haproxy
[incoming]->[haproxy:443]->[haproxy:7000]->[www.intern.lan]
[incoming]->[haproxy:443]->[haproxy:8000]->[private.intern.lan]
Voici la partie de configuration.
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
Si quelqu'un a des idées à ce sujet, ou une idée de la raison pour laquelle cela pourrait être une mauvaise idée s'il vous plaît faites le moi savoir. Cela fonctionne, mais je me demande pourquoi utiliser_frontend n'est pas une option. Peut-être parce que c'est quelque chose qui ne devrait pas être fait pour les raisons.
les versions récentes de Haproxy supportent un paramètre appelé crt-list
qui vous permet de spécifier différents paramètres TLS en fonction du certificat correspondant
vous pouvez l'utiliser comme ceci:
haparroxy.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]
plus d'infos: https://cbonte.github.io/haproxy-dconv/1.9/configuration.html#5.1-crt-list
nOTE SUR LA SÉCURITÉ: Faites toujours correspondre vos noms d'hôte (sensibles) contre Sni ssl_fc_sni
, pas le nom d'hôte http. Sinon, un attaquant pourrait éventuellement contourner votre authentification de votre client en envoyant la SNI TLS de www.example.org
Mais définissez le nom d'hôte HTTP sur private.example.org
!