Publi

Entorno de pruebas para nuestra web en función de una cookie

¿Qué es una cookie?

Hace unas semanas hablábamos de cómo hacer una redirección transparente en Apache en función de una cookie. Uno de los ejemplos que puse es el acceso a un entorno de test de nuestra aplicación. Un entorno de test al que podamos acceder nosotros como desarrolladores o incluso se lo podamos enseñar a un cliente final sin afectar al funcionamiento normal de la web (que por otro lado está funcionando).
A veces, podemos crear una dirección paralela tipo test.miweb.com, pero otras veces no es posible. Y decirle a todo el mundo que añada una dirección IP a su archivo hosts, y que nos haga caso, es complicado. Pensemos en aplicaciones que tienen una fuerte dependencia del host al que están vinculada. Un ejemplo sencillo es WordPress, muchas veces nos encontramos con plugins o temas que, tanto en su configuración como en otras tablas almacenan el host y se complicado estar todo el rato haciendo cambios en la base de datos. Pero no solo WordPress, esta necesidad nos puede surgir con multitud de aplicaciones.

Un poco de historia (personal)

Todo empezó buscando una manera de cambiar el DocumentRoot de un VirtualHost en función de una cookie. Aunque la propiedad DocumentRoot no soporta condiciones ni se puede cambiar tan fácilmente. Lo que debemos hacer es una redirección con proxy en función de una condición. Esta redirección puede ser a la misma máquina, o a otra diferente, incluso máquinas virtuales o contenedores docker, siempre que tengamos acceso por red. Estas máquinas también pueden ser privadas. Por lo que nuestro servidor principal puede tener un segundo interfaz de red que esté conectado a otro servidor y hacer el proxy hacia ese segundo servidor.

Así que, si en este momento tenemos suficiente con la máquina donde tenemos el servidor web principal podemos utilizar otro puerto en el que también levantaremos el servidor web. A mí me gusta el 180, por poner un puerto. Ese puerto debemos mantenerlo privado, para que el acceso sea solo dentro del host local y no esté expuesto a Internet (cosa que no queremos). Podemos elegir, si la página de pruebas está en otro host, perfecto. Si queremos que dicha web de pruebas esté en el mismo host, seguid leyendo.

Escuchando por el puerto 180

Lo primero es que Apache escuche en el puerto 180, aunque podríamos utilizar otro servidor web como Nginx, lighthttpd, etc. Aunque si lo que queremos es utilizarlo como entorno de test, es conveniente que utilicemos siempre el mismo servidor web (por lo que pueda pasar).

Aunque nuestra web la sirvamos por HTTPs. La redirección no hace falta hacerla también por HTTPs. Ya que la conexión segura se seguirá haciendo entre Apache y el usuario final que pide la web, y luego Apache hará una conexión no segura con él mismo para acceder a la web de pruebas. Puede que, según nuestros contratos con el cliente, o según lo paranoicos que seamos con la seguridad, nos interese también cifrar esta comunicación interna, pero eso ya es cuestión de gustos.

En Apache, la configuración puertos suele estar en /etc/apache2/httpd.conf, /etc/apache2/apache2.conf, /etc/apache2/ports.conf o incluso los archivos pueden estar situados en /etc/httpd/ . En mi caso, en la instalación en Ubuntu, suele estar en /etc/apache2/ports.conf, y finalmente lo podemos dejar así:

1
2
3
4
5
6
7
8
9
Listen 80
Listen 180
<IfModule ssl_module>
        Listen 443
</IfModule>

<IfModule mod_gnutls.c>
        Listen 443
</IfModule>

O incluso podríamos cercar más el acceso así, haciendo que solo escuchemos en el host local:

1
Listen 127.0.0.1:180

