Certificado SSL+TLS auto-firmado para XAMPP en Windows

¡Hola nuevamente! Realizo el segundo tutorial de este mes por la necesidad de explicar cómo generar certificados SSL auto-firmados (self signed SSL certificate) para XAMPP. El proceso será muy detallado, explicando todos los comandos que realizaremos.

Lo cierto es que en los últimos días estuve leyendo un par de tutoriales que no explicaban totalmente porqué se realizaban esos pasos, o cometían fallos respecto al almacenamiento de los certificados y las claves. Por eso, hoy traigo este tutorial, donde enseñaré a crear un certificado SSL para localhost y otro para un virtualhost en Windows utilizando OpenSSL 1.0.2.

Notas iniciales:

Este tutorial se realizó en Windows 7 (64 bits) recién instalado en una máquina virtual (VirtualBox) (esto no hace que varíe nada, es solo un detalle), utilizando un XAMPP (Apache 2.4.18) recién instalado con la versión 3.2.2 (compilado: 12 Noviembre 2015). Para seguir este tutorial es necesaria una cuenta de administrador.

Importante:

Estos certificados NO son recomendables para ambientes de producción, están pensados para ambientes de desarrollo. La mayoría de los navegadores no reconocerían que este certificado haya sido emitido por una entidad confiable (como Verisign o GoDaddy), e impedirían el acceso a la página.

¿Cómo generar un certificado para localhost?

El primer paso es generar una carpeta donde guardaremos nuestros certificados. Esta carpeta debemos crearla en la carpeta conf que está dentro de apache. La ruta, siempre teniendo en cuenta que se haya instalado XAMPP en la ubicación por defecto, sería:

C:\xampp\apache\conf

A esa carpeta yo la llamaré mis_certificados, pero puedes nombrarla como desees.

Dentro de mis_certificados, crearé una carpeta para el certificado de localhost. A esta carpeta la llamaré localhost, aunque puede llamarse de cualquier manera, pero esto lo deja más organizado.

Bien, una vez tenemos estas carpetas, vamos a proceder a generar el certificado. Lo primero para esto es abrir la consola de comandos (cmd) ejecutándola como administrador.

Ahora debemos movernos a la ruta donde está OpenSSL, el cual viene incluido con XAMPP. La ruta por defecto es:

C:\xampp\apache\bin

Para esto escribiremos cd (change directory) y la ruta.

Ahora generaremos un clave RSA escribiendo el siguiente comando:

openssl genrsa -aes256 -out C:\xampp\apache\conf\mis_certificados\localhost\local.key 2048

Y aquí viene la explicación, basada en la documentación oficial.

  • openssl -> Establece que vamos a trabajar con OpenSSL.
  • genrsa -> Indica que se va a generar una clave RSA.
  • -aes256 -> Define el tipo de encriptación (yo usaré AES con un bloque de 256 bits, pero se pueden utilizar los siguientes cifrados: -aes128 | -aes192 | -aes256 | -camellia128 | -camellia192 | -camellia256 | -des | -des3 | -idea).
  • -out [nombre del archivo] -> Establece donde guardará y el nombre de salida del archivo que contiene la private key.
  • 2048 -> Define el largo en bits de la clave (se puede usar 1024 o 2048, si no se define, usa 512 bits por defecto).

Una vez escrito este comando, al introducirlo es probable que nos avise, con un WARNING, que no se puede encontrar el archivo de configuración en c:/openssl-1.0.2e-win32/ssl/openssl.cnf, pero no hay problema por eso, pues ese archivo de configuración se encuentra en otra ruta (dentro de la carpeta de XAMPP) que especificaremos cuando sea necesario. Esto es porque no instalamos OpenSSL, sino que utilizamos la aplicación que trae XAMPP.

A continuación debe generar la clave privada y va a pedirnos que le otorguemos una “pass phrase, una contraseña para esa clave privada. Escribimos la contraseña y pulsamos Enter.

NOTA: no se verá ningún carácter cuando escribas la contraseña, así que, si te encuentras en un ambiente confiable (preferiblemente donde nadie pueda ver lo que haces), te recomiendo que escribas la contraseña en un bloc de notas (o cualquier editor de texto) y copies y pegues cuando sea necesario. Sino, tendrás que escribir correctamente la contraseña en varias ocasiones en los próximos pasos.

Ahora nos pedirá que verifiquemos la contraseña. Una vez realizado, ya tendremos la clave privada.

Ahora necesitamos generar el CSR (Certificate Signing Request), esto es una “solicitud de firma” que incluye datos del “dueño” del certificado SSL.

Para esto, vamos a escribir el siguiente comando:

openssl req -new -key C:\xampp\apache\conf\mis_certificados\localhost\local.key -config "C:\xampp\php\extras\openssl\openssl.cnf" -out C:\xampp\apache\conf\mis_certificados\localhost\local.csr

La explicación para esto es:

  • req -> Realiza la petición para crear un certificado PKCS#10 (un estándar, ver RFC 2986).
  • -new -> Genera un nuevo certificado, en caso de no usarlo se generaría una clave privada RSA con la configuración hecha en el archivo de configuración.
  • -key [nombre del archivo] -> Especifica el archivo del cual vamos a leer la clave privada (local.key), también acepta claves privadas con el formato de PKCS#8.
  • -config [nombre del archivo] -> Permite una configuración alternativa. En este caso usamos la que viene por defecto en XAMPP.
  • -out [nombre del archivo] -> Establece donde guardará y el nombre de salida del archivo del CSR.

Una vez hayamos introducido este comando, debemos volver a ingresar la contraseña de la clave privada.

Y a continuación introduciremos los datos que sean necesarios para este CSR. Estos datos son:

  • Nombre del país (utilizando para ello 2 letras especificadas en el ISO 3166).
  • Nombre completo del estado o provincia.
  • Nombre de la localidad (por ejemplo, la ciudad).
  • Nombre de la organización (por ejemplo, de la compañía).
  • “Common Name”, este dato es de vital importancia: aquí debemos introducir el dominio (preferiblemente sin www) de la web donde vamos a utilizar este certificado. En este caso, será localhost.
  • Dirección de email.
  • Datos complementarios: una contraseña y un nombre opcional para la compañía.

Si no queremos rellenar alguno de los datos, simplemente ponemos un punto y pulsamos Enter.

ç

El siguiente paso es importante: Windows no permite que se utilice la directiva SSLPassPhraseDialog de Apache, ya sea en httpd.conf o en ssl.conf, conllevando esto a que, cuando intentemos entrar en la página que contenga SSL (HTTPS), el error.log del servidor nos muestre, entre otros fallos, el siguiente error:

[error] Init: SSLPassPhraseDialog builtin is not supported on Win32

Para evitar esto, lo único que debemos hacer es generar una copia de la clave privada sin contraseña. En este caso es común que la copia se llame [nombre original].key.org, teniendo así el archivo [nombre original].key como clave privada sin contraseña.

copy C:\xampp\apache\conf\mis_certificados\localhost\local.key C:\xampp\apache\conf\mis_certificados\localhost\local.key.org

Y ahora le indicamos a OpenSSL que le quite la contraseña, reemplazando el archivo original. Para esto, nos pedirá la contraseña, obviamente.

openssl rsa -in C:\xampp\apache\conf\mis_certificados\localhost\local.key.org -out C:\xampp\apache\conf\mis_certificados\localhost\local.key

Y por último, debemos crear y firmar el certificado. Esto se hace de la siguiente manera:

openssl x509 -req -days 365 -in C:\xampp\apache\conf\mis_certificados\localhost\local.csr -signkey C:\xampp\apache\conf\mis_certificados\localhost\local.key -out C:\xampp\apache\conf\mis_certificados\localhost\local.crt

Esto es:

  • x509 -> Utilidad de OpenSSL para mostrar y firmar certificados.
  • -req -> Con esta opción, en lugar de un certificado (valor esperado por defecto de la utilidad x509), se espera una petición de certificado (CSR).
  • -days [valor numérico] -> La cantidad de días que se espera que el certificado sea válido (por defecto son 30 días), en este caso lo establezco en un año (365 días).
  • -in [nombre del archivo] -> Especifica el nombre del archivo desde donde se van a tomar los datos (en este caso, el archivo CSR).
  • -signkey [nombre del archivo] -> Esta opción hace que el archivo input (CSR) sea auto-firmado usando la clave privada provista (en este caso, el archivo local.key).
  • -out [nombre del archivo] -> Establece el nombre de salida del archivo (certificado) recién firmado.

Finalizado este proceso, deberíamos tener en nuestra carpeta de certificados, los siguientes archivos:

  1. local.crt
  2. local.csr
  3. local.key
  4. local.key.org

Ahora debemos cambiar la dirección donde apunta el certificado y la clave privada del localhost en la configuración del SSL de Apache. Para esto, teniendo el servidor apagado, hacemos click en “Config > httpd-ssl.conf”, buscamos el VirtualHost _default_:433, y cambiamos _default_ por localhost y el dominio de ejemplo por localhost:

Ahora podemos encender el servidor y acceder a https://localhost

Como decía al comienzo de esta entrada, el navegador (en este caso Google Chrome) no confía en el certificado SSL, lo cual es un método de seguridad útil para evitar certificados falsos. Como nosotros sí confiamos (porque es nuestro CA auto-generado), hacemos click en “Avanzada” y continuamos a localhost.

Página por defecto de XAMPP.

Página por defecto de XAMPP.

Ahora lo correcto sería agregar este certificado a los CA de confianza en nuestro(s) navegador(es). En Chrome es sencillo; vamos a chrome://settings, bajamos hasta donde dice “Mostrar configuración avanzada…” y en la sección HTTPS/SSL hacemos click en “Administrar certificados…“.

Cuando se nos abra la ventana de Certificados, debemos ir hasta la pestaña “Entidades de certificación raíz de confianza“, y hacer click en “Importar…“:

Entonces se nos abrirá el “asistente para importación de certificados”. Click en “Siguiente“.

A continuación, hacemos click en “Examinar…” y especificamos el certificado (local.crt):

Click en “Siguiente” para definir donde se va a ubicar el certificado. Debemos elegir “Colocar todos los certificados en el siguiente almacén” > “Entidades de certificación raíz de confianza”.

Después finalizamos el asistente…

Y en este caso Chrome me avisa que corro riesgo al instalar este certificado. Le decimos que sí queremos instalar el certificado y listo.

Ya deberíamos tenerlo en la lista de certificados de confianza:

Esto quiere decir que ya tenemos el candadito verde de HTTPS en localhost:

Y listo. Ahora pasemos al siguiente tutorial.

¿Cómo generar un certificado para un virtualhost?

En este caso, tengo una carpeta llamada mmv dentro de htdocs, donde hay un index.php que únicamente contiene un echo que dice “¡SSL configurado!“.

Lo primero que haré es crear el virtualhost desde el archivo de hosts de Windows. Para esto debemos ejecutar el bloc de notas como administrador y abrir el archivo hosts que hay en:

C:\Windows\System32\drivers\etc

En este archivo encontraremos algo como esto:

Entonces añadiremos la IP de local junto a el dominio de nuestro virtualhost, que en mi caso será “mmv.local“.

NOTA: No debemos (ni podemos) utilizar dominios comunes (“.com”, “.net”, “.org”, etcétera), debemos usar un dominio inventado (por ejemplo: “.local”, “.dev”, “.proyecto”…).

Ahora debemos crear en la carpeta de certificados (mis_certificados) una carpeta con el nombre/dominio del virtualhost (no tiene porque ser así, pero es más fácil para organizarlo).

Y repetimos los pasos que hicimos con el localhost, pero cambiando las rutas y los nombres.

A continuación tenemos que añadir el virtualhost para que lo identifique Apache. Esto se hace yendo al archivo de configuración de los vhosts que se encuentra en:

C:\xampp\apache\conf\extra

con el nombre httpd-vhosts.conf, y lo abrimos con el bloc de notas.

Y al final de este archivo debemos añadir nuestra configuración para el puerto 443 y activar el SSLEngine. No olvides poner las rutas correctas del certificado y la clave privada.

Dejo la misma configuración que yo utilicé. Recuerda editarlo según tus necesidades.

<Directory "C:/xampp/htdocs/mmv">
	Options All
        AllowOverride All
        order allow,deny
        allow from all
</Directory>

<VirtualHost mmv.local:443>

DocumentRoot "C:/xampp/htdocs/mmv"
ServerName mmv.local
#ServerAlias www.mmv.local
ServerAdmin admin@example.com
ErrorLog "C:/xampp/apache/logs/error.log"
TransferLog "C:/xampp/apache/logs/access.log"

