Integration of 1C-Bitrix with Cloudflare
1C-Bitrix historically assumes direct client-to-server connection. When placed behind Cloudflare, IP detection breaks, proactive protection stops working, composite cache conflicts with CDN cache, and security module starts banning Cloudflare IPs instead of real visitors. Integration is not "connect DNS and forget" but system-wide setup of both sides.
IP detection problem
Cloudflare proxies traffic, substituting its IP in REMOTE_ADDR. Real client IP passed in CF-Connecting-IP header. Bitrix uses $_SERVER['REMOTE_ADDR'] everywhere: in security module (proactive filter, WAF), in statistic module (visit statistics), in sale module (geolocation for delivery).
Solution — redefine REMOTE_ADDR in dbconn.php (or /bitrix/.settings.php):
if (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
$_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_CF_CONNECTING_IP'];
}
This code must execute before Bitrix core loads. Place it at the beginning of /bitrix/php_interface/dbconn.php.
Security: verify request really comes from Cloudflare. List of Cloudflare IP ranges available at https://www.cloudflare.com/ips-v4. If server accepts direct connections bypassing Cloudflare, attacker can fake CF-Connecting-IP header. Close ports 80/443 for all IPs except Cloudflare ranges at firewall level.
Cache conflict: composite vs. Cloudflare
Bitrix composite cache (composite) serves HTML snapshot without PHP execution. Cloudflare Cache also caches HTML. Result is double caching with different invalidation rules — page updates in Bitrix but Cloudflare still serves old version.
Solution options:
Option 1: Disable HTML caching in Cloudflare. In Page Rules set Cache Level: Bypass for *.php and dynamic pages. Cloudflare will cache only static files (JS, CSS, images). Bitrix composite works normally. This is the recommended approach for most projects.
Option 2: Disable composite, cache in Cloudflare. Suitable for info sites with rare updates. Set Edge Cache TTL in Cloudflare and use Cloudflare API to clear cache on content update. Call POST /zones/{zone_id}/purge_cache from OnAfterIBlockElementUpdate handler.
Option 3: Combined. Composite works for authorized (not cached in Cloudflare), Cloudflare caches pages for anonymous. Separation via Cache-Control: private for authorized and Cache-Control: public, max-age=300 for anonymous. Headers set in init.php based on $USER->IsAuthorized().
SSL setup
Cloudflare offers three SSL modes: Flexible, Full, Full (Strict). For Bitrix only one is correct — Full (Strict) with valid server certificate.
In Flexible mode Cloudflare connects to server over HTTP. Bitrix doesn't see HTTPS connection, \Bitrix\Main\Context::getCurrent()->getRequest()->isHttps() returns false. Result: infinite redirects if "Redirect to HTTPS" is on in settings, or mixed content, or forms submit over HTTP.
If Full (Strict) is impossible (no server certificate), use Cloudflare Origin Certificate — free certificate working only when proxied through Cloudflare.
Proactive protection and WAF
Bitrix security module contains its own WAF. When working through Cloudflare both WAFs are active. Conflicts:
- Cloudflare WAF blocks request, Bitrix logs error 403 without details — unclear who blocked.
- Cloudflare and Bitrix rules may contradict — Cloudflare passes, Bitrix blocks, or vice versa.
Recommendation: use Cloudflare WAF as first line (block bots, DDoS, known attacks) and Bitrix proactive filter as second (CMS-specific attacks). Don't disable either completely.
Setup timeline
| Task | Duration |
|---|---|
| DNS, SSL, basic setup | 2–3 hours |
| IP redefinition + firewall | 2–3 hours |
| Cache configuration (Page Rules, composite) | 1 day |
| WAF: rule reconciliation | 1–2 days |
| Testing (cart, auth, forms, account) | 2–3 days |
| First week monitoring | background |
| Total | 1–2 weeks |
Separately account for testing integrations: payment systems, callback notifications from ERIP or banks, webhooks from 1С. All call server directly and if ports are closed for non-Cloudflare IPs — notifications stop coming. For callback URLs add firewall exceptions or use separate subdomain without proxying.

