Cómo Configurar Login con Office 365 (Microsoft Entra ID) en Authentik

Como ya vimos en la anterior entrada es bastante sencillo instalar un sistema SSO como authentik en nuestra infraestructura. De todas formas, crear un login centralizado no es más que una manera de tener que recordar menos contraseñas, pero el objetivo final es no tener que recordar más que unas pocas para poder acceder a todos los servicios, ¿qué hacemos si ya tenemos cuenta en alguno de los servicios más populares como office 365 o google? Lo suyo sería poder hacer login con estas credenciales en cualquier servicio, sea online o sea auto hospedado. Por suerte, authentik puede hacer uso de estos servicios externos de autenticación de manera «relativamente» sencilla. En este post os voy a explicar paso a paso (que sobre todo la parte a realizar con office es un poco liosa) cómo integrar el login de office 365 con authentik y así poder usarlo para acceder a nuestras aplicaciones (eso ya lo explicaremos en próximos posts).

Para poder realizar este tutorial debes tener:

  • Servidor authentik instalado y configurado (con acceso como administrador)
  • Cuenta de administrador office365 de tu organización
  • Un poco de paciencia (esto nunca viene mal)

Paso 1: registrar una aplicación de microsoft entra

Entramos como administrador en portal.office.com

Pedimos que nos muestre todas las opciones (estos de MS suelen ocultarnos cosas)

Seleccionamos la opción Identidad (nos llevará a entra)

Seleccionamos la opción Registro de aplicaciones

Y seleccionamos Nuevo registro

Y rellenamos los datos básicos (yo voy a llamar authentik a la nueva aplicación)

Hemos elegido que solo se pueda entrar con cuentas de nuestra organización, que será lo normal, aunque si queremos que cualquiera que tenga una cuenta de office365 pueda hacer logn tendremos que escoger una de las otras opciones. Atento a la ui de redirección, en principio tendrá el formato https://<direccion-de-tu-authentik>/source/oauth/callback/<nombre-de-fuente> Si no lo configuras ahora lo podrás hacer después cuando termines la configuración en authentik.

Anotamos los datos que vamos a necesitar de la aplicación y creamos un nuevo secreto:

Es muy importante que copiemos el valor del secreto que lo vamos a necesitar luego

El valor del secreto no se va a poder copiar en otro momento, mejor que lo guardes ahora.

Con esto hemos terminado (en principio) con la configuración necesaria en el portal de office. Lo que hemos hecho, básicamente, es configurar los endpoints de oauth2 que podemos consultar en la opción.

Paso 2: crear un nuevo login social

Las siguientes acciones las haremos como administrador en nuestro servidor authentik

El primer paso es crear un inicio de sesión federado

del tipo azure AD

Ahora deberemos introducir todos los datos que hemos guardado al crear la aplicación en entra:

Los endpoint serán como estos (revisar los que vimos en la pantalla del portal de office):

Cambiaremos la URL del perfil a https://graph.microsoft.com/oidc/userinfo

Y damos a terminar por ahora. Esto nos configura el método para entrar usando las credenciales de Microsoft, pero todavía nos falta un par de cosas para que sea útil del todo.

Paso 3: mapeo de atributos

Ahora necesitamos hacer la equivalencia entre los atributos que vienen de office con los que nosotros vamos a utilizar en nuestro directorio, para eso crearemos una política de expresión:

La llamamos (por ejemplo) azure-ad-mapping y ponemos este contenido:

# save existing prompt data
current_prompt_data = context.get('prompt_data', {})
# make sure we are used in an oauth flow
if 'oauth_userinfo' not in context:
  ak_logger.warning(f"Missing expected oauth_userinfo in context. Context{context}")
  return False
oauth_data = context['oauth_userinfo']
# map fields directly to user left hand are the field names provided by
# the microsoft graph api on the right the user field names as used by authentik
required_fields_map = {
  'name': 'username',
  'email': 'email',
  'given_name': 'name'
}
missing_fields = set(required_fields_map.keys()) - set(oauth_data.keys())
if missing_fields:
  ak_logger.warning(f"Missing expected fields. Missing fields {missing_fields}.")
  return False
for oauth_field, user_field in required_fields_map.items():
  current_prompt_data[user_field] = oauth_data[oauth_field]
# Define fields that should be mapped as extra user attributes
attributes_map = {
  'name': 'upn',
  'sub': 'sn',
  'name': 'name'
}
missing_attributes = set(attributes_map.keys()) - set(oauth_data.keys())
if missing_attributes:
  ak_logger.warning(f"Missing attributes: {missing_attributes}.")
  return False
# again make sure not to overwrite existing data
current_attributes = current_prompt_data.get('attributes', {})
for oauth_field, user_field in attributes_map.items():
  current_attributes[user_field] = oauth_data[oauth_field]
current_prompt_data['attributes'] = current_attributes
context['prompt_data'] = current_prompt_data
return True

Paso 4: configurar el flujo de alistamiento

Queremos que cualquiera que tenga cuenta en el dominio office pueda entrar a nuestras aplicaciones, por lo que necesitamos registrar los usuarios nuevos cuando entran por primera vez, para ello vamos a crear uun flujo nuevo.

Le ponemos un nombre

Y una vez creado, editarlo, ir a la sección d Vinculaciones de Políticas / Grupos / Usuarios y ahí a Bind existing policy

Y ahí ligar defaultsource-enrollment-if-sso

Ir ahora a vinculos de etapa -> Bind Existing stage

Añadir default-source-enrollment-write (orden 0) y default-source-enrollment-login (orden 10)

Desplegar luego la etapa con orden cero y añadir una política existente azur-ad-mapping que creamos antes:

Por último editarmos la fuente que creamos al principio (Directory -> Federation ..) y le añadimos en la configuración de flujo el flujo de inscrpción a azure-ad-enrollment (o el nombre que le hayamos puesto)

Paso 5: hacer que se vea en el login

Pues ya solo nos faltaría hacer que aparezca una opción para hacer login con este proveedor, esto se hace editando el flujo default-authentication-flow

Y editas la etapa

Y añades desde las fuentes disponibles a Fuentes seleccionadas

Ahora cuando entres en tu authentik ya te aparecerá la opción nueva para acceder. La primera vez que accedas debes aprobar unos permisos especiales a Microsoft:

Ha sido un proceso un poco largo, pero ahora ya tenéis centralizada la información de seguridad y cualquier aplicación que pueda conectarse a authentik podrá usar los usuarios de nuestro dominio… Ahora queda que lo probéis vosotros.

Instala tu propio servidor SSO (Single Sing-On)

Es posible que, como nosotros, ester harto de tantas contraseñas y tantas veces que tienes que autenticarte para acceder a tus aplicaciones. Nosotros ya inventamos nomorepass para no tener que andar recordando la contraseñas, pero eso no quita a que cada vez que instalamos un nuevo sistema en nuestro laboratorio personal nos toque volver a lidiar con las credenciales de acceso. Hay veces que intentamos centralizarlo en algún proveedor externo (como google o microsoft), pero esto no es del todo seguro y corremos el riesgo de tener que andar configurando nuestras aplicaciones con credenciales que, como las de Microsoft Hello caducan cada cierto tiempo.

Por eso os propongo algo mejor, ¿porqué no hospedar nosotros nuestro propio sistema de autenticación? En este post vamos a ver como instalar y configurar uno de los más populares y potentes sistemas SSO: Authentik. La instalación es bastante sencilla y está bien explicada en su documentación. Os resumo cómo quedaría la cosa. Necesitamos:

  • Servidor donde instalarlo (2VCPU / 2Gb memoria mínimo)
  • Docker y docker compose (v2 mejor)
  • wget y openssl instalado (necesarios solo para la instalación)

Una vez que tenemos el servidor con docker y docker compose instalado nos descargamos la plantilla:

wget https://goauthentik.io/docker-compose.yml

Y generamos los elementos de seguridad necesarios y los guardamos en el archivo .env

echo "PG_PASS=$(openssl rand -base64 36 | tr -d '\n')" >> .env
echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 60 | tr -d '\n')" >> .env

Con esto ya podemos arrancar el servidor. Hay cosas que sería recomendable configurar, como la salida de email, bien con un servidor propio, o podéis utilizar cualquier servicio que os ofrezca smtp. También se puede cambiar el puerto por el que se accede, que generalmente está en el 9000/9443 para cambiarlos a los estándar 80/443. Como ejemplo os dejo mi docker-compose y mi .env (cambiando las cosas privadas, claro):

services:
  postgresql:
    image: docker.io/library/postgres:16-alpine
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
      start_period: 20s
      interval: 30s
      retries: 5
      timeout: 5s
    volumes:
      - database:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: ${PG_PASS:?database password required}
      POSTGRES_USER: ${PG_USER:-authentik}
      POSTGRES_DB: ${PG_DB:-authentik}
    env_file:
      - .env
  redis:
    image: docker.io/library/redis:alpine
    command: --save 60 1 --loglevel warning
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
      start_period: 20s
      interval: 30s
      retries: 5
      timeout: 3s
    volumes:
      - redis:/data
  server:
    image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.2.4}
    restart: unless-stopped
    command: server
    environment:
      AUTHENTIK_REDIS__HOST: redis
      AUTHENTIK_POSTGRESQL__HOST: postgresql
      AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
      AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
      AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
    volumes:
      - ./media:/media
      - ./custom-templates:/templates
    env_file:
      - .env
    ports:
      - "${COMPOSE_PORT_HTTP:-9000}:9000"
      - "${COMPOSE_PORT_HTTPS:-9443}:9443"
    depends_on:
      postgresql:
        condition: service_healthy
      redis:
        condition: service_healthy
  worker:
    image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.2.3}
    restart: unless-stopped
    command: worker
    environment:
      AUTHENTIK_REDIS__HOST: redis
      AUTHENTIK_POSTGRESQL__HOST: postgresql
      AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
      AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
      AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
    user: root
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./media:/media
      - ./certs:/certs
      - ./custom-templates:/templates
    env_file:
      - .env
    depends_on:
      postgresql:
        condition: service_healthy
      redis:
        condition: service_healthy

volumes:
  database:
    driver: local
  redis:
    driver: local

.env:

PG_PASS=<esto-lo-tienes-que-generar>
AUTHENTIK_SECRET_KEY=<esto-lo-generas-tambien>
AUTHENTIK_ERROR_REPORTING__ENABLED=true
# SMTP Host Emails are sent to
AUTHENTIK_EMAIL__HOST=mail.biblioeteca.net
AUTHENTIK_EMAIL__PORT=587
[email protected]
AUTHENTIK_EMAIL__PASSWORD=<el que sea>
AUTHENTIK_EMAIL__USE_TLS=false
AUTHENTIK_EMAIL__USE_SSL=false
AUTHENTIK_EMAIL__TIMEOUT=10
[email protected]
AUTHENTIK_TAG=2025.6.2

Si todo hay ido bien ya puedes arrancarlo:

docker compose up -d

Y ya puedes empezar a configurar tu nuevo SSO navegando a la página:

http://<IP servidor>:9000/if/flow/initial-setup/

Con esto ya tenemos un sistema que nos permite hacer login con los usuarios que queramos… ¿Qué más podemos hacer con este sistema?… Pues un montón de cosas. Quedaos atentos y en los siguientes posts os enseñaré como hacer cosas interesantes como conectar con sistemas externos (como office365 o google) y hacer uso de esas credenciales.

Monta una conexión de respaldo en opnsense

Esta semana pasada he sufrido la experiencia traumática de tener que mudarme de oficina… El casero ha dicho que no renueva el contrato y no me ha quedado más remedio que mudarme (con 14 años de trastos a mis espaldas) a otra oficina diferente… Y, aunque no soy muy tiquismiquis hay una cosa que siempre necesito… Internet.

Tengo contratado masmovil desde hace muchos años, 1Gb de fibra y una IP fija, cosas que me vienen muy bien para el tipo de cosas que tengo que hacer, y quiero seguir manteniendo estas cosas (y el número de teléfono que viene asociado a la conexión), así que indiqué a Masmovil el día del traslado y me confirmaron que ese mismo día pasaría por la nueva oficina un instalador a realizar el paso de mi conexión a esa nueva oficina.

Ahora bien, resulta que la dirección estaba mal registrada o que habían separado en oficinas lo que antes era solo un edificio o que-se-yo, el caso es que solo daba servicio movistar y el primer instalador me dijo que solicitaban el cambio y que ya me avisarían cuando estuviese la cosa. Al día siguiente me vino otro instalador que me dejó todo correctamente instalado perjurando que el instalador anterior podía haberlo hecho el otro día sin problemas (en fin…) al cabo de unos minutos ya tenía otra vez mi IP fija y mi casi-1g con los que he estado funcionando hasta ayer.

Ayer los vecinos llamaron a su instalador de movistar porque no tenían conexión y resulta que lo que pasaba es que ellos estaban (vete tu a saber porqué) enchufados a la roseta que estaba en mi oficina y, claro, al cambiarla yo el cable que iba a su router ya no estaba conectado (ni la conexión activa)… El caso es que el instalador se encabronó con el tema de tener que tirar ellos el cable otra vez (ya me dirás qué tendrían que hacer si no había fibra que llegase a esa oficina) y no se lo que hizo que me dejó a mi sin conexión (y estoy seguro que algo podría haber hecho para mantenerla). El caso es que llevo desde ayer a medio día sin conexión a internet. Puse la incidencia, me dijeron que era cosa de fuera y que ya lo arreglarían (hace más de 28 horas de eso)… Y como yo tengo que trabajar pues no me ha quedado más remedio que usar un router 4G que tenía por aquí y contratar una SIM con gigas para poder tener algo de internet mientras tanto.

Como la wifi solo la puedo usar desde móviles y portátiles y yo quería usar mi torre (y tener conectividad en general) me puse a ver si era sencillo poner esa conexión como fallback en el router opnsense que monté con un ordenador chino (bastante bueno y con dos puertos SFP+ que me permiten llegar a 10Gb)… Y si, después de penar un poco (porque hay cosas que no están bien pulidas del todo) conseguí hacerlo funcionar. Estos son los pasos que di:

1.- Enchufar el router 4G a la salida ethernet que tenía libre mi ordenador-router (os pongo la foto de uno parecido)

En eth0 estaba el router de masmovil configurando este como DMZ para poder recibir el tráfico entrante y en eth1 la nueva conexión.

En SPF0 tenía conectado el router del resto de mi red.

2.- En opnsense doy de alta el interfaz nuevo (en este caso por dhcp)

3.- En System > gateways > configuration creo un gateway nuevo, le digo que active la monitorización del gateway y le pongo la IP de un servidor dns fiable (como 8.8.4.4) y le pongo como IP la IP del router 4G (192.168.0.1 en mi caso).

4.- El gateway existente lo modifico para habilitar el monitoreo y añado como IP la 8.8.8.8 (puede ser cualquiera mientras sea diferente de la anterior)

5.- En system > settings > general añado estos dos DNS como DNS Servers y les asocio a cada uno el gateway correspondiente y activo la opción «Allow default gateway switching»

6.- En System > gateway > group creo un grupo nuevo, le pongo un nombre y hago que el interfaz de la WAN principal sea Tier1 y de la secundaria Tier2, ponemos Trigger Level a «Packet Loss or high latency» y una descripción adecuada (yo también puse Pool Options a Round Robin, pero eso no es tan importante)

7.- En Firewall > rules > LAN (o como llaméis a vuestro interfaz de red local) modificamos la configuración de la regla genérica que permite todo para indicar que el gateway será el nuevo grupo que acabamos de crear

8.- Por último, y esto lo he descubierto después de mucho tiempo, la generación automática de reglas NAT > Outbound no es perfecta y tuve que añadir una regla para que permitiese todo el tráfico desde la WAN2 indicando que su dirección de NAT sería la de WAN2

Y, en principio, esto es todo… Haced vuestras pruebas de ping, mtr y demás y veréis que cuando está caída la conexión principal saldréis a internet por la secundaria… Espero que masmovil me lo arregle pronto que los GB de la tarjeta sim ya se me están gastando. Grrr.

Usando GPU en Proxmox

Quizá todavía no lo conceis, pero Proxmox es el software definitivo si queréis montar vuestra propia infraestructura en casa (o en vuestra empresa), es un hypervisor que os permite tener vuestra propia «nube» creando máquinas virtuales, contenedores y gestionando almacenamiento, backups y alta disponibilidad.