SSLEngine on

SSLCertificateFile "C:/xampp/apache/conf/mis_certificados/mmv.local/mmv.crt"
SSLCertificateKeyFile "C:/xampp/apache/conf/mis_certificados/mmv.local/mmv.key"

<FilesMatch "\.(cgi|shtml|phtml|php)$">
    SSLOptions +StdEnvVars
</FilesMatch>
<Directory "C:/xampp/apache/cgi-bin">
    SSLOptions +StdEnvVars
</Directory>

BrowserMatch "MSIE [2-5]" \
         nokeepalive ssl-unclean-shutdown \
CustomLog "C:/xampp/apache/logs/ssl_request.log" \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

</VirtualHost>

Ahora accedo a https://mmv.local y me encuentro lo mismo de antes: un aviso de certificado no válido.

Así que importo el certificado en el navegador como hice antes…

Y listo; virtualhost asegurado.

Transport Layer Security

Para mejorar la seguridad y la compatibilidad lo recomendable sería usar TLS igual o mayor a v1.1 y evitar SSL (v1, v2 y/o v3). Por una cuestión muy simple: SSL es bastante antiguo, tiene fallos de seguridad (así como TLS 1.0 y 1.1) que son, en su mayoría, corregidos en/con TLS 1.2. Algunas diferencias en este enlace (año 2010, en inglés).

////////////////////////////////////

Comentario oficial en httpd-ssl.conf (extraído de XAMPP v3.2.2):
Disable SSLv2 and SSLv3 by default (cf. RFC 7525 3.1.1). TLSv1 (1.0) should be disabled as quickly as practical. By the end of 2016, only the TLSv1.2 protocol or later should remain in use.

////////////////////////////////////

Además, evitaremos que se negocie, en el handshake SSL (intercambio de claves RSA entre el cliente y el servidor), el uso de MD5, RC4 y SHA, los cuales son bastante inseguros, y añadiremos más posibilidades de encriptación (en este caso, más posibilidades de AES con diferentes bloques, handshakes y hashes). Además, no incluimos kRSA, el cual es, según Apache, un algoritmo para intercambio de claves que “no ofrece confidencialidad directa”.

Usaremos la siguientes directivas de Apache: SSLCipherSuite, SSLProxyCipherSuite, SSLProtocol y SSLProxyProtocol dentro de httpd-ssl.conf. Por defecto SSLHonorCipherOrder está activada (on), pero si estuviese en desactivada, te recomiendo que lo actives.

SSLCipherSuite !kRSA:!MD5:!RC4:!SHA!:SSLv3:!SSLv2:EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GC$
SSLProxyCipherSuite HIGH:MEDIUM:!SSLv3:!kRSA:!MD5:!RC4:!SHA

SSLHonorCipherOrder on

SSLProtocol -all -SSLv2 -SSLv3 +TLSv1.1 +TLSv1.2
SSLProxyProtocol all -SSLv3

Esto hará que el mensaje “Tu conexión a [dominio] está encriptada con un conjunto de cifrado obsoleto […] con HMAC-SHA1 para la autenticación de mensajes […]” sea eliminado, dejando así de usar SHA1 (aunque sea con HMAC).

localhost asegurado

localhost asegurado

virtualhost asegurado

virtualhost asegurado

Conclusión:

Ojalá hayan quedado claros todos los pasos para completar el proceso de creación de este certificado SSL auto-generado y auto-firmado, y la importancia de usar TLS. Recuerda que estos certificados son únicamente para entornos de desarrollo.

Por supuesto podemos seguir accediendo a nuestros hosts con HTTP.

Espero que el tutorial haya sido de utilidad. Nos leemos, ¡saludos!

