Cloudflare Security Controls for Public Apps: WAF, DNS, Rate Limiting, and Access
A practical Cloudflare security guide for public apps covering DNS hygiene, TLS, WAF, rate limiting, access controls, logging integration, operational mistakes, and a repeatable hardening checklist.
Put a fresh domain behind a new server and watch the access log. Within a few hours you will see requests for /wp-login.php, /.env, /.git/config, and /actuator/health — on a site that runs none of those. Nobody targeted you. Certificate transparency logs publish every new hostname you certify, and there are people who read that firehose and scan everything on it.
Cloudflare is a good answer to a lot of that, and the way teams get it wrong is remarkably consistent: they flip DNS to proxied, see the orange cloud, and stop. Meanwhile the origin IP is still resolvable from a two-year-old MX record, TLS is on Flexible so the Cloudflare-to-origin hop is plaintext, and the WAF is in whatever mode the onboarding wizard picked.
None of those are hard to fix. They just require knowing they exist. This guide covers the controls that carry the most weight for a public app, the order to do them in, and — the part that gets skipped — how to stop the configuration decaying once it works.
Why edge controls matter (and what they can’t do)
The value of an edge is arithmetic. Ninety-something per cent of what hits a public app is undirected scanning, and every request the edge absorbs is one your application never parses, never logs, and never pays CPU for. WAF rules drop injection strings before your ORM sees them. Rate limits make credential stuffing economically pointless against your login endpoint. Strict TLS removes the downgrade path.
What none of that touches is the application itself. If /api/orders/{id} doesn’t check ownership, the request that exploits it is syntactically perfect, semantically valid, and indistinguishable at the edge from a legitimate one. Cloudflare will forward it, correctly, and log it as allowed. The same goes for an unpatched dependency reachable through a normal code path.
So the mental model is not “Cloudflare secures the app”. It is: the edge deletes the noise so that the signal reaching your origin is small enough for your application controls and your logging to cope with. That is worth a great deal, and it is not the same thing as protection.
Start with the controls that close the biggest gaps
Cloudflare’s dashboard presents a few hundred toggles as though they were peers. They are not. Five of them do most of the work, and the first one is load-bearing for all the others — if your origin is directly reachable, every control below it is optional from the attacker’s point of view.
- DNS hygiene and origin IP protection — if attackers find your origin IP, they bypass your edge entirely
- TLS mode and HTTPS enforcement — weak TLS settings undo the security value of proxying through Cloudflare
- WAF managed rules — broad protection against common web attack classes with minimal configuration effort
- Rate limiting on auth and API paths — login pages and password reset flows are constant brute-force targets
- Logging integration — you can’t detect or respond to attacks you can’t see
Everything else builds on top of these foundations.
The full control picture
Here’s a reference view of what each control actually protects against and how to think about using it:
| Control | Threat It Reduces | Key Usage Note |
|---|---|---|
| DNS Hygiene | Domain takeover, stale record abuse, misrouting | Remove unused records monthly; document ownership |
| Proxy Enablement | Direct origin exposure and bypass attempts | Proxy all public app records; verify origin isn’t reachable directly |
| TLS Configuration | Session interception, weak crypto, HTTPS downgrade | Enforce Full (Strict) mode; test before enabling HSTS |
| WAF Managed Rules | Known web attacks — SQLi, XSS, path traversal | Enable baseline rules, then tune based on false positive rate |
| Custom WAF Rules | App-specific abuse not covered by generic rule sets | Protect sensitive paths with targeted logic; document every rule |
| Bot Protection | Credential stuffing, scraping, automated API abuse | Apply progressive challenges on sensitive endpoints |
| Rate Limiting | Brute force, API burst abuse, resource exhaustion | Set per-endpoint thresholds based on business function |
| DDoS Protection | Traffic flood attacks at edge and application layers | Keep baseline protection active; plan for origin scaling |
| Security Headers | Browser-side exposure, weak client-side controls | Standardise header policy; validate against app behaviour |
| Zero Trust Access | Unauthorised access to admin portals and internal tools | Require identity-based access for any non-public admin surface |
| Log Integration | Delayed detection, poor incident response visibility | Export to SIEM; normalise fields for triage workflows |
DNS and origin protection: where most incidents start
Both of the failures in this section are the same shape: something that used to be true stayed in DNS after it stopped being true.
On DNS hygiene. A team spins up assets-staging.example.com as a CNAME to a cloud storage bucket, ships the feature, deletes the bucket, and leaves the CNAME. Months later someone else registers that bucket name on the same provider and now serves content from your domain, under your certificate, with your cookies in scope. Subdomain takeover is not exotic — it is the single most common finding in bug bounty programmes precisely because DNS records outlive the things they point at. Keep an owner recorded against every record, and audit monthly while you are actively building, quarterly once you are not.
On origin exposure. Proxying hides your origin IP going forward. It does nothing about the past. That IP is likely still sitting in historical DNS databases, in Received: headers on every email your server ever sent, in certificate transparency entries from before you moved to Cloudflare’s certificates, and in Shodan’s index. Finding it takes minutes and costs nothing, and once someone has it they connect straight to port 443 with a Host: header for your domain — arriving past the WAF, past rate limiting, past bot management, past your logs.
Two checks close this. First, from a machine outside your network, confirm the origin refuses connections on 80 and 443. Second, make that structural rather than hopeful: the origin’s firewall or security group should allow inbound web traffic only from Cloudflare’s published IP ranges, denying everything else by default. Those ranges change occasionally, so pull them from Cloudflare’s endpoint on a schedule rather than pasting them in once.
TLS: get this right before anything else
Flexible mode is the setting that catches people, because it looks like it works. Browsers show the padlock. Your users see HTTPS. Behind the padlock, the hop from Cloudflare’s edge to your origin is plain HTTP over the public internet, and anyone positioned along that path — a compromised router, a hostile transit provider, a curious hosting neighbour — reads session cookies in the clear.
It exists for a reason: it lets a legacy origin with no certificate sit behind HTTPS immediately. That is a migration convenience, not a destination, and plenty of setups have been sitting in it for years.
What to aim for:
- Set Cloudflare encryption mode to Full (Strict) — this validates the certificate on your origin server
- Enable Always Use HTTPS so HTTP requests are automatically redirected
- Enable HSTS with a reasonable max-age after you’ve confirmed your HTTPS setup is stable
- Disable older TLS protocol versions (TLS 1.0 and 1.1) through Cloudflare’s TLS settings
Sequence matters here, and HSTS is the one to be careful with. It instructs every browser that has visited you to refuse plain HTTP for max-age seconds — and there is no remote off switch. Publish a one-year max-age, then hit a certificate problem you can only fix by temporarily serving HTTP, and you cannot: returning visitors are locked out until the header expires or you fix the certificate. Start at a few minutes, watch for a week, then raise it in steps. Only add preload when you are certain, because removal from the browser preload lists takes months.
| Check | Why It Matters |
|---|---|
| Full (Strict) encryption mode | Prevents unencrypted origin traffic |
| Always Use HTTPS enabled | Ensures no plaintext exposure for any user |
| Certificate lifecycle monitored | Expired origin certs break Full Strict mode |
| HSTS configured deliberately | Locks browsers into HTTPS — test before enabling |
WAF: start broad, then get precise
Cloudflare’s managed WAF rules give you immediate protection against common web attack classes — SQL injection, cross-site scripting, path traversal, and more — without requiring you to write every rule yourself. Enable the Cloudflare Managed Ruleset and the OWASP Core Rule Set as your baseline.
Turn them straight to blocking and you will find out about the false positives from your support queue. Run the first week in log-only mode instead, or at minimum watch challenge and block rates against known-good traffic. The OWASP Core Rule Set in particular is tuned for coverage over precision — its default paranoia level flags plenty of legitimate input, and that is by design rather than a defect.
The predictable false-positive sources:
- APIs that send unusual but valid payloads
- Search functionality with complex query parameters
- Admin tools with rich form inputs
Scope every exception to one path and one rule ID. The tempting shortcut — disabling the whole ruleset for /api/* because one rule misfired on one endpoint — is how a WAF ends up nominally enabled and practically off, which is worse than not having one, because everyone believes it is working.
Custom rules are where you add app-specific protection:
- Restrict HTTP methods on sensitive endpoints (your
/api/usersendpoint shouldn’t accept DELETE from anonymous users) - Block or challenge access to admin paths from countries or ASNs you don’t serve
- Protect known high-risk routes from prior incidents with targeted logic
Every custom rule should have a clear abuse case it addresses, an owner, and a review date. Rules without these decay into noise that nobody wants to touch.
Rate limiting: one size does not fit all
A single global limit has to be set loose enough for your busiest legitimate endpoint, which means it is far too loose for your login page. Set it at 100 requests a minute so the product listing works, and you have just authorised a hundred password guesses a minute per IP. Per-endpoint limits exist because the risk profiles are not comparable.
One caveat on all of it: limits keyed on client IP are trivially diluted by a distributed botnet, and they punish shared NAT egress — offices, universities, mobile carriers — where hundreds of real users appear as one address. Where the endpoint matters, key on something more specific than IP, or pair the limit with a challenge rather than an outright block.
| Endpoint Type | Risk | Recommended Approach |
|---|---|---|
| Login / Authentication | Credential stuffing, brute force | Tight limits (e.g. 5 attempts per minute per IP) with progressive challenges |
| Password Reset | Account takeover via reset abuse | Very strict limits with additional identity signals |
| Public Search / Read APIs | Scraping, resource exhaustion | Moderate limits with bot-score-based escalation |
| API Write / Mutation Endpoints | Automated abuse, data integrity attacks | Low burst tolerance with per-client controls |
| Admin Panels | Unauthorised probing, high-impact actions | Extremely restrictive access plus identity gates |
Review your rate limit thresholds after significant traffic events — marketing campaigns, product launches, or viral moments can spike legitimate traffic patterns and cause your limits to fire on real users.
Keep origin hardening in place
There is a specific trap in a working WAF: the dashboard shows thousands of blocked attacks a day, which feels like proof, and it becomes the reason origin patching slips. The blocks are real. They are also almost entirely undirected scanner traffic that would have 404’d anyway.
The attacks that matter arrive looking normal. Authentication and authorisation logic still has to be correct at the application layer, sessions still have to be handled properly, dependencies still have to be patched on a schedule, and secrets still have to live somewhere other than the repository. Cloudflare stops the probing. It cannot stop the exploitation of something the probing already found.
Logging: from visibility to response
Cloudflare generates useful security telemetry, but it only becomes actionable when it’s integrated into your broader detection and response workflow.
At minimum, you want:
- Edge event logs exported to your SIEM or log storage with reliable retention
- WAF block/challenge events normalised with consistent field names (IP, path, method, rule ID, action, timestamp)
- Correlation between Cloudflare events and your application and auth logs
The distinction that matters in IR: a Cloudflare block tells you an attack was attempted. A correlated block — where you can see the edge blocked it and the application received no impact — confirms you were protected. Without correlation, you’re guessing.
| Field | Why IR Teams Need It |
|---|---|
| Timestamp (UTC) | Timeline integrity across log sources |
| Host / Path / Method | Identifies which service was targeted |
| Action Taken | Shows whether the attack was blocked, challenged, or allowed |
| Rule ID | Maps the event back to specific control logic |
| Client IP Context | Supports source pattern analysis and blocking decisions |
| Correlated Backend Signal | Distinguishes blocked probes from successful impact |
Common mistakes that undercut Cloudflare’s value
Ranked roughly by how often they turn up and how much damage each one does:
- Origin IP still exposed after enabling proxy — the most critical gap; attackers who find it bypass everything
- Flexible TLS mode for convenience — leaves origin traffic unencrypted
- No endpoint-specific rate limits on auth paths — login endpoints become brute-force targets
- Admin panels left public without Zero Trust or identity-based access controls
- WAF enabled but never tuned — false positives pile up, get excepted, and protection degrades
- Stale rules and exceptions with no owner or review date — rule sprawl that nobody wants to audit
- Logs available but disconnected from detection and response workflows
Keeping these in check requires discipline, not complexity. A monthly origin exposure check, a quarterly rule review, and TLS posture validation after infrastructure changes catch most drift before it becomes a problem.
Cloudflare hardening checklist
Use this as your acceptance bar before considering an app’s edge security baseline complete:
| Control Area | Checklist Item | Done |
|---|---|---|
| DNS Governance | Stale records removed; ownership documented | ☐ |
| Origin Protection | Origin not directly reachable from public internet | ☐ |
| TLS Posture | Full (Strict) mode enabled; HTTPS enforced globally | ☐ |
| WAF Baseline | Managed rulesets enabled and actively monitored | ☐ |
| Custom Rules | Sensitive routes protected with app-specific logic | ☐ |
| Rate Limiting | Auth, API, and admin endpoints have tailored limits | ☐ |
| Access Control | Admin surfaces protected with identity-based controls | ☐ |
| Logging | Edge and security logs exported with normalisation | ☐ |
| SIEM Correlation | Edge events linked to application and auth telemetry | ☐ |
| Governance | Rule ownership, review cadence, and exception tracking active | ☐ |
30-day implementation roadmap
You don’t need to do everything at once. This sequence gets the highest-value controls in place first.
Week 1 — Visibility and baseline Inventory your public DNS records and identify which are proxied through Cloudflare. Validate that your origin is not reachable directly. Document the top endpoints by risk exposure.
Week 2 — Core protection Tighten TLS to Full (Strict) mode and enforce HTTPS. Enable managed WAF rulesets and watch for false positives. Add custom rules for your highest-risk paths.
Week 3 — Abuse controls and access hardening Implement endpoint-specific rate limits on auth and API paths. Protect admin interfaces with identity-based access. Validate bot-abuse handling on login and registration flows.
Week 4 — Detection and governance Complete log export and SIEM correlation. Define your review cadence for rules and exceptions. Document the operational runbook for Cloudflare change management.
Keeping controls healthy over time
Nothing in this configuration degrades loudly. Rules do not expire, exceptions do not announce themselves, and origin firewall drift produces no alert. What you get instead is a config that was correct in March, an application that shipped four new endpoints since, and a dashboard that still looks exactly as green as it did on the day you finished.
A few discipline habits that prevent drift:
- Before any WAF or rate limit change: identify what real users could get blocked, start in log mode if possible, define rollback conditions, and confirm who’s watching dashboards during the rollout
- Monthly: verify origin IP protection; review high-volume WAF events for noise or missed signals
- Quarterly: audit the full rule and exception inventory; close stale exceptions; verify admin path access controls are current
| Operational KPI | Target Direction |
|---|---|
| WAF blocks generating false-positive support tickets | Down |
| Confirmed attack traffic blocked at edge | Up |
| Rate-limit false positives on legitimate users | Down |
| Time to roll back a bad rule change | Down |
Cloudflare delivers the most value when its controls are tuned to real application behaviour, origin hardening stays intact, and logs feed an active detection and response process. Edge security is a practice, not a one-time configuration.