HTTPS en localhost con mkcert

Desde que Google en 2018 empezara a marcar como “no seguras” las páginas webs que carecían de un certificado válido (no hacían uso de un protocolo seguro HTTPS), se empezó a vislumbrar la necesidad de trabajar con dicho protocolo en entornos de desarrollos locales. Sin embargo, ninguna entidad certificadora iba a “validar” que nuestro entorno de desarrollo local era un entorno seguro y por lo tanto se producía una paradoja algo extraña y difícil de subsanar. En este artículo os enseñaré a configurar HTTPS en localhost en pocos pasos.

Una primera solución para trabajar con HTTPS en localhost, es la de generar nuestro propio certificado auto-firmado. Aunque inicialmente podremos haber solucionado el problema y podamos trabajar con HTTPS en localhost, los navegadores seguirán advirtiendo que el sitio web es “no es seguro”. Esto hace que tengamos que aceptar el certificado emitido por nosotros mismos de forma manual en cada inicio de sesión.

Hace poco tuve que volver a trabajar en un proyecto con HTTPS en local y me entró la curiosidad por si había una solución más limpia y eficaz que la de certificados auto-firmados. Buscando de nuevo una solución a HTTPS en localhost, me topé con la herramienta mkcert de Filippo Valsorda. La idea principal consiste en que este programa creará una autoridad certificadora local, la cual se añade a las entidades de confianza de nuestra máquina. Los certificados emitidos y firmados por esta nueva autoridad certificadora local, son asumidos por los navegadores como certificados válidos, mostrando el icono de confianza HTTPS en la barra de navegación, sin la necesidad de estar aceptando de forma manual dicho certificado en cada inicio de sesión.

Esta herramienta está disponible para macOS, Linux y Windows. En mi caso al ser usuario de Windows la instalé mediante el gesto de paquetes Chocolatey.

Paso 1: Instalar mkcert desde Chocolatey

choco install mkcert
Instalar mkcert con Chocolatey
mkcert -install

Una vez lanzado el proceso se nos advierte que se va a proceder a instalar un certificado desde una entidad de certificación (CA) que afirma representar  a: <nuestra máquina>. Le damos a “Sí”.

Antes que nada, es muy recomendable abrir el terminal (con permisos de Administrador) en el directorio \conf de nuestra instalación de Apache. Por ejemplo, en mi caso sería la siguiente:

C:\wamp\bin\apache\apache2.4.46\conf

De esta forma, nos será muy sencillo trabajar con las rutas de los certificados y configurar más rápidamente nuestro VirtualHost con protocolo HTTPS.

Paso 2: Generar certificados para nuestro proyecto

Para nuestro ejemplo, vamos a querer que nuestro VirtualHost proyecto.com funcione con HTTPS en localhost, por lo tanto tendremos que ejecutar el siguiente comando:

mkcert proyecto.com "*.proyecto.com"

De esta manera y gracias a mkcert tenemos la posibilidad de crear una wildcard que nos permitirá trabajar tanto con “www” como sin ellas. Sin embargo hay que señalar que sólo es posible un nivel de profundidad para subdominios. Por lo tanto, dominios como “mobile.es.proyecto.com” no son posibles.

Esto nos generará dos ficheros con extensión pem que pasaremos a renombrar de la siguiente manera. Por un lado obtendremos el fichero con extensión crt:

xcopy .\proyecto.com+1.pem .\ssl.crt\proyecto.com.crt

Y por otro lado obtendremos el fichero con extensión key:

xcopy .\proyecto.com+1-key.pem .\ssl.key\proyecto.com.key

Paso 3: Instalar certificado generado

Instalando certificado en el sistema

Una vez que hemos generado el certificado y disponible con la extensión crt, procedemos a instalarlo en el sistema. Para ello deberás ejecutar el fichero y Windows nos mostrará una ventana con el certificado en cuestión. Le damos a la opción de “Instalar certificado…”. En el siguiente paso escogemos “Equipo local” y le damos a “Siguiente”. Escogemos la opción “Seleccionar automáticamente el almacén…” y le damos a “Siguiente” y luego a “Finalizar”. De esta forma este certificado validado por nuestra propia máquina ya forma parte del sistema y será reconocido por navegadores basados en Blink (Chromium, Chrome, Opera, Brave, Vivaldi, Maxthon y Microsoft Edge 2020). Entonces ¿Qué pasa con Firefox? Firefox funciona distinto ya que no utiliza el registro de certificados del sistema, utiliza el suyo propio y por lo tanto al navegar con Firefox veremos algo así al finalizar la configuración.

Advertencia certificado no válido en Firefox

Para no tener que estar lidiando con esta advertencia en el futuro, hay que añadir de forma manual el certificado raíz de mkcert en Firefox (No el de tu sitio web, sino el de la autoridad certificadora, en este caso mkcert). Ve a opciones de “Privacidad & Seguridad” y en la sección “Seguridad” pulsa sobre ver “Ver certificados”. Pulsa sobre “Importar…”

El fichero que debemos importar es rootCA.pem que se encuentra en la ruta AppData de tu usuario:

C:\Users\<Tu usuario>\AppData\Local\mkcert

AppData es una carpeta oculta, por lo que si no has habilitado nunca “Ver archivos ocultos” es probable que no la veas. Igualmente puedes escribir manualmente la ruta añadiendo \AppData o copiando y pegando sustituyendo <Tu usuario> por el tuyo.

