Introducción

Buenas, en este post vamos a instalar y configurar un servidor web con Nginx siguiendo los siguientes puntos:

  • Virtual Hosting.
  • Mapeo de URL.
  • Autentificación, Autorización, y Control de Acceso.

Vamos a realizarlo en una máquina que tenemos en un cloud privado, podríamos realizarlo también en una máquina con vagrant.

Instalación

Instalamos nginx en la máquina del cloud:

apt install nginx

Modificamos algo la página que viene por defecto:

nano /var/www/html/index.nginx-debian.html

Y accedemos por el navegador no sin antes añadir una regla que abra el puerto 80 en nuestro proyecto del cloud:

1

Virtual hosting

Queremos que nuestro servidor web ofrezca dos sitios web, teniendo en cuenta lo siguiente:

  1. Cada sitio web tendrá nombres distintos.
  2. Cada sitio web compartirán la misma dirección IP y el mismo puerto (80).

Los dos sitios web tendrán las siguientes características:

  • El nombre de dominio del primero será www.iesgn.org, su directorio base será /srv/www/iesgn y contendrá una página llamada index.html, donde sólo se verá una bienvenida a la página del Instituto Gonzalo Nazareno.
  • En el segundo sitio vamos a crear una página donde se pondrán noticias por parte de los departamentos, el nombre de este sitio será departamentos.iesgn.org, y su directorio base será /srv/www/departamentos. En este sitio sólo tendremos una página inicial index.html, dando la bienvenida a la página de los departamentos del instituto.

Vamos a crear las dos carpetas que alojarán los sitios en nginx:

sudo mkdir -p /srv/www/www.iesgn.org
sudo mkdir /srv/www/departamentos.iesgn.org

Le creamos un html con algo de contenido en cada directorio:

# echo "<p>Bienvenido al instituto Gonzalo Nazareno</p" > /srv/www/www.iesgn.org/index.html

# echo "<p>Bienvenido a los DEPARTAMENTOS del IES Gonzalo Nazareno</p" > /srv/www/departamentos.iesgn.org/index.html

Borramos el sitio por defecto que trae nginx:

sudo rm /etc/nginx/sites-enabled/default

Creamos dos nuevos ficheros de configuración para cada sitio y le damos algo de contenido:

sudo nano /etc/nginx/sites-available/www.iesgn.org

server {
        listen 80;
        server_name www.iesgn.org iesgn.org;
        root /srv/www/www.iesgn.org;
        index index.html;
        location / {
                try_files $uri $uri/ =404;
        }
}
sudo nano /etc/nginx/sites-available/departamentos.iesgn.org

server {
        listen 80;
        server_name departamentos.iesgn.org iesgn.org;
        root /srv/www/departamentos.iesgn.org;
        index index.html;
        location / {
                try_files $uri $uri/ =404;
        }
}

Y creamos dos enlaces simbólicos para que estén activos:

sudo ln -s /etc/nginx/sites-available/www.iesgn.org /etc/nginx/sites-enabled/www.iesgn.org

sudo ln -s /etc/nginx/sites-available/departamentos.iesgn.org /etc/nginx/sites-enabled/departamentos.iesgn.org

Damos los permisos al usuario www-data:

sudo chown -R www-data. /srv/www/

Reiniciamos el servicio de nginx:

sudo systemctl restart nginx

Y solo nos faltaría añadir en el fichero /etc/hosts del cliente las siguientes líneas:

172.22.200.123 www.iesgn.org
172.22.200.123 departamentos.iesgn.org

Comprobamos:

12

3

Redirección

Vamos a añadirle las siguientes características a nuestro sitio:

  • Cuando se entre a la dirección www.iesgn.org se redireccionará automáticamente a www.iesgn.org/principal, donde se mostrará el mensaje de bienvenida. En el directorio principal no se permite ver la lista de los ficheros, no se permite que se siga los enlaces simbólicos y no se permite negociación de contenido.

Creamos el directorio principal y movemos el directorio de bienvenida:

sudo mkdir /srv/www/www.iesgn.org/principal
sudo mv /srv/www/www.iesgn.org/index.html /srv/www/www.iesgn.org/principal/

Damos los permisos al usuario www-data:

sudo chown -R www-data. /srv/www/

Si no tuvieramos ningún index.html en la carpeta www.iesgn.org automáticamente buscaría dentro de la carpeta principal y nos mostraría su index.html.

Y modificamos el archivo de configuración de nuestro VirtualHost añadiendole el rewrite:

server {
        listen 80;
        server_name www.iesgn.org iesgn.org;

        root /srv/www/www.iesgn.org;
        index index.html;

        rewrite ^/$ principal/ permanent;

        location / {
                try_files $uri $uri/ =404;
        }
}

Con return es complicado hacer que funcione correctamente, así que opte por rewrite.

Para que no se permita la lista de los ficheros, que se siga los enlaces simbólicos y no se permita negociación de contenido añadimos otro location:

location /principal {
          autoindex off;
          disable_symlinks on;
}

No he encontrado niguna opción que sustituya completamente a las Multiviews de Apache2, lo más parecido que hay es el try files que ya viene por defecto si le añadimos lo siguiente:

location ~ ^(/.+)/ {
    try_files $uri $1?$args $1.php?$args;
}

Alias

Si accedes a la página www.iesgn.org/principal/documentos se visualizarán los documentos que hay en /srv/doc. Por lo tanto se permitirá el listado de ficheros y el seguimiento de enlaces simbólicos siempre que sean a ficheros o directorios cuyo dueño sea el usuario.

Creamos la carpeta doc en srv:

mkdir /srv/doc

Y creamos dos ficheros de prueba:

echo "dentro de prueba1" > /srv/doc/prueba1.txt
echo "dentro de prueba2" > /srv/doc/prueba2.txt

Creamos otro location en el fichero de configuración de nuestro virtualhost:

nano /etc/nginx/sites-available/www.iesgn.org

location /principal/documentos {
                alias /srv/doc;
                autoindex on;
                disable_symlinks if_not_owner;
}

Y comprobamos que se muestran los ficheros:

4

Para comprobar que funciona el seguimiento de enlaces simbólicos si el dueño es el mismo creamos otro fichero de prueba:

echo "dentro de prueba3" > /home/debian/prueba3.txt

Y creamos el enlace simbólico a ese fichero:

ln -s /home/debian/prueba3.txt /srv/doc/prueba3.txt

Si ponemos un propietario diferente del enlace que del fichero tal que así:

chown -R www-data. /home/debian/prueba3.txt
ls -l /srv/doc/
total 8
-rw-r--r-- 1 www-data www-data 18 Nov  8 10:24 prueba1.txt
-rw-r--r-- 1 www-data www-data 18 Nov  8 10:24 prueba2.txt
lrwxrwxrwx 1 www-data www-data 24 Nov  8 11:14 prueba3.txt -> /home/debian/prueba3.txt
chown -R debian. /home/debian/prueba3.txt

ls -l /home/debian/prueba3.txt 
-rw-r--r-- 1 debian debian 18 Nov  8 11:14 /home/debian/prueba3.txt

E intentamos acceder al fichero no podremos:

5

Mensajes de error personalizados

Para poder hacer páginas de error personalizadas vamos a crear un directorio en el cuál las vamos a guardar:

sudo mkdir /srv/www/www.iesgn.org/error

Creamos las páginas personalizadas:

echo "<h1>Pagina prohibida</h1>" > /srv/www/www.iesgn.org/error/err403.html
echo "<h1>Pagina no encontrada</h1>" > /srv/www/www.iesgn.org/error/err404.html

Ahora añadiremos la ruta a seguir en el fichero de configuración:

sudo nano /etc/nginx/sites-available/www.iesgn.org

Añadimos:

error_page 403 /error/err403.html;
error_page 404 /error/err404.html;

Y si comprobamos página no encontrada:

6

Y página no permitida:

7

Control de acceso

Vamos a añadir otra máquina a nuestro escenario conectada a la red interna. A la URL departamentos.iesgn.org/intranet sólo se debe tener acceso desde el cliente de la red local, y no se pueda acceder desde la anfitriona por la red pública. A la URL departamentos.iesgn.org/internet, sin embargo, sólo se debe tener acceso desde la anfitriona por la red pública, y no desde la red local.

Partiendo del siguiente escenario en OpenStack:

8

Creamos los directorios intranet y internet:

mkdir /srv/www/departamentos.iesgn.org/intranet
mkdir /srv/www/departamentos.iesgn.org/internet

Y le ponemos un index:

echo "Esto es INTRANET" > /srv/www/departamentos.iesgn.org/intranet/index.html
echo "Esto es INTERNET" > /srv/www/departamentos.iesgn.org/internet/index.html

Ahora editamos el fichero de configuración de nuestro VirtualHost:

nano /etc/nginx/sites-available/departamentos.iesgn.org

Y añadimos lo siguiente:

location /intranet {
                allow 192.168.200.0/24;
                deny all;
}

location /internet {
                allow 172.23.0.0/16;
                deny all;
}

Hemos añadido la red que tenemos con la VPN para poder acceder.

Y comprobamos si accedemos desde la red pública a internet:

9

Desde la red pública a intranet:

10

Comprobamos desde el cliente acceder a la intranet:

lynx departamentos.iesgn.org/intranet

Y comprobamos que funciona correctamente:

11

Y comprobamos entrar en internet desde el cliente local:

lynx departamentos.iesgn.org/internet

Y observamos que no nos lo permite:

12

Autentificación básica

Vamos a limitar el acceso a la URL departamentos.iesgn.org/secreto y comprobaremos las cabeceras de los mensajes que se intercambian entre el servidor y el cliente.

Creamos el directorio secreto y le añadimos algo de contenido:

mkdir /srv/www/departamentos.iesgn.org/secreto
echo "Esto es SECRETO" > /srv/www/departamentos.iesgn.org/secreto/index.html

Instalamos las utilidades de apache para poder crear el archivo de contraseñas:

apt install apache2-utils

Creamos el archivo de contraseñas:

htpasswd -c /etc/nginx/.htpasswd ale
New password: 
Re-type new password: 
Adding password for user ale

Ahora editamos el archivo de configuración del virtualhost:

location /secreto {
                auth_basic "Secreto";
                auth_basic_user_file /etc/nginx/.htpasswd;
}

Y comprobamos que nos pide la contraseña al intentar acceder:

13

Y cuando ingresamos la contraseña nos muestra el contenido:

14

Control de acceso y autentificación combinados

El acceso a la URL departamentos.iesgn.org/secreto se hace forma directa desde la intranet, desde la red pública te pide la autentificación.

Para que desde la intranet accedamos directamente y desde el exterior nos pida autenticación, modificaremos el archivo de configuración añadiendo las siguientes lineas:

location /secreto {
  satisfy any;

  allow 192.168.200.0/24;
  deny all;

  auth_basic "Acceso exterior";
  auth_basic_user_file /etc/nginx/.htpasswd;
 }

Y reiniciamos el servicio:

sudo systemctl restart nginx