miércoles, 13 de mayo de 2015

SSL fortalecido con Tomcat 7 y Java 8

Tanto por seguridad como para salir bien parado en las auditorias (común en instalaciones corporativas), es importante tener bien configurado el SSL en Tomcat. En nuestro caso (instalaciones del Framework Dinámica) usamos Tomcat 7 sin Apache por delante, cuando mucho un Load Balancer o un Firewall, así que en este artículo nos concentramos en cómo configurar el SSL en Tomcat 7 para obtener un grado aceptable de seguridad.

El punto de referencia lo marca el riguroso test de SSL Labs:
https://www.ssllabs.com/ssltest/

Actualmente con esta configuración logramos obtener un "A", dejando aparte los temas del certificado no confiable que usamos para la prueba:


Como se puede apreciar arriba, este Tomcat también soporta HTTP Strict Transport Security, más adelante explicamos cómo hacerlo.

Actualizando los Certificados SSL

Viene una gran migración a certificados con algoritmo de firma SHA2,  ya los navegadores comenzaron a quejarse de los certificados firmados con SHA1, y pronto dejarán de soportarlos. Esto no tiene que ver con al configuración SSL de Tomcat 7 sino con el proceso de crear el KeyStore y solicitar la firma del certificado. Es bueno saber que al migrar a un certificado actualizado con firma SHA2 (SHA256withRSA) se dejan de soportar clientes viejos como IE 8 en XP SP2 o inferior, con XP SP3 se puede soportar IE8.

En todo caso, es importante actualizar el certificado para que sea ampliamente aceptado y no levante advertencias de seguridad, para ello se usa el algoritmo de firma SHA256withRSA con keytool de Java.

Usar Java 8

Para fortalecer SSL en Tomcat es necesario migrar a Java 8, porque esta versión contiene mejoras importantes en el componente JSSE (el que provee soporte SSL) que no están en versiones anteriores.

En particular se activan estas opciones para el proceso Java que correrá a Tomcat:

-Djdk.tls.rejectClientInitiatedRenegotiation=true
-Djdk.tls.ephemeralDHKeySize=2048

Por otro lado es MUY IMPORTANTE actualizar la instalación de Java 8 con las políticas de encriptamiento fuerte, que son dos JARs que se descargan desde el website oficial de Java en Oracle. El componente se denomina "Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files for JDK/JRE 8" y se descarga aquí:

http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html

Los JARs se copian en:

C:\Program Files\Java\jdk1.8.0_XX\jre\lib\security

reemplazando los existentes.

Usar Tomcat 7.0.61

Es necesario usar Tomcat 7.0.61 o superior, porque es a partir de esta versión que Tomcat permite indicar que se respete el orden de los Ciphers especificados del lado server, en el test de SSL Labs esto se puede comprobar:



En server.xml, en el bloque "Connector" donde configuramos SSL se añade este atributo:

useServerCipherSuitesOrder="true"

Anular ataques POODLE

En server.xml indicamos el uso de protocolos TLS únicamente:

sslEnabledProtocols="TLSv1,TLSv1.1,TLSv1.2"



El ataque BEAST es algo que no se puede evitar a menos que se elimine el uso de TLS 1.0 (afectando potencialmente la compatibilidad con una base amplia de navegadores) o se utilice RC4, lo cual es peor porque el protocolo no se considera seguro, su uso levanta alertas de seguridad y rebaja la calificación en el test, así que de los males el menor. De hecho a pesar de aparecer que no se mitiga BEAST del lado server (es un ataque que se orquesta desde el lado cliente), aun así la calificación es "A". Si solo se soporta TLS 1.2 (para los navegadores modernos únicamente) entonces se elimina el riesgo del BEAST.

Configuración de Ciphers fuerte y minimalista