Yo llevo unos meses con esto, desde que me compré y quise dar uso, unas placas chinas para aprovechar los Xeon de segunda mano que ahora se encuentran tan baratos y, la verdad, es como tener un AWS particular (salvando muuuuchas diferencias). El caso es que lo único que me quedaba por probar era cómo tener una máquina virtual controlada por proxmox que me permitiese hacer AI… Pero para eso necesitaba usar una GPU y esto no es taaan sencillo. Así que partamos de un servidor que tiene una tarjeta gráfica (en mi caso una RTX 3070) y veamos cómo configurar el ordenador para meterlo en un cluster proxmox estando preparado para tener VMs que usen esa GPU.

¿cual es el problema realmente?

El problema es que un hypervisor lo que hace es ejecutar máquinas virtuales a las que ha asignado cierta parte de sus recursos (disco, memoria, etc) y permitir el uso compartido de todo lo que se puede compartir. Por desgracia la GPU no se puede compartir de la misma manera que una CPU (hay algunos modelos que tienen una tecnología que se llama VGPU que parece que si permitirán hacerlo, pero por ahora las que tengo yo no). Es por eso que lo que se hace es pasarle a la máquina virtual todo el bus PCI en cuestión para que lo gestione de manera independiente. Para que esto se pueda llevar a cabo es importante que el SO de proxmox no esté usando este bus para nada (que no tenga los drives instalados siquiera). El servidor que yo he usado tenía video integrado y configuré la bios para que usase ese como video primario (y así instalé proxmox sin utilizar la tarjeta gráfica). Pasos importantes con la BIOS:

  • Activar la tarjeta integrada (si la tiene)
  • Activar todos los modos de multihilo VT-d y cualquier referencia a IOMMU

Dejo un enlace que lo explica para varias placas base.

Lo siguiente, desde el servidor con ya proxmox instalado será editar el arranque de grub poniendo lo siguiente en el archivo /etc/default/grub:

GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt"

Y ejecuta después update-grub, tras lo cual tendrás que reiniciar la máquina.

Para comprobar que está todo activo ejecuta este comandos:

dmesg | grep -e DMAR -e IOMMU

El resultado tendría que ser algo como esto:

[    0.008366] ACPI: DMAR 0x000000007A29ED38 0000A8 (v01 INTEL  EDK2     00000002      01000013)
[    0.008390] ACPI: Reserving DMAR table memory at [mem 0x7a29ed38-0x7a29eddf]
[    0.098662] DMAR: IOMMU enabled
[    0.255710] DMAR: Host address width 39
[    0.255711] DMAR: DRHD base: 0x000000fed90000 flags: 0x0
[    0.255721] DMAR: dmar0: reg_base_addr fed90000 ver 1:0 cap 1c0000c40660462 ecap 19e2ff0505e
[    0.255723] DMAR: DRHD base: 0x000000fed91000 flags: 0x1
[    0.255727] DMAR: dmar1: reg_base_addr fed91000 ver 1:0 cap d2008c40660462 ecap f050da
[    0.255728] DMAR: RMRR base: 0x00000079d2f000 end: 0x00000079d4efff
[    0.255731] DMAR: RMRR base: 0x0000007b800000 end: 0x0000007fffffff
[    0.255733] DMAR-IR: IOAPIC id 2 under DRHD base  0xfed91000 IOMMU 1
[    0.255734] DMAR-IR: HPET id 0 under DRHD base 0xfed91000
[    0.255735] DMAR-IR: Queued invalidation will be enabled to support x2apic and Intr-remapping.
[    0.257485] DMAR-IR: Enabled IRQ remapping in x2apic mode
[    0.600499] DMAR: No ATSR found
[    0.600500] DMAR: No SATC found
[    0.600501] DMAR: IOMMU feature fl1gp_support inconsistent
[    0.600502] DMAR: IOMMU feature pgsel_inv inconsistent
[    0.600503] DMAR: IOMMU feature nwfs inconsistent
[    0.600504] DMAR: IOMMU feature pasid inconsistent
[    0.600505] DMAR: IOMMU feature eafs inconsistent
[    0.600506] DMAR: IOMMU feature prs inconsistent
[    0.600507] DMAR: IOMMU feature nest inconsistent
[    0.600508] DMAR: IOMMU feature mts inconsistent
[    0.600509] DMAR: IOMMU feature sc_support inconsistent
[    0.600509] DMAR: IOMMU feature dev_iotlb_support inconsistent
[    0.600510] DMAR: dmar0: Using Queued invalidation
[    0.600513] DMAR: dmar1: Using Queued invalidation
[    0.600990] DMAR: Intel(R) Virtualization Technology for Directed I/O

