htaccess para WordPress – Tips y trucos

El .htaccess es uno de los archivos protagonistas en entornos web, un archivo original de Apache que también entienden otros servidores web como LiteSpeed (el que usamos en Raiola Networks).
A través del archivo .htaccess le damos “instrucciones” al servidor web sobre cómo tiene que comportarse, sin necesidad de realizar parametrizaciones sobre los archivos de configuración del propio servicio.
En resumen, la posibilidad que nos ofrece el archivo .htaccess es la de que cualquier usuario pueda configurar algunas cosas básicas en el servidor directamente desde su cuenta de hosting y para su cuenta de hosting.
En este post vamos a hablar de algunas cosas que podemos configurar en el .htaccess de nuestro hosting y que van a influir en la forma de funcionar de nuestro WordPress.
Algunos tweaks que voy a comentar aquí son recomendables solo para algunas situaciones. Quiero dejar claro que no debes aplicarlos todos sin control y sin estar seguro de que los necesitas y de que no van a causar conflictos entre ellos.
Empecemos por el principio. Este es el .htaccess predeterminado de un WordPress recién instalado con los enlaces permanentes o URL amigables activos:
RewriteEngine On RewriteBase / RewriteRule ^index.php$ – [L] # add a trailing slash to /wp-admin RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L] RewriteCond %{REQUEST_FILENAME} -f [OR] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^ – [L] RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L] RewriteRule ^([_0-9a-zA-Z-]+/)?(.*.php)$ $2 [L] RewriteRule . index.php [L]
1
2
3
4
5
6
7
8
9
10
11
12
13 
RewriteEngine On
RewriteBase /
RewriteRule ^index.php$ – [L]
# add a trailing slash to /wp-admin
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ – [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*.php)$ $2 [L]
RewriteRule . index.php [L]
Hago especial hincapié en “.htaccess predeterminado”, ya que los plugins que vamos instalando en nuestro WordPress van añadiendo cosas al .htaccess y parametrizando el funcionamiento del servidor web.
A continuación, listaré todos los “tweaks” que podemos usar en el .htaccess y una explicación de para qué se utilizan.
Activar la compresión GZIP / DEFLATE
Si el servidor Apache tiene mod_deflate activado y listo para usarse, podemos activar la compresión GZIP o Deflate simplemente utilizando el siguiente código en el .htaccess.
<IfModule mod_deflate.c> # Compress HTML, CSS, JavaScript, Text, XML and fonts AddOutputFilterByType DEFLATE application/javascript AddOutputFilterByType DEFLATE application/rss+xml AddOutputFilterByType DEFLATE application/vnd.ms-fontobject AddOutputFilterByType DEFLATE application/x-font AddOutputFilterByType DEFLATE application/x-font-opentype AddOutputFilterByType DEFLATE application/x-font-otf AddOutputFilterByType DEFLATE application/x-font-truetype AddOutputFilterByType DEFLATE application/x-font-ttf AddOutputFilterByType DEFLATE application/x-javascript AddOutputFilterByType DEFLATE application/xhtml+xml AddOutputFilterByType DEFLATE application/xml AddOutputFilterByType DEFLATE font/opentype AddOutputFilterByType DEFLATE font/otf AddOutputFilterByType DEFLATE font/ttf AddOutputFilterByType DEFLATE image/svg+xml AddOutputFilterByType DEFLATE image/x-icon AddOutputFilterByType DEFLATE text/css AddOutputFilterByType DEFLATE text/html AddOutputFilterByType DEFLATE text/javascript AddOutputFilterByType DEFLATE text/plain AddOutputFilterByType DEFLATE text/xml </IfModule>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 
<IfModule mod_deflate.c>
# Compress HTML, CSS, JavaScript, Text, XML and fonts
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
AddOutputFilterByType DEFLATE application/x-font
AddOutputFilterByType DEFLATE application/x-font-opentype
AddOutputFilterByType DEFLATE application/x-font-otf
AddOutputFilterByType DEFLATE application/x-font-truetype
AddOutputFilterByType DEFLATE application/x-font-ttf
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE font/opentype
AddOutputFilterByType DEFLATE font/otf
AddOutputFilterByType DEFLATE font/ttf
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE image/x-icon
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/xml
</IfModule>
Aunque ahora mismo el formato Brotli impulsado por Google es la “novedad”, la base de compresión sigue siendo o GZIP o Deflate. Muchos plugins de cache o WPO para WordPress realizan directamente las modificaciones en el .htaccess. En caso contrario, debemos hacerlo nosotros con el código anterior.
Para que te hagas una idea de lo útil que es la compresión, existe un caso de éxito de Netflix relacionado con la compresión GZIP. Puedes verlo aquí: https://alvarofontela.com/casos-reales-wpo-velocidad-carga/
Activar Keep Alive en Apache
El parámetro Keep Alive permite que la conexión entre el servidor y el navegador del visitante no se cierre. Como resultado, si hay que realizar varias peticiones consecutivas, al mantener la conexión abierta se realizarán mucho más rápidamente. Es lo que comúnmente se llama “conexión persistente”.
Podemos activar Keep Alive siempre y cuando el servidor web lo tenga activo y utilizando este código:
# Activar Keep Alive KeepAlive On # Conexiones maximas persistentes por Keep Alive MaxKeepAliveRequests 100 # Keep Alive Timeout de cada conexion KeepAliveTimeout 100
1
2
3
4
5
6
7
# Activar Keep Alive
KeepAlive On
# Conexiones maximas persistentes por Keep Alive
MaxKeepAliveRequests 100
# Keep Alive Timeout de cada conexion
KeepAliveTimeout 100
¿Qué razones existen para tener Keep Alive desactivado? Pues el consumo de recursos en el servidor, ya que un servidor con Keep Alive consume bastantes más recursos que uno con la misma opción desactivada debido a la gran cantidad de peticiones que hay que mantener abiertas.
Solucionar “Specy a Vary: Accept-Encoding Header”
Este error suele aparecer en Pingdom Tools y en GTMetrix. Antes también aparecía en Google PageSpeed Insights, pero desde hace algún tiempo lo he dejado de ver.
Se trata de una cabecera que se envía desde el servidor al visitante. Se utiliza para que el servidor y el navegador del visitante se entiendan en cuanto a la codificación del contenido y la compresión.
En Apache puedes especificar esto en el .htaccess con el siguiente código:
<IfModule mod_headers.c> <FilesMatch «.(js|css|xml|gz|html)$»> Header append Vary: Accept-Encoding </FilesMatch> </IfModule>
1
2
3
4
<IfModule mod_headers.c>
<FilesMatch «.(js|css|xml|gz|html)$»>
Header append Vary: Accept-Encoding
</FilesMatch>
</IfModule>
Aunque las herramientas de WPO marcan esto como un fallo relacionado con la velocidad de carga, puede causar más un problema de funcionalidad que de rendimiento.
Activar cache de navegador o browser cache
La cache de navegador es una de las cosas más útiles que me he encontrado en los 10 años que llevo metido en esto del WPO. Y eso que al principio la infravaloraba.
El browser cache nos permite ahorrar recursos en el servidor web y también ancho de banda en el hosting o servidor.
Puedes activar la cache de navegador para los tipos de archivos más comunes con este código en el .htaccess:
<IfModule mod_expires.c> ExpiresActive On ExpiresByType image/jpeg «access plus 1 year» ExpiresByType image/gif «access plus 1 year» ExpiresByType image/png «access plus 1 year» ExpiresByType image/webp «access plus 1 year» ExpiresByType image/svg+xml «access plus 1 year» ExpiresByType image/x-icon «access plus 1 year» ExpiresByType video/mp4 «access plus 1 year» ExpiresByType video/mpeg «access plus 1 year» ExpiresByType text/css «access plus 1 month» ExpiresByType text/javascript «access plus 1 month» ExpiresByType application/javascript «access plus 1 month» ExpiresByType application/pdf «access plus 1 month» ExpiresByType application/x-shockwave-flash «access plus 1 month» </IfModule>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpeg «access plus 1 year»
ExpiresByType image/gif «access plus 1 year»
ExpiresByType image/png «access plus 1 year»
ExpiresByType image/webp «access plus 1 year»
ExpiresByType image/svg+xml «access plus 1 year»
ExpiresByType image/x-icon «access plus 1 year»
ExpiresByType video/mp4 «access plus 1 year»
ExpiresByType video/mpeg «access plus 1 year»
ExpiresByType text/css «access plus 1 month»
ExpiresByType text/javascript «access plus 1 month»
ExpiresByType application/javascript «access plus 1 month»
ExpiresByType application/pdf «access plus 1 month»
ExpiresByType application/x-shockwave-flash «access plus 1 month»
</IfModule>
Esto sí que está directamente relacionado con el WPO y con el rendimiento web.
Como en el caso de la compresión GZIP / Deflate, la mayoría de plugins de cache ya se encargan de configurar la cache de navegador, aunque si queremos hacerlo de forma más “configurable” tenemos disponible este código.
Desactivar la etiqueta Etag
Las etiquetas ETag son identificadores únicos que se marcan en cada archivo enviado del servidor al navegador web. La utilidad del ETag es marcar esos archivos para se distingan las versiones cacheadas de las no cacheadas (siempre dentro del cache de navegador).
Podemos desactivar las etiquetas ETag simplemente poniendo esto en el .htaccess:
<IfModule mod_headers.c> Header unset ETag Header set Connection keep-alive </IfModule> FileETag None
1
2
3
4
<IfModule mod_headers.c>
Header unset ETag
Header set Connection keep-alive
</IfModule>
FileETag None
Las etiquetas ETag no hacen milagros de cara al WPO, pero pueden ayudar a resolver problemas de cache de navegador o browser cache.
Deshabilitar el listado de carpetas
De forma predeterminada, en muchas ocasiones el servidor web envía un listado de carpetas y archivos al navegador del visitante si este introduce una URL que no está disponible.
Esto es un problema de seguridad, ya que permite que cualquier visitante vea todos los archivos subidos a nuestro hosting.
Con este código en el .htaccess podemos deshabilitar el listado de directorios si está activado.
Options -Indexes
Options -Indexes
En principio, este snippet funciona solo en Apache. Creo que no es válido para LiteSpeed.
Recuerda: esto es un básico para la seguridad de cualquier sitio web.
Desactivar el acceso a los tipos de archivos NO listados
Con este código mejoramos la seguridad, aunque de una forma bastante radical, ya que bloqueamos los accesos a todos los tipos de archivos menos los especificados en el .htaccess:
Order deny,allow Deny from all <Files ~ «.(xml|css|js|jpeg|png|gif|pdf|docx|rtf|odf|zip|rar)$»> Allow from all </Files>
1
2
3
4
Order deny,allow
Deny from all
<Files ~ «.(xml|css|js|jpeg|png|gif|pdf|docx|rtf|odf|zip|rar)$»>
Allow from all
</Files>
Debemos personalizar el código de acuerdo a nuestras necesidades, aunque los del ejemplo son los tipos de archivo más comunes.
Desactivar la ejecución de PHP en Uploads
Este código es algo diferente. Debemos utilizarlo en un archivo .htaccess dentro de la carpeta UPLOADS de WordPress con el fin de que no se pueda ejecutar PHP dentro de esa carpeta.
¿Cuál es la razón para hacer esto? Pues que, en la práctica, no tiene por qué haber ningún archivo PHP dentro de UPLOADS. Con este código, evitamos que se pueda ejecutar uno en caso de que se use algún “exploit” para subirlo.
<Files *.php> deny from all </Files>
1
2
<Files *.php>
deny from all
</Files>
Recuerda: no lo utilices en el .htaccess principal del sitio web o lo que conseguirás es que falle.
Bloquear el acceso a los archivos importantes
Con este snippet en el .htaccess de un WordPress, mejoramos la seguridad de la instalación al bloquear el acceso externo a ciertos archivos importantes de WordPress que, en condiciones normales, no necesitan ser descargados nunca desde el navegador del visitante.
<FilesMatch «^.*(error_log|wp-config|install|wp-login|xmlrpc.php|php.ini|.[hH][tT][aApP].*)$»> Order deny,allow Deny from all </FilesMatch>
1
2
3
<FilesMatch «^.*(error_log|wp-config|install|wp-login|xmlrpc.php|php.ini|.[hH][tT][aApP].*)$»>
Order deny,allow
Deny from all
</FilesMatch>
Una vez más, te recuerdo que para casos específicos debes personalizar este archivo y entenderlo. El motivo es que incluye comodines y, en ciertos casos, pueden llegar a dar problemas con algún plugin o componente de la instalación WordPress.
Bloquear AUTORES en WordPress
En versiones antiguas de WordPress y en ciertas circunstancias, es posible saber el nombre de usuario de un autor simplemente probando IDs.
Ahora verás cómo solucionarlo bloqueando de raíz, sobre todo si no utilizas los autores de WordPress para nada.
RewriteEngine On RewriteBase / RewriteCond %{QUERY_STRING} (author=d+) [NC] RewriteRule .* – [F] RewriteEngine on RewriteBase / RewriteCond %{QUERY_STRING} author=d RewriteRule ^ /? [L,R=301]
1
2
3
4
5
6
7
8
RewriteEngine On
RewriteBase /
RewriteCond %{QUERY_STRING} (author=d+) [NC]
RewriteRule .* – [F]
RewriteEngine on
RewriteBase /
RewriteCond %{QUERY_STRING} author=d
RewriteRule ^ /? [L,R=301]
Esto es una mejora importante para la seguridad de un WordPress y creo que deberíamos bloquearlo siempre.
Bloquear el acceso a WP-INCLUDES de WordPress
La carpeta WP-INCLUDES de WordPress es una de las más importantes, ya que guarda librerías y componentes internos necesarios para que WordPress funcione.
Sin embargo, a la carpeta WP-INCLUDES no se tiene que acceder para nada desde fuera, es decir, desde el navegador del visitante. Por eso, podemos bloquear el acceso mediante el .htaccess con este código:
<IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteRule ^wp-admin/includes/ – [F,L] RewriteRule !^wp-includes/ – [S=3] RewriteRule ^wp-includes/[^/]+.php$ – [F,L] RewriteRule ^wp-includes/js/tinymce/langs/.+.php – [F,L] RewriteRule ^wp-includes/theme-compat/ – [F,L] </IfModule>
1
2
3
4
5
6
7
8
<IfModule mod_rewrite.c> 
RewriteEngine On 
RewriteBase / 
RewriteRule ^wp-admin/includes/ – [F,L] 
RewriteRule !^wp-includes/ – [S=3] 
RewriteRule ^wp-includes/[^/]+.php$ – [F,L] 
RewriteRule ^wp-includes/js/tinymce/langs/.+.php – [F,L] 
RewriteRule ^wp-includes/theme-compat/ – [F,L] 
</IfModule>
Es una manera de mejorar la seguridad, aunque tampoco hay muchos “ataques” contra esta carpeta excepto si por alguna razón ya existe previamente una brecha de seguridad.
Código para prevenir posibles inyecciones de código
Con este código en el .htaccess podemos llegar a bloquear algunas inyecciones de código básicas realizadas desde bots.
Options +FollowSymLinks RewriteEngine On RewriteCond %{QUERY_STRING} (<|%3C).*script.*(>|%3E) [NC,OR] RewriteCond %{QUERY_STRING} GLOBALS(=|[|%[0-9A-Z]{0,2}) [OR] RewriteCond %{QUERY_STRING} _REQUEST(=|[|%[0-9A-Z]{0,2}) RewriteRule ^(.*)$ index.php [F,L]
1
2
3
4
5
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{QUERY_STRING} (<|%3C).*script.*(>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} GLOBALS(=|[|%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} _REQUEST(=|[|%[0-9A-Z]{0,2})
RewriteRule ^(.*)$ index.php [F,L]
Ten cuidado con el efecto de este código, ya que puede provocar problemas y conflictos con algunos plugins para WordPress. En teoría ayuda a solucionar problemas, pero es importante estar preparados para los fallos que pueda llegar a dar. Es posible que tengamos que personalizar el código para adaptarlo a nuestro sitio web.
Protección contra HOTLINKING en WordPress
El hotlink puede llegar a dar muchos problemas en sitios web pequeños, ya que si te enlazan una imagen desde un sitio web grande con mucho tráfico puede llegar a “reventarte” el tráfico o ancho de banda de tu hosting rápidamente.
Podemos protegernos del hotlinking de una forma bastante “rastrera” pero eficaz con el siguiente código en el .htaccess:
<IfModule mod_rewrite.c> RewriteEngine on RewriteCond %{HTTP_REFERER} !^$ RewriteCond %{HTTP_REFERER} !^http://(www.)?midominio.com/.*$ [NC] RewriteRule .*.(gif|jpg)$ http://midominio.com/bloqueo.jpe [R,NC,L] </ifModule>
1
2
3
4
5
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www.)?midominio.com/.*$ [NC]
RewriteRule .*.(gif|jpg)$ http://midominio.com/bloqueo.jpe [R,NC,L]
</ifModule>
Aunque esto también es para nosotros, es decir, no podremos enlazar una imagen de nuestro sitio web y cargarla desde otro, ya que nos va a dar error. Incluso Google Images va a tener problemas con esto, ya que realmente Google Images hace bastante hotlinking.
Si quieres protegerte contra esto de otra forma, también puedes configurar un CDN como CloudFlare para servir las imágenes y no tener que preocuparte por el tema del ancho de banda en el hosting.
Modificar configuración de PHP
En algunos entornos (no en todos), podemos modificar el comportamiento del intérprete PHP directamente desde el .htaccess. Eso quiere decir que podemos modificar los límites.
Como he dicho esto no siempre es así, pero por si lo necesitas y quieres probar, te dejo el código que tienes que poner en el .htaccess:
php_value upload_max_filesize 64M php_value post_max_size 64M php_value max_execution_time 300 php_value max_input_time 300
1
2
3
php_value upload_max_filesize 64M
php_value post_max_size 64M
php_value max_execution_time 300
php_value max_input_time 300
Aunque existe la opción, esto es más recomendable hacerlo desde un php.ini o desde el panel de control, como ocurre en todos los servidores cPanel o VestaCP de Raiola Networks.
Bloquear el XML-RPC.PHP en WordPress
El tweak del functions.php de WordPress no es la única forma de desactivar el XMLRPC, un protocolo que actualmente es objeto de bastantes ataques.
Con el .htaccess también puedes bloquear el funcionamiento del XML-RPC.PHP para evitar ataques de fuerza bruta contra él:
<Files xmlrpc.php> order deny,allow deny from all </Files>
1
2
3
<Files xmlrpc.php>
order deny,allow
deny from all
</Files>
Esto es solo un parche. Si quieres hacerlo bien, debes hacerlo con un plugin o con el functions.php. Si buscas un plugin para hacer esto, tal vez te interese probar el plugin Perfmatters.
Redirecciones desde el .htaccess
Sobra decir que desde el .htaccess podemos hacer todo tipo de redirecciones. Como no es el objetivo de este artículo, no voy a explicar todas las opciones que existen para esto.
Solo quiero recomendarte que, si tienes que hacer muchas redirecciones y quieres llevar más control sobre esto, puedes hacerlo mejor con un plugin de redirecciones como el de RankMath. 
Share on twitter
Twitter 
Share on facebook
Facebook 
Share on linkedin

Deja una respuesta