Django: peticiones wsgi y asgi simultaneas (htmx y websockets)

Muy feliz de finalmente tenerlo funcionando! no sé si es la mejor forma, pero la cuestión es que funciona :D

Estos días me estoy peleando en hacer funcionar un chatbot con stream de openai sobre django. Me ha llevado un par de días de hacerlo funcionar pero aquí lo tenemos :D

Básicamente después de perderme entre decenas de páginas de documentación y abrir y cerrar otras decenas más de pestañas del navegador, lo que terminé haciendo fue localizar una aplicación que sí hacía lo que yo quería y luego la he implementado a mi aplicación. La aplicación que funcionaba like a charm en local es Django OpenAI-Powered Chatbot with HTMX Streaming. También recomiendo esta otra documentación (Learn to use Websockets with Django by building your own ChatGPT) que si eres relativamente nuevo con esto de htmx y websockets te va a aclarar mucho el tema :)

Inicié implementando el manual de saaspegasus pero no funcionaba. Así que he decidido directamente integrar el código de django_chatbot a mi aplicación y tampoco funcionaba… hasta que he visto lo de daphne! El python manage.py runserver de toda la vida no es síncrono pero daphne si, y lo que permite es activar las conexiones asíncronas. Al aplicar esto, todo ha empezado a funcionar :D

Después ha venido la parte de ponerlo en producción que de nuevo me he perdido entre múltiples páginas pero finalmente lo que sacado y aquí lo dejo para saber como implementarlo la próxima vez y también para otro …

Saltando bloqueos de los ISP: HAProxy y autossh

¡Este último mes podríamos decir que he estado muy entretenida! Hace ya casi dos años, un cliente vino a mi harto de que los proveedores de hosting le cerrasen el servidor, durante todo este tiempo de maravilla, hasta que hace un mes y medio Movistar y Vodafone bloquearon el dominio. Ahí es cuando el cliente me contactó de nuevo para realizar un análisis y un informe pericial. El motivo es que el cliente no está realizando ningún acto delictivo que lleve a los proveedores de hosting e ISP a bloquear el servicio, aún así, lo hacen, estamos delante de un caso de Internet Blackout, bloqueo interesado de un servicio en concreto para que los usuarios no puedan acceder a él. ¿Algo ha tenido que ver el recién finalizado y polémico Mundial de Fútbol en Qatar?.

En la fecha del bloqueo del dominio del cliente, mi propuesta al identificar que el bloqueo se estaba realizando a nivel de dominio (que no de DNS, ya que estos si resolvían), le propuse al cliente de registrar otro dominio. La solución funcionó durante 2 semanas más hasta que Movistar y Vodafone bloquearon la dirección IP, como tal, la solución de añadir mas dominios apuntando al servidor, ya no era útil. Por mas INRI, el bloqueo se extendió a más ISP, aislando casi por completo el servidor de Internet (y no sólo en España, otros países de Europa y LatinoAmérica se vieron afectados), pero no todos lo bloquearon!

A partir de aquí se empezó a …

Desplegando un servidor web con alta capacidad

Aquí estoy lamiéndome las heridas de esta noche pasada. Hace unas semanas un cliente me contactó para preparar para alta capacidad una página web que administra. La página web sirve para hacer las inscripciones a una carrera de motos y el día de las inscripciones aquello se pone a fuego.

Tras un presupuesto super ajustado, el cliente opta por la opción más económica. El resultado? pues tras varios “yaque” (instálame un servidor de correo “yaqueestás”), prisas y cambios a último momento, un aumento considerable del tráfico respeto el año pasado y vete a saber que más, el servidor ha estado super saturado y no ha podido servir todas las peticiones necesarias en tiempo y forma; al menos lo importante, que son las inscripciones, se hicieron y con un bajo porcentaje de fallo.

La aplicación está hecha con zendframework2, ergo php5.6, con configuraciones a fuego en el código de la configuración del servidor, correo, etc. Además la web se encontraba en un servidor CentOS 7.0 (del 2014), con unas configuraciones crípticas, no, lo siguiente. ¿Lo de respetar los directorios según LHFS?, ¡¿pa’qué?!.

Para no tener que tocar la configuración del servidor que estaba funcionando, decidí desplegar la página web en otro servidor en mi humilde infraestructura y realizar primero ahí las pruebas.

El entorno de pruebas
Se montó una maquina virtual lxc con debian 11, con 8Gb de RAM y 2 CPU Intel(R) Xeon(R) CPU E5-2670 0 @ 2.60GHz, en mi humilde infraestructura tengo un cuello de botella pendiente de …

Proxy nginx: Redirigir las IPs reales

Me encuentro con una aplicación la cual tengo detrás de un frontal de nginx. La cuestión es que la petición al servidor llega con la IP interna del frontal de nginx en lugar de la IP real del cliente.

Para ello tendremos que realizar una configuración en el frontal de nginx para pasar la IP real del usuario y otra en el nginx de la aplicación para que interprete correctamente la IP.

Frontal nginx

root@frontal1-nginx:~# vi /etc/nginx/sites-enabled/app.capa8.net
server {
    listen 80;

    server_name app.capa8.net;
    return 301 https://app.capa8.net$request_uri;
    #root /var/www/html/;
}

server {
        server_name app.capa8.net;

        listen 443 ssl;
        ssl_certificate /etc/letsencrypt/live/app.capa8.net/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/app.capa8.net/privkey.pem;
        include /etc/letsencrypt/options-ssl-nginx.conf;
        ssl_trusted_certificate /etc/letsencrypt/live/app.capa8.net/chain.pem;

        location / {
                proxy_set_header  Host $host;
                proxy_set_header  X-Real-IP $remote_addr;
                proxy_set_header  X-Forwarded-Proto https;
                proxy_set_header  X-Forwarded-For $remote_addr;
                proxy_set_header  X-Forwarded-Host $remote_addr;
                proxy_pass http://192.168.100.15:80;
        }
}

nginx Aplicación

Siendo set_real_ip_from la subred por donde pueden venir las peticiones de proxy

root@app:~# vi /etc/nginx/sites-enabled/app
server {
    listen 80;
    server_name app.capa8.net;

    set_real_ip_from 192.168.100.0/24;
    real_ip_header X-Real-IP;
    real_ip_recursive on;

    location / {
        include uwsgi_params;
        uwsgi_pass unix:/tmp/uwsgi-app.sock;
    }

    # /static
    location /static/ {
        autoindex off;
        root /var/www/app/web/;
    }

    location /static/admin {
        autoindex off;
        root /var/www/app/venv/lib/python3.5/site-packages/django/contrib/admin/;
    }
}

Reiniciamos ambos nginx y comprobamos en los logs que la ip pasa correctamente.

Fuente: Forward IP Addresses with NGINX Proxy

Redirección de puertos con iptables + contrack

Pues seguimos con éstos pequeños errores que hemos cometido siempre y que ahora en un momento de cambios y con mucho mas entendimiento llegan mejores soluciones para que las cosas funcionen mejor (tanto a nivel técnico como personal). Hoy estoy tiernecilla y quiero agradecer con éste post todas éstas personas que seguís los posts que publico y tenéis al igual que yo éste blog como una herramienta de consulta, un lugar claro, sin muchas complicaciones donde encontrar justo aquello que necesito en cada momento o me da la pista para poder seguir avanzando con algo mas grande que estoy construyendo con el paso de los días.

Ésta vez me encuentro solucionando un problema que inicialmente parecía de nginx pero ha resultado ser de iptables, y es que las cosas nunca son lo que parecen a primera vista y es necesario tener un gran conocimiento del sistema para entender como poder solucionar los problemas de base y encontrar una solución definitiva que evita fallos futuros, para casos como hoy que ya en producción me encuentro con un problema grave de base. Para que un sistema funcione bien, las capas inferiores (base) deben estar bien.

Me dejo ya de palabrerías y comentarios dobles y me pongo en materia. El post que rectifico es éste: Proxmox + nat + iptables.

Gracias a las configuraciones de las antenas en los supernodos entiendo que se deben marcar los paquetes tanto de entrada (prerouting) como de salida (postrouting). En TCP hay una llamada de un …

Bloquear facebook con iptables

Tenemos un proxy transparente con squidguard bloqueando algunas webs, pero sólo se bloquean las webs que no són https, ya que si le indicamos que las conexiones https se envien al proxy, nos encontramos que se modifica la cadena de verificación de las webs a las cuales accedemos por https y nos avisa de un “man in the middle”.

