Cloudflare blocks (LaLiga): automatic switch to direct connection

The MuseDock CMS automatic switch for Cloudflare blocks keeps your websites reachable when internet providers in a country block Cloudflare IPs, or when Cloudflare itself stops responding. It works on its own: it detects which IPs have stopped answering, turns off the orange cloud (the proxy) on the affected domains so they go straight to your server and, once the IP is stable again, turns the proxy back on.

It is built into the CMS core (it is not a separate module) and is configured in Settings → Cloudflare blocks.

It is not a shield. Turning off the Cloudflare proxy has a cost: while the block lasts, your site loses Cloudflare's protection and cache, and your server's IP is exposed. It is a risk taken on purpose, because it is the only way to keep your site reachable in the country of the block. That is why it only happens when needed, only on the affected domains, for as short a time as possible, and backed by MuseDock's fail2ban protection.

The problem: blocks on shared IPs

Cloudflare does not give each website its own IP: many websites share the same ones. In Spain, under a court order, internet providers (Movistar, Orange, Vodafone, Digi…) block the Cloudflare IPs where LaLiga detects pirate football streams, during matches. Because those IPs are shared, every legitimate website using them goes down too, even if it has nothing to do with football.

From inside the country, visitors see a connection error (ERR_CONNECTION_TIMED_OUT). From abroad, the site works normally. On regular Cloudflare plans you cannot choose different IPs: the only way to stay reachable is to turn off the proxy while the block lasts.

How it works

  1. Inventory. The CMS reads from Cloudflare the DNS records of its domains (tenants, aliases and redirects) using the accounts in DNS accounts, and records which ones have the orange cloud and which Cloudflare IPs they answer on.
  2. Probes. One or more machines in the country you want to watch (the probes) check every minute whether they can reach those IPs, through each internet connection they have (for example, two different providers), and send the results to the CMS.
  3. Decision. If an IP fails two reports in a row from any provider, it is considered blocked. Before changing anything, the probe checks that your server answers directly, without Cloudflare, with a valid certificate.
  4. Change. The orange cloud is turned off on the affected records (60 s TTL) and a snapshot of how they were is saved.
  5. Rollback. Once the IP has answered from every probe for a while (30 minutes by default), the proxy is turned back on.

The CMS also checks the IP from its own server: if it answers there, the notice says it is a provider block; if it answers nowhere, a Cloudflare outage. Both cases are handled the same way.

Rules that are never broken

  • Only records that had the proxy on when the block started are touched. A domain that was already direct never enters the cycle, so it never gets the proxy.
  • Manual changes are respected. On rollback, the proxy is only turned on if the record is exactly as the system left it. If someone changed it in the meantime (in Cloudflare, the Domain Manager or a client), the change is kept and you are notified.
  • When in doubt, do nothing. If no probe has reported in the last 5 minutes, nothing is changed.
  • No healthy server, no change. If your server does not answer directly with a valid certificate, the domain is left as it is: turning off the proxy would make things worse.
  • Probes never hold Cloudflare credentials. They only report; the CMS is the one that changes DNS.

Modes

ModeWhat it does
OffTurns off nothing. If there are active changes, it still rolls them back when the IP recovers.
SimulationDetects and reports what it would do, without touching Cloudflare. Recommended to start with.
AutomaticTurns the proxy off and back on by itself, and emails you about every change.

Setup

