Solución:
Primero, repasemos brevemente cómo funciona la negociación del conjunto de cifrado. Por ejemplo, podemos usar el documento TLS 1.2 RFC 5246 comenzando en la sección 7.4.1.2 para ver, en forma abreviada:
- ClientHello: el cliente le dice al servidor qué conjuntos de cifrado admite el cliente
- Ahora el servidor elige uno
- ¡Hablaré sobre cómo controlar cuál elige a continuación!
- ServerHello: El servidor le dice al cliente qué suite de cifrado ha elegido o le da al cliente un mensaje de error.
Ahora, en cuanto a la selección real. He utilizado la documentación del módulo ssl de nginx, el artículo de Qualys 2013 sobre la configuración de Apache, Nginx y OpenSSL para el secreto directo, y el artículo de cifrados SSL de Hynek Hardening Your Web Server como referencia. Los dos últimos cubren tanto Apache como Nginx (ya que ambos usan OpenSSL como base).
Esencialmente, debe decirle a Nginx que use el orden que seleccione, y debe seleccionar un pedido. Para ver cuáles serían los resultados de ese orden, puede usar la línea de comando de OpenSSL, p. Ej.
openssl ciphers -v 'EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA256:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EDH+aRSA+AESGCM:EDH+aRSA+SHA256:EDH+aRSA:EECDH:!aNULL:!eNULL:!MEDIUM:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4:!SEED'
NOTA: Es posible que desee eliminar:! 3DES de esa cadena; El triple DES de 3 teclas no es eficiente, pero sigue siendo seguro en sí mismo para más o menos 112 bits de seguridad, y es muy, muy común.
Utilice el comando anterior para determinar qué conjuntos de cifrado serán los más preferidos y los menos preferidos en su configuración, y cámbielo hasta que le gusten los resultados. Las referencias que he dado tienen sus propias cadenas; Lo modifiqué ligeramente para obtener el ejemplo anterior (eliminando RC4 y SEED, y colocando cada conjunto de cifrado TLS 1.2 por encima de cualquier conjunto de cifrado ‘SSLv3’, por ejemplo).
Luego, para Nginx en particular, modificaría su archivo de configuración para incluir algo como:
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA256:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EDH+aRSA+AESGCM:EDH+aRSA+SHA256:EDH+aRSA:EECDH:!aNULL:!eNULL:!MEDIUM:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4:!SEED";
Agregue SSLv3 a ssl_protocols si realmente insiste en ello.
Ssl_prefer_server_ciphers informará a nginx que use el orden que especifiquemos, e ignorará el orden en el que el cliente presenta su lista de cifrado. Ahora, si el único conjunto de cifrado compartido entre ClientHello y la lista de cifrados OpenSSL -v … es nuestro menos preferido cifrado, eso es, por supuesto, lo que usará nginx. Si nada coincide, enviamos al cliente un aviso de falla.
El comando ssl_ciphers es la carne de la elección, aquí, ya que nginx informará a OpenSSL de nuestra lista de conjuntos de cifrado preferidos. Por favor, utilice el comando openssl ciphers -v para ver los resultados que obtiene en su plataforma. Lo ideal es comprobarlo de nuevo después de cambiar las versiones de OpenSSL.
Además, lea el artículo de Scott Helme sobre Configuración de HSTS (HTTP Strict Transport Security) en nginx, que permitirá a un host hacer cumplir el uso de HTTPS en el lado del cliente. Asegúrese de incluir el encabezado HSTS dentro del bloque http con la instrucción de escucha ssl.
Editado para agregar: al menos después de esto (si no antes también), vaya a Qualys SSL Labs para ver la información de seguridad HTTPS y probar su servidor que se ha mantenido bastante actualizado durante los últimos años. Las recomendaciones cambian con regularidad y, a veces, incluso con frecuencia se invierten (RC4, por ejemplo, lo que casi induce a un latigazo). ¡Incluso puede probar su navegador!
Mozilla tiene una herramienta en línea que le ayudará a elegir el paquete de cifrado correcto.
https://mozilla.github.io/server-side-tls/ssl-config-generator/
Le permitirá ingresar la versión de su servidor, la versión del software, etc. y luego elegir entre un equilibrio de seguridad y soporte heredado.
OpenSSL, naturalmente, preferirá MAC más nuevos para de lo contrario equivalente suites de cifrado. Por ejemplo, el largo openssl ciphers -v
la salida para su cadena de cifrado comienza con:
ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD
ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(256) Mac=AEAD
ECDHE-RSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA384
ECDHE-ECDSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA384
ECDHE-RSA-AES256-SHA SSLv3 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA1
ECDHE-ECDSA-AES256-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA1
Por supuesto, TLS solo usará conjuntos de cifrado compatibles entre el servidor y el cliente, y ni Chrome ni Firefox admiten conjuntos de cifrado HMAC-SHA256. Dado que HMAC-SHA1 (e incluso HMAC-MD5) todavía se consideran seguros, creo que sus desarrolladores (y los de NSS, la biblioteca TLS que ambos usan) se muestran escépticos sobre el desperdicio del esfuerzo del desarrollador y el tamaño del protocolo de enlace TLS agregando nuevos, innecesarios y al revés -Suites de cifrado incompatibles.
Mire, por ejemplo, los conjuntos de cifrado compatibles con Chrome 33 en orden de preferencia:
- ChaCha20-Poly1305,
- AES-128-GCM,
- AES-256-CBC con HMAC-SHA1,
- RC4 (ugh) y AES-128-CBC con HMAC-SHA1, …
OpenSSL no es compatible con ChaCha20-Poly1305. Si el suyo tampoco es compatible con AES-GCM (???) y utiliza un certificado RSA, ECDHE-RSA-AES256-SHA
es, naturalmente, el conjunto de cifrado que utilizará Chrome. (Firefox 29 usaría ECDHE-RSA-AES128-SHA
.)
(Los conjuntos de cifrado “SHA-256” que ha visto que se utilizan en otros sitios web son presumiblemente ChaCha20-Poly1305 o AES-128-GCM, que son AEAD que no utilizan HMAC, pero cuyos conjuntos de cifrado utilizan SHA-256 en el PRF.)