Skip to main content

Evitar MFA en casa con Authentik


Introducción

Evitar que Authentik pida el segundo factor en casa, donde es una molestia constante. Se aplica solo bajo una IP fija, y sin comprometer la seguridad externa.


Características

  • Login sin MFA desde casa (o IP elegida).
  • Flujo normal para el resto del mundo.
  • Compatible con Cloudflare como proxy.
  • Logs limpios con IP y usuario reales.
  • Reversible en segundos.

Requisitos previos

  • IP pública fija o semiestable (por rango).
  • Caddy como reverse proxy.
  • Outpost de Authentik funcionando.
  • Dominio configurado en Cloudflare con API activa.

Flujo general

Navegador ─▶ Cloudflare ─▶ Caddy ─▶ Authentik Outpost ─▶ App
                 ▲ IP real via X-Forwarded-For     ▲
                 └─────────────────────────────────┘
  • Caddy extrae la IP real con {client_ip} y la pasa como cabecera.
  • Authentik la lee en ak_client_ip y salta el MFA si coincide con la IP marcada.

Caddyfile adaptado

Importante: este ejemplo solo aplica a aplicaciones que estén protegidas por Authentik. Si una app no utiliza Authentik como sistema de autenticación, este snippet no tendrá efecto sobre ella.

Antes de modificar nada, se recomienda hacer una copia de seguridad de tu Caddyfile actual. Por la naturaleza de los cambios (cabeceras, autenticación, DNS...), un error puede dejarte sin acceso a tus servicios.

Antes de modificar nada, se recomienda hacer una copia de seguridad de tu Caddyfile actual. Por la naturaleza de los cambios (cabeceras, autenticación, DNS...), un error puede dejarte sin acceso a tus servicios.

Ejemplo con datos falsos para documentar el flujo.

{
	email     ejemplo@dominio.com
	acme_dns  cloudflare "API_KEY_FAKE123"

	servers {
		trusted_proxies static private_ranges \
			203.0.113.0/24 198.51.100.0/24 192.0.2.0/24
	}
}

(authentik) {
	reverse_proxy /outpost.goauthentik.io/* http://10.0.0.3:15500

	forward_auth http://10.0.0.3:15500 {
		uri /outpost.goauthentik.io/auth/caddy

		copy_headers {
			X-Authentik-Username
			X-Authentik-Email
			X-Authentik-Groups
			X-Authentik-Name
			X-Authentik-Uid
		}

		header_up X-Real-IP   {client_ip}
		header_up X-Client-IP {client_ip}
	}
}

# Cada app que requiera autenticación debe seguir este mismo patrón.
# Primero importamos el snippet de Authentik, luego definimos el reverse_proxy de la app.

app.midominio.com {
	log {
		output file /var/log/caddy/app-access.log
		format transform "{request>headers>X-Forwarded-For>[0]:request>remote_ip} - {user_id} [{ts}] \"{request>method} {request>uri} {request>proto}\" {status} {size}" {
			time_format "02/Jan/2006:15:04:05 -0700"
		}
	}

	route {
		# 1) Llama al snippet que gestiona la autenticación
		import authentik

		# 2) Redirige a la app protegida
		reverse_proxy http://10.0.0.3:8080
	}
}

Policy en Authentik

  1. Expression Policy Nombre: Skip-Home-IP

    from ipaddress import ip_address
    return ak_client_ip == ip_address("203.0.113.42")
    
  2. Aplica la policy Ruta: Flows and Stages → Flows → default-authentication-flow → Stage Bindings → default-authentication-mfa-validation Bindea: la policy Skip-Home-IP Orden: 0 Negate: desactivado

Si tienes IP dinámica pero dentro de un rango:

from ipaddress import ip_network
return ak_client_ip in ip_network("203.0.113.0/24")

Verificación

Prueba Esperado
Desde casa Sin MFA.
Fuera de casa MFA/login normal.
Audit → Requests ALLOW (policy) y IP correcta en Client-IP.
caddy validate Configuración válida.

Ventajas

Qué Por qué
Sin MFA en casa Nada de abrir el móvil cada dos por tres.
IP real protegida trusted_proxies evita que te cuelen cabeceras falsas.
Mantenimiento mínimo Solo un snippet + una policy.
Logs decentes Se ve quién accedió, desde dónde, sin cosas raras.
Reversible fácil Borra la policy o el import, y listo.

Resumen breve

  • trusted_proxies + {client_ip} → IP real segura.
  • Policy de tipo Expression comparando ak_client_ip.
  • Todo controlado desde Caddy con un solo snippet.
  • Flujo transparente, sin MFA en casa pero con seguridad fuera.

Referencias

Caddy:

Authentik: