Why CloudFlare’s Flexible SSL Setting Is Unsafe

CloudFlare Universal SSL is getting more webmasters on board with encrypting the entire Internet than ever — and that’s a good thing. But it’s important to understand the technical characteristics of CloudFlare’s free shared SSL certificate, and its limitations. As we interact with our clientele, it has become clear that the differences between CloudFlare SSL and an ordinary SSL certificate can be confusing. Alarmingly we see many customers using the default SSL settings “Flexible” or “Full” instead of “Full (Strict)”, meaning hackers can potentially listen into the traffic between CloudFlare and your origin server. Read on to check whether you’re vulnerable and how to fix this.

The main purpose of CloudFlare isn’t to “encrypt your website” — their service is first-and-foremost a content delivery network (CDN) caching copies of your web pages at edge locations around the world to accelerate page load times for visitors. Universal SSL is a feature that CloudFlare launched later to simplify the move from HTTP to HTTPS for domains pointed to its nameservers.

Some cybersecurity experts criticize CloudFlare Universal SSL for aiming to “man in the middle” the entire Internet, and therefore discourage using the CDN. We’ll look behind these experts’ reasoning and leave it up to you to decide.

It’s true using CloudFlare Universal SSL (or CloudFlare at all) requires placing an inherent degree of trust in CloudFlare to handle the information that’s transmitted to and from your website. When CloudFlare serves an HTTPS site, it requires knowledge of the private key for the certificate that’s presented to the visitor’s browser.

With a free CloudFlare account, the only option is a shared SSL certificate issued by Comodo through your CloudFlare dashboard. A shared certificate isn’t inherently less secure than a dedicated certificate, but if an inquisitive user were to inspect the CloudFlare Universal SSL certificate, they might find it odd that the Common Name lists domains unrelated to your organization.

CloudFlare Free Shared SSL Common Names

For paying CloudFlare customers on the Business ($200/month) or Enterprise plans (custom quotation), they have the option to upload their own certificate from another CA along with the associated private key. Either way, the CDN decrypts and re-encrypts the traffic as it travels through their network — meaning CloudFlare could theoretically view the contents of your encrypted connections.

Unless your threat model involves state-level actors, or your organization operates in an industry with heightened regulations, we think it is safe to trust CloudFlare to terminate SSL. If you have a good reason not to trust CloudFlare, we suggest terminating SSL directly on a load balancer you control (not a managed load balancer), or at the origin server itself.

If your application is highly sensitive, consider that the certificate and private key needs to be stored somewhere to negotiate connections over HTTPS. At the end of the day, you have to trust some datacenter, be it a cloud provider such as Amazon or a co-location facility — unless you keep the servers on-premises.

For general websites that use CloudFlare caching features to accelerate delivery, relying on CloudFlare to also handle SSL is a logical choice for simplicity & ease of configuration. Trusting CloudFlare isn’t the issue — but the way most CloudFlare users have their Crypto settings configured is.

CloudFlare “Flexible” SSL setting

CloudFlare Flexible SSL

For the sake of expediency, CloudFlare’s default setting for SSL is “Flexible.” This means the connection between the visitor and CloudFlare is encrypted, but between CloudFlare and your server is over plain HTTP (not encrypted). Understanding many novice webmasters have never installed a certificate on their web server, CloudFlare decided not to require a valid SSL certificate on the origin server to “enable HTTPS” through the CDN. The problem is: The uninformed masses see the “green padlock” in the address bar for their website, and call it a day — under the false impression that everything is secure. The harsh truth is nothing is being encrypted between CloudFlare and their web host. The data remains vulnerable to being intercepted or modified in-transit.

CloudFlare “Full” SSL setting

CloudFlare Full SSL

One step up in CloudFlare’s setting for SSL is “Full”, a bit better but not entirely secure. With the “Full” setting, the connection is encrypted between the visitor and CloudFlare using the shared SSL certificate, and CloudFlare also requests that the origin server present a certificate when fetching resources from it. The problem is: CloudFlare does not require the origin certificate be valid, i.e. signed by a trusted certificate authority. The CDN will accept any certificate, including self-signed certificates. A determined attacker could MITM the connection and present a self-signed certificate, and CloudFlare would continue communicating with the attackers’ server revealing your encrypted information.

CloudFlare “Full (Strict)” SSL setting

CloudFlare Full (Strict) SSL

The only safe setting for using CloudFlare Universal SSL is “Full (Strict).” CloudFlare requires the connection be encrypted all the way from the visitor, to the CDN, to the origin server using valid certificates (not self-signed certificates). The biggest hurdle with adopting this option is installing a valid certificate at the origin server, which could be your web server, a reverse proxy, or load balancer. What certificates are considered valid by CloudFlare?

  • “Dedicated SSL Certificate” ($5/month) or “Dedicated SSL Certificate with Custom Hostnames” ($10/month) ordered through CloudFlare dashboard
  • Certificate issued by a trusted CA such as Comodo, DigiCert, GoDaddy, or Verisign
  • CloudFlare Origin Certificate generated within the dashboard

If you plan to serve many subdomains of your second-level domain bypassing CloudFlare (grey cloud in DNS settings), obtaining a wildcard certificate from a commercial Certificate Authority and installing it at the origin is the best option.

Free Wildcard SSL Certificate from CloudFlare

