¿Cómo funciona el cambio de certificado HTTPS (como en suche.org)?

20

Para aquellos que no saben qué es Suche.org, es un sitio web que tiene una calificación A + perfecta en SSL Labs en todas las categorías: (resultado de Suche.org SSL Labs ). Conocí este sitio web cuando abrí otro ticket sobre los certificados ECC que no funcionaban en Chrome , y uno de los que respondieron lo utilizó como ejemplo.

Lo que me confunde es que, aunque la Protocol Supportsección del informe dice que el sitio web solo usa TLSv1.2 ...

TLS 1.2 Yes
TLS 1.1 No
TLS 1.0 No
SSL 3   No
SSL 2   No

Claramente, ese no es el caso, ya que en la Handshake Simulationsección, se muestra que algunos de los clientes antiguos simulados están utilizando TLSv1.0 para conectarse ...

Android 4.0.4   EC 384 (SHA256)     TLS 1.0 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA   ECDH secp521r1  FS
Android 4.1.1   EC 384 (SHA256)     TLS 1.0 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA   ECDH secp521r1  FS
Android 4.2.2   EC 384 (SHA256)     TLS 1.0 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA   ECDH secp521r1  FS
Android 4.3     EC 384 (SHA256)     TLS 1.0 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA   ECDH secp521r1  FS
Android 4.4.2   EC 384 (SHA256)     TLS 1.2 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384   ECDH secp521r1  FS

Esto es un poco frustrante porque si desactivo TLSv1.0 en mi sitio web de prueba así ...

# Apache example
SSLProtocol all -SSLv3 -SSLv2 -TLSv1

Ejecutar el análisis SSL Labs en mi sitio web de prueba produce lo siguiente para algunos de los clientes más antiguos:

Android 4.0.4   Server closed connection
Android 4.1.1   Server closed connection
Android 4.2.2   Server closed connection
Android 4.3     Server closed connection
Android 4.4.2   EC 384 (SHA256)     TLS 1.2 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256   ECDH secp256r1  FS

¿Cómo es posible permitir simultáneamente solo conexiones TLSv1.2, pero también admitir clientes más antiguos?

Scott Crooks
fuente
¿Deberíamos hacer que el título sea más genérico, algo así como "lógica de conmutación de certificados HTTPS"?
gf_
1
@gf_ Buena idea. Hecho.
Scott Crooks

Respuestas:

17

Estoy bastante seguro de que están verificando las capacidades del cliente y actúan en consecuencia, como se explica en el hilo vinculado a la respuesta de @Jeff .

Para tener una idea de cómo esto podría ser similar en detalle, echar un vistazo a este . Muestra una implementación hecha HAProxypara servir a diferentes clientes diferentes certs, dependiendo de sus capacidades. He copiado / pegado completo, para evitar la pudrición del enlace, y porque creo que esta pregunta podría ser de interés en el futuro:

Los certificados SHA-1 están saliendo, y debe actualizar a un certificado SHA-256 lo antes posible ... a menos que tenga clientes muy antiguos y deba mantener la compatibilidad SHA-1 por un tiempo.

Si se encuentra en esta situación, debe obligar a sus clientes a actualizar (difícil) o implementar alguna forma de lógica de selección de certificados: a eso le llamamos "cambio de certificado".

El método de selección más determinista es entregar certificados SHA-256 a clientes que presentan un HOLA CLIENTE TLS1.2 que anuncia explícitamente su soporte para SHA256-RSA (0x0401) en la extensión signature_algorithms.

extensiones de algoritmo de firma

Los navegadores web modernos enviarán esta extensión. Sin embargo, no conozco ningún equilibrador de carga de código abierto que actualmente pueda inspeccionar el contenido de la extensión signature_algorithms. Puede venir en el futuro, pero por ahora la forma más fácil de lograr la conmutación de certificados es usar las ACL SNI de HAProxy: si un cliente presenta la extensión SNI, diríjala a un servidor que presente un certificado SHA-256. Si no presenta la extensión, suponga que es un cliente antiguo que habla SSLv3 o alguna versión dañada de TLS, y preséntele un certificado SHA-1.

Esto se puede lograr en HAProxy encadenando frontend y backends:

Conmutación cert HAProxy

global
        ssl-default-bind-ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128
-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-R
SA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK

frontend https-in
        bind 0.0.0.0:443
        mode tcp
        tcp-request inspect-delay 5s
        tcp-request content accept if { req_ssl_hello_type 1 }
        use_backend jve_https if { req.ssl_sni -i jve.linuxwall.info }

        # fallback to backward compatible sha1
        default_backend jve_https_sha1

backend jve_https
        mode tcp
        server jve_https 127.0.0.1:1665
frontend jve_https
        bind 127.0.0.1:1665 ssl no-sslv3 no-tlsv10 crt /etc/haproxy/certs/jve_sha256.pem tfo
        mode http
        option forwardfor
        use_backend jve

backend jve_https_sha1
        mode tcp
        server jve_https 127.0.0.1:1667
frontend jve_https_sha1
        bind 127.0.0.1:1667 ssl crt /etc/haproxy/certs/jve_sha1.pem tfo ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
        mode http
        option forwardfor
        use_backend jve

backend jve
        rspadd Strict-Transport-Security:\ max-age=15768000
        server jve 172.16.0.6:80 maxconn 128

La configuración anterior recibe tráfico entrante en la interfaz llamada "https-in". Ese frontend está en modo TCP e inspecciona el CLIENTE HELLO proveniente del cliente por el valor de la extensión SNI. Si ese valor existe y coincide con nuestro sitio de destino, envía la conexión al backend llamado "jve_https", que redirige a una interfaz también llamada "jve_https" donde el certificado SHA256 se configura y sirve al cliente.

Si el cliente no puede presentar un CLIENTE HOLA con SNI, o presenta un SNI que no coincide con nuestro sitio de destino, se redirige al backend "https_jve_sha1", luego a su interfaz correspondiente donde se sirve un certificado SHA1. Esa interfaz también admite un conjunto de cifrado más antiguo para acomodar a clientes más antiguos.

Ambas interfaces eventualmente redirigen a un único backend llamado "jve" que envía tráfico a los servidores web de destino.

Esta es una configuración muy simple, y eventualmente podría mejorarse usando mejores ACL (HAproxy agrega regularmente nuevas), pero para una configuración básica de conmutación de certificados, ¡hace el trabajo!

gf_
fuente
9

Se hizo una pregunta similar en https://community.qualys.com/thread/16387

Creo que esta respuesta es la solución:

suche.org es una implementación inteligente. Por lo que yo entiendo, consulta las capacidades del cliente y luego solo ofrece lo mejor disponible, para eliminar cualquier duda.

Jeff
fuente
2
Sin embargo, "consulta las capacidades del cliente" no es exactamente una descripción útil. Apenas hay suficiente información para que alguien más pueda hacer su propia implementación.
womble