Ver índice
 Servidor seguro en Ubuntu 

        Ocultar índice  

   Índice de contenidos
   Instalación en Windows
   Instalación en Ubuntu
   Servidores seguros
   Páginas dinámicas
   Sintaxis básica
   Operaciones
   Arrays
   Formatos de presentación
   Operadores
   Bucles
   Extraer y ord. información
   Funciones
   Ficheros externos
   Imágenes dinámicas
   Gestión de directorios
   Cookies y sesiones
   Clases y objetos
   Ficheros en formato PDF
   Bases de datos MySQL
   PHP y XML
   PDO - Bases SQLite / MySQL
   MySQL a traves de misqli
   Algo de JavaScript y AJAX


Comunicación en modo seguro

Una comunicación en modo seguro mediante el protocolo HTTPS se desencadena de la forma siguiente:

Configuración del servidor Apache en modo seguro

Area segura del servidor

Es bastante frecuente que los servidores dispongan de dos áreas. La zona no segura a la que se accede mediante el protocolo HTTP y la zona segura en la que será imprescindible utilizar el protocolo HTTPS.

Nuestro propósito es que el servidor web tenga una configuración tradicional –no segura– en la que el directorio raíz sea /var/www y establecer uno de sus subdirectorios como accesible únicamente en modo seguro.

Crearemos un nuevo subdirectorio de /var/www poniéndole como nombre zona_segura y le otorgaremos todos los permisos de lectura y escritura.


   sudo mkdir /var/www/zona_segura
   sudo chmod -R 777 /var/www/zona_segura

El paso siguiente será la compilación del módulo ssl de Apahe. Para ello ejecutaremos desde el terminal el comando:


   sudo a2enmod ssl   

Reiniciaremos el servidor y accederemos a http://localhost/info.php para comprobar que tenemos activo el módulo SSL. Deberemos ver que OpenSSL support aparece en modo enabled.

Certificados de servidor

El primer paso mantener una comunicación segura es tener la certeza de que realmente estamos en comunicación con quien pensamos que lo estamos haciendo. Como hemos descrito más arriba, el protocolo HTTPS requiere con carácter ineludible que el servidor disponga de un certificado digital. Estos certificados puedes extraerlos del fichero certificados.zip o crearlos siguiendo el proceso descrito en esta página

Una vez dispongamos de los certificados digitales hemos de colocarlos en algún lugar del equipo que alberga el servidor Apache sin que sea en ningún caso necesario ubicarlos dentro del root de servidor. Crearemos un subdirectorio con nombre ssl en /etc/apache2/ siendo, por tanto, su ruta absoluta /etc/apache2/ssl/. Copiaremos en él los archivos que contienen los certificados del servidor que son: servidor_certificado.crt (certificado digital del servidor) y Servidor_privada.key que (clave privada).

Modificaciones en el fichero de configuración de Apache

Una vez hayamos creado los directorios zona_segura y certificados e incluido en este el certificado y la clave privada del servidor ya estaremos en disposición de poder modificar la configuración del servidor Apache para su uso en modo seguro. Las modificaciones requeridas son las siguientes:

Fichero inicial    /etc/apache2/sites-enabled/000-defaultLa copia de seguridad nos permitirá recuperar la configuración actual si es necesario.
Guardar como    /etc/apache2/sites-enabled/000-noseguro
Abrir    sudo gedit /etc/apache2/sites-enabled/000-default
Modificaciones en el fichero inicial
Final del documento Agregar:
<Directory "/var/www/zona_segura">
       SSLRequireSSL
</Directory>
SSLRequireSSL establece el modo seguro como único modo de acceso al directorio zona_segura. Cualquier petición no realizada mediante el protocolo https será rechazada.
NameVirtualHost *:443

NameVirtualHost es una directiva de Apache que permite especificar la IP a través de la que un host virtual puede recibir las peticiones.
Al indicar *:443 estamos señalando como válida cualquier IP siempre que utilice el puerto 443 que es el reservado para conexiones seguras.
<VirtualHost *:443>

     SSLEngine On
     SSLOptions +StdEnvVars +ExportCertData
     SSLCertificateFile /etc/apache2/ssl/Servidor_certificado.crt
      SSLCertificateKeyFile /etc/apache2/ssl/Servidor_privada.key
     DocumentRoot /var/www/zona_segura
     ErrorLog /var/log/apache2/error.log
     LogLevel warn

