optimizar el servidor proxy

Optimizar el servidor Proxy

Hasta ahora todo muy bien, nuestro servidor Squid Proxy responde perfecto a una red menor a 50 usuarios. Sin embargo, la red de datos se nos puede crecer, los clientes y servicios aumentar, y el servidor podría flaquear. De manera que para soportar este crecimiento debemos optimizar el servidor Proxy. 

La optimización comienza con un parámetro llamado File Descriptor. y se prosigue con otras ‘perillas‘. Bueno, se trata de aumentar el valor del File Descriptor. Un File Descriptor no es más que un número que representa un archivo, o un socket. Cada vez que un proceso abre un archivo, o un socket, se asigna un nuevo File Descriptor. En general, un File Descriptor puede ser un una conexión TCP, un archivo abierto, o sockets de comunicaciones entre procesos. Por ejemplo, una conexión con un cliente requiere tres Files Descriptors: uno para la conexión, otro para la escritura de logs y otro para la lectura de configuración.

Con ayuda del comando lsof, podemos visualizar la cantidad de file descriptors asignados a determinado puerto del servidor, en nuestro caso el 8080:

sudo lsof -i @la_ip_del_servidor:8080 | wc -l

Puede ampliar más sobre File Descriptor, aquí

Optimización técnica del servidor Proxy


Squid proxy viene de forma predeterminada con un tope de 1024 File Descriptors, y con ese número Squid trabaja bien con 40 clientes (relación de 25). Para aumentar ese tope, adicionamos la siguiente directiva en el archivo de configuración de Squid:

max_filedesc 8192

De manera que uno de los pasos para optimizar el servidor Proxy para que soporte más de 300 clientes, es aumentar el número de File Descriptors a un valor mayor de 7500 (300 x 25). De ahí que se haya configurado un tope de 8192.

Podemos verificar que efectivamente Squid proxy tiene un tope de 8192 file descriptors, así:

16786 es el PID de Squid en ese momento

Para validar la cantidad máxima permitida general de file descriptors en nuestro Linux, usamos el siguiente comando:

cat /proc/sys/fs/file-nr

Y para validar la cantidad máxima permitida de file descriptors por proceso en ejecución en Linux, usamos el siguiente comando:

sudo systemctl show --property=DefaultLimitNOFILE

Opciones adicionales para optimizar el servidor Proxy


Continuando con los ajustes para optimizar el servidor Proxy, podemos adicionar las siguientes líneas al /etc/sysctl.conf del sistema operativo:

net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_max_syn_backlog = 4096

Aplicamos con el comando:

sudo sysctl -p

Agregamos las siguientes líneas al squid.conf:

maximum_object_size 512 KB
maximum_object_size_in_memory 256 KB

Si el servidor cuenta con una cantidad generosa de memoria RAM, digamos que 20 GB, podemos configurar

maximum_object_size_in_memory en 64 MB

SMP en Squid


También podemos hacer un balanceo de las peticiones que le llegan a Squid Proxy. Dicho balanceo consiste en distribuir las peticiones que recibe Squid, entre los núcleos del procesador. A esta técnica se le llama SMP (Symmetric Multi Processing) y podemos activarlo así suponiendo que lo tenemos funcionando sobre una CPU Dual Core:

workers 2
cpu_affinity_map process_numbers=1,2 cores=1,2

Con CPU de 8 núcleos:

workers 8
cpu_affinity_map process_numbers=1,8 cores=1,8

SMP requiere que el método de gestión de objetos sea rock y habilitar la caché compartida para procesos:

cache_dir rock /opt/squid/var/cache/rock 51200
memory_cache_shared on

Siempre que realicemos un cambio en el método de gestión de objetos, debemos inicializar nuevamente la caché de Squid

Nota: Si el método rock no fue incluido en la compilación de Squid, no nos funcionara SMP. Con el comando sudo /opt/squid/sbin/squid -v podemos validarlo.

Más opciones para mejorar la velocidad de conexión


fqdncache_size 8192  # es el tamaño máximo de la caché de nombres de dominio completamente
cualificados (FQDN Cache). En este caso 8192 entradas

ipcache_size 20000  # Almacena mapeos de nombres de dominio (FQDN) → direcciones IP (resolución DNS directa),
entonces acelera la resolución DNS evitando consultas repetidas a servidores DNS externos.
ipcache_high 95 # Cuando el caché de IP alcanza el 95 % de su capacidad máxima (ipcache_size), Squid activa
una purga automática.
ipcache_low 80 # Squid deja de purgar el caché cuando el uso baja a este porcentaje.

check_hostnames off  # desactivando esta opción puede acelerar 
positive_dns_ttl 60 hours # define el tiempo de vida (TTL en segundos) que Squid debe almacenar
en caché las respuestas DNS correctas (es decir, cuando un nombre de dominio se resuelve exitosamente
a una dirección IP).
read_ahead_gap 4096 # relacionada con la lectura anticipada (read-ahead) de datos desde el disco
duro hacia la memoria caché. Cuando Squid lee un objeto almacenado en disco, el sistema operativo
puede cargar datos adicionales adyacentes en memoria (aunque aún no se soliciten). Esto aprovecha la
localidad espacial, anticipando que los próximos bytes probablemente serán requeridos pronto.
negative_dns_ttl # define el tiempo de vida (TTL en segundos) que Squid almacenará en caché las
respuestas DNS fallidas o negativas, es decir, cuando un nombre de dominio no puede resolverse.
refresh_pattern \.(jpg|jpeg|png|gif|webp|css|js|woff2|ico)$ 43200 50% 43200  # Cachear imágenes por
30 días

Limpieza de la caché y rotación de logs para Squid Proxy


Una actividad periódica que suele exigir esta solución, es su mantenimiento, es decir, limpieza de logs y reconstrucción de la caché. Entonces, podemos emplear un par de scripts sencillos para esas dos labores.

Llamaremos al de la reconstrucción de la caché «cache_squid.sh» y al encargado de la rotación de logs «rotalog_squid.sh«. Ambos con permiso de ejecución

El primer archivo contiene la siguiente secuencia de comandos:

#!/bin/bash
# echo "Parando Squid"
/opt/squid/sbin/squid -k interrupt
echo "Borrando cache de Squid"
rm -rf /opt/squid/var/cache/squid/*
echo "cache borrada"
sleep 1
echo "Iniciando la cache de Squid"
/opt/squid/sbin/squid -f /etc/squid/squid.conf -z
sleep 1
nice -n -20 /opt/squid/sbin/squid &
echo "Squid iniciado"
exit 0

 

El segundo ármalo con esta secuencia de comandos:

#!/bin/bash
# echo "Rotando logs de Squid"
/opt/squid/sbin/squid -k rotate
sleep 1
echo "Logs rotados"
sleep 1

exit 0

Puede colocarlos en tu home directory y programarlos con crontab para que se ejecuten todos los domingos a las 4 y 4:30 PM

00 16 * * 7 root /home/tu_usuario/cache_squid.sh
30 16 * * 7 root /home/tu_usuario/rotalog_squid.sh

Squid con Máxima Prioridad


Podemos decirle al kernel que nos ejecute a Squid Proxy con la mayor prioridad posible en el planificador de tareas. Solo basta con iniciar Squid con el comando nice, así:

nice -n -20 /opt/squid/sbin/squid &

Hasta aquí podemos decir que ya tenemos un servidor Proxy optimizado para alta carga de trabajo. Sin embargo, acá solo hemos optimizado gran parte de Squid, y algo de Linux. En la siguiente parte de este tutorial vamos a ampliar la optimización de este servidor, afinando el tratamiento de paquetes a nivel de kernel.

Optimización de la memoria


Debido a que un servidor como Squid puede estar haciendo muchísimas asignaciones y liberaciones de memoria con el tradicional malloc de glibc, el espacio de memoria que Squid usa para su trabajo queda fragmentado, es decir, pueden quedar espacios libre en memoria pero divididos o interrumpidos por otros datos. Con un manejador como Jemalloc la cosa mejora. Jamelloc es un administrador de memoria dinámica para programas en Linux/Unix.  Con Jmalloc el rendimiento en el manejo de paquetes puede mejorar en un 10%, respecto a allocator de glibc.

Instalamos a los paquetes de desarrollo jemalloc.

sudo apt install libjemalloc-dev

Luego, en la interfaz de Squid en Webmin, modificamos el comandos de inicio de Squid para que se ejecute enlazado con Jemalloc:

nice -n -20 env LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 /opt/squid/sbin/squid &

Y con el siguiente script podemos validar a los workers de Squid enlazados con Jemalloc.

#!/bin/bash
for p in $(pgrep squid); do
  echo "===== PID $p ====="
  grep -i jemalloc /proc/$p/maps
done

 

Importante: Si nuestro Proxy va a servir como equipo de frontera, asegurémonos que su puerto de trabajo (8080) esté bloqueado de cara a Internet. Es para evitar que naveguen en Internet  desde la calle por medio de nuestra máquina.

Bloqueamos el puerto 8080 en la interfaz conectada a Internet.

sudo iptables -A INPUT -i interfaz_internet -p tcp --dport 8080 -j DROP

¿Qué diferencia tenemos al lado de equipos propietarios?


Cuando usamos a Squid Proxy como filtrado web, y a Linux como seguridad perimetral, tenemos tres diferencias básicas frente a soluciones propietarias:

  • Hardware: A Linux podemos implementarlo en casi cualquier hardware, así que tendríamos dos, tres, cuatro veces o más capacidad de hardware, y rendimiento, frente a una solución gama entrada o media tipo Fortinet. En este enlace podemos ver el hardware de los Fortigate.
  • Costos de licenciamiento: Ninguno con GNU/Linux. Algunos decenas de dólares, hasta algunos miles con marcas propietarias.
  • Flexibilidad: Código abierto con GNU/Linux, más opciones de monitoreo sin costos financieros adicionales y más control de los recursos. Con marcas propietarias no tenemos acceso a parámetros del kernel.

 

< Quinta Parte   Séptima Parte >

Comparte esto en
Publicado en Servidor Proxy.