If all your hostnames sit behind CloudFlare, a free (and equally secure) alternative is the CloudFlare Origin Certificate. The CloudFlare Origin Certificate is only valid for communication between the CDN and your servers – no major browsers such as Chrome, Edge, Firefox, or Safari will recognize it as valid. If you try to serve up CloudFlare’s origin cert directly to the world (not behind the CDN), it will trigger a nasty security warning in your visitors’ browsers.

Installing CloudFlare Origin Certificate in Apache or Nginx

Here’s how to generate a CloudFlare Origin Certificate and install it for Apache or Nginx, two of the most popular web servers in the world.

1 – Login to your CloudFlare account and browse to the “Crypto” tab.

2 – In the “Origin Certificates” section, click “Create Certificate.”

CloudFlare Origin Certificate Issuance Options

  • Select “Let CloudFlare generate a private key and a CSR” in the modal window which appears.
  • For the hostnames the certificate should be signed for, the default “*.example.com” and “example.com” covers the main domain and third-level subdomains (including www.example.com). If you use forth-level or deeper subdomains, remember to list them while creating the certificate.
  • The default validity period for the certificate is 15 years, which means it doesn’t need to be replaced on the origin server for that length of time. Like all other SSL certificates, each time a CloudFlare Origin Certificate expires, it must be reinstalled by a server admin.

Click “Next” to generate the CloudFlare Origin Certificate.

3 – In the next window, you’ll see two textboxes, one containing a certificate block and another containing a private key block. PEM is the most suitable key format for modern web servers including Apache and Nginx.

Copy and paste the Origin Certificate to a local file called cloudflare_ssl.pem and the Private key to cloudflare_privkey.pem. Save it with no additional spaces or empty lines, ideally using Unix line endings with a text editor such as Notepad++ if using Windows.

CloudFlare Origin Certificate Output

4 – Download the CloudFlare Origin CA Root Certificate from this link. Expand, then copy & paste the contents of the certificate from “Cloudflare Origin CA — RSA Root” and save it on your local machine as cloudflare_origin_rsa.pem.

5 – SSH into the origin server and create a folder to store the keys.
Correctly set the folder permissions and ownership to protect the key files.
The folder and key files should be created by, and therefore owned as root.

sudo mkdir -p /etc/ssl/certs
sudo chmod 700 /etc/ssl/certs

6 – Upload the keys into your origin server from the directory on your local machine (Linux or Mac) using scp at the command line, or WinSCP (Windows). If your remote server uses key based authentication, pass the -i flag with the absolute path to your SSH private key.

scp cloudflare_ssl.pem cloudflare_privkey.pem cloudflare_origin_rsa.pem root@example.com:/etc/ssl/certs/

For Apache-based Web Servers

7a. Add the following lines to a configuration file listening on port 443 in /etc/httpd/conf.d (RHEL or CentOS) or /etc/apache2/sites-available (Apache or Debian). Test the configuration with apachectl -t to check there are no errors (Syntax OK), before restarting the web server with systemctl restart httpd (RHEL or CentOS) or service apache2 restart (Apache or Debian).

For instance you could name the file below ssl.conf. Note that some lines, such as <Directory></Directory> blocks are ellipsized with …

Listen 443

SSLUseStapling on
SSLStaplingCache "shmcb:logs/stapling-cache(150000)"

<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
ServerAdmin webmaster@example.com
DocumentRoot /var/www/html
CustomLog /var/log/httpd/example.com.log combined
ErrorLog /var/log/httpd/example.com.error.log

SSLEngine on
SSLProtocol All -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
SSLCompression off
SSLSessionTickets Off
SSLCertificateFile /etc/ssl/certs/cloudflare_ssl.pem
SSLCertificateKeyFile /etc/ssl/certs/cloudflare_privkey.pem
SSLCertificateChainFile /etc/ssl/certs/cloudflare_origin_rsa.pem


For Nginx-based Web Servers

7b. Nginx requires two additional steps to enable SSL securely compared to Apache.

Generate a dhparam.pem file.
sudo openssl dhparam -out /etc/nginx/dhparam.pem 4096

Concatenate the certificate and intermediate CA file.

sudo cat /etc/ssl/certs/cloudflare_ssl.pem /etc/ssl/certs/cloudflare_origin_rsa.pem > /etc/ssl/certs/cloudflare/cloudflare_bundle.pem

Add the following lines to a configuration file listening on port 443 in /etc/nginx/conf.d. Test the configuration with nginx -t to check there are no errors, before restarting the web server with systemctl restart nginx (RHEL or CentOS) or service nginx restart (Apache or Debian).

For instance you could name the file below ssl.conf. Note that some lines, such as location blocks are ellipsized with …

server {
listen 443 ssl;
server_name example.com www.example.com
error_log  /var/log/nginx/example.com.log error;

ssl_certificate /etc/ssl/certs/cloudflare_bundle.pem;
ssl_certificate_key /etc/ssl/certs/cloudflare_privkey.pem;
ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/nginx/dhparam.pem;
ssl_ecdh_curve secp384r1;
ssl_session_timeout  10m;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver valid=300s;
resolver_timeout 5s;


8 – Secure the certificate files with 600 permissions, and ensure they are owned by root.

chmod 600 /etc/ssl/certs/cloudflare*
chown root:root /etc/ssl/certs/cloudflare*

9 – Change CloudFlare SSL setting to “Full (strict)” and congratulate yourself on a job well done. By enabling end-to-end encryption between your origin server <-> CloudFlare <-> visitor, you are taking full advantage of CloudFlare’s security features to protect you and your users.

Enable Full (strict) SSL setting in CloudFlare