</VirtualHost>
Los comentarios relativos a estas inclusiones están en la parte inferior de la tabla
Lo contenido entre <VirtualHost> y </VirtualHost> son las directivas que se aplicarán solo al host virtual al que acabamos de aludir. Hemos incluido las siguientes:
  • SSLEngine On que es la directiva que habilita el uso del motor SSL del servidor.
  • SSLOptions es una directiva a través de la que pueden establcerse condiciones específicas en los directorios a los que precede. Esas condiciones pueden ir precedidas de un signo + o de un signo -. En el primer caso se entiende que la nueva condición se agrega a las preexistentes. En el segundo caso, signo menos-, estaríamos indicando que se desactive esa condición manteniendo activas las demás.
    Activaremos dos de ellas: +StdEnvVars y +ExportCertData. De esta forma podremos leer y utilizar desde PHP la información contenida en las variables de entorno del servidor y en los certificados del cliente y del servidor.
  • SSLCertificateFile es una directiva imprescindible para poder indicar la ruta absoluta hasta el certificado del servidor.
  • SSLCertificateKeyFile igual que el anterior, indicando esta la ruta absoluta hasta la clave privada de cifrado del servidor.
  • DocumentRoot especifica la ruta absoluta hasta el directorio que será considerado como DocumenRoot de este servidor virtual que trabajará en modo seguro.
  • ErrLog especifica la ruta absoluta hasta el fichero que ha de recoger el informes sobre errores producidos durante el funcionamiento del servidor.
  • LogLevel establece los tipos de eventos que van a registrarse como errores. En este caso se registrarán desde advertencias (warn) y/o los errores de mayor gravedad que estas

Una página de prueba

Antes de reiniciar el servidor con la nueva configuración crearemos una página de prueba que puede tener unas características similares a esta.

 <?php print "Estás en la zona segura del servidor"; ?>

La guardaremos con nombre index.php en el directorio zona_segura del servidor Apache.

Comprobaremos los resultados de intentar acceder a estas direcciones: https://localhost, http://localhost y http://localhost/zona_segura/

En le primer caso (https) estaremos accediendo en modo seguro y por lo tanto seremos dirigidos a la página index.php que hemos incluido en el directorio zona_segura que es el DocumentRoot del servidor cuando trabaja en ese modo.

En el segundo caso (http) estaremos accediendo en modo no seguro y visualizaremos la página index alojada en htdocs (directorio raíz del servidor).

El tercer supuesto, intento de acceder en modo no seguro (http) a un directorio seguro (zona_segura) nos dará un mensaje de error y nos será impedido el acceso.

Mensajes de advertencia en los navegadores

    Hechas las modificaciones en la configuración y reiniciado el servidor cuando intentamos acceder a él en modo seguro (requiere siempre que escribamos https:// en vez del clásico http:// que los navegadores añaden por defecto) van a aparecernos algunos mensajes de advertencia tales como los que puedes ver en los diferentes apartados de este gráfico.

Pulsando sobre la flechas de la imagen podrás visualizar los diferentes pasos del proceso


Formatos de los certificados

Los certificados digitales pueden tener diferentes formatos. Los más comunes son el formato DER (un formato binario utilizado básicamente por Java y por Macintosh) y el formato PEM (una representación de los certificados DER en base64, con marcas de inicio y final). El primero es el formato en el que el Cuerpo Nacional de Policía nos facilita los certificados raíz del DNIe cuyos ficheros disponibles puedes ver en este enlace de dónde podremos descargar el fichero ACRAIZ-SHA1.zip que vamos a utilizar para la configuración de nuestro servidor.

La FNMT nos permite descargar su certificado raíz FNMTClase2CA.cer en ese mismo formato DER.

El servidor Apache requiere que los certificados tengan formato PEM (que coincide coun el certificados autofirmados que hemos creado en páginas anteriores. Por tanto nuestros certificados van a poder ser utilizados sin ninguna modificación por el servidor Apache.

Los certificados emitidos por la Dirección General de la Policía y por la FNMT tienen formato DER y por tanto es preciso hacer un cambio de formato (de DER a PEM) para poder utilizarlos en Apache. La transformación puede hacerse mediante OpenSSL ejecutando el siguiente comando:

sudo openssl x509 -in nombre_del fichero_der -inform DER -out nombre_del_fichero_pem -outform PEM

Para facilitarte la tarea hemos incluido en el fichero certificados.zip los certificados raíz del DNIe y de la FNMT transformados a formato PEM por medio de los siguientes comandos:

sudo openssl x509 -in ACRAIZ-SHA1.crt -inform DER -out RaizDNIe.crt -outform PEM

sudo openssl x509 -in FNMTClase2CA.cer -inform DER -out RaizFNMT.crt -outform PEM

Tenemos por tanto los certificados raíz de tres entidades certificadoras: nuestra propia CA (CA_certificado.crt, en formato PEM), el DNIe (ACRAIZ-SHA1.crt, en formato DER, y su equivalente en formato PEM, RaizDNIe.crt) y la FNMT (FNMTClase2CA.cer en formato DER y su equivalente en formato PEM, RaizFNMT.crt).

Accesos restringidos

Podemos establecer conexiones en modo seguro con un servidor si que se nos exija cumplir ningún requisito. El concepto seguro significaría que el servidor posee un certificado digital y que la información circula encriptada mediante una clave simétrica pero desconociendo la identidad del cliente.

Son habituales las webs que requieren un registro previo del usuario en el que se le facilita un nombre de usuario y contraseña que le serán requeridas siempre que intente acceder a un área restringida del servidor. Disponiendo de un servidor seguro es posible exigir al cliente disponga de un certificado digital (certificado de cliente) para acceder al área segura del servidor o algunos de sus directorios. Veamos como hacerlo.

Empezaremos creando un subdirectorio de zona_segura al que pondremos el nombre de restringido e incluiremos en él una página, a la que llamaremos index.php, que nos permita hacer la comprobación de funcionamiento y que puede contener algo como esto:

<?php print "Aquí solo acceden los usuarios autorizados"; ?>

Nuestro propósito es que sólo puedan acceder acceder al directorio restringido los cliente que dispongan de: nuestro certificado autofirmado de pruebas, de un DNIe o de un certificado de la FNMT.

Establecer esa exigencia nos obliga a configurar Apache de forma que sepa qué ha de requerir un certificado de cliente y, además, qué tipo o tipos de certificados debe considerar válidos. Esto se logra a través de la directiva SSLCACertificateFile que debe ir seguida de la ruta absoluta hasta un único fichero que ha de contener el certificado o certificados raíz de las entidades certificadoras a cuyos usuarios se va a permitir el acceso.

En el epígrafe anterior hemos visto como obtener, en formato PEM, los tres certificados (CA_certificado.crt, RaizDNIe.crt y RaizFNMT.crt). Hemos de juntarlos en un único fichero. Podemos copiar al Escritorio los tres certificados en formato PEM y ejecutar desde la consola el siguiente comando:

cd Escritorio

sudo CA_certificado.crt cat RaizFNMT.crt RaizDNIe.crt > todos.crt


Guardaremos el fichero resultante –al que hemos puesto como nombre todos.crt– en el almacén de certificados del servidor ( /etc/apache2/ssl/) ya solo nos faltaría modificar el fichero de configuración de Apache para que contemple la nueva situación. La modificaciones a realizar son las que puedes ver en esta tabla

Fichero inicial     /etc/apache2/sites-enabled/000-default
Guardar como     /etc/apache2/sites-enabled/000-seguro_parcial
Nos permitirá recuperar la configuración actual si es necesario
Abrir     sudo gedit /etc/apache2/sites-enabled/000-default
Trabajaremos sobre la configuración previa una vez asegurada una copia de ella
Modificaciones en el fichero inicial
  Donde dice:
SSLCertificateKeyFile /etc/apache2/ssl/Servidor_privada.key
insertar inmediatamente después
SSLCACertificateFile "/etc/apache2/ssl/todos.crt"
Final del documento Agregar inmediatamente antes de la etiqueta de cierre </VirtualHost> que hay al final del fichero :
   <Directory "/var/www/zona_segura/restringido">
      SSLVerifyClient require
      SSLVerifyDepth 2
      SSLRequire (%{SSL_CLIENT_V_REMAIN} >= "0")
   </Directory>

Se trata de señalar la existencia un fichero con los certificados raíz de las entidades certificadoras autorizadas mediante la directiva SSLCACertificateFile seguida de la ruta absoluta hasta el fichero que contiene tales certificados y de indicar qué directorio debe restringirse y cuales son las condiciones de acceso. Esto se indica en el contexto de las etiquetas <Directory > y </Directory >. Dentro de la etiqueta de apertura indicamos la ruta absoluta del directorio objeto de la restricción (en este caso será restringido) y entre la etiqueta de apertura y cierre incluimos las restantes directivas.

Mediante el valor require de la directiva SSLVerifyClient Apache interpretará que debe exigir uno de los certificados de usuario permitidos para acceder al directorio en el que se incluye tal directiva. Si esta directiva no se incluyera entre las etiquetas <Directory></Directory> se entendería que la directiva habría de afectar a todo el espacio del servidor seguro.

Con las modificaciones anteriores el servidor ya debería funcionar de acuerdo con nuestros propósitos. Sin embargo, si observas con detenimiento las propuestas de modificaciones, verás que hemos incluido la directiva SSLVerifyDepth 2.

Esto es consecuencia de la inclusión de la opción DNIe. La Autoridad de Certificación de Primer Nivel de la Dirección General de la Policía sólo emite certificados para sí misma y para sus tres autoridades certificadoras subordinadas. Por tanto, ninguno de los certificados incluidos en los DNie es emitido por la Autoridad Certificadora de primer nivel. Quien certifica nuestro DNIe es una de las tres entidades subordinadas (segundo nivel) que dependen de aquella. Por medio de la directiva SSLVerifyDepth 2 lo que hacemos es indicarle a Apache que, si es necesario, profundice hasta ese segundo nivel para comprobar la validez del certificado del cliente.

Aunque es un aspecto que será comentado con un poco más de profundidad en párrafos suguientes, la línea dónde dice SSLRequire (%{SSL_CLIENT_V_REMAIN} >= "0") tiene como finalidad que Apache impida el acceso a usuarios cuyos certificados del cliente han superado su período de validez (qué «han caducado»).

Hechas estas modificaciones y reiniciado Apache podremos comprobar que para acceder a la dirección https://localhost" no es preciso disponer de ningún certificado. Por el contrario, si pretendemos acceder a https://localhost/restringido/ nos será requerido uno cualquiera de estos tres certificados: nuestro certificado autofirmado, un certificado de la FNMT ó el DNIe.

Condicionando las restricciones

En la configuración anterior establecimos como única condición para el acceso al directorio restringido disponer de uno de los certificados permitidos y que este no hubiera expirado (un poco más abajo comentamos la directiva SSLRequire que es la que hace esta comprobación).

Vamos a crear ahora dos nuevos subdirectorios en la zona_segura. A uno le llamaremos dnie y al otro certificado. Incluiremos en cada uno de ellos, una página con nombre index.php para hacer las pruebas de funcionamiento. El acceso al primero –dnie– lo limitaremos a los usuarios que dispongan de un DNIe o un certificado de la FNMT e impediremos que pueda hacerlo quien sólo disponga del certificado autofirmado creado para nuestros ejemplos.

Para el acceso al directorio certificado invertiremos las condiciones. Sólo estará permitido el acceso autentificándose mediante el certificado autofirmado. Dado que en el fichero todos.crt están incluidos los certificados raíz de las tres entidades certificadoras permitidas, las nuevas limitaciones requieren hacer uso de la directiva SSLRequire. Veamos que ocurre con ella.

Cuando hacemos una petición en modo seguro y la directiva SSLOptions está configurada +StdEnvVars se transfieren al servidor una serie de variables de entorno cuyos nombres y valores para cada uno de los tres tipos de certificado (lógicamente con datos ficticios) puedes ver en este enlace:

Variables de entorno

Los valores que se visualizan en este ejemplo son el resumen de la comprobación de los tres tipos de certificados digitales y han sido obtenidos desde PHP mediante funciones similares a esta: <?php print getenv('SSL_CLIENT_S_DN');?> dónde a la función getenv se el incluye como parámetro el nombre de una variable de entorno. Aquí tienes el código fuente del script que hemos utilizado para leer todas esas variables (https) y la lista de sus nombres.

Si observamos con un poco de detenimiento la tabla del enlace anterior podremos ver que hay una variable de entorno llamada SSL_CLIENT_V_REMAIN que recoge los días que faltan hasta la fecha de caducidad de cada uno de los certificados.

También podemos ver como SSL_CLIENT_I_DN_OU recoge los valores: certNORA, FNMT Clase 2 CA y DNIE y que en SSL_CLIENT_I_DN_O se incluyen: ACREDITACIONES DEL NORA, S.L.U., FNMT y DIRECCION GENERAL DE LA POLICIA.

Mediante la directiva SSLRequire y manejando esas variables, a las que se alude mediante la sintaxis %{nombre de la variable} , los operadores lógicos and y/o or (en minúsculas porque SSLRequire es sensible a mayúsculas/minúsculas) y los operadores de comparación == (o su equivalente eq), <, > podemos establecer las condiciones requeridas para el acceso a un directorio determinado. Analicemos este ejemplo.

SSLRequire (%{SSL_CLIENT_V_REMAIN} >= "0" \

and (%{SSL_CLIENT_I_DN_O} eq "FNMT" or %{SSL_CLIENT_I_DN_OU} == "DNIE"))

SSLRequire() incluye, dentro del paréntesis, las condiciones restriccitivas que son las siguientes: %{SSL_CLIENT_V_REMAIN} >= "0" que exige que el certificado no haya expirado con anterioridad a la fecha (le quede un número de días de vigencia mayor o igual que cero). Aunque se trate de un valor númerico el cero lo pondremos entre comillas.

La barra invertida (\) es un carácter imprescindible para indicar que el condicionado continúa en la línea siguiente y el operador and agrega como nueva condición que %{SSL_CLIENT_I_DN_O} eq "FNMT" or %{SSL_CLIENT_I_DN_OU}=="DNIE" lo cual significa la exigencia de que solo serán admisibles certificados en los que SSL_CLIENT_I_DN_O="FNMT" o aquellos en los que SSL_CLIENT_I_DN_OU="DNIE".

De esta forma, las últimas modificaciones de la configuración de Apache, serían las siguientes:

Fichero inicial     /etc/apache2/sites-enabled/000-default
Guardar como    /etc/apache2/sites-enabled/000-seguro_parcial_1
Nos permitirá recuperar la configuración actual si es necesario
Abrir     sudo gedit /etc/apache2/sites-enabled/000-default
Trabajaremos sobre la configuración previa una vez asegurada una copia de ella
Modificaciones en el fichero inicial
Final del documento Agregar inmediatamente antes de la etiqueta de cierre </VirtualHost> que hay al final del fichero :
   <Directory "/var/www/zona_segura/dnie">
      SSLVerifyClient require
      SSLVerifyDepth 2
      SSLRequire (%{SSL_CLIENT_V_REMAIN} >= "0" \
         and (%{SSL_CLIENT_I_DN_O} eq "FNMT" \
         or %{SSL_CLIENT_I_DN_OU} == "DNIE"))
      ErrorDocument 403 https://localhost/error_dnie.html
   </Directory>

   <Directory "/var/www/zona_segura/certificado">
      SSLVerifyClient require
      SSLVerifyDepth 2
      SSLRequire (%{SSL_CLIENT_V_REMAIN} >= "0" \
         and %{SSL_CLIENT_I_DN_OU} =="certNORA")
      ErrorDocument 403 https://localhost/error_certificado.html
   </Directory>

    Las líneas ErrorDocument tienen por finalidad redirigir el navegador hacia una página de error cuando intentemos acceder a un directorio restringido sin cumplir los requisitos exigidos para ello.

Una vez hayas reiniciado el servidor después de finalizar la configuración podrás comprobar el funcionamiento accediendo a las direcciones: https://localhost, http://localhost y http://localhost/zona_segura/

Para acceder la primera de ellas necesitarás uno de los tres certificados. El segundo requiere disponer de DNIe o un certificado de la FNMT y al tercero podrás acceder si tienes instalado en tu navegador el certificado auto firmado de cliente.