Por defecto un servidor SSL en Java 8 soporta una gama amplia de protocolos, algunos considerados inseguros y su uso rebaja la calificación en el test de SSL Labs, además de levantar alertas de auditoria de seguridad de servidores, se sugiere usar una lista restringida de protocolos. Nosotros usamos la configuración de Ciphers que aparece abajo y obtenemos amplia compatibilidad con los navegadores más populares, soportando "Forward Secrecy"  donde es posible, lo cual fortalece la seguridad del protocolo, e incluso se soporta IE8 a partir de XP SP3, con lo que se gana un SSL robusto y amplia base de clientes soportados. El orden de los ciphers es importante y hace que los navegadores selecciones un Cipher fuerte antes que uno débil cuando inician la "conversación" con el servidor:

ciphers="TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
SSL_RSA_WITH_3DES_EDE_CBC_SHA"

Este es un atributo del Connector en server.xml claro está, A continuación un ejemplo completo de la configuración del conector SSL en Tomcat:

<Connector port="443" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="500" scheme="https" secure="true"
clientAuth="false" keystoreType="JKS" sslEnabledProtocols="TLSv1,TLSv1.1,TLSv1.2"
useServerCipherSuitesOrder="true"
keystoreFile="${catalina.home}/conf/localhost.jks"
keystorePass="xyz123*"
ciphers="TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
SSL_RSA_WITH_3DES_EDE_CBC_SHA"
>

Solo desde que salió Java 8 y sumado a la última actualización de Tomcat 7 se puede lograr una configuración de SSL razonablemente robusta, sin necesidad de utilizar ningún software por delante de Tomcat.

Hay una protección que JSSE en Java 8 no soporta: TLS Fallback SCSV, que en pocas palabras se trata de evitar que un cliente pueda negociar usar un protocolo más antiguo con la intención de vulnerar la seguridad. Sin embargo si se utilizan ciphers fuertes e incluso si solo se soporta TLS 1.2 este riesgo se reduce o incluso desaparece.

jueves, 26 de febrero de 2015

Acelerando el arranque de Tomcat 7

Regresamos con un mini-artículo sobre como mejorar los tiempos de arranque del servicio Tomcat, específicamente de la distribución de Tomcat 7 para el Framework Dinámica, que por correr aplicaciones creadas con este framework, no necesita JSPs, TagLibs, anotaciones de Servlet Spec 3.x ni otros artificios. Dinámica es minimalista, usa un solo Servlet (el Controller) y algunos filtros/listeners, nada ajeno a la especificación de servlets 3.0. Por este motivo hay varias cosas que se pueden desactivar en Tomcat para que arranque considerablemente más rápido.

La velocidad de arranque del servicio es importante para mantener la interrupción del mismo en un mínimo aceptable, sea por controles de cambio o contingencias.

Paso 1

En ${tomcat.home}/conf/catalina.properties se definen las reglas de scanning de anotaciones en los JARs, es el primer punto a tocar. La configuración por defecto pecha bastante el tiempo de arranque haciendo revisiones innecesarias (para Dinámica) en los JARs. El tiempo de arranque en nuestro Tomcat 7 con 4 WebApps instaladas es el siguiente:

[2015-02-25 16:01:57] INFORMACIËN: Initializing ProtocolHandler ["http-bio-80"]
[2015-02-25 16:01:57] INFORMACIËN: Initialization processed in 300 ms
[2015-02-25 16:01:57] INFORMACIËN: Arrancando servicio Catalina
[2015-02-25 16:01:57] INFORMACIËN: Starting Servlet Engine: Apache Tomcat/7.0.59
[2015-02-25 16:01:57] INFORMACIËN: Despliegue del directorio C:\tomcat7\webapps\admin de la aplicaci¾n web
[2015-02-25 16:01:57] INFORMACIËN: Despliegue del directorio C:\tomcat7\webapps\devel de la aplicaci¾n web
[2015-02-25 16:01:57] INFORMACIËN: Despliegue del directorio C:\tomcat7\webapps\nws de la aplicaci¾n web
[2015-02-25 16:01:57] INFORMACIËN: Despliegue del directorio C:\tomcat7\webapps\ROOT de la aplicaci¾n web
[2015-02-25 16:02:00] INFORMACIËN: Deployment of web application directory C:\tomcat7\webapps\ROOT has finished in 2.367 ms
[2015-02-25 16:02:00] INFORMACIËN: Deployment of web application directory C:\tomcat7\webapps\nws has finished in 2.517 ms
[2015-02-25 16:02:00] INFORMACIËN: [Dinamica] SecurityFilter started for context: AdminConsole
[2015-02-25 16:02:00] INFORMACIËN: Deployment of web application directory C:\tomcat7\webapps\admin has finished in 2.690 ms
[2015-02-25 16:02:01] INFORMACIËN: WSSERVLET14: inicializando el servlet de JAX-WS
[2015-02-25 16:02:01] INFORMACIËN: WSSERVLET12: inicializando el listener de contexto de JAX-WS
[2015-02-25 16:02:01] INFORMACIËN: Deployment of web application directory C:\tomcat7\webapps\devel has finished in 3.220 ms
[2015-02-25 16:02:01] INFORMACIËN: Starting ProtocolHandler ["http-bio-80"]
[2015-02-25 16:02:01] INFORMACIËN: Server startup in 3256 ms

Lo que vamos a hacer es desactivar el scanning de los JARs, configurando estos parámetros con los valores mostrados abajo:

tomcat.util.scan.DefaultJarScanner.jarsToSkip=*.jar
org.apache.catalina.startup.ContextConfig.jarsToSkip=*.jar
org.apache.catalina.startup.TldConfig.jarsToSkip=*.jar

Con este no se desactiva el uso de anotaciones muy útiles, como @WebService y @MultipartConfig.
Si reiniciamos Tomcat obtenemos estos tiempos:

[2015-02-25 16:09:21] INFORMACIËN: Initializing ProtocolHandler ["http-bio-80"]
[2015-02-25 16:09:21] INFORMACIËN: Initialization processed in 287 ms
[2015-02-25 16:09:21] INFORMACIËN: Arrancando servicio Catalina
[2015-02-25 16:09:21] INFORMACIËN: Starting Servlet Engine: Apache Tomcat/7.0.59
[2015-02-25 16:09:21] INFORMACIËN: Despliegue del directorio C:\tomcat7\webapps\admin de la aplicaci¾n web
[2015-02-25 16:09:21] INFORMACIËN: Despliegue del directorio C:\tomcat7\webapps\devel de la aplicaci¾n web
[2015-02-25 16:09:21] INFORMACIËN: Despliegue del directorio C:\tomcat7\webapps\nws de la aplicaci¾n web
[2015-02-25 16:09:21] INFORMACIËN: Despliegue del directorio C:\tomcat7\webapps\ROOT de la aplicaci¾n web
[2015-02-25 16:09:22] INFORMACIËN: Deployment of web application directory C:\tomcat7\webapps\ROOT has finished in 610 m
s
[2015-02-25 16:09:22] INFORMACIËN: Deployment of web application directory C:\tomcat7\webapps\nws has finished in 770 ms

[2015-02-25 16:09:22] INFORMACIËN: [Dinamica] SecurityFilter started for context: AdminConsole
[2015-02-25 16:09:22] INFORMACIËN: Deployment of web application directory C:\tomcat7\webapps\admin has finished in 1.01
1 ms
[2015-02-25 16:09:23] INFORMACIËN: WSSERVLET14: inicializando el servlet de JAX-WS
[2015-02-25 16:09:23] INFORMACIËN: WSSERVLET12: inicializando el listener de contexto de JAX-WS
[2015-02-25 16:09:23] INFORMACIËN: Deployment of web application directory C:\tomcat7\webapps\devel has finished in 1.59
1 ms
[2015-02-25 16:09:23] INFORMACIËN: Starting ProtocolHandler ["http-bio-80"]
[2015-02-25 16:09:23] INFORMACIËN: Server startup in 1617 ms

Una reducción de aproximadamente el 50%, nada mal.

Paso 2

A nivel de cada WebApp es necesario desactivar el scanning de TLDs, No sirve hacerlo en el context.xml global de Tomcat 7, ya lo probamos y no tiene efecto. Es necesario hacerlo en el context.xml privado de cada WebApp que está en /META-INF. Las WebApps creadas con Dinámica para correr en Tomcat usan la definición de su pool de conexiones a BD dentro de este archivo. Y el plugin del Framework para crear WebApps en Eclipse ya incluye esta entonación cuando crea el proyecto. Se trata de añadir el siguiente elemento (resaltado en amarillo):

<Context processTlds="false">

... el pool se define aquí ...

</Context>

Antes de esta optimización podríamos ver con JConsole el tiempo gastado en procesar TLDs aunque no los estemos usando:


Luego de aplicar el cambio en TODAS las WebApps instaladas, observamos que el tiempo del atributo tldScanTime=0 para cada WebApp.


Y el log de arranque del servicio muestra el resultado final de la entonación:

[2015-02-25 16:11:34] INFORMACIËN: Initializing ProtocolHandler ["http-bio-80"]
[2015-02-25 16:11:34] INFORMACIËN: Initialization processed in 297 ms
[2015-02-25 16:11:34] INFORMACIËN: Arrancando servicio Catalina
[2015-02-25 16:11:34] INFORMACIËN: Starting Servlet Engine: Apache Tomcat/7.0.59
[2015-02-25 16:11:34] INFORMACIËN: Despliegue del directorio C:\tomcat7\webapps\admin de la aplicaci¾n web
[2015-02-25 16:11:34] INFORMACIËN: Despliegue del directorio C:\tomcat7\webapps\devel de la aplicaci¾n web
[2015-02-25 16:11:34] INFORMACIËN: Despliegue del directorio C:\tomcat7\webapps\ROOT de la aplicaci¾n web
[2015-02-25 16:11:34] INFORMACIËN: Despliegue del directorio C:\tomcat7\webapps\nws de la aplicaci¾n web
[2015-02-25 16:11:34] INFORMACIËN: Deployment of web application directory C:\tomcat7\webapps\nws has finished in 441 ms

[2015-02-25 16:11:34] INFORMACIËN: Deployment of web application directory C:\tomcat7\webapps\ROOT has finished in 441 m
s
[2015-02-25 16:11:34] INFORMACIËN: [Dinamica] SecurityFilter started for context: AdminConsole
[2015-02-25 16:11:34] INFORMACIËN: Deployment of web application directory C:\tomcat7\webapps\admin has finished in 561
ms
[2015-02-25 16:11:35] INFORMACIËN: WSSERVLET14: inicializando el servlet de JAX-WS
[2015-02-25 16:11:35] INFORMACIËN: WSSERVLET12: inicializando el listener de contexto de JAX-WS
[2015-02-25 16:11:35] INFORMACIËN: Deployment of web application directory C:\tomcat7\webapps\devel has finished in 1.15
3 ms
[2015-02-25 16:11:35] INFORMACIËN: Starting ProtocolHandler ["http-bio-80"]
[2015-02-25 16:11:35] INFORMACIËN: Server startup in 1179 ms

¡El tiempo de arranque se redujo en 64%! Otra ventaja de usar el estilo Dinámica de programación simple, sin las complicaciones asociadas usualmente al desarrollo web con Java.

Plataforma utilizada:

  • Tomcat 7.0.59
  • Java 1.8 update 31 x64
  • Windows 7 Home Premium x64


Esperamos les resulte de utilidad este mini blog, sobre todo a los suscriptores del Framework (Dinámica se vende por suscripción), aprovechamos de celebrar con esto los 11 años de Dinámica en producción, utilizado a escala global en docenas de proyectos que traspasan dominios de negocios y le ha permitido nutrirse y robustecerse como herramienta de hiper productividad.