Donde lo relevante es el IOMMU enabled y Enabled IRQ remmaping. Si todo está ok podemos ver os grupos iommu con este comando:

pvesh get /nodes/pascal/hardware/pci --pci-class-blacklist ""

Que nos debería dar una salida como la siguiente:

??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
? class    ? device ? id           ? iommugroup ? vendor ? device_name                                                                             ? mdev ? su
??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
...
?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
? 0x030000 ? 0x2484 ? 0000:01:00.0 ?          2 ? 0x10de ? GA104 [GeForce RTX 3070]                                                                ?      ? 0x
??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

Ahora nos falta asegurarnos de que proxmox no va a utilizar esta gpu y estaríamos casi listos para crear nuestra vm:

echo "options vfio_iommu_type1 allow_unsafe_interrupts=1" > /etc/modprobe.d/iommu_unsafe_interrupts.conf
echo "vfio" >> /etc/modules
echo "vfio_iommu_type1" >> /etc/modules
echo "vfio_pci" >> /etc/modules
update-initramfs -u -k all
systemctl reboot

Comprobaremos que se carga vfio y pondremos en lista negra los drivers de nuestra gpu

dmesg | grep -i vfio
echo "options kvm ignore_msrs=1 report_ignored_msrs=0" > /etc/modprobe.d/kvm.conf
lspci -nn | grep 'NVIDIA'

Veremos los ids de nuestro dispositivo

01:00.0 VGA compatible controller [0300]: NVIDIA Corporation GA104 [GeForce RTX 3070] [10de:2484] (rev a1)
01:00.1 Audio device [0403]: NVIDIA Corporation GA104 High Definition Audio Controller [10de:228b] (rev a1)

Y los usaremos para ponerlos en lista negra para los drivers posibles:

echo "options vfio-pci ids=10de:2484,10de:228b" >> /etc/modprobe.d/vfio.conf
echo "blacklist nouveau" >> /etc/modprobe.d/blacklist.conf
echo "blacklist nvidia" >> /etc/modprobe.d/blacklist.conf
echo "blacklist nvidiafb" >> /etc/modprobe.d/blacklist.conf
echo "blacklist nvidia_drm" >> /etc/modprobe.d/blacklist.conf
systemctl reboot

Y con esto ya está listo nuestro proxmox para compartir el PCI… Os recomiendo que si vais a unirlo a un cluster lo hagáis ahora, luego si creais una vm os va a ser más complicado. En cualquier caso, lo que queda es crear una máquina virtual y añadirle el pci de la tarjeta.

Para ello simplement creamos una máquina virtual, en mi caso digo que voy a instalar un linux y antes de arrancarla vamos al apartado de hardware y añadimos estos PCI:

Una vez arrancada la máquina e instalado el sistema operativo podemos comprobar si tenemos los drivers de nvida configurados ejecutando nvidia-smi

Así que ya tenemos una máquina con GPU para poder ejecutar nuestros trabajos de AI. Para ello podéis seguir estas instrucciones para instalar ollama o stable difussion en esta máquina virtual… Con la ventaja que aporta tenerlo controlado por Proxmox para hacer backups arrancarlo o pararlo a voluntad, monitorizarlo, etc.

Movistar Bloquea Cloudflare: Impacto en Webs y Solución

Aunque pareciese que no tiene nada que ver una cosa con otra, lo que es cierto es que estas últimas semanas han ido ligadas de la mano, pero de la manera mala. Dejadme que me explique.

El caso es que una de las aplicaciones que mantenemos empezó en un momento dado a recibir incidencias como si estuviese caída. El servidor estaba bien y yo desde mi oficina llegaba perfectamente, después de mucho indagar descubirmos que no se llegaba desde las conexiones Movistar u O2, además, lo que vimos es que había ya quejas de otros servidores que estaban afectados y solo tenían en común una cosa, que estaban detrás de Cloudflare. La cosa es que media internet utiliza los servicios de cloudflare, como CDN o como protección contra ataques DDOS o como proxy para ahorrar ancho de banda. Entendimos que debía ser un problema de enrutamiento de Movistar y desactivamos cloudflare momentaneamente a la espera de que lo solucionasen… Estamos hablando del día 3 de febrero.

