Issue: Using Cloudflare for 301 redirect does not work when origin host is pointed to Canva web hosting.
This was a simple job I got from a client where they needed a simple redirect on CloudFlare. Simple enough right? I’ve made this work plenty of times.
Tested This on https://dmarc.fun
Fast forward past the DNS migration to CF, we have the DNS in place. I have replicated the setup with my domain dmarc.fun pointing to my VPS on namecheap. Note: though the redirect rule is on, the domain is NOT proxied, so we do not expect the redirect to work (obviously)
Pointed to Namecheap , without CF proxy, the redirect is nowhere to be found Normal 200 OK response.
And, as expected, when CF proxy is enabled on the Namecheap A-record, the 301 redirect occurs as specified in my redirect rule in CF
Now, my client needed to point his domain to Canva to make his site active. So, we point it to Canva’s provided IP address, and we leave it un-proxied so Canva can verify the records and activate the website
So, Canva sees the records, the site goes active. All is well.
Here’s where it just gets weird. We turn on the proxy in CF, with the end goal of the 301 redirect. So the browser makes the request. But the 301 is not being served. Just a 200 OK to the Canva site.
I can even see the response is now coming from CloudFlare (104.21.0.224) instead of Canva (103.169.142.0). But Canva’s server response is somehow breaking my CloudFlare 301 redirect and forcing it to serve a 200 OK instead.
Here’s the breakdown of the faulty Cloudflare/Canva request/response
- Request URL: https://dmarc.fun/ (This is the URL of the requested resource)
- Request Method: GET (This is the HTTP method used for the request)
- Status Code: 200 OK (This is the HTTP status code returned by the server indicating that the request was successful)
- Remote Address: 104.21.0.224:443 (This is the IP address and port number of the server that the request was sent to)
- Referrer Policy: strict-origin-when-cross-origin (This is the referrer policy for the request, which controls how much referrer information should be included with requests made from the page)
REQUEST
- Authority: dmarc.fun (This header indicates the authority portion of the URL, in this case, it’s the domain name “dmarc.fun”)
- Method: GET (This header specifies the HTTP method used in the request, in this case, it’s a GET request)
- Path: / (This header specifies the path portion of the URL, in this case, it’s the root path)
- Scheme: https (This header specifies the protocol scheme used in the URL, in this case, it’s HTTPS)
- Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.7 (This header specifies the MIME types that the client can handle and their relative priorities)
- Accept-Encoding: gzip, deflate, br (This header indicates the encoding algorithms that the client can understand and accept)
- Accept-Language: en-US,en;q=0.9,mt;q=0.8,fr;q=0.7 (This header specifies the natural languages that the client can understand and their relative priorities)
- Cache-Control: no-cache (This header specifies directives for caching mechanisms in both requests and responses, in this case, it’s requesting not to use cache)
- Pragma: no-cache (This header is a backward-compatible header for specifying directives that must be obeyed by all caching mechanisms along the request-response chain)
- Sec-Ch-Ua: “Chromium”;v=”122″, “Not(A:Brand”;v=”24″, “Google Chrome”;v=”122″ (This header indicates the user-agent client hints for the request)
- Sec-Ch-Ua-Mobile: ?0 (This header indicates whether the user agent is in a mobile context)
- Sec-Ch-Ua-Platform: “Windows” (This header indicates the platform of the user agent)
- Sec-Fetch-Dest: document (This header indicates the destination of the fetch, in this case, it’s a document)
- Sec-Fetch-Mode: navigate (This header indicates the mode of the fetch, in this case, it’s navigating to a new browsing context)
- Sec-Fetch-Site: none (This header indicates the site type of the request, in this case, it’s none)
- Sec-Fetch-User: ?1 (This header indicates whether the request is initiated by a user gesture)
- Upgrade-Insecure-Requests: 1 (This header indicates that the client would like to access the resource over a more secure transport, such as HTTPS)
- User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 (This header identifies the client software and its version)
RESPONSE:
- Age: 10 (This header indicates how long the response has been cached by a proxy or intermediary, in this case, it’s 10 seconds old)
- Alt-Svc: h3=”:443″; ma=86400 (This header specifies alternative services for HTTP/3, indicating that the server supports HTTP/3 on port 443 and the alternative service should be cached for 86400 seconds)
- Cache-Control: public, max-age=30 (This header controls caching behavior, allowing public caches to cache the response for up to 30 seconds)
- Cf-Cache-Status: HIT (Cloudflare cache status is indicating that the response was served from the cache)
- Cf-Ray: 8740b9a18fc81357-ATL (This header is a Cloudflare-specific identifier for the request)
- Content-Encoding: br (This header specifies the content encoding used for the response, in this case, it’s Brotli compression)
- Content-Security-Policy: frame-ancestors ‘self’ *.canva.com canva.com; report-uri https://csp.canva.com/_cspreport?app=websites; base-uri ‘self’; object-src ‘none’; script-src ‘report-sample’ ‘strict-dynamic’ ‘nonce-9250de66-6b98-4b8a-9824-4a941d40e878’ https://www.google.com/recaptcha/api.js; (This header defines the content security policy for the page, specifying where various resources can be loaded from and where reports should be sent in case of violations)
- Content-Type: text/html (This header specifies the MIME type of the content, indicating it’s HTML)
- Date: Sun, 14 Apr 2024 03:49:17 GMT (This header indicates the date and time when the response was generated)
- Expect-Ct: max-age=86400, enforce (This header is used for Certificate Transparency, specifying that the browser should expect Certificate Transparency information for up to 86400 seconds and enforce it)
- Expires: Sun, 14 Apr 2024 03:49:47 GMT (This header indicates the date and time when the response expires and should no longer be considered fresh)
- Last-Modified: Sun, 14 Apr 2024 03:49:07 GMT (This header indicates the last modification date and time of the resource)
- Referrer-Policy: same-origin (This header controls how much referrer information should be included with requests made from the page, in this case, it’s restricted to the same origin)
- Server: cloudflare (This header indicates the server software being used, in this case, it’s Cloudflare)
- Strict-Transport-Security: max-age=31536000 (This header indicates that the browser should only access the site over HTTPS for the next 31536000 seconds, which is a year)
- Vary: Accept-Encoding (This header indicates the request header fields that can affect the response, in this case, it’s indicating that the response varies depending on the Accept-Encoding header)
- X-Content-Type-Options: nosniff (This header prevents browsers from MIME-sniffing a response away from the declared content-type)
- X-Deployment-Id: f02f0425081ba5aebffd554a7eab0658377d0eb0208515bd22f3c56dd791ce07 (This header is a deployment identifier)
- X-Frame-Options: SAMEORIGIN (This header indicates that the page can only be framed by pages from the same origin)
- X-Robots-Tag: none (This header indicates directives for search engine crawlers, in this case, it’s specifying no specific directives)
- X-Xss-Protection: 1; mode=block (This header enables the Cross-site scripting (XSS) filter built into most modern web browsers
What the hell?