How to get the real visitor IP in Magento behind Cloudflare
Every Magento order shows a Cloudflare IP? Restore the real visitor address from CF-Connecting-IP safely, fix load balancers, and verify it.

Open any order placed since the store went behind Cloudflare and look at the IP it was placed from. It is a Cloudflare address, and so is the one on every other order.
That is the default state of Magento behind any proxy. Cloudflare opens a new connection to your origin, the web server records Cloudflare's address in REMOTE_ADDR, and Magento stores that as the Magento customer IP address on the order. OCM Labs Cloudflare, which is free and open source, fixes it in a few minutes. The interesting part is doing it without opening a spoofing hole. If the module is not installed yet, start with setting up Cloudflare for Magento.
What breaks when Magento only sees Cloudflare
The wrong IP on an order is the visible symptom. The quieter ones cost more:
- Fraud and velocity checks see one visitor. Rules built on orders-per-IP either fire on everyone or get switched off.
- Geo-IP features point at a data center, so anything keyed on the visitor's location resolves to wherever Cloudflare's edge sits.
- Admin IP allowlists cannot be used. Every request arrives from Cloudflare, so the allowlist either blocks everyone or has to be opened to Cloudflare entirely.
How CF-Connecting-IP works, and why trusting it blindly is a mistake
Cloudflare adds the real visitor address to every proxied request in the CF-Connecting-IP header. The naive fix is to tell Magento to read that header instead of REMOTE_ADDR.
The problem: anyone who can reach your origin directly can send a CF-Connecting-IP header with whatever value they like. If Magento trusts it unconditionally, someone pointing curl at your origin IP can claim to be your office range, or a fresh address for every order. The allowlist you were trying to fix becomes the thing they walk through.
The module handles this with a peer check. With Trust CF-Connecting-IP on (the default), it plugs into Magento's remote address resolver and returns the header's value instead of REMOTE_ADDR, but only when the TCP peer, the raw REMOTE_ADDR, is inside Cloudflare's published IP ranges. A request from any other address keeps REMOTE_ADDR, header or not. IPv4-mapped IPv6 peers are recognized, so an origin that listens on a dual-stack socket still passes the check.
The ranges are refreshed daily from Cloudflare by a cron job at 04:30 and stored in the module's ocmlabs_cloudflare cache type. A copy ships with the module as a fallback, so the check works before the first cron run and keeps working if the fetch ever fails. You do not maintain the list by hand.
Step 1: Confirm the setting is on
- Go to Stores > Configuration > OCMLabs > Cloudflare > Real IP.
- Check Trust CF-Connecting-IP. The default is Yes, so on a fresh install it is already on. The group is default scope; there is nothing to set per website.
- Make sure Enable Cloudflare Integration under General is also Yes. It is the kill switch for the whole module, and with it off there is no real IP handling at all.
From the command line or in a deploy script, the path is:
bin/magento config:set ocmlabs_cloudflare/real_ip/trust_cf_connecting_ip 1
bin/magento cache:clean configWhat to expect: for any request that arrives from a Cloudflare address, Magento now sees the visitor's real IP everywhere it calls the remote address resolver, so orders and anything else built on the standard resolver pick it up without their own configuration.
Step 2: Run the Real visitor IP health check
The module ships 25 health checks, and one of them exists for this feature. The "Real visitor IP" check inspects the current admin request and reports which of three cases you are in:
| PEER WAS CLOUDFLARE, HEADER HONORED | Working. Orders will carry the real address. |
|---|---|
| PEER WAS NOT CLOUDFLARE, HEADER IGNORED | Something between Cloudflare and Magento is rewriting the peer. See step 3. |
| HEADER MISSING | The request did not come through Cloudflare at all. |
To run it:
- Open the admin through the hostname Cloudflare proxies. A direct origin address or a hosts-file override makes the check report on that request instead of a real customer's.
- Go to System > Cloudflare > Dashboard > Health and click Run checks now.
- Find the "Real visitor IP" row and read the evidence column. It shows what
REMOTE_ADDRwas and whetherCF-Connecting-IPwas used.
Note that bin/magento ocmlabs:cloudflare:health skips this check. A CLI run has no Cloudflare request to inspect, so the row shows skip rather than a result. Only an admin request that came through Cloudflare means anything here. For the rest of the checks and how to read them, see running Cloudflare health checks for Magento.
Step 3: Fix the load balancer or proxy case
If the check reports that the peer was not Cloudflare, the usual cause is something sitting between Cloudflare and your web server that does not rewrite REMOTE_ADDR. An AWS Application Load Balancer is the common one; an nginx reverse proxy is another. The peer Magento sees is the proxy, which is not in Cloudflare's ranges, so the module correctly ignores the header.
The fix belongs in the web server, not in Magento. Restore REMOTE_ADDR from the proxy's X-Forwarded-For header, trusting only the proxy's own range. For nginx:
set_real_ip_from 10.0.0.0/16; # your load balancer or proxy range
real_ip_header X-Forwarded-For;Replace 10.0.0.0/16 with the range your load balancer actually uses. For Apache, mod_remoteip with RemoteIPInternalProxy set to the same range does the same job.
Once REMOTE_ADDR is Cloudflare's address again, the module takes over and reads CF-Connecting-IP. The two layers compose: the web server strips the load balancer, the module strips Cloudflare.
Reload the web server, then repeat step 2. The health check should now report that the peer was Cloudflare and the header was honored.
Doing this at the web server is worth it anyway. Your access logs and anything else on the host get the right IP too, not just Magento.
Step 4: Place a test order
The health check covers one admin request. An order proves it end to end.
- From a device that is not on the same network as the server, open the storefront through Cloudflare and place a test order.
- In the admin, open the order and check the IP it was placed from.
- Compare it with the public address of the device you ordered from.
If it matches, you are done. If it still shows a Cloudflare address, check that the module is enabled, that bin/magento setup:di:compile has been run since install, and that the order went through the proxied hostname.
When to turn the setting off
Some hosts already restore the real IP in the web server from CF-Connecting-IP itself, with set_real_ip_from listing Cloudflare's ranges and real_ip_header CF-Connecting-IP. If that is your setup, REMOTE_ADDR is already the visitor's address by the time PHP starts, and the module has nothing to do.
Set Trust CF-Connecting-IP to No in that case. The two approaches are equivalent. Doing it twice is harmless but pointless, and one source of truth makes the next person's debugging shorter. If you list Cloudflare's ranges in nginx by hand, you own keeping them current.
The full reference, including the three health check cases, is on the Real Visitor IP docs page.
If your setup has more moving parts than one load balancer, or you want someone to audit the whole path from edge to origin, our performance and infrastructure team does this work.
✦ FAQ
Why do all my Magento orders show the same Cloudflare IP?+–
Is it safe to trust the CF-Connecting-IP header?+–
Where is the Trust CF-Connecting-IP setting in Magento?+–
Why is the Real visitor IP health check skipped from the CLI?+–
Does the real IP work behind an AWS Application Load Balancer?+–
How does the module keep Cloudflare's IP ranges current?+–

Shane Blandford
Founder of Orange Collar Media, a Denver ecommerce agency behind 800+ Magento and Shopify builds. In Magento since version 1.x - building, rescuing, and supporting revenue-critical stores since 2008.
✦ KEEP READING
Related from the Journal.
Why put Cloudflare in front of Magento: what a CDN does for a store, what it does not, and what breaks
What Cloudflare does for a Magento store: a CDN for static files, edge-cached HTML, DDoS and bot protection, a WAF, and the five settings that break checkout.

OCM Labs Cloudflare: free edge caching for Magento, on Magento's own terms
A free, open-source Magento module that caches storefront HTML at the Cloudflare edge using Magento's own full page cache rules, and purges by cache tag.

How to use Cloudflare development mode and analytics from the Magento admin
Turn Cloudflare development mode on before a theme deploy, run a quick purge and read Cloudflare analytics from the Magento admin with a free module.