Ahora, nuestro Virtualhost de la web quedaría así (lo pongo completo, con SSL y todo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<VirtualHost *:80>
     ServerName www.miweb.com
     ServerAlias miweb.com

     ServerAdmin administrador@miweb.com
     DocumentRoot /var/www/miweb.com/www

     RewriteEngine On
     RewriteCond %{HTTPS} off
     RewriteCond %{REQUEST_URI} "!/.well-known/acme-challenge/"
     RewriteRule (.*) https://www.%{HTTP_HOST}%{REQUEST_URI} [NE,L,R=301]

     ErrorLog ${APACHE_LOG_DIR}/error.log
     CustomLog ${APACHE_LOG_DIR}/access.log ombined

# Include conf-available/php7.0-fpm.conf

</VirtualHost>

<VirtualHost *:180>
     ServerName www.miweb.com

     ServerAlias miweb.com

     DocumentRoot /var/www/miweb.com_testing/www

     ErrorLog ${APACHE_LOG_DIR}/error.log
     CustomLog ${APACHE_LOG_DIR}/access.log combined
     Include conf-available/php7.0-fpm.conf
</VirtualHost>

<IfModule mod_ssl.c>
     <VirtualHost _default_:443>

          ServerName www.miweb.com
          ServerAlias miweb.com

          ServerAdmin administrador@miweb.com
          DocumentRoot /var/www/miweb.com/www

          ProxyPreserveHost On
          RewriteEngine On

          RewriteCond %{HTTP_COOKIE} cookie=([^;]+)
          RewriteCond %1 ^pruebas$
          RewriteRule ^/(.*) http://127.0.0.1:180/$1 [P,L]

          ErrorLog ${APACHE_LOG_DIR}/error.log
          CustomLog ${APACHE_LOG_DIR}/access.log combined

          Include conf-available/php7.0-fpm.conf

          SSLEngine on

          SSLCertificateFile /etc/letsencrypt/live/miweb.com/cert.pem
          SSLCertificateKeyFile /etc/letsencrypt/live/miweb.com/privkey.pem

          SSLCertificateChainFile /etc/letsencrypt/live/miweb.com/fullchain.pem

          <FilesMatch "\.(cgi|shtml|phtml|php)$">
               SSLOptions +StdEnvVars
          </FilesMatch>
          <Directory /usr/lib/cgi-bin>
               SSLOptions +StdEnvVars
          </Directory>
     </VirtualHost>
</IfModule>

Posibles cambios

Al estar utilizando otro VirtualHost, en este caso, el del puerto 180, podemos utilizar otra versión de PHP (En este caso, la web usa PHP), por supuesto otro DocumentRoot diferente, por lo que podríamos tener otra rama del repositorio de nuestra aplicación y la ésta podrá tener configuración de caché/logs/base de datos diferente a la aplicación principal.

Este sistema nos podría ayudar mucho a la hora de probar nuestra aplicación web en un entorno real o incluso con datos reales (si es posible), justo antes de desplegarla definitivamente.

Seguridad

Como dije antes, el puerto 180 no debe estar expuesto al exterior. No nos interesa que personas no autorizadas entren a nuestro sistema de pruebas. Podríamos tener contraseñas débiles, datos no reales o información de depuración activada que pueda dar pistas para atacar nuestra aplicación. Este puerto lo podemos bloquear desde nuestro proveedor de servicio, o desde la misma máquina, aplicando una restricción con UFW o desde iptables, así:

iptables -A INPUT -i eth0 -p tcp --dport 180 -j DROP

Ahora, debemos ser cuidadosos con las personas a las que les establecemos los valores de la cookie, porque podrán entrar a una zona privada de nuestro sistema. Sería conveniente no tener el acceso activado constantemente, sino activarlo solo cuando sea necesario, o poner también reglas por IP. Yo también, en los servicios donde utilizo esta técnica utilizo cookies como:
accesodepruebas=hn8JV9V1IfJylvQCmo+VUJb8ENgEIs/cbA8pWa7j1mE

La cadena aleatoria la podemos obtener así:

openssl rand -base64 32

De manera que sea muy muy difícil para alguien hallar el valor adecuado de la cookie.

Foto principal: unsplash-logoPietro De Grandi

También podría interesarte....

Leave a Reply