How to lock your server to Cloudflare addresses only

Your server still answers anyone who knows its address. Here is how to accept Cloudflare and refuse the rest, without taking your own website offline.

Your server accepts web traffic from Cloudflare and refuses direct requests, and you have checked that visitors can still reach your website.

Your origin, the real server your website runs on, answers requests from anyone who sends them. Pointing your name at Cloudflare does not change that, so there are two ways in: through Cloudflare, and straight to the machine.

This closes the second one. You tell the server to accept web traffic from Cloudflare addresses and refuse everything else. Nothing here depends on us and there is nothing to buy: it is your server and your rule.

This is the one guide here that can take your website offline. A rule that refuses Cloudflare along with everyone else stops every visitor, and a rule that covers only half of your addresses stops some of them. Read the whole page before you apply anything.

What locking the server actually does

Visitors reach Cloudflare, and Cloudflare reaches your server. Nothing else needs to. So the rule you want is narrow: on the ports your website answers on, normally 80 and 443, accept connections from the ranges Cloudflare publishes and refuse the rest.

It does not hide your address. Anyone who already learned the number still has it. What changes is that the number stops being useful, and that is the part that matters. Why this is worth doing at all is the subject of what an exposed origin is; this page is the how.

Step 1: take the address list from Cloudflare, not from an article

Cloudflare publishes its address ranges on one page, and that page is the only copy worth working from.

This guide deliberately does not print the ranges. A list copied into an article is right on the day it was written and quietly wrong afterwards, and nothing on the page tells you which day you are reading. The page above is the one that gets updated.

There are two lists there, IPv4 and IPv6. Taking only the first is the most common way this goes wrong. Depending on which way your firewall refuses by default, the missing half either blocks Cloudflare over IPv6 and breaks your website for some visitors, or leaves the direct door open so the whole exercise changes nothing.

Step 2: choose one place for the rule

There are usually three places it can live, and you want it in exactly one of them. Two half finished rules in two places are much harder to undo than one.

  • A firewall in front of the machine: the security group or firewall page in your hosting or cloud panel. Usually the cleanest, because it refuses the connection before your machine spends anything on it.
  • A firewall on the machine, such as ufw, firewalld or nftables. Same effect, and it is what you have when the panel offers nothing.
  • A rule inside the web server config. Often the only option on shared hosting. It is the weakest of the three: the connection still completes and your web server still answers, it just answers with a refusal.
Check what else on that machine answers on ports 80 and 443. A staging subdomain, a control panel, or a second website whose name points straight at the address rather than through Cloudflare will stop working too. The rule is doing exactly what you asked; it just did not know about them.

Step 3: keep a way in that does not use ports 80 and 443

Before you apply anything, make sure you can still reach the machine if the rule turns out to be wrong. Two things do that.

  1. Restrict only the web ports. Leave your administrative access, SSH or the panel login, exactly as it is. A blanket refuse everything rule is the version of this that locks you out of your own server.
  2. Find the console in your hosting panel and check that it opens, before you need it. That path does not travel over ports 80 and 443, so a rule on those ports cannot take it away from you.

Write down what the rules look like before you touch them. Undoing a change is quick when you know the previous state and slow when you have to reconstruct it.

Step 4: write the rule

The two examples below are about shape, not syntax to copy. Each is written for one common tool, and the exact wording depends on what you are running. Where they say <range> you paste one line per range from the Cloudflare page, IPv4 and IPv6 both.

# ufw. One line per range from https://www.cloudflare.com/ips/
sudo ufw allow from <range> to any port 443 proto tcp
sudo ufw allow from <range> to any port 80 proto tcp

Two things decide whether those lines do anything at all. The firewall has to refuse by default, because otherwise an allow list is only a list. And an older rule that opened those ports to everyone has to go first: rules are read in order and the first match wins, so a rule added earlier answers before yours is ever reached. sudo ufw status numbered shows what is there and in what order.

Inside a web server config the same idea looks like this, in the block that serves your website.

# one allow line per range, IPv4 and IPv6 both
allow <range>;
deny all;

Order matters here as well: the lines are read top to bottom and the first match wins, so deny all; belongs at the end. Most web servers can check a config file for errors before loading it, and doing that first turns a typo into a message instead of an outage.

If your web server is already set up to read the visitor address out of a Cloudflare header, an allow list written this way gets compared against the visitor address rather than the Cloudflare one, and it will refuse everybody. Check which address your rule is actually reading before you rely on it.

Step 5: check both directions before you walk away

There are two questions here, and passing one of them proves nothing about the other.

  1. Load your website by its name, from a device that is not the server, in a private window. You are checking that Cloudflare can still reach your machine, and a page served out of your own cache will tell you it can when it cannot.
  2. Request your website from the origin address directly, the way what an exposed origin is describes. Before the rule, that request returned your website. After it, you should get a refused connection or a timeout. A certificate warning is not the answer you are looking for, because it means something answered.
  3. Do both again over IPv6 if your server has an IPv6 address. A rule can be complete on one family and missing on the other, and the family you did not test is the one that fails.
Testing from the server itself proves nothing. A request that never leaves the machine does not pass through the rule you just wrote.

If your website is in a OneLineShield account, whether that direct door is open is one of the checks that run every ten minutes, measured from outside Cloudflare. It only reports once Cloudflare has confirmed your website is behind the gateway, because before that an origin that answers is ordinary rather than a hole. There is no alert email for it yet, so the result sits on your dashboard and you have to be the one who goes and reads it.

What that warning means when you see it, and how to read the case where we cannot tell either way, is in how to confirm an exposed origin and close it.

How to take it back off

The undo is whatever you wrote, removed. Firewalls list their rules with numbers and delete by number; a web server block goes away when you delete the lines and reload the config.

If your website is down right now, take the whole rule off first and work out which line was wrong afterwards. Diagnosing with visitors waiting is the expensive order to do it in.

If you can no longer reach the machine over the network, use the hosting panel console, the one you opened in step 3. It does not travel over the ports you just changed.

If you do not administer the server yourself

Plenty of people cannot touch the machine their website runs on, and that is normal rather than a blocker. Your hosting company can do this, and the request is short enough to send as it stands.

Please allow inbound connections on ports 80 and 443 only from the IP ranges Cloudflare publishes at https://www.cloudflare.com/ips/, including the IPv6 ranges, and refuse everything else. Please leave my administrative access unchanged, and tell me when it is done so I can check the website.

Two details are worth keeping word for word: the IPv6 ranges, because that is the half most often left out, and the line about administrative access. When they say it is done, run step 5 yourself rather than treating the confirmation as the test.

What this does not change

  • Your nameservers. They stay where they are, and so does the rest of your DNS, mail included.
  • Your hosting. Same machine, same files, same company.
  • What Cloudflare does in front of your website. This rule decides who your server answers, not what happens at the edge.

One thing to remember for later, because it bites months afterwards: the rule assumes your visitors arrive through Cloudflare. If you ever point your website straight back at your server, whether that is removing us or leaving Cloudflare altogether, the rule has to come off in the same sitting or your website goes dark.

Otherwise none of this depends on us. Locking a server to Cloudflare addresses works the same whether your name points at our gateway, at your own Cloudflare account, or at neither yet. The most we do is measure it from outside and report back what we found.

All guides