Tengo HAProxy para mis dos sitios, uno público y otro privado.
www.mysite.com private.mysite.com
Atm, estoy usando haproxy como este:
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
Lo que debe hacer es solicitar un certificado de cliente (opcionalmente) y continuar. Si el dominio no es www.example.com y el visitante no puede proporcionar el certificado correcto o la ruta es / ghost / y el visitante no puede proporcionar el certificado correcto, debe redirigirse a https://www.example.com
Hasta ahora, esto funciona bien. Sin embargo, recibí quejas de los usuarios de Mac que navegan en mi sitio con Safari de que se les sigue pidiendo el certificado cuando navegan en https://www.example.com/ mientras que, por ejemplo, Firefox solo pregunta cuando navega en https: //private.example .com / o https://www.example.com/ghost/ .
Aparentemente así es como funciona Safari, así que no puedo solucionarlo. Mi idea era usar SNI para dividir entre diferentes interfaces
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
Por supuesto que eso no funciona porque
a. No puedo tener dos frontends escuchando en el puerto 443 con una sola IP pública b. Todavía no he encontrado una manera de decir "use_frontend if domain_www" o algo así. (Solo use_backend o use-server)
También intenté hacerlo con tres servidores 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
Esto funciona, sin embargo, el problema aquí es que haproxy-private solicita el certificado del cliente, pero la solicitud no llega al navegador. De alguna manera, haproxy-sni deja caer la solicitud.
Además, ahora tengo tres servidores haproxy que no es deseable (aunque es una opción posible si no puedo encontrar una solución mejor).
Preferiblemente me gustaría algo como esto (inventado ... no sé las opciones reales)
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
...
Espero que alguien pueda ayudarme con esto...
Las versiones recientes de haproxy admiten una configuración llamada
crt-list
que le permite especificar diferentes configuraciones de TLS en función del certificado coincidentepuedes usarlo así:
haproxy.conf:
crt-list.conf:
Más información: https://cbonte.github.io/haproxy-dconv/1.9/configuration.html#5.1-crt-list
nota sobre seguridad: siempre haga coincidir sus nombres de host (confidenciales) con SNI
ssl_fc_sni
, no el nombre de host HTTP. De lo contrario, un atacante podría omitir la autenticación de su certificado de cliente enviando el SNI de TLSwww.example.org
pero estableciendo el nombre de host HTTP enprivate.example.org
!fuente
ca-file
entorno diferente .