Django runserver sobre https

Estos dos últimos meses he estado trabajando con una tienda virtual desarrollada con django llamada django oscar. Muy interesante el juguete, tunearla ha habido momentos de todo, en algunos momentos era una delicia por la documentación que tienen y por otros iba más perdida que un pingüino en el desierto y los atascos eran monumentales además de la presión del cliente que tenía que tener el proyecto en funcionamiento un mes y pico antes de que se me diese acceso al código para poder arreglar y aplicar las funcionalidades extra que se requerían. El proyecto era uno que había dejado a medias otro desarrollador y tuve que rehacer todo el código porqué tal como se me entregó la aplicación había cosas básicas de funcionamiento rotas, además de variables en inglés, en castellano y catalán (no es el primer proyecto que me encuentro así).

Django oscar se usa como aplicación de Backend y de frontend hay desplegado un NextJS que tras dar alguna que otra vuelta he terminado modificando alguna cosa.

En entorno local de desarrollo todo funcionaba correctamente, pero al ponerlo en producción la cosa se ha puesto divertida y ha requerido investigar varias cosas que voy a exponer en este post en modo de notas.

La aplicación de frontend se conecta con django oscar por API y hasta que no añadí la opción CSRF_TRUSTED_ORIGINS la comunicación era infructuosa.

# vi settings.py
# this allows nextjs to connect to django without using csrf_token
CSRF_TRUSTED_ORIGINS = 'http://127.0.0.1'
CSRF_COOKIE_SAMESITE = "None"

Instalar php8.2 en debian 11

La versión de php de debian 11 es la 7.4 y algunas aplicaciones ya piden sólo php 8, así que vamos a ver como instalamos php 8.

# echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" /etc/apt/sources.list.d/php.list
# apt -y install gnupg2
# wget -qO - https://packages.sury.org/php/apt.gpg | apt-key add -
# apt update

Ahora lo siguiente será ver qué librerías tenemos instaladas, instalar las nuevas y cambiar la configuración de apache2 o nginx

# dpkg -l |grep php

Una vez esté todo funcionando, eliminamos las versiones antiguas de php

# apt remove --purge php7.3* php7.4* libapache2-mod-php7.3 libapache2-mod-php7.4
# apt-get clean

Generar certificado autofirmado con openssl

Llega el momento de poner a producción un programa que llevas más de un año desarrollando, para montarlo necesito generar unos certificados autofirmados para cuando el dominio apunte a mi servidor generar los certificados de letsencrypt. De mientras el apunte de como generarlos con openssl:

# cd /etc/autosigned-certs/
# mkdir domain.com
# cd domain.com
# openssl req -nodes -newkey rsa:2048 -keyout domain.com.key -out domain.com.csr
# openssl x509 -req -in domain.com.csr -signkey domain.com.key -out domain.com.crt

En nginx comento las líneas que corresponderían al certificado de letsencrypt y añado los certificados autofirmados

        #ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem; # managed by Certbot
        #ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem; # managed by Certbot
        #include /etc/letsencrypt/options-ssl-nginx.conf;
        #ssl_trusted_certificate /etc/letsencrypt/live/domain.com/chain.pem;
        ssl_certificate /etc/autosigned-certs/domain.com/domain.com.crt;
        ssl_certificate_key /etc/autosigned-certs/domain.com/domain.com.key;

Tip del día.…

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 …

ip real con frontal proxy nginx, backend apache y wordpress

Por fin he encontrado la solución! otra de estas tareas pendientes que hacía que una instalación no funcionase como era esperado! en este caso me encuentro con dos frontales de nginx que actúan como proxy http y detrás de ellos está un wordpress sobre apache. Hace un tiempo, hice un post similar a éste, pero detrás estaba otro nginx.

Así que aquí dejo la solución.

Frontal nginx
En este caso tengo 2 ficheros, el de la configuración del dominio y otro con la configuración específica para los wordpress almacenado en el directorio snippets

# vi /etc/nginx/sites-available/lamardebits.org
server {
    listen 80;
    listen [::]:80;

    server_name lamardebits.org
                www.lamardebits.org;
    return 301 https://lamardebits.org$request_uri;

    #root /var/www/html/;
    include snippets/certbot.conf;
}