Esto estuvo pasando durante toda la tarde, llegado un momento nos dijeron que ya volvía a funcionar (y que todo debería ser una avería, no nos dijeron otra cosa)

Peeero, casualidades de la vida, el día 8 se jugaba el derbi y, mira por donde, resulta que empezamos a recibir incidencias de nuevo… Vuelta a desactivar cloudflare y esperando de nuevo… Pero esta vez no lo arreglaron, el domingo seguía la cosa igual:

Y esto se quedó así hasta el lunes (qué curioso!) sin que nadie se dignase dar ninguna explicación ni disculpa. Miles de negocios perdidos y webs expuestas a ataques sin remedio por alimentar a las alimañas del deporte. Era tan evidente que ya se publicó como noticia en varios medios (https://hipertextual.com/2025/02/movistar-cloudflare-futbol). El caso es que estuvo funcionando bien hasta los partidos de champions en los que se repitieron cortes de 15 minutos alternos (igual esto había cantado demasiado).

¿Qué hacer?

Ahora nos surge el problema de qué hacer el fin de semana. No podemos irnos a descansar porque si nos vuelven a cortar cloudflare tendríamos que volver a desactivarlo a mano, así que, para todos aquellos que tengáis cloudflare os recomiendo usar algo como esto:

import requests
import subprocess
import os

def check_ip_reachable(ip):
    try:
        result = subprocess.run(['ping', '-c', '4', ip], capture_output=True, text=True, timeout=10)
        return result.returncode == 0
    except subprocess.TimeoutExpired:
        return False

def pause_cloudflare(domain, email, api_key):
    headers = {
        'X-Auth-Email': email,
        'X-Auth-Key': api_key,
        'Content-Type': 'application/json'
    }
    
    # Obtener el Zone ID
    zone_response = requests.get(f'https://api.cloudflare.com/client/v4/zones?name={domain}', headers=headers)
    zone_data = zone_response.json()
    
    if not zone_data['success']:
        print("Error al obtener el Zone ID")
        return False
    
    zone_id = zone_data['result'][0]['id']
    
    # Pausar el servicio
    pause_url = f'https://api.cloudflare.com/client/v4/zones/{zone_id}'
    pause_data = {'paused': True}
    
    response = requests.patch(pause_url, headers=headers, json=pause_data)
    result = response.json()
    
    if result['success']:
        print(f"Servicio pausado para el dominio {domain}")
        return True
    else:
        print(f"Error al pausar el servicio: {result['errors']}")
        return False

# Configuración
ip_to_check = "192.168.1.1"  # Reemplaza con la IP que quieres comprobar
domain = "ejemplo.com"  # Reemplaza con tu dominio
cloudflare_email = "[email protected]"  # Reemplaza con tu email de Cloudflare
cloudflare_api_key = "tu_api_key"  # Reemplaza con tu API key de Cloudflare

# Comprobar si la IP está accesible
if not check_ip_reachable(ip_to_check):
    print(f"La IP {ip_to_check} no está accesible. Pausando el servicio en Cloudflare...")
    if pause_cloudflare(domain, cloudflare_email, cloudflare_api_key):
        print("Servicio pausado exitosamente")
    else:
        print("No se pudo pausar el servicio")
else:
    print(f"La IP {ip_to_check} está accesible")

Este programita básicamente lo que hace es comprobar si una IP responde al ping y si no lo hace pone en pausa cloudflare para el dominio que queramos. Para ello solo hay que configurarlo con la IP, el dominio y los datos del API de cloudflare de nuestra cuenta. Lo recomendable es hacer un bucle que lo chequee cada cierto tiempo y (código que todavía no he hecho) que cuando vuelva la conectividad se vuelva a activar cloudflare.

Para mi estas actuaciones son completamente ilegales y atentan contra la neutralidad de la red. ¿Qué será lo siguiente? ¿Evitar que visitemos blogs de ideologías no aprobadas?, ¿Hacer inaccesible el porno? Por desgracia en mi casa usamos O2, pero igual tengo que cambiarme visto lo visto.