Saltar al contenido principal

Redireccións

Un dos usos máis comúns das redireccións é o de reenviar ao porto 443 o tráfico entrante a través do porto 80, é dicir, redireccionar o tráfico de HTTP a HTTPS.

Redireccións en Apache co módulo rewrite

Apache fai uso do módulo rewrite para implementar esta característica.

Debemos activar o módulo co seguinte comando:

$ sudo a2enmod rewrite

Unha vez realizado este cambio, editamos o ficheiro do servidor virtual desexado:

$ sudo nano /etc/apache2/sites-available/000-default.conf

Engadimos as seguintes liñas:

<VirtualHost *:80>      
# The ServerName directive sets the request scheme, hostname and port that
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request's Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
#ServerName www.example.com

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(.*)$ https://localhost$1 [L,R=302]
</IfModule>

ServerAdmin webmaster@localhost
DocumentRoot /var/www/html

# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn

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

# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with "a2disconf".
#Include conf-available/serve-cgi-bin.conf
</VirtualHost>

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

Como para realizar unha redirección é necesario ter activado o módulo rewrite, utilízase unha directiva <IfModule> para comprobar se está activado o módulo. Estas liñas pódense omitir, pero no caso de non utilizalas e non ter o módulo activado, produciríase un error.

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(.*)$ https://localhost$1 [L,R=302]
</IfModule>

A directiva RewriteEngine debe ter valor On para que as redireccións se produzan. No caso de omitir a liña ou non poñerlle o valor On, non se terán en conta o resto das directivas relacionadas coas redireccións.

A directiva RewriteRule contén unha regra de redirección. Neste caso redirixe a https://localhost mantendo a URL completa. Por exemplo, se a petición orixinal é http://localhost/docs/readme.html, a redirección será cara https://localhost/docs/readme.html, é dicir, mantense tamén a parte final da URL /docs/readme.html.

Se queremos unha regra de redirección que sirva para calquera dominio e non só para localhost, podemos utilizar as seguintes liñas no lugar das anteriores:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=302]
</IfModule>

Unha alternativa á configuración no ficheiro do virtual host é empregar un ficheiro de configuración distrubída .htaccess co seguinte contido:

/var/www/html/.htaccess
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=302]
</IfModule>

Neste caso, o cambio é inmediato. Non é necesario reiniciar o servidor.

Redireccións en Apache coa directiva Redirect

Outra forma moito máis sinxela, pero máis limitada, é utilizar a directiva Redirect. Coa directiva Redirect non é necesario ter o módulo rewrite activado.

Redirect / https://localhost/
Redireccións incorrectas con Redirect

Cando utilicemos a directiva Redirect, a URL á cal queremos redireccionar deberá levar sempre un / ao final.

Redirect / https://localhost      # Incorrecto
Redirect / https://localhost/ # Correcto

O feito de non poñer un / ao final producirá redireccións mal formadas cando se acceda a un recurso que non sexa a raíz.

Por exemplo, supoñemos o seguinte ficheiro de configuración de host virtual:

<VirtualHost *:80>
ServerName server.local
DocumentRoot /var/www/server/

# A URL producirá redireccións mal formadas
Redirect / https://server.local
</VirtualHost>

A raíz deste servidor sería http://server.local/ ou http://server.local. Se accedemos a unha das URL anteriores, a redirección realízase correctamente. O problema vén cando a URL non é ningunha das dúas anteriores. Por exemplo, se accedemos a http://server.local/imaxe.jpg, a redirección realizarase á URL https://server.localimaxe.jpg en lugar de https://server.local/imaxe.jpg. Para que se realice de xeito correcto, temos que engadir un / ao final da URL da directiva Redirect. O ficheiro de configuración do host virtual quedaría da seguinte maneira:

<VirtualHost *:80>
ServerName server.local
DocumentRoot /var/www/server/

# A URL producirá redireccións correctas en todos o casos
Redirect / https://server.local/
</VirtualHost>

No caso de querer realizar unha redirección permanente, debemos utilizar a opción permanent:

Redirect permanent / https://localhost/

Unha redirección permanente, unha vez que o navegador xa realizou a petición, rexístraa na caché e, en futuras peticións, xa realiza a petición directamente ao recurso final. Por exemplo, coa liña anterior, faría directamente a petición a https://localhost en lugar de https://localhost. As redireccións que non son permanentes denomínanse temporais.

Dependendo do tipo de redirección, o código de estado HTTP é diferente:

  • Redirección permanente: 301 Moved Permanently
  • Redirección temporal: 302 Found

Por último, temos que reiniciar o servidor para aplicar os cambios:

$ sudo systemctl restart apache2

Unha vez reiniciado, se accedemos a http://localhost redirixiranos automaticamente a https://localhost.

Condicións nas redireccións

Se queremos establecer condicións nas redireccións, podemos empregar a directiva <If>.

Por exemplo, se só queremos aplicar unha redirección para unha dirección IP, podemos empregar as seguintes directivas:

<If "%{REMOTE_ADDR} == '127.0.0.1'">
Redirect / http://hosting.local/
</If>

As liñas anteriores só realizan unha redirección a http://hosting.local cando a dirección IP do cliente é 127.0.0.1. As direccións IP que se indican nestas liñas son as direccións IP de quen realiza a petición, non do servidor web.

As liñas anteriores pódense poñer doutra forma máis curta:

<If "-R '127.0.0.1'">
Redirect / http://hosting.local/
</If>

Redireccións e control de acceso

Se nun ficheiro de configuración temos definidas unhas directivas de control de accceso e, ao mesmo tempo, unha directiva que define unha redirección, as directivas de control de acceso serán ignoradas.

Supoñamos o seguinte exemplo:

<VirtualHost *:80>
ServerName server.local
DocumentRoot /var/www/server/

<Directory /var/www/server/>
Require all denied # Directiva ignorada debido a Redirect
</Directory>

Redirect / https://server.local/
</VirtualHost>

Tendo en conta as directivas anteriores, cando accedemos a http://server.local, seremos redirixidos a https://server.local. En ningún momento se mostra un error que nos indique que non temos acceso a http://server.local. Isto é porque a directiva Require all denied só se ten en conta cando se accede a un ficheiro do directorio /var/www/server/. Debido á redirección, en ningún momento se chega a mostrar un ficheiro dese directorio, polo tanto, non se chega a mostrar ningún error de acceso denegado. É indiferente que poñamos a directiva Redirect antes do bloque Directory ou despois, o comportamento será idéntico.

Polo tanto, o ficheiro anterior sería equivalente a ter o seguinte:

<VirtualHost *:80>
ServerName server.local
DocumentRoot /var/www/server/

Redirect / https://server.local/
</VirtualHost>