Marcaremos la opción “Confiar en esta CA para identificar sitios web.” y pulsamos en “Aceptar”.

Paso 3: Editar el fichero httpd.conf

Abre el fichero httpd.conf de la configuración de Apache y descomenta (quita el símbolo #) de las siguientes 3 líneas:

LoadModule ssl_module modules/mod_ssl.so
Include conf/extra/httpd-ssl.conf
LoadModule socache_shmcb_module modules/mod_socache_shmcb.so

Paso 4: Editar el fichero httpd-ssl.conf

Abre el fichero httpd-ssl.conf dentro del directorio \extra y busca la siguiente línea: <VirtualHost _default_:443>. Aquí es donde estableceremos la configuración para nuestro VirtualHost con HTTPS. Para nuestro ejemplo la configuración quedaría de la siguiente manera:

<VirtualHost *:443>
    DocumentRoot "${INSTALL_DIR}/www/proyecto.com"
    ServerName proyectom.com
    Alias proyecto.com wwww.proyecto.com
    ServerAdmin admin@example.com
    ErrorLog "${SRVROOT}/logs/error.log"
    TransferLog "${SRVROOT}/logs/access.log"
    SSLEngine on
    SSLCertificateFile "${SRVROOT}/conf/ssl.crt/proyecto.com.crt"
    SSLCertificateKeyFile "${SRVROOT}/conf/ssl.key/proyecto.com.key"
    <FilesMatch "\.(cgi|shtml|phtml|php)$">
        SSLOptions +StdEnvVars
    </FilesMatch>
    <Directory "${SRVROOT}/cgi-bin">
        SSLOptions +StdEnvVars
    </Directory>
    BrowserMatch "MSIE [2-5]" \
            nokeepalive ssl-unclean-shutdown \
            downgrade-1.0 force-response-1.0
    CustomLog "${SRVROOT}/logs/ssl_request.log" \
            "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
</VirtualHost>

No te olvides de guardar los cambios para ambos ficheros 😉

Paso 6: Reiniciar WAMPServer

Si todo ha ido bien, el icono de WAMPServer estará de nuevo en color verde, si por el contrario se quede en color naranja lo más probable es que haya un error de sintaxis. Cosas a revisar y a tener en cuenta para subsanar el problema:

  • Revisa el log de Apache (Lo puedes encontrar en el apartado Apache del menú WAMPServer).
  • WAMPServer también dispone de herramientas (Accede con el botón secundario). En ellas encontrarás “Check httpd.conf syntax” que revisa la sintaxis de los ficheros de configuración, especificando qué fichero y qué línea tiene el error. (Lo mismo que ejecutar httpd.exe -t).
  • Por último, dispones de la configuración original en la carpeta \conf\original por si deseas restaurar o comparar ficheros.

Paso 7: Editar el fichero Hosts

En este momento, nuestro VirtualHost con HTTPS estaría configurado. Podemos comprobarlo si iniciamos la navegación en https://localhost/proyecto.com pero muy acertadamente (aún teniendo un certificado) el navegador nos devuelve:

NET::ERR_CERT_COMMON_NAME_INVALID

Es decir, el nombre del dominio no corresponde con el nombre del certificado instalado. Es decir, nuestro VirtualHost está funcionando pero debemos solucionar el nombre del dominio. Aquí es donde entra nuestro queridísimo fichero Hosts. Si trabajas con varios entornos y tienes que activar y desactivar dominios de producción y desarrollo, te recomiendo que utilices la herramienta Hosts File Editor. También disponible en Chocolatey mediante el siguiente comando:

choco install hosts.editor

Añadimos una nueva entrada para nuestro proyecto HTTPS en el fichero Hosts:

127.0.0.1 proyecto.com www.proyecto.com
::1 proyecto.com www.proyecto.com

Ahora tendremos acceso a nuestro proyecto con o sin subdominio.

VirtualHost funcionando con HTTPS

Paso 8: Redireccionar HTTP a HTTPS

Aunque ya hemos visto que nuestro VirtualHost está funcionando correctamente bajo HTTPS, los navegadores trabajan por defecto con el puerto 80. Por lo tanto es muy probable que al navegar por primera vez a “www.proyecto.com” visualices el panel localhost de WAMPServer.

Para evitar esto y trabajar siempre con HTTPS hay que añadir nuevas entradas en el fichero de configuración de Apache:

# Sin wwww
<VirtualHost *:80>
  ServerName proyecto.com
  Redirect permanent / https://proyecto.com	
</VirtualHost>

# Con wwww
<VirtualHost *:80>
  ServerName www.proyecto.com
  Redirect permanent / https://www.proyecto.com	
</VirtualHost>

Normalmente se suele trabajar sin “www” por lo que yo personalmente añadiría una única entrada de la siguiente forma:

<VirtualHost *:80>
  ServerName proyecto.com
  ServerAlias *.proyecto.com
  Redirect permanent / https://proyecto.com
</VirtualHost>

 

Fuentes consultadas:

  • https://blog.filippo.io/mkcert-valid-https-certificates-for-localhost/
  • https://www.jasoft.org/Blog/post/como-generar-certificados-https-para-desarrollo-local-que-no-produzcan-errores
    https://zuziko.com/tutorials/how-to-enable-https-ssl-on-wamp-server/
  • http://forum.wampserver.com/read.php?2,141479,141484#msg-141484