15 comments

  1. Rafael · marzo 3

    Hola buenas tardes, leí la parte que dice “Recuerda que estos certificados son únicamente para entornos de desarrollo”. Actualmente tengo instalado xampp en una computadora con windows7, tengo un siitio web con ip publica para que los usuarios lo puedan ver, hace poco me pidieron que el sitio estuviera cifrado con ssl, por lo que veo no me va a funcionar el xampp. ¿cual seria tu recomendación? Recomendarias hacer todo desde 0 con un servidor centos e intsalar el apache y posteriormente configurar el ssl, saludos

    Me gusta

    • Rocanrol · marzo 3

      Hola, Rafael.

      Mi recomendación sería que consigas un servidor + hosting que se adapte a tus necesidades (en este caso un servidor LAMP), y comprar después un certificado a una entidad confiable. No son un regalo, pero a veces sí es importante contar con un factor de seguridad como lo es SSL o TLS si vas a manejar datos privados en un entorno web “real” (no local).

      De todas formas te aviso que recientemente se detectó una [nueva] vulnerabilidad en SSLv2. Más información: http://thenextweb.com/dd/2016/03/01/drown-attack-breaks-https-on-33-of-websites/

      Te aviso para que evites cualquier tipo de conexión a tu web desde HTTPS usando el protocolo SSLv2. Esto se puede hacer desde la configuración de Apache, como se explica en el tutorial.

      Un saludo.

      Me gusta

  2. Hola, te felicito por tremendo tutorial, solo tengo un problema. Luego de hacer todo al pie de la letra, no logro que me aparezca el “candadito verde” ¿Que podrá ser?

    Me gusta

    • Rocanrol · junio 27

      Gracias!

      ¿Agregaste correctamente el certificado en el navegador?

      Saludos.

      Me gusta

  3. Sergio de PatagoniaIT · agosto 2

    UPDATE 1/8/2016
    Me funciono en XAMP V3.2.2 + Windows 10 64Bit, lo unico para tener el Check VERDE en los navegadores tenes que agregar el Certificado por medio de “certlm.msc” con permiso de Administrador dentro de la carpeta “Entidades de certificacion raiz de confianza” lo tenes que hacer en ese lugar ya que desde el navegador te va a seguir poniendo que no es un certificado de confianza.

    Print de donde instalar correctamente el certificado: http://s32.postimg.org/uh95jac85/Print_de_pantalla_30.png

    Gracias por el Tutorial

    Me gusta

  4. Excelente tutorial, me funciono correctamente. Solo una pequeña duda. Si voy a trabajar con un puerto en especifico digamos el 8050, se siguen los mismos pasos o que se tendría que cambiar?
    Saludos y Gracias!

    Me gusta

    • Rocanrol · septiembre 21

      ¡Gracias por tu comentario!

      Hasta donde tengo entendido sí, sigue los mismos pasos, porque SSL trabaja en 443.
      De todas formas, no estoy 100% seguro, así que sería genial si me/nos mantienes al tanto por acá🙂

      ¡Saludos!

      Me gusta

  5. Dayanci · octubre 10

    Hola, muy bueno el tutorial, he conseguido que me salga el candado verde en chrome, pero en firefox por el contrario me sigue poniendo lo de “Su conexión no es segura”, y no quiero hacer lo de “añadir excepción”, que me recomiendas que haga?.
    Un saludo.

    Me gusta

    • Rocanrol · octubre 11

      ¿Por qué no “añadir excepción”? Me parece la única manera lógica de que el navegador no interprete el certificado como malicioso.

      Me gusta

  6. Steven Bedoya · octubre 19

    Hola Muchas gracias! por este tutorial, esta completísimo y de mucha ayuda

    Me gusta

    • Rocanrol · octubre 19

      Me alegra que te haya sido de utilidad🙂 Saludos!

      Me gusta

  7. Robério Rebeca · octubre 22

    Ótimo. Consegui configurar o ssl no meu sisitema. Eu não tinha reparado a obrigatoriedade do nome localhost, e não estava dando certo, depois refiz os passos conforme o tutorial e deu certinho. Muito agradecido.

    Me gusta

  8. Carlos · 3 Days Ago

    Hay que seguir los mismos pasos si lo quiero realizar en una unidad de almacenamiento externo(memoria usb), porque sigo todos los pasos que están detallados pero después de cambiar el fichero de configuración “httpd-ssl.conf” ya funciona cuando le doy a iniciar el Apache.

    Le gusta a 1 persona

    • Rocanrol · 3 Days Ago

      Hola. ¿A qué te referís al decir “después de cambiar el fichero de configuración”?

      Porque cualquier cambio que se haga en archivos del servidor (httpd-ssl.conf, .htaccess…) requiere reiniciarlo.

      Me gusta

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s