I have an API on an AWS EC2 machine and want to use Cloudflare WAF as part of its protection. However there is little point in doing this if a hacker can access the IP address of the API server directly and avoid the WAF.
Cloudflare themselves acknowledge IP obfuscation should not be relied upon (https://support.cloudflare.com/hc/en-us/articles/200172646-Will-Cloudflare-hide-my-IP-online- ) to keep an IP hidden. Whitelisting Cloudflare IPs in the EC2 security group (AWS firewall) is not foolproof either as someone can just create a Cloudflare account (with no or a different WAF) and point it to my IP.
So it seems there is no way on my EC2 machine to be sure traffic has come via my Cloudflare WAF.
The way to fight this is to make sure your EC2 load balancer, or your backend web server only respond to the right HOST header (this can be achieved with Apache/httpd VirtualHost or a bogus default nginx server block). This also protects against XSS via cached host header (even though CF already protects against this now).
Once the above is set up, PLUS setting up your security group to only accept Cloudflare IPs, there should be no way to get around Cloudflare.
Cloudflare also has something like this - however, it’s a global CF Client certificate so just using this doesn’t mean a request came from your specific CF account.
This is just how HTTP works when you configure multiple websites on a server. Since each CF datacenter handles multiple websites, the Host header is the single thing which tells it what features to enable, the plan of the site, what origin IP to proxy, etc.
So if an attacker sets the Host header to your website, Cloudflare thinks it’s going right to your Cloudflare zone along with all the WAF rules you have set up in your account. If the Host header is their malicious website, it forwards that Host header to your server which then shows a default 403/404/etc page since the Host: header isn’t your website.
As for the article you linked, it’s only available to Enterprise customers, and for good reason. Each enterprise customer has a full contract with Cloudflare stating that they won’t intentionally try to harm other customers’ websites, so if someone really attempted to purchase enterprise just to attack a website, Cloudflare could investigate and take them to court for breach of contract and potentially report them for computer misuse.
here’s also a good reason by CF staff for why Cloudflare doesn’t allow the Host header to be changed via workers:
I was thinking of the case where an attacker set up a Cloudflare account for evil-dot-com and then supplied an absolute URL based on evil-dot-com but gave a HOST header based on example.com to defeat HOST header filtering on AWS backend for example.com. My understanding is that when an absolute URL and HOST header are in conflict the absolute URL is used (see e.g. wcf - Can the Host Header be different from the URL - Stack Overflow ). Thus the request would go to the evil-dot-com Cloudflare account not the example.com Cloudflare account whose WAF would be avoided.
But I think what your answer and link suggests is that Cloudflare would not allow through a request with conflicting absolute URL and HOST header except for trusted enterprise customers.
Is this correct?
I would still be much more comfortable with certificate-based proof-of-source. If someone from Cloudflare is reading this, please implement such a feature.
So it sounds like you want something like Authenticated Origin Pulls, but with a unique certificate for your domain. I don’t expect that would be free, since that certificate needs to be distributed across all datacenters.