security: harden traefik auth flow — fix header spoofing, TLS leak, DERP rate-limit
- Auth-proxy fallback now sets ALL X-authentik-* headers (username, uid, email, name, groups) to prevent client-supplied header spoofing when Authentik is down. Previously only username was set, allowing a malicious client to inject fake X-authentik-groups. - Catch-all IngressRoute restricted to *.viktorbarzin.me only. Non-matching domains no longer get the wildcard cert served (TLS info leak). - Added rate-limit and CrowdSec middleware to catch-all IngressRoute. - Added rate-limit middleware to Headscale DERP IngressRoute. - Rotated auth-proxy basicAuth credentials (bcrypt cost 5 → 12, admin → emergency-admin). - Created Authentik brute-force reputation policy (threshold -5, IP+username).
This commit is contained in:
parent
3d02036a18
commit
0e3c0fb503
3 changed files with 50 additions and 8 deletions
|
|
@ -324,11 +324,17 @@ resource "kubernetes_manifest" "derp_ingress_route" {
|
|||
name = kubernetes_service.headscale.metadata[0].name
|
||||
port = 8080
|
||||
}]
|
||||
# Only retry middleware — no CrowdSec, rate limit, anti-AI, error pages
|
||||
middlewares = [{
|
||||
name = "retry"
|
||||
namespace = "traefik"
|
||||
}]
|
||||
# Minimal middleware — retry + rate-limit. No CrowdSec/anti-AI (DERP is a relay protocol)
|
||||
middlewares = [
|
||||
{
|
||||
name = "retry"
|
||||
namespace = "traefik"
|
||||
},
|
||||
{
|
||||
name = "rate-limit"
|
||||
namespace = "traefik"
|
||||
},
|
||||
]
|
||||
}]
|
||||
tls = {
|
||||
secretName = var.tls_secret_name
|
||||
|
|
|
|||
|
|
@ -158,7 +158,9 @@ resource "kubernetes_manifest" "tlsstore_default" {
|
|||
depends_on = [helm_release.traefik, module.tls_secret]
|
||||
}
|
||||
|
||||
# Catch-all IngressRoute — serves 404 for unknown hosts (lowest priority)
|
||||
# Catch-all IngressRoute — serves 404 for unmatched *.viktorbarzin.me hosts (lowest priority)
|
||||
# Only matches *.viktorbarzin.me — non-viktorbarzin.me domains get TLS rejection (no matching router)
|
||||
# This prevents leaking the wildcard cert to attackers who point arbitrary domains at our IP
|
||||
resource "kubernetes_manifest" "ingressroute_catchall" {
|
||||
manifest = {
|
||||
apiVersion = "traefik.io/v1alpha1"
|
||||
|
|
@ -170,9 +172,13 @@ resource "kubernetes_manifest" "ingressroute_catchall" {
|
|||
spec = {
|
||||
entryPoints = ["websecure"]
|
||||
routes = [{
|
||||
match = "HostRegexp(`.+`)"
|
||||
match = "HostRegexp(`^(.+\\.)?viktorbarzin\\.me$`)"
|
||||
kind = "Rule"
|
||||
priority = 1
|
||||
middlewares = [
|
||||
{ name = "rate-limit", namespace = kubernetes_namespace.traefik.metadata[0].name },
|
||||
{ name = "crowdsec", namespace = kubernetes_namespace.traefik.metadata[0].name },
|
||||
]
|
||||
services = [{
|
||||
name = "error-pages"
|
||||
namespace = kubernetes_namespace.traefik.metadata[0].name
|
||||
|
|
|
|||
|
|
@ -494,9 +494,17 @@ resource "kubernetes_config_map" "auth_proxy_config" {
|
|||
location @fallback_auth {
|
||||
auth_basic "Emergency Access";
|
||||
auth_basic_user_file /etc/nginx/htpasswd;
|
||||
# Set ALL X-authentik-* headers to prevent client-supplied header spoofing.
|
||||
# Without this, a client could inject fake X-authentik-groups and backends
|
||||
# that trust these headers would grant elevated access.
|
||||
add_header X-authentik-username $remote_user always;
|
||||
add_header X-authentik-uid "" always;
|
||||
add_header X-authentik-email "" always;
|
||||
add_header X-authentik-name "" always;
|
||||
add_header X-authentik-groups "" always;
|
||||
add_header X-Auth-Fallback "true" always;
|
||||
return 200;
|
||||
root /usr/share/nginx/fallback;
|
||||
try_files /ok =403;
|
||||
}
|
||||
|
||||
location /outpost.goauthentik.io/ {
|
||||
|
|
@ -518,6 +526,17 @@ resource "kubernetes_config_map" "auth_proxy_config" {
|
|||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_config_map" "auth_proxy_fallback" {
|
||||
metadata {
|
||||
name = "auth-proxy-fallback"
|
||||
namespace = kubernetes_namespace.traefik.metadata[0].name
|
||||
}
|
||||
|
||||
data = {
|
||||
"ok" = "authenticated"
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_deployment" "auth_proxy" {
|
||||
metadata {
|
||||
name = "auth-proxy"
|
||||
|
|
@ -577,6 +596,11 @@ resource "kubernetes_deployment" "auth_proxy" {
|
|||
sub_path = "htpasswd"
|
||||
read_only = true
|
||||
}
|
||||
volume_mount {
|
||||
name = "fallback"
|
||||
mount_path = "/usr/share/nginx/fallback"
|
||||
read_only = true
|
||||
}
|
||||
|
||||
liveness_probe {
|
||||
http_get {
|
||||
|
|
@ -618,6 +642,12 @@ resource "kubernetes_deployment" "auth_proxy" {
|
|||
secret_name = kubernetes_secret.auth_proxy_htpasswd.metadata[0].name
|
||||
}
|
||||
}
|
||||
volume {
|
||||
name = "fallback"
|
||||
config_map {
|
||||
name = kubernetes_config_map.auth_proxy_fallback.metadata[0].name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue