Network zones
Define networks by address range or country, block from them or write policy against them, and roll it out without locking your own organisation out.
A network zone is a named set of network addresses. Once a zone exists you can do one of two things with it: block sign-ins that come from it, or reference it from an authentication policy rule — for example, to skip a second factor when someone is sitting in your own office.
Zones are the feature most likely to lock you out of your own console, so this article spends as much space on the safe rollout as on the model. Read the rollout section before you activate anything.
The two kinds of zone, and why the distinction is not cosmetic
Every zone has a usage, and it is the single most important field on the object.
- `POLICY` — the zone is a selector
- It names a network so that a policy rule can match on it. On its own it grants nothing and blocks nothing. 'Require a second factor unless the request is in zone Office' is a policy rule that references a
POLICYzone. - `BLOCKLIST` — the zone is enforced
- A request from a matching address is denied outright, before any rule is evaluated. Nothing later in the chain can override it, which is the entire point: a blocklist that a subsequent allow rule could reach around is not a blocklist.
A zone also carries a type of IP or DYNAMIC. That field is descriptive only — it is there to make a list of zones readable. The matcher evaluates whichever predicates you have populated regardless of what the type says.
What a zone can match on
Four predicates, plus a catch-all. Any one of them matching is enough — they are combined with OR, not AND — and the anonymiser constraint is then applied as a filter on top of whatever matched.
| Predicate | Accepts | Notes |
|---|---|---|
| Gateways | 203.0.113.0/24, a single address 203.0.113.7, or an inclusive range 203.0.113.1-203.0.113.20 | IPv6 is supported throughout. A range whose two ends are different address families is rejected as meaningless; reversed bounds are swapped for you. |
| Countries | Two-letter ISO country codes | Requires the address to have been resolved. Anything that is not a valid two-letter code is refused at save time. |
| Networks (ASNs) | Autonomous system numbers, with or without the AS prefix | Also requires resolution. |
| Anonymiser type | ANY, TOR, NOT_TOR, ANONYMIZER, NOT_ANONYMIZER | Normally a filter on the other predicates. A zone with no other predicates uses it as the predicate itself, which is how you express 'any Tor exit node, wherever it is'. |
| Include all | A flag | Matches every address, subject to the anonymiser filter. Refused on a blocklist zone, because it would deny every sign-in. |
Network (ASN) matching still depends entirely on your organisation's own IP intelligence entries — the mapping from address ranges to a network operator. There is no automatic source for that one; if you have not populated intelligence for a range, an ASN predicate against it will not match. Country matching is different now — see the section below.
Zone names are compared without regard to case when a policy rule references them, because administrators type those names by hand and office against Office must not become a silent hole in a policy.
Country resolution: no longer only manual IP intelligence
This matters most for exactly the kind of zone this article already warns you is easiest to get wrong: a country-only zone. Before this, such a zone matched nobody, full stop, unless you had hand-populated intelligence for every relevant address. Now, on a deployment fronted by Cloudflare (or one with a MaxMind database configured), a country predicate genuinely resolves for ordinary traffic without you doing anything extra.
Where in the sequence the check happens
This is the question that decides what a zone is actually good for, so here is the whole sequence:
- The password is verified.
- The account state is checked — is it active, is it locked out.
- Email verification is checked.
- Network zones. Blocklists are evaluated first and stop everything; matching policy zones are recorded as facts.
- Risk is scored.
- Policy rules are evaluated in order, first match wins.
- A second factor is demanded, if the winning rule says so.
Within the zone stage itself, blocklists are evaluated in a first pass on their own and return immediately on a match. Policy zones are collected in a second pass. Only zones with a status of ACTIVE participate in either pass, which is what makes staging a zone safe.
A blocked sign-in is answered with HTTP 403 and this message, which is what the person will read:
Sign-in from your current network is not permitted.
The decision trace records it as a matched entry named network blocklist followed by the zone name, with a reason naming the address and stating that blocklists are enforced before rule evaluation. So a blocked user is distinguishable from a user denied by a rule, which matters when somebody rings you.
Which address we actually judge
Everything above depends on getting the client's address right, and that is harder than it looks when there are proxies and load balancers in the path.
Forwarding headers are honoured only when the machine that connected to us is itself one of your configured trusted proxies. With no trusted proxies configured, the address of the immediate peer wins and the headers are ignored. Trusting a forwarding header unconditionally would let any caller claim to be inside your office range, which is a complete bypass of the feature.
When the peer is trusted, the forwarding chain is walked from the right, and the right-most entry that is not itself one of your trusted proxies is taken as the client. The left-most entry — the one most guides tell you to use — is fully controlled by whoever made the request.
Private addresses — the ranges used inside offices and homes — are recognised as such, which is why they lower the risk score slightly and why they carry no country or network facts.
What a new organisation starts with
Two zones are created for you, and both are inactive, so enabling either is a deliberate act.
| Zone | Usage | What it ships as |
|---|---|---|
| Corporate Network | POLICY | A single placeholder range, 198.51.100.0/24, which is a documentation range and matches nothing real. Replace it with your own public addresses. |
| Anonymising Proxies | BLOCKLIST | No addresses, an anonymiser constraint of ANONYMIZER, and a dependence on your IP intelligence entries to recognise anything. |
The default authentication policy contains a rule that references Corporate Network by name to allow a trusted device on the office network through without a second factor. Because the zone is inactive and its range is a placeholder, that rule cannot match on a fresh tenant. Neither of these is broken — they are staged. But it means that on the day you sign up, network enforcement is doing nothing at all, and any claim to the contrary would be wrong.
The safe rollout, in order
Everybody who locks themselves out does it the same way: by activating a blocklist, or a rule that depends on a zone, from a network that turns out not to be the one they thought they were on. Working addresses change. Home broadband changes overnight. A mobile hotspot is a different country's network operator.
Find out what address you actually arrive from
Not the address of your router, and not the one on a colleague's laptop over the same VPN. Use the evaluate surface on the network-zone endpoints, which tells you which zones a given address falls into, and confirm it from each site and each connection you care about.
Create the zone inactive, and get the predicates right first
A zone with no predicates and no include-all flag is refused at save time with
netzone: invalid zone definition: zone has no predicates and would never match; set include_all or add gateways/countries/asns/proxy_type— an empty zone used in a deny rule that matched everything would lock a tenant out, so the guard exists. A blocklist zone that sets include-all is refused for the same reason.Simulate the policy before you activate the zone
The authentication policy has a simulation surface that reuses the real evaluator without persisting anything. Run your own account and one ordinary member's account through it, from an office address and from an outside one. A simulator that does not share the evaluator is a simulator that lies, so this one shares it.
Make sure you have a route back in
An emergency access account that is not affected by the rule you are about to enable, credentials stored the way you store the keys to the building, and a second administrator who is not sitting on the same network as you. Test it before you need it.
Activate the zone, then watch the risk events
Every sign-in writes a row recording the zones it matched. Within an hour you will see whether the people you expected to be inside the zone actually are. See Adaptive MFA and risk signals.
Only then tighten the rule
Blocklists first, with a narrow definition. Rules that depend on a zone being matched — anything that relaxes a requirement inside the office — after you have a week of evidence that the zone matches when you think it does.
What a rejected zone definition says
Every validation failure is refused at save time with a message naming the field, so an invalid zone can never be persisted into a state where it silently misbehaves.
netzone: invalid zone definition: name is required
netzone: invalid zone definition: unparseable gateways: <list>
netzone: invalid zone definition: unparseable proxies: <list>
netzone: invalid zone definition: country "<c>" is not an ISO-3166-1 alpha-2 code
netzone: invalid zone definition: usage must be POLICY or BLOCKLIST
netzone: invalid zone definition: unknown proxy_type "<t>"
netzone: invalid zone definition: status must be ACTIVE or INACTIVE
netzone: invalid zone definition: a BLOCKLIST zone cannot set include_all — it
would deny every sign-in
netzone: invalid zone definition: zone has no predicates and would never match;
set include_all or add gateways/countries/asns/proxy_typeReusing a zone name is refused with a zone with that name already exists and HTTP 409. Zone administration is gated on iam:network_zones.read, .write and .delete, so you can grant somebody visibility into the zone definitions without granting the ability to change them — see The permission model.