server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name lamardebits.org;

    include snippets/certbot.conf;

    # Aquí s'inclou el servidor intern i la protecció específica de WP
    include snippets/wordpress10.conf;

    ssl_certificate /etc/letsencrypt/live/lamardebits.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/lamardebits.org/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_trusted_certificate /etc/letsencrypt/live/lamardebits.org/chain.pem;
}

Y la configuración específica para los wordpress

# vi /etc/nginx/snippets/wordpress10.conf
include conf.d/external-log.conf;
location / {
    proxy_pass http://172.31.0.145:6081;
    include proxy_params;

    location ~ \.php$ {
        proxy_pass http://172.31.0.145:6081;
        include proxy_params;

        location ~* wp\-login\.php {
            client_max_body_size 40M;
            proxy_pass http://172.31.0.145:6081;
            include proxy_params;
            include snippets/lmdb-protected.conf;
        }
    }

    proxy_headers_hash_max_size 512;
    proxy_headers_hash_bucket_size 128;

    fastcgi_read_timeout 300;
    proxy_read_timeout 300;

    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Real-IP       $remote_addr;
    proxy_set_header  X-Forwarded-For $remote_addr;
    proxy_set_header  X-Forwarded-Host $remote_addr;

    add_header X-Frame-Options SAMEORIGIN;

}

La configuración de proxy de nginx la tengo así

# vi /etc/nginx/conf.d/proxy.conf
proxy_buffer_size         128k;
proxy_buffers           4 256k;
proxy_busy_buffers_size   256k;
client_max_body_size      32M;

proxy_read_timeout 1800;
proxy_connect_timeout 1800;
proxy_send_timeout 1800;
send_timeout 1800;             

Backend apache + wordpress

A …

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 …

Proxy apache con https

Cuando tienes pocas IPs y muchas maquinas una de las opciones que tienes para preservar IPs es usar proxy_http de apache, pero ¿qué ocurre cuando quieres proxyear conexiones https?

Lo lógico ha sido crear el certificado en la máquina que contiene el servicio bajo ssl, hasta aquí todo OK, pero se complicaba la cosa al tratar de hacerlo pasar por el servidor que hace de proxy apache.

Vamos a ver como lo he hecho, no es exactamente como quería, pero la cosa es que funciona :P

Para recopilar un poco y como ha habido cambios en la web startssl voy a poner el paso a paso, además que el post que tengo es un poco viejuno ya!…

Generar certificados válidos startssl en apache

Es importante que ciertas comunicaciones estén cifradas, para ello vamos a generar un certificado y lo vamos a verificar con la entidad certificadora startssl que nos permite validar certificados SSL. También podríamos hacer este paso sin validarlo en startssl, pero luego nos saldría cuando navegamos en el servidor que el certificado no es válido, pero la navegación sería segura igualmente.

Lo primero es generar los ficheros de certificado, el .csr, el .key y el .crt en nuestro servidor. Vamos a generar las claves para admin.sip.polaris.capa8.cat.

Verificaremos que tenemos instalado el paquete openssl, si no es así, lo instalamos:

root@polaris-pbx:~# apt-get install openssl

Nos iremos al directorio /etc/ssl/private y ahí generamos las claves…

Limitar el ancho de banda de apache

Cuando tienes un datacenter montado en casa, probablemente tengas una conexión con un ancho de banda de subida de mierda (hablando en claro hehe), así que cuando algún usuario se dedica a descargar algún vídeo o imagen un poco grande te encuentras que una sola instancia de apache hace que la red no funcione en absoluto, ya que para descargar, necesitas mandar datos a internet, pero como tienes la subida colapsada, la descarga no funciona.

Así que limitaremos el ancho de banda de subida para que así las peticiones de apache no causen problemas en nuestra conexión :)

Instalamos el módulo de apache libapache2-mod-bw

# apt-get install libapache2-mod-bw

Lo activamos

# a2enmod bw

Modificamos el virtualhost



#... el resto de cosas de este virtualhost

BandWidthModule On
ForceBandWidthModule On
BandWidth 192.168.1.0/24 0
BandWidth all 32000

32000 = 4Mbps, Mbps*100/8

Y reiniciamos apache

# service apache2 restart