Requirements

  • Your domains on Cloudflare, with the account added in Settings → DNS accounts. The token needs permission to read zones and edit DNS records.
  • A machine in the country you want to watch, with Python 3 and curl, connected through your visitors' provider or providers. An office server, a mini PC or a Raspberry Pi will do.
  • To watch several providers from one machine: one network interface per provider and root permissions, so the outgoing connection can be chosen.
  • Your server must have its own certificate for each domain (for example, Let's Encrypt). A Cloudflare origin certificate only works behind the proxy.

1. Create the probe in the CMS (this is where its API access is created)

In Settings → Cloudflare blocks → Probes, type a name (for example, the machine's) and click Create probe. The CMS generates a token, the probe's key to its API:

  • It is shown only once: copy it right away. The CMS only stores its fingerprint.
  • It only works for two calls: GET /api/v1/edge-guard/targets (which IPs to test) and POST /api/v1/edge-guard/report (submit results). It gives access to nothing else.
  • If you lose it, create the probe again with the same name: the old token stops working. You can revoke it from the same list.

2. Prepare the probe machine

Any Linux box in the country you want to watch will do (an office server, a mini PC, a Raspberry Pi) with Python 3 and curl, connected through your visitors' provider or providers. To watch several providers from one machine, each must come in through its own network interface. To find their names:

ip -br addr        # interface names and their IPs (eth0, eth1, enp3s0…)
ip route           # which gateway each one uses

To check each interface goes out through its provider, look at each one's public IP:

curl --interface eth0 https://api.ipify.org
curl --interface eth1 https://api.ipify.org

3. Install the probe

Download the script with the Download probe button on the screen, or from the machine itself:

curl -fsS https://your-cms.example/api/v1/edge-guard/probe.py -o /usr/local/bin/musedock-edge-probe.py
chmod 755 /usr/local/bin/musedock-edge-probe.py

The script contains none of your data: everything that changes between installs goes into two files. Store the token (and only the token) in a file only root can read:

install -m 600 /dev/null /etc/musedock-edge-probe.token
nano /etc/musedock-edge-probe.token      # paste the token and save

Then create the configuration, /etc/musedock-edge-probe.conf:

URL=https://your-cms.example
TOKEN_FILE=/etc/musedock-edge-probe.token
PATHS=Provider1:eth0,Provider2:eth1
RESOLVE=10.66.0.1
OptionWhat to set
URLYour MuseDock CMS address, the same one you use to log in to the admin.
TOKEN_FILEThe token file (permissions 600).
PATHSEach internet connection to watch, as name:interface, comma separated. The name is free text (it is shown on screen). If the machine has a single connection, delete the line: the default route is used.
RESOLVERecommended: your CMS's private IP inside a VPN, so the probe can report even if your own CMS's Cloudflare IP is blocked. How to set it up: connect the probe to the CMS over WireGuard. Without a VPN, delete the line.
CONTROLOptional. A control website to know the connection has internet (a Google one by default). If it fails, that connection's report does not count.

4. Test it by hand

python3 -I /usr/local/bin/musedock-edge-probe.py -v

You will see one line per connection, with its public IP, how many IPs it tested and which ones do not answer, and finally "Informe entregado al CMS" (report delivered). For example, during a block:

[Provider1] interfaz=eth0 ip_publica=203.0.113.10 control=ok objetivos=42 fallan=2
    no responde: cf:188.114.96.3 (código 000)
    no responde: cf:188.114.97.3 (código 000)
[Provider2] interfaz=eth1 ip_publica=198.51.100.20 control=ok objetivos=42 fallan=2
    …
Informe entregado al CMS: {"ok":true,"stored":87}

HTTP 401 means a wrong token; HTTP 000 means the probe cannot reach the CMS (check URL and RESOLVE); HTTP 429 means it delivered another report less than 20 seconds ago, which is normal.

5. Run it every minute

echo '* * * * * root flock -n /run/musedock-edge-probe.lock python3 -I /usr/local/bin/musedock-edge-probe.py' > /etc/cron.d/musedock-edge-probe

It runs as root because choosing the outgoing interface requires it. If something fails, cron leaves it in root's mail or its log.

6. Check and enable in the CMS

Within a couple of minutes the probe shows as live on screen, with each connection's public IP. Click Read Cloudflare for the inventory right away (it refreshes every 30 minutes on its own). Leave it in Simulation for a few days and, once the notices look right, switch to Automatic.

On the CMS server, the watcher runs every minute from the system cron:

* * * * * php /path/to/cms/cli/cron-edge-guard.php >> /path/to/cms/storage/logs/cron-edge-guard.log 2>&1

To see the status from the terminal: php cli/cron-edge-guard.php --status.

The screen

  • Summary at the top: what is happening right now (all normal, domains without proxy because of a block, simulation…).
  • Probes: each connection with its public IP and the time of its last report.
  • Cloudflare IPs: the status of each IP (Responding, Blocked, One-off failure, Recovering) and which domains depend on it. It refreshes every minute.
  • Your domains on Cloudflare: each name's original configuration (with or without proxy) and its current state.
  • Changes and log: the full history. Clear log deletes closed entries and keeps active changes, which are needed to roll them back.
  • Never touch these domains: an exclusion list (includes subdomains).

Changing the original configuration by hand

In Your domains on Cloudflare, click the badge in the "Original configuration" column (With proxy or Without proxy) to change it. A window explains exactly what will happen and asks for your password. From then on the system respects the new configuration, in later blocks too.

The change is smart: it takes any ongoing block into account.

ChangeNo blockBlock in progress
From "without proxy" to "with proxy"The orange cloud is turned on right away.If the domain's zone has blocked Cloudflare IPs, it stays direct and becomes pending: the proxy is turned on by itself when the block ends, like the rest.
From "with proxy" to "without proxy"The orange cloud is turned off right away.If it is already direct because of the block, Cloudflare is not touched: the rollback is cancelled and the proxy is not turned back on when the block ends.

To know whether a direct domain would land on a blocked IP, the system looks at the IPs of the other names in its zone, because Cloudflare usually gives the whole zone the same ones. If the zone has no other proxied name, the proxy is turned on and, if it got a blocked IP, the system detects it within a minute or two and turns it off until the block ends. Every manual change is logged with who made it.

The risk of going without the proxy and how MuseDock offsets it: fail2ban

With the orange cloud on, attacks hit Cloudflare first. Without it, they reach your server directly. To cover that gap, MuseDock pairs the CMS with fail2ban, which bans attacking IPs at the firewall:

  • Failed logins (superadmin, tenant admins, clients and 2FA codes): 8 failures in 10 minutes from one IP → 1-hour ban.
  • Scanners looking for files no visitor requests (/.env, /.git, wp-login.php on non-WordPress sites, stray *.php files…): 10 attempts in 5 minutes → 24-hour ban.
  • Repeat offenders: the ban grows each time.
  • It works with and without Cloudflare: it blocks direct connections at the firewall (iptables) and Cloudflare-proxied ones at the web server (Caddy).

Be realistic: fail2ban stops password guessing and scanning, but it does not replace Cloudflare's protection against a large denial-of-service (DDoS) attack. That is why the direct connection only lasts as long as the block.

What is included by default and what is not

PieceWhere it livesIncluded by default?
Automatic switch for Cloudflare blocksMuseDock CMS coreYes, in every CMS install. It is not a module. It ships in Off mode until you configure it.
Security event log (failed logins and scanners)MuseDock CMS core (storage/logs/security-events.log)Yes, always on. No emails or passwords; it never logs Cloudflare or private IPs.
fail2ban jails that ban using that logMuseDock PanelYes, if the CMS runs on a server managed with MuseDock Panel: they are installed automatically when the panel updates.
fail2ban without MuseDock PanelYour serverNo: install fail2ban and add the two jails by hand (configuration below).

fail2ban without MuseDock Panel

If you run MuseDock CMS on your own server, install fail2ban and create these two filters and their jails. Replace the log path with your install's.

# /etc/fail2ban/filter.d/musedock-cms-login.conf
[Definition]
failregex = ^ musedock-cms event=(?:login_failed|twofa_failed) ip=<HOST> host=\S+ path=\S+$
datepattern = ^%%Y-%%m-%%dT%%H:%%M:%%S(?:[+-]\d\d:\d\d)?

# /etc/fail2ban/filter.d/musedock-cms-probe.conf
[Definition]
failregex = ^ musedock-cms event=probe ip=<HOST> host=\S+ path=\S+$
datepattern = ^%%Y-%%m-%%dT%%H:%%M:%%S(?:[+-]\d\d:\d\d)?

# /etc/fail2ban/jail.d/musedock-cms.conf
[musedock-cms-login]
enabled  = true
filter   = musedock-cms-login
logpath  = /path/to/cms/storage/logs/security-events.log
port     = http,https
maxretry = 8
findtime = 600
bantime  = 3600

[musedock-cms-probe]
enabled  = true
filter   = musedock-cms-probe
logpath  = /path/to/cms/storage/logs/security-events.log
port     = http,https
maxretry = 10
findtime = 300
bantime  = 86400

With the Cloudflare proxy on, iptables does not see the attacker's real IP (it sees Cloudflare's). To also ban visitors coming through Cloudflare you need a block at the web server or at Cloudflare; MuseDock Panel does it with its Caddy action. While a domain is direct because of a block, iptables is enough.

Security

  • A probe token only allows two things: fetching the list of IPs to test and submitting results. It gives no access to the admin panel or to the domains.
  • The CMS only accepts results for targets it asked for, and at most one report every 20 seconds per probe.
  • A forged report could at worst turn off a proxy for a while, and only if your server answers fine directly. A probe can be revoked with one click.
  • Probe requests create no session or cookies in the CMS.

Things to know

  • While the block lasts, your server's IP is exposed and those domains lose Cloudflare's cache and protection. It is usually a couple of hours.
  • R2 bucket and Workers custom domains cannot go direct: they only work through Cloudflare.
  • Only A and CNAME records are managed. Proxied AAAA (IPv6) records stay as they are.
  • DNS changes take as long as each visitor's cache (up to 5 minutes for proxied records).
  • On a replica server (read-only database) the watcher does nothing: the primary decides.

Frequently asked questions

Is it only for football?

No. It looks at what actually happens, not at a calendar: it covers any block on Cloudflare IPs in the probe's country, and Cloudflare outages too, as long as your server answers.

Does it affect visitors from other countries?

Provider blocks only affect people connecting from that country. When the system turns off the proxy, visitors from abroad also go straight to your server until it is restored, with no problem.

Why do some Cloudflare IPs work and others don't?

Each domain uses its own pair of Cloudflare IPs, and some are shared with far more websites than others. The specific IPs where pirate sites show up get blocked; your domains on other IPs keep working.

Can I pick other Cloudflare IPs instead of turning off the proxy?

Not on the Free, Pro and Business plans: Cloudflare assigns the IPs and there is no way to request others. It is only possible with dedicated IPs or BYOIP on Enterprise.

What if I change a record by hand during a block?

When the block ends, the system sees the record is no longer as it left it, does not touch it and notifies you. Your change wins.

Do I need MuseDock Panel?

For the switch itself, no: it works with MuseDock CMS alone plus one machine acting as a probe. For the fail2ban hardening, MuseDock Panel installs the jails automatically; without the panel you can set them up by hand (see fail2ban).

Troubleshooting

SymptomLikely cause and fix
The probe shows as "silent"It has not reported for 5 minutes. Run the client by hand (python3 -I /usr/local/bin/musedock-edge-probe.py): a 401 error means a wrong token; if it cannot connect, check URL and RESOLVE.
Every IP shows "No data"The control website fails from the probe: the machine has no internet on that connection. Check the interface name in PATHS.
"The origin server does not answer directly with a valid certificate"Your server has no certificate of its own for that domain, or its firewall only lets Cloudflare in. Until you fix it, that domain is not changed.
A domain is missingOnly CMS domains whose DNS is in a Cloudflare account under DNS accounts are included. Click Read Cloudflare and check the read errors.
I still can't see the site after the proxy was turned offDNS cache on your computer or router: wait a few minutes or restart the browser.