Security Headers not Working with Reverse Proxy?

1. My Caddy version (caddy version): v2, RC3

2. How I run Caddy: Docker

d. My complete Caddyfile or JSON config:

example.ca {
        file_server {
        root /mnt/welcome
        index index.html
        }
        tls email@example.ca
        import /config/caddy/caddy_security.conf
}

subdomain1.example.ca {
        reverse_proxy 10.10.2.10:80
        tls email@example.ca
        import /config/caddy/caddy_security.conf
        redir / "/word/#/tp"
}


subdomain2.example.ca {
        file_server {
        root /mnt/somefiles
        browse
        }
        tls email@example.ca
        import /config/caddy/caddy_security.conf
}

caddy_security.conf:

header / {
    Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
    X-Xss-Protection "1; mode=block"
    X-Content-Type-Options "nosniff"
    X-Frame-Options "DENY"
    Content-Security-Policy "upgrade-insecure-requests"
    Referrer-Policy "strict-origin-when-cross-origin"
    Cache-Control "public, max-age=15, must-revalidate"
    Feature-Policy "accelerometer 'none'; ambient-light-sensor 'none'; autoplay 'self'; camera 'none'; encrypted-media 'none'; fullscreen 'self'; geolocation 'none'; gyroscope 'none';       magnetometer 'none'; microphone 'none'; midi 'none'; payment 'none'; picture-in-picture *; speaker 'none'; sync-xhr 'none'; usb 'none'; vr 'none'"
    Server "No."

3. The problem I’m having:

Visiting securityheaders.io, example.ca and subdomain2.example.ca pass with A+, with a whole set of correctly set headers.
subdomain1.example.ca fails with an F, with not a single set header.
Now of course, the difference between example.ca and subdomain2.example.ca if that they serve static files, while subdomain1 is a reverse proxy. There must be something obvious I’m missing here, but I’ve been at it trying so many things for about 2 hours.

Any ideas would be appreciated!

edit: Aha, I did notice that by commenting out the redir, it passes with an A+ and all the headers are correctly set! So is the redir bypassing the headers? Input the full URL that the redir normally points to gives an F. I checked the other subdomains, and if I throw in a directory at the end of it they also fail too.

Adding a * after the header / resolved the issue. I believe this is a Caddy v1/v2 quirk.

header /* {
    Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
    X-Xss-Protection "1; mode=block"
    X-Content-Type-Options "nosniff"
    X-Frame-Options "DENY"
    Content-Security-Policy "upgrade-insecure-requests"
    Referrer-Policy "strict-origin-when-cross-origin"
    Cache-Control "public, max-age=15, must-revalidate"
    Feature-Policy "accelerometer 'none'; ambient-light-sensor 'none'; autoplay 'self'; camera 'none'; encrypted-media 'none'; fullscreen 'self'; geolocation 'none'; gyroscope 'none';       magnetometer 'none'; microphone 'none'; midi 'none'; payment 'none'; picture-in-picture *; speaker 'none'; sync-xhr 'none'; usb 'none'; vr 'none'"
    Server "No."
1 Like

Yes, this is indeed a difference between v1 and v2.

In v2, matches are assumed to be exact rather than path prefix. Asterisks are used to wildcard/prefix/suffix match.

You can also, however, entirely remove that matcher, e.g.

header {
  # Headers here
}
1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.