Para ello tenemos dos opciones, ssl-bump de squid3, con el que le pasamos un certificado intermedio o usamos reglas de iptables. La primera opción no se ha dejado, así que he pasado a la opción de bloquearlas con iptables.

Lo primero que tenemos que saber es que si pasan conexiones https a través de nuestro servidor proxy transparente, dichas conexiones van cifradas y no es posible distingir la url a la que se dirigen. Para ello tenemos que filtrar por IP, pero… si lo que queremos bloquear es un site con muchas ips y además de que pueden ir variando, la cosa se complica.

Por suerte tras buscar un poco he encontrado una solución realmente interesante. Con un poco de bash y una petición al AS de facebook, podemos sacar los rangos de IPs con los cuales trabaja esta empresa.

# BLOCK FACEBOOK
for i in $(/usr/bin/whois -h whois.radb.net '!gAS32934' | tr ' ' 'n' | sort -n -k1,1 -k2,2 -k3,3 -k4,4 |grep /)
do iptables -A FORWARD -d $i -j DROP
done

Luego si queremos ver como se ha aplicado la regla

# iptables -L -n 

Adicionalmente, aunque la dejo …

Squid3: pequeña broma con las imágenes

Hace ya mucho tiempo, cuando empezaba con la administración de sistemas a mis compañeros de piso les hice una pequeña broma, monté un proxy transparente e hice pasar todas las conexiones http por este server, y una vez ahí me dediqué a girarles las imágenes.

Así que vamos a hacer lo mismo :)

No entro en detalles de como montar un proxy transparente, haced uso del buscador de este mismo blog y encontraréis la respuesta!

Contamos con una maquina que tiene apache y squid3 instalado, así que crearemos un directorio donde se guardaran las imágenes modificadas, por ejemplo /var/www/images, que será accesible desde http://ipdelservidor/images/.

Creamos el directorio y le damos permisos a www-data:

# cd /var/www
# mkdir images
# chown -R www-data:www-data images

Y cruzamos los grupos de los usuarios proxy y www-data, para que puedan leer los directorios necesarios para la bromita :)…

Proxy transparente dentro de un contenedor openVZ

Todos sabemos que los contenedores cuando se trata de comunicarse con el núcleo del sistema operativo siempre nos deja algun regalito, así que aquí tenemos otro caso, en este caso queremos montar un proxy transparente dentro de un contenedor OpenVZ (Proxmox).

Nos encontramos que queremos ejecutar una línea de iptables en nuestro contenedor, pero nos sale este error:

iptables v1.4.8: can't initialize iptables table `nat': Table does not exist (do you need to insmod?)
Perhaps iptables or your kernel needs to be upgraded.

Lo primero de todo tendremos que configurar el fichero /etc/vz/vz.conf y comentaremos la línea con el parámetro IPTABLES= y pondremos otra así:

IPTABLES="ipt_REJECT ipt_recent ipt_owner ipt_REDIRECT ipt_tos ipt_TOS ipt_LOG ip_conntrack ipt_limit ipt_multiport iptable_filter iptable_mangle ipt_TCPMSS ipt_tcpmss ipt_ttl ipt_length ipt_state iptable_nat ip_nat_ftp"

Configurar apt por terminal para salir por un proxy

Otro tip of the day:

# vi /etc/apt/apt.conf.d/90-apt-proxy

es probable que el fichero no exista, así que lo creamos y añadimos lo siguiente:

Acquire::http::Proxy "http://usuario:password@ipproxy:puerto";
Acquire::ftp::Proxy "http://usuario:password@ipproxy:puerto";

guardamos, salimos y actualizamos los repositorios

# apt-get update

y apa ;)

thnks emi por la corrección, así queda todo más ordenado :)…

Socks Proxy con dante o sacar el correo por guifi

Otro post mas sobre proxys, se nos ha atascado el cuerno con esto y hasta que no lo podamos sacar vamos dándole, como tiene que ser :)

De momento no hay autenticación con los usuarios de la web de guifi, para ello se tiene que rascar un poquito más, así que de momento dejaremos el proxy abierto y la recomendación es configurar el cliente de correo con el socks proxy y el cliente de http por el proxy squid de cabecera, con la autenticación de los usuarios y tal.

La instalación de dante es realmente sencilla:

# apt-get install dante-server

Justo con esto tendremos que empezar a configurar el fichero de configuración /etc/danted.conf…