¿Conexión ADSL lenta? Mejora la velocidad de tu conexión a Internet (Capítulo III de III)

Índice:

19/07/2009 – Capítulo I – Revisar y mejorar la instalación telefónica de nuestra casa
21/07/2009 – Capítulo II – Parámetros y configuraciones de ADSL, cómo configurar el router para sacar el mayor partido a tu ADSL
28/07/2009 – Capítulo III – Cuando no hay pan, buenas son migas. Si tu conexión es lenta, te interesará saber cómo cachear contenidos para acelerar la conexión a Internet

Para terminar, en esta última entrega hablaremos sobre como intentar hacer un uso eficiente del ancho de banda. La idea general es, teniendo una conexión a internet lenta, tratar de hacer el menor número de peticiones hacia ella y utilizar contenido cacheado para ahorrar ancho de banda.

Para racionar el uso de ancho de banda entre cualquier protocolo, tal y como mencionaba en el anterior capítulo, puede conseguirse usando QoS. En este capítulo vamos a centrarnos en mejorar la navegación Web especialmente, ya que es uno de los principales usos que le daremos a nuestra conexión.

Para conocer como mejorar la navegación debemos conocer como funciona nuestro navegador (en resumidas cuentas):

  1. Tecleamos una dirección web en la barra de direcciones.
  2. El navegador tiene que utilizar el protocolo DNS (Domain Name System) para resolver que ordenador es el que maneja ese dominio.
  3. Tras conocer la IP del ordenador, se conecta a él y hace una petición HTTP (Hyper Text Transfer Protocol) para obtener el contenido de la página.
  4. Si la página posee imágenes o enlaces, deberá solicitarlas al mismo servidor (o a otro externo) volviendo al punto 2. Si se trata del mismo servidor generalmente no necesita volver a resolver la IP.

Ejemplo peticion DNS y HTTP

En una página web típica como podría ser la web de Marca, puede haber más de 120 imágenes estáticas repartidas entre varios servidores de contenidos (estaticos[01,02,03,04,05].marca.com), enlaces de publicidad, vídeos, etc…

Esto implica que el navegador tendrá que resolver cada uno de los dominios que alojan los contenidos y tendrá que ir conectándose a cada uno para solicitar los datos y finalmente componer la página web final.

Si hacemos cuentas, una resolución DNS suele tardar alrededor de unos 100 milisegundos (dependiendo de la carga de la red y del servidor), si la web hace referencia a unos 30 dominios distintos, sólo en resoluciones DNS se perderán 3 segundos. Después tiene que conectarse a cada servidor y hacer más de 120 peticiones, añadiendo al propio retraso de la transferencia de las imágenes un pequeño retraso en el manejo del protocolo HTTP.

En definitiva, la web no carga rápidamente. Muchos navegadores son muy competentes y para solucionar esto hacen lo que se llama cacheo de contenidos, es decir, almacenan durante algún tiempo los dominios ya resueltos y el contenido estático para no tener que volver a solicitarlo al servidor.

El protocolo HTTP implementa una serie de controles para marcar la caducidad de los contenidos, el problema es que en muchos casos las páginas web son dinámicas y usan trucos anti-cache para asegurarse de que el contenido que recibe el cliente sea fresco, a costa de consumir un mayor ancho de banda y ralentizar la carga.

Lo que voy a explicar a continuación es cómo montar un servidor DNS local y un proxy caché web. El servidor DNS local nos permitirá hacer cache de las resoluciones DNS durante más tiempo, además, si tenemos una red con varios equipos ahorraremos peticiones desde éstos.

Proxy Cache Web HTTP

En mi caso tengo montado un equipo en red actuando como servidor de ficheros, proxy web, cache DNS, etc… usando debian GNU/Linux. No es estrictamente necesario tener un equipo destinado exclusivamente como servidor, aunque si te gusta experimentar seguramente podrás conseguir un ordenador entre 400 y 800 Mhz que cumpla con la tarea. Existen más programas que los utilizados en este post, inclusive para Windows, así que si no te convence alguno siempre puedes utilizar otro que se ajuste más a tus necesidades.

Como caché de DNS voy a utilizar dnsmasq, que es un pequeño servidor DNS ligero que implementa caché de DNS por defecto y está en los repositorios de debian:

Ni siquiera es necesario modificar la configuración por defecto, a menos que queramos que escuche en una interfaz determinada. Además nos da una serie de configuraciones interesantes:

Podemos bloquear ciertos dominios que sabemos que sólo aportan publicidad para que el navegador no consiga conectarse a ellos, también podemos asignar un nombre de dominio a nuestro router o, si tenemos un dominio propio, hacer que los equipos de dentro de la red resuelvan la IP local del servidor en lugar de la de Internet.

Modificamos el archivo /etc/resolv.conf para utilizar nuestro servidor DNS:

Y probamos que funcione:

Indiscutiblemente, mucho mejor con el cache DNS. 🙂

El proxy caché web que vamos a utilizar es squid. También está disponible en los repositorios de debian  e incluso hay versiones portadas a Windows. Se trata de un proxy HTTP altamente configurable y muy utilizado a nivel empresarial.

squid es muy flexible, nos permite hacer un proxy HTTP que no haga cache (sólo para controlar que páginas se visitan y generar estadísticas de uso) o incluso un servidor proxy caché transparente (que cachea todo el contenido de forma transparente para el usuario final, almacenando el contenido incluso durante más tiempo que el indicado por el servidor).

En nuestro caso queremos cachear todo el contenido estático de la web, en general, la mayor parte de las páginas no suelen modificar las imágenes que ya tienen sino que añaden imágenes nuevas o las sustituyen. Existen páginas web que generan contenido dinámico (misma imagen renombrada cada vez que se pide, por ejemplo) evitando que podamos cachearlo. Un ejemplo perfecto de web incacheable es Youtube :(.

Instalamos el servidor squid y una utilidad para ver como está procesando las peticiones:

Y procedemos a configurarlo:

# Primero configuramos el puerto donde va a escuchar el servidor y le indicamos que queremos utilizar un proxy transparente
http_port 8080 transparent
icp_port 3130

# Las ACL (Access lists, Listas de Acceso) definen grupos de IPs a las que se le aplicarán determinados permisos, es crucial tener bien definida la siguiente:
acl all src 0.0.0.0-0.0.0.0/0.0.0.0

# Definimos los nuevos periodos de refresco segun el dominio o el tipo de contenido, probablemente no es la mejor configuración, la modifiqué de otra que encontré en la web en su momento.
# Por defecto el contenido se cacheará durante una semana, ampliable hasta un mes segun el caso
# los modificadores añadidos al final significan lo siguiente:
# override-lastmod -> Ignorar la fecha de última modificación,se utilizará la indicada en la configuración
# override-expire -> Ignorar la fecha de caducidad indicada por el servidor
# ignore-private -> Ignorar las etiquetas que indican que el contenido es privado, se cacheará de todas formas
# reload-into-ims -> Las peticiones que fuerzan la recarga de la página (Control + F5 en Internet Explorer ó Control + Shift + R en Mozilla Firefox) se convierten en peticiones If-Modified-Since, es decir, sólo actualizará si el contenido se ha modificado desde la última vez.
# ignore-reload -> Se ignoran las peticiones de recarga forzada de la página

refresh_pattern windowsupdate.com/.*\.(cab|exe) 4320 100% 43200
refresh_pattern download.microsoft.com/.*\.(cab|exe) 4320 100% 43200
refresh_pattern ^http://.*\.cnn\.com 360 50% 4320 override-lastmod
refresh_pattern ^http://news\.bbc\.co\.uk 360 50% 4320 override-lastmod
refresh_pattern microsoft 1080 150% 10080 override-lastmod
refresh_pattern msn\.com 4320 150% 10080 override-lastmod
refresh_pattern ^http://.*\.doubleclick\.net 10080 300% 40320 override-lastmod override-expire ignore-private reload-into-ims ignore-reload
refresh_pattern ^http://.*\.google-analytics\.com 10080 300% 40320 override-lastmod override-expire ignore-private reload-into-ims ignore-reload
refresh_pattern ^http://.*FIDO 360 1000% 480
refresh_pattern \.r[0-9][0-0]$ 10080 150% 40320
refresh_pattern ^http://.*\.gif$ 1440 50% 20160 ignore-no-cache override-lastmod ignore-private reload-into-ims ignore-reload
refresh_pattern ^http://.*\.asis$ 1440 50% 20160
refresh_pattern -i \.pdf$ 10080 90% 43200
refresh_pattern -i \.art$ 10080 150% 43200
refresh_pattern -i \.avi$ 10080 150% 40320
refresh_pattern -i \.mov$ 10080 150% 40320
refresh_pattern -i \.wav$ 10080 150% 40320
refresh_pattern -i \.mp3$ 10080 150% 40320
refresh_pattern -i \.qtm$ 10080 150% 40320
refresh_pattern -i \.mid$ 10080 150% 40320
refresh_pattern -i \.viv$ 10080 150% 40320
refresh_pattern -i \.mpg$ 10080 150% 40320
refresh_pattern -i \.flv$ 10080 150% 40320 ignore-no-cache override-expire ignore-private reload-into-ims ignore-reload
refresh_pattern -i \.swf$ 10080 150% 40320 override-lastmod ignore-no-cache override-expire reload-into-ims ignore-reload
refresh_pattern -i \.jpg$ 10080 150% 40320 override-lastmod ignore-no-cache ignore-private reload-into-ims ignore-reload
refresh_pattern -i \.rar$ 10080 150% 40320
refresh_pattern -i \.ram$ 10080 150% 40320
refresh_pattern -i \.gif$ 10080 300% 40320 override-lastmod ignore-no-cache ignore-private reload-into-ims ignore-reload
refresh_pattern -i \.txt$ 1440 100% 20160  override-lastmod ignore-no-cache ignore-private reload-into-ims ignore-reload
refresh_pattern -i \.zip$ 2880 200% 40320
refresh_pattern -i \.arj$ 2880 200% 40320
refresh_pattern -i \.exe$ 2880 200% 40320
refresh_pattern -i \.tgz$ 10080 200% 40320
refresh_pattern -i \.gz$ 10080 200% 40320
refresh_pattern -i \.tgz$ 10080 200% 40320
refresh_pattern -i \.tar$ 10080 200% 40320
refresh_pattern -i \.Z$ 10080 200% 40320
refresh_pattern -i \.png$ 10080 150% 40320 override-lastmod ignore-no-cache ignore-private reload-into-ims ignore-reload

# Estos son los patrones de refresco por defecto segun el protocolo utilizado, es muy importante dejar el último con un retraso de 0, sino puede suceder que las páginas web dinámicas no se actualicen correctamente
refresh_pattern ^ftp:// 1440 50% 10080
refresh_pattern ^gopher:// 1440 10% 1440
refresh_pattern . 0 20% 4320

# Recordamos las páginas web que dieron error al intentar solicitarlas
negative_ttl 1 minutes
positive_dns_ttl 15 hours
negative_dns_ttl 1 minutes
half_closed_clients off

# Definimos ciertas listas de acceso para dominios que queremos intentar cachear
acl youtube dstdomain .youtube.com
acl youtubeip dst 64.15.112.0/24
acl youtubeip2 dst 74.125.15.0/24
acl googlevideo dstdomain .googlevideo.com
acl imageshack dstdomain .imageshack.us
acl router dst 192.168.1.1

# Permitimos cachear estas listas de acceso
cache allow youtubeip
cache allow youtubeip2
cache allow youtube
cache allow googlevideo
cache allow imageshack

# Evitamos cachear la web del router, por ejemplo
no_cache deny router

# Modifico la cabecera User-Agent para que parezca que todos los equipos de la red utilizan Linux
header_access User-Agent deny all
header_replace User-Agent Mozilla/5.0 (X11; U; Linux x86_64; es-ES; rv:1.9.0.11) Gecko/2009060309 Ubuntu/9.04 (jaunty) Firefox/3.0.12

# Podemos indicarle a squid que cachee los contenidos en base al tipo de objeto MIME, estas configuraciones pueden guardarse en un archivo externo, como es el caso:
acl CACHEMIME rep_mime_type -i “/etc/squid/cache_mime.lst”

# De las configuraciones que utilizamos antes, algunas violan el protocolo HTTP, así que es posible que tengamos problemas de fresco con determinadas páginas web. Para subsanarlo creamos un archivo con una lista de dominios que no queremos cachear. En mi caso me he topado con que as.com y elpais.com dan problemas con el caché.
acl NOCACHE dstdomain “/etc/squid/nocache.lst”

cache allow CACHEMIME
no_cache deny NOCACHE

# Aquellas páginas web que sean dinámicas (esten en cgi-bin o tengan parámetros) no se cachean nunca
hierarchy_stoplist cgi-bin ?
acl QUERY urlpath_regex cgi-bin \?
no_cache deny QUERY

# Le indicamos que muestren los mensajes de error en Español
error_directory /usr/share/squid/errors/Spanish

# Bloqueamos algunas cabeceras HTTP para que no se note que estamos utilizando un proxy:
header_access X-Cache deny all
header_access X-Cache-Lookup deny all
header_access X-Cache-Hit deny all
header_access Via deny all
header_access X-Forwarded-For deny all

# Usamos 128 Mb de memoria
cache_mem 128 MB
cache_swap_low 90
cache_swap_high 95

# No se cachearan contenidos mayores de 64 Mb
maximum_object_size 65535 KB

# La caché en disco podrá ocupar hasta 15 Gb
cache_dir ufs /var/spool/squid 15000 16 256

# Sólo queremos el log de acceso
cache_access_log /var/log/squid/access.log
cache_log none
cache_store_log none

El resto de configuración del squid puede dejarse por defecto, más que nada quería centrarme en aquellos parámetros menos comunes.

Para poder ver si funciona el proxy, debemos configurarlo en los navegadores en las opciones de conexión, o si tenemos el servidor haciendo NAT entre el router y el resto de la red, redirigir las peticiones al puerto HTTP 80 hacia el puerto de nuestro proxy.

Desde consola usando squidview podemos ver la efectividad de las peticiones:

Recomiendo consultar la página web oficial para entender los datos que se muestran por pantalla.

Si queremos generar estadísticas diarias de la efectividad del proxy recomiendo utilizar calamaris (también disponible en el repositorio de debian) que genera un informe muy detallado con el ratio de efectividad del proxy, porcentaje de ahorro de ancho de banda, dominios más consultados, etc…

Aquí podeis ver la sección de resumen del informe que genera:

Calamaris Report

Si probamos a navegar a través del proxy notaremos que tiene mucha más fluidez y menos latencia. Las páginas cargan casi instantáneamente y el contenido dinámico se actualiza bien. Esto se debe a que la mayor parte del tráfico de la página, especialmente todo el contenido estático (imágenes, flash, etc…), nos lo sirve nuestro servidor proxy sin tener que conectar al servidor real; sólo es necesario actualizar el código html de la página, que es realmente lo que varía.

Y bueno, hasta aquí pretendía llegar, si has conseguido leer los tres capítulo te felicito, me temo que han sido bastante extensos (espero que no fuesen espesos ;)).

Si tienes cualquier duda no dudes en preguntar. Espero que estos consejos le sean útiles a alguien (aparte de mí mismo, claro xD), si es así agradecería que me dejases un comentario. 🙂

P.D.- Por petición popular, en unos días liberaré el código fuente completo del script que almacena datos estadísticos del router de Ya.com. Puede ser adaptado para funcionar con cualquier router, puliré un poco el código fuente y será publicado bajo licencia GPL. Con él puedes intentar diagnosticar cual es el origen de tus problemas basandote en los horarios, así como poder reclamarle a tu operadora cualquier tipo de incidencia con datos reales. No lo publico directamente aquí porque creo que el capítulo ha sido suficientemente extenso.

7 comentarios

  1. Me parece un truco excelente y un gran ejemplo de para qué sirve un servidor (valga la redundancia). Pero… ¿compensa para un usuario doméstico? Me refiero a si la energía que consume este equipo compensa el incremento de velocidad…

    Supongo que para una biblioteca, un cibercafé o una universidad es casi imprescindible…

  2. Depende en parte del equipo que utilices, en general un ordenador encendido consume alrededor de 60~80W, y si soporta escalado de velocidad permitirá ahorrar más energía aun.
    Casi todo el mundo que conozco no tiene un servidor en casa, pero sí que deja su ordenador encendido bajando cosas con algun programa P2P. Si usas el servidor para descargar el P2P tienes varias mejoras, entre ellas si el pc se quema no es el PC potente que usas para jugar, y encima te sirve para hacer pruebas e instalar servicios de red.

    Hace años que lo vengo utilizando y no me arrepiento. 🙂

  3. Hola, pues la verdad es que nunca he intentado la intercepción ssl, pero buscando un poco he encontrado lo siguiente:

    To utilize the no SSL option for your network, configure the DNS entry for Google to be a CNAME for nosslsearch.google.com.

    http://www.edugeek.net/forums/internet-related-filtering-firewall/84872-blocking-google-personal-gmail-accounts-but-not-apps-education-accounts-2.html

    De esta forma la configuración del bloqueo se puede hacer mediante DNS.

    Espero haberte sido de ayuda. 🙂

  4. muy bien lo leeré con detenimiento se ve con mucha estructuración. Lo felicito.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *