Í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 AJAXComunicació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.
El paso siguiente será la compilación del módulo ssl de Apahe. Para ello ejecutaremos desde el terminal el comando:
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-default | La 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:
| ||
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 navegadoresFormatos 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:
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:
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> | |
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.