El módulo mod_rewrite da una gran flexibilidad a Apache a la hora de implementar redirecciones que modifiquen el comportamiento de nuestro servidor web: bloquear IPs, forzar tráfico HTTPS para determinados contextos, etc… Vamos a hacer un repaso de las situaciones más comunes que nos podremos encontrar como administradores de sistemas y las diversas opciones que tenemos de aplicar redirecciones para alcanzar el objetivo deseado.
Como prerrequisitos necesitaremos tener cargado y activado el módulo mod_rewrite en Apache:
LoadModule rewrite_module modules/mod_rewrite.so RewriteEngine on
También tened en cuenta que para controlar bien qué hacemos con dicho módulo necesitaremos tener claros ciertos conceptos de expresiones regulares y determinados «flags» específicos para mod_rewrite en Apache.
Se utilizarán en los ejemplos RewriteRules o Redirect cuando sea posible, teniendo en cuenta que en ocasiones es preferible aplicar un Redirect a una RewriteRule
Las reglas son aplicables a nivel de configuración global o de VirtualHost.
Redirigir de HTTP a HTTPS
Si necesitamos redirigir un determinado contexto de HTTP a HTTPS podemos hacerlo con redirect
. Esto es muy útil por ejemplo para securizar paneles de administración que siempre deben ir por HTTPS, como wp-admin
y wp-login.php
en el caso de WordPress:
Redirect permanent /wp-admin https://www.example.com/wp-admin Redirect permanent /wp-login.php https://www.example.com/wp-login.php
El redirect
también puede llevar a un subdominio si queremos:
Redirect permanent /secure https://secure.example.com/
Si quisiéramos implementarlo con RewriteRules
:
RewriteCond %{HTTPS} !=on RewriteRule ^/?(wp-admin/|wp-login\.php) https://%{HTTP_HOST}%{REQUEST_URI}%{QUERY_STRING} [R=301,QSA,L]
La condición inicial es suficientemente explicativa, aclaraciones sobre el resto:
- R=301 es el código HTTP de respuesta (movido permanentemente)
- QSA respeta cualquier string que se hubiera añadido anteriormente a la URI
- L deja de evaluar reglas posteriores
Si quisiéramos redirigir todo el tráfico de HTTP a HTTPS podemos hacerlo de la siguiente manera:
RewriteCond %{HTTPS} !on RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
O más directo con la directiva redirect
:
Redirect / https://www.example.com/
Añadir contexto de aplicación
Útil cuando tenemos un servidor de aplicaciones como backend. Imaginemos que tenemos una aplicación cuyo contexto es my-app y tenemos que añadirlo en cada petición que realice el usuario si la aplicación no expande correctamente dicho contexto. Introducimos:
ServerName example.com ... RewriteCond %{REQUEST_URI} ^/$ [NC] RewriteRule $ http://example.com/my-app [NC,R,L]
Donde NC significa No Case (no tener en cuenta mayúsculas en la petición) y R es Redirección (si no especificamos código como anteriormente con R=301, se aplica 302 por defecto)
Añadir o quitar www en nuestro nombre de dominio
Si queremos forzar que siempre se muestre www en nuestro dominio:
RewriteCond %{HTTP_HOST} !^www.example.com$ [NC] RewriteRule .? http://www.example.com%{REQUEST_URI} [R=301,L]
Más sencillo con redirect
:
Redirect permanent / http://www.example.com/
Si por el contrario queremos quitarlo:
RewriteBase / RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC] RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
También con redirect
mucho más sencillo:
Redirect permanent / http://example.com/
Redirigir un dominio a otro
Útil cuando hacemos una migración de dominio. Por ejemplo en mi caso, anteriormente tenía el dominio juliojosesanz.com que migré a elarraydejota.com
Para ello me bastó con el siguiente redirect en el VirtualHost
de juliojosesanz.com:
Redirect permanent / https://www.elarraydejota.com/
Redirigiendo de esta manera todo el tráfico a mi nuevo site.
Bloqueos
También podemos utilizar mod_rewrite para bloquear determinadas IPs:
RewriteCond %{REMOTE_ADDR} ^123\.456\.789\.1 [OR] RewriteCond %{REMOTE_ADDR} ^456\.789\.123\.2 [OR] RewriteCond %{REMOTE_ADDR} ^789\.123\.456\.3 [OR] RewriteRule ^(.*)$ - [F,L]
Donde F significa Forbidden.
Bloquear rangos de IPs:
RewriteCond %{REMOTE_ADDR} ^123\. [OR] RewriteCond %{REMOTE_ADDR} ^456\.789\. [OR] RewriteCond %{REMOTE_ADDR} ^789\.123\.456\. [OR] RewriteRule ^(.*)$ - [F,L]
Bloquear determinadas requests:
RewriteCond %{THE_REQUEST} etc/passwd [NC,OR] RewriteCond %{THE_REQUEST} cgi-bin [NC] RewriteRule .* - [F,L]
Puede que no queramos que ciertos robots indexen nuestro contenido. Esto es especialmente útil para bots que no hacen caso de las indicaciones de nuestro robots.txt:
RewriteCond %{HTTP_USER_AGENT} Foobot [NC,OR] RewriteCond %{HTTP_USER_AGENT} HTTrack [NC,OR] RewriteCond %{HTTP_USER_AGENT} WebCopier [NC,OR] RewriteCond %{HTTP_USER_AGENT} WebZIP [NC,OR] RewriteCond %{HTTP_USER_AGENT} wget [NC] RewriteRule .* - [F,L]
Para bloquear las peticiones sin User Agent especificado:
RewriteCond %{HTTP_USER_AGENT} ^-?$ RewriteRule .* - [F,L]
Redirigir a una página de mantenimiento
Si estamos realizando tareas de mantenimiento en nuestra web, podemos crear una página sencilla a la que llamaremos mantenimiento.html con el contenido que consideremos oportuno y añadir las siguientes directivas mientras dure el tiempo de mantenimiento:
RewriteCond %{DOCUMENT_ROOT}/mantenimiento.html -f RewriteCond %{REQUEST_FILENAME} !/mantenimiento.html RewriteRule ^.*$ /mantenimiento.html [L]
Donde:
- La opción -f comprueba que el fichero exista previamente
- %{REQUEST_FILENAME} !/maintenance.html comprueba que la petición sea maintenance.html
- En la
RewriteRule
tenemos ^.*$ que viene a ser lo que empiece ^ por lo que sea . una o más veces * hasta el final $ (es decir, esta expresión coincide con cualquier ocurrencia)
Conclusión
Existen por supuesto muchas otras aplicaciones de redirecciones para Apache. Las mencionadas en el artículo son de uso bastante común. La principal dificultad a la hora de construir reglas son las expresiones regulares complejas. Siempre podremos echar mano de herramientas para probarlas como Regexpal y Regexr o incluso aprender desde lo más básico si lo necesitamos.