Rewriting Cloudflare's requests to HTTPs

Hi,

Is it possible to auto-detect requests from CloudFlare and rewrite them so that they request HTTPs and not HTTP to prevent infinite redirects (mentioned here)?

Thanks very much.

What I do with cloudflare is put it in “full” crypto mode. So all requests from cloudflare to my server are over https.

I set up caddy to use the dns challenge to issue certs, or else it is much trickier to get working.

1 Like

Yes, putting it in Full or Strict mode works (or disabling the cloud feature).

However, we are serving the sites for our users and I was just wondering if we could create a workaround without them requiring to make any changes on their CloudFlare accounts.

You’ve got two options.

  1. Configure CloudFlare to use the correct scheme
  2. Configure Caddy to relax the scheme requirement

For the latter you will need to have a vhost in your Caddyfile that is configured explicitly for HTTP. You’d then want to duplicate the vhost and define the second as HTTPS.

To re-enable redirection for non-CloudFlare users (in case anyone is accessing your origin directly), you could use a redir with an if statement to check for the (non)existence of the CF-Connecting-IP header that CloudFlare will add when proxying requests.

1 Like

I have chosen to go with step2, yet couldn’t make it work.

My updated Caddfile is as:

    *.mydomain.com {
    	bind 71.161.64.153
    	proxy / 71.161.64.154:80 {
    		header_upstream Host {host}
    		header_upstream X-Real-IP {remote}
    		header_upstream X-Forwarded-For {remote}
    		header_upstream X-Forwarded-Proto {scheme}
    	}
    	tls { 
    		max_certs 10
    	}
    	redir 301 {
    		if {>X-Forwarded-Proto} is http
    		/  https://{host}{uri}
    	}
    }

I simply chose to rewrite all HTTP requests as HTTPs (rather than only Cloudflare) but that still ended in infinite redirect.

Am I missing a detail?

I think you might be misunderstanding a few key concepts regarding rewrite vs. redirect and how they apply to HTTP vs HTTPS.

Firstly, you can’t rewrite HTTP to HTTPS. Scheme is independent of the resource served by Caddy. To serve HTTPS, the client must make the connection via HTTPS. Rewriting is very different from redirection.

What a redirection does, is when someone connects to Caddy via HTTP, Caddy says “Nope, go away and come back via HTTPS.” CloudFlare doesn’t want to come back via HTTPS, so it keeps trying HTTP, ad nauseum. You will not be able to redirect CloudFlare from HTTP to HTTPS.

I repeat, if you want CloudFlare to access your HTTPS site, you must:

  1. Configure CloudFlare to access your site via HTTPS, OR;
  2. Configure your site to allow CloudFlare to access HTTP without being redirected

Secondly, I would not suggest the use of X-Forwarded-Proto. It’s not unique to CloudFlare, which is what you want to test for and why I suggested the CF-Connecting-IP header.

Thirdly, a duplicated vhost setup would have to look something like this:

http://*.mydomain.com {
    ...
    redir 301 {
        if {>CF-Connecting-IP} not_has .
        / https://{host}{uri}
    }
}

https://*.mydomain.com {
    ...
}

Ninja edit: corrected if statement from has to not_has as we want to redirect only when the client is NOT CloudFlare. There may be a better way to test but this is just a quick suggestion that should work.

2 Likes

Thanks very much for all the help and I believe that it is all clear now.

One last question though:

  • Rather than defining the same vhost twice for http and https, Is it possible to disable tls if the request is from CloudFlare.

Maybe a rule like:

*.mydomain.com {
	bind 71.161.64.153
	proxy / 71.161.64.154:80 {
		header_upstream Host {host}
		header_upstream X-Real-IP {remote}
		header_upstream X-Forwarded-For {remote}
		header_upstream X-Forwarded-Proto {scheme}
	}
	if {>CF-Connecting-IP} not_has .
	tls {max_certs 10}
	if {>CF-Connecting-IP} has .
	tls off
}

Sorry if I’m sounding illogical. Just new to that, trying to understand and appreciate the patience :).

I’m afraid not. You can’t disable TLS based on who’s connecting, as the client is the one who determines the protocol used to make a request to your server. There’s no mechanism to migrate between HTTP and HTTPS mid-request, and no function of the tls Caddy directive exists that you can use to instruct it to conditionally not issue redirects.

The behaviour you need - serve content over HTTP to CloudFlare clients, and serve redirects to HTTPS for non-CloudFlare clients - is incompatible with the default behaviour of Caddy’s automatic HTTPS. You must define a non-redirecting, explicit-HTTP vhost and then define your own redirection behaviour. The unfortunate side effect is that you must then duplicate some the content-specific configuration in another, explicit-HTTPS vhost for regular clients to use.

Unless I’m mistaken, this is the only way to achieve the behaviour you need.

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