Network policy L4 — blocking non-HTTP, DoH bypass, and app rules

Network policy deep dive: blocking non-HTTP (SSH, RDP, SMTP), preventing DoH bypass, app rules for SaaS, WARP keeping user traffic on Gateway, prod checklist, hardening playbook.

· 13 min read · Đọc bản tiếng Việt
Gateway Network policy L4 deep-dive: blocking non-HTTP traffic (SSH, RDP, SMTP, MySQL), shutting down DoH resolvers that bypass DNS filtering, SaaS app rules, and pairing with WARP to keep user traffic on Gateway

TL;DR

Network policy is Gateway’s layer 2 — the L4 filter between DNS (Part 11) and HTTP (Part 12). It inspects TCP/UDP connections without decrypting or reading the body. Its job:

  • Block non-HTTP traffic — SSH, RDP, SMTP, MySQL, custom ports.
  • Prevent DoH bypass — block DNS-over-HTTPS to third-party resolvers so the DNS policies in Part 11 can’t be routed around.
  • App rules — allow/block by application (Dropbox, BitTorrent); Gateway maintains the app → domain / IP mapping.
  • Direct-IP connections — malware using hard-coded IPs (no DNS) is only catchable at L4 by IP/CIDR.
  • Country / ASN filters — geo-based blocking.

This post covers:

  • Network vs DNS vs HTTP layers — which rule belongs where.
  • DoH bypass as the big deal — how to detect and block.
  • SNI inspection — Gateway sees the SNI without decryption and can rule on it.
  • App rules vs raw IP/port rules.
  • WARP tunnel vs DNS location — the L4 enforcement differences.
  • Logs and SIEM integration.

The thesis:

The network layer is the glue between DNS and HTTP. It closes the DoH gap, handles non-HTTP, and provides a fallback when HTTP decryption is exempted. Without L4 rules, an attacker bypasses the DNS filter via DoH or direct IPs — completely invisible to Gateway.

This is Part 13 of the Cloudflare One Handbook and closes the Policy & Filtering block (Parts 11–13).


Who this is for

  • Security engineers already running DNS + HTTP rules, needing to close the remaining gap.
  • SOC analysts investigating L4 anomalies.
  • Platform engineers setting up egress control for cloud workloads.

Recommended prior reading:

After this post you will:

  • Be able to write rules that block DoH bypass and non-HTTP traffic.
  • Understand SNI inspection vs full decryption — when each is enough.
  • Configure app rules for shadow IT.
  • Integrate L4 logs into a SIEM with useful fields.
  • Have a production checklist + hardening roadmap.

What this post does not cover

  • Magic WAN / Magic Firewall — Part 10, different context (site-to-site traffic).
  • Gateway API connectors for cloud egress — briefly referenced.
  • Browser Isolation — L7-specific.
  • WARP mode details — Part 9.
  • Email security — separate product (Area 1).

Concepts

  • Network policy — Gateway L4 rule: IP, port, protocol, SNI, app, country.
  • SNI (Server Name Indication) — hostname inside the TLS ClientHello, in plaintext. Gateway sees it without decryption.
  • DoH (DNS over HTTPS) — DNS queries over HTTPS, bypassing a plain DNS filter. Uses port 443 on the resolver host (Google dns.google, Quad9 dns.quad9.net).
  • DoT (DNS over TLS) — DNS over TLS, port 853. Less common but similar.
  • App (application) — Gateway-maintained mapping: app name → domains + IP ranges. For example, “Dropbox” = *.dropbox.com + its IP list.
  • Egress — traffic from an internal network (WARP / Magic WAN) going out to the Internet.
  • ASN (Autonomous System Number) — BGP network identifier; Gateway can filter by ASN (block sources in Russia, Iran, etc.).
  • Geo-IP — IP → country mapping from Cloudflare Radar.

Three-layer positioning — where network fits

Gateway 3 layers mapping: DNS handles queries, Network (L4) handles connections, HTTP handles requests. Each catches different threats. Network catches DoH bypass, direct IP, non-HTTP.

Threat coverage matrix

ThreatDNSNetworkHTTP
Domain-based malware✓ (SNI)
IP-direct C2
DoH bypass
Non-HTTP protocol
URL-path exfil
DLP body
Country blocklimited
Tor / VPN bypasspartial✓ (IP)
Cert-pinned app threat✓ (SNI)

Network fills the gaps: IP-direct, DoH, non-HTTP, Tor.

SNI — the real value of L4 inspection

The SNI is a plaintext hostname inside the TLS handshake. Gateway sees it even without decryption:

ClientHello → SNI: c2.badactor.io
           → Gateway matches SNI against policy
           → Block before TLS completes

SNI rules recover about 70% of the value of full decryption without the privacy/legal cost. If compliance forbids decryption, SNI rules still catch domain-based threats.

Pitfall: ECH (Encrypted ClientHello) encrypts the SNI. Browsers and clients that support ECH hide the SNI entirely. Gateway has to detect + block ECH attempts if SNI-based rules are to remain effective.


DoH bypass — the big one

DoH bypass flow: Attacker malware on endpoint → sends DNS-over-HTTPS (port 443) directly to dns.google / dns.quad9.net / any DoH resolver → bypasses the Gateway DNS filter. Network policy blocks DoH destinations to close the gap.

The problem

The DNS filter (Part 11) blocks malicious.com at the DNS layer. But:

  1. Malware doesn’t use the system resolver.
  2. Malware sends a DoH request to dns.google/dns-query on port 443.
  3. The Gateway DNS filter doesn’t see it — it isn’t plain DNS (UDP/53).
  4. Malware resolves the malicious domain → connects → exfiltrates.

The DNS filter is fully bypassed.

Who uses DoH

  • Modern browsers (Firefox, Edge, Chrome) have built-in DoH.
  • Advanced malware (post-2022) uses DoH to evade DNS filters.
  • Tech-savvy users who manually configure the OS resolver.

The L4 solution

Block third-party DoH hosts:

name: "Block third-party DoH resolvers"
action: block
condition: |
  net.dns.over_https
  or net.sni in {
    "dns.google",
    "dns.quad9.net",
    "cloudflare-dns.com",
    "mozilla.cloudflare-dns.com",
    "doh.opendns.com",
    "dns.nextdns.io",
    "dns.adguard.com"
  }
  or net.host in {
    "8.8.8.8", "8.8.4.4",
    "9.9.9.9", "149.112.112.112",
    "1.1.1.1", "1.0.0.1",
    "208.67.222.222"
  }

Allow only the tenant-specific DoH endpoint (WARP generates a tenant URL → whitelist that):

name: "Allow tenant DoH only"
action: allow
condition: |
  net.dns.over_https
  and net.sni == "[tenant-id].cloudflareaccess.com"

Block DoT (DNS over TLS, port 853)

name: "Block DoT"
action: block
condition: net.port == 853

Detecting DoH attempts in logs

Gateway logs filtered by Action: block, Policy: doh_block:

  • Source IP / user.
  • Destination SNI / IP.
  • Time.

A spike = investigate: endpoint compromise or a user manually configured it.


SNI-based rule examples

Block SaaS shadow IT at the SNI level

name: "Block personal cloud storage"
action: block
condition: |
  net.sni in {
    "*.dropbox.com", "*.box.com",
    "*.drive.google.com",
    "www.icloud.com",
    "mega.nz", "*.mega.nz"
  }
# Exception: the HTTP-layer policy allows the corporate Dropbox tenant.

Block crypto exchanges (internal policy)

name: "Block crypto exchanges"
action: block
condition: |
  net.sni in {
    "*.binance.com", "*.coinbase.com",
    "*.kraken.com", "*.kucoin.com"
  }

Allow only company-approved AI services

name: "Default-block AI"
action: block
condition: |
  net.sni in {
    "*.openai.com", "*.anthropic.com",
    "gemini.google.com", "*.copilot.microsoft.com"
  }
  and not (identity.groups in {"AI-approved"})

App rules — shortcuts for common apps

App rule matching: Gateway maintains mapping "Dropbox" → wildcard domains + IP ranges. User rule says "block Dropbox"; Gateway translates it to 15 hostnames + 200 IPs that auto-update.

Why app rules

Shadow-IT apps use many domains, CDNs, and IP ranges. Maintaining the list manually means it goes stale.

Cloudflare Gateway ships an app catalogue: Tor, BitTorrent, Dropbox, WhatsApp, and so on. Each app is a group of domains + IPs + SNI patterns.

Rule examples

name: "Block Tor network"
action: block
condition: net.app == "Tor"
# Gateway expands to: Tor entry-node IPs + Tor domains + Tor bridge relays,
# auto-updated via Cloudflare threat intel.
name: "Block torrents"
action: block
condition: net.app in {"Bittorrent", "eDonkey", "Gnutella"}
name: "Allow corporate Dropbox tenant, block personal"
# HTTP layer does the tenant check;
# network layer just allows the Dropbox app base.
action: allow
condition: net.app == "Dropbox"

Limitations

  • App definitions are maintained by Cloudflare — a new app may not be in the catalogue yet.
  • Fall back to a manual SNI/domain rule if an app is missing.

Non-HTTP traffic rules

Block outbound SSH, except approved hosts

name: "Block outbound SSH to non-corporate"
action: block
condition: |
  net.port == 22
  and not (net.host in $corporate_ssh_hosts)
# $corporate_ssh_hosts = approved jumpboxes, bastions, git.internal.

Block outbound RDP

name: "Block outbound RDP"
action: block
condition: |
  net.port == 3389
  and net.protocol == "TCP"
# RDP to the Internet = likely lateral movement from a compromised endpoint.
# Corporate RDP should go through ZTNA / Cloudflare Tunnel, not direct outbound.

Block direct SMTP (prevent spam)

name: "Block direct SMTP"
action: block
condition: |
  net.port in {25, 465, 587}
  and not (net.host in $approved_email_gateway)
# Only the approved gateway (e.g. Google Workspace MX) can send mail.

Block direct DB connections

name: "Block direct database connection to the Internet"
action: block
condition: |
  net.port in {3306, 5432, 1433, 27017, 6379}
  and net.direction == "outbound"
# MySQL, PostgreSQL, MSSQL, MongoDB, Redis.
# Internal DB access should go through Tunnel / Magic WAN.

Block Tor

name: "Block Tor"
action: block
condition: |
  net.app == "Tor"
  or net.port in {9001, 9030}
# Tor ORPort + DirPort.

Country / ASN rules

Block traffic to sanctioned countries

name: "Block sanctioned-country destinations"
action: block
condition: |
  net.geo.country in {"IR", "KP", "CU", "SY"}
# Compliance: the OFAC list. Review quarterly.

Allow admin access only from specific countries

name: "Admin tools only from office countries"
action: block
condition: |
  identity.groups in {"Admin"}
  and net.sni matches "*.admin.internal"
  and not (net.geo.country in {"VN", "SG", "US"})

WARP vs DNS location — L4 enforcement

WARP vs DNS location at L4: WARP encapsulates all packets through the tunnel (full L4 inspection available); DNS-location mode only sees DNS queries (L4 inspection requires traffic routed via a CF proxy separately).

Different enforcement models

WARP client:

  • Tunnels all network traffic (split-tunnel exceptions aside) to Cloudflare.
  • Gateway sees every TCP/UDP connection → L4 rules apply fully.
  • Identity-bound → per-user L4 rules.

DNS location:

  • Only DNS queries route to Cloudflare.
  • Non-DNS traffic goes direct to the Internet — Cloudflare never sees it.
  • L4 rules don’t apply in location mode.
  • Gap: malware on-site can still exfiltrate — only DNS is filtered.

Solutions for site mode

Option 1: Magic WAN — the site tunnels to Cloudflare, all traffic is inspected → Magic Firewall (not Gateway) — Part 10.

Option 2: an on-site proxy endpoint that routes HTTP to Cloudflare. Explicit proxy, not transparent — the workload has to know the proxy URL.

Option 3: upgrade to WARP per-device — best granularity.

Realistic enterprise mix: WARP (users) + Magic WAN (sites) + DNS location (guest/IoT). L4 coverage is complete for WARP + Magic WAN; guest/IoT gets DNS-only (acceptable as long as they don’t handle sensitive data).


Reference configuration — starter network policy

# Policy 1 — allow tenant infrastructure (whitelist first)
- name: "Allow corporate tenant DoH"
  action: allow
  condition: |
    net.sni == "[tenant].cloudflareaccess.com"

# Policy 2 — allow approved outbound
- name: "Allow approved outbound protocols"
  action: allow
  condition: |
    net.port in {80, 443, 53}
    or net.host in $approved_corp_hosts

# Policy 3 — block DoH bypass
- name: "Block third-party DoH/DoT resolvers"
  action: block
  condition: |
    net.dns.over_https
    or net.port == 853
    or net.sni matches "*.dns.google"
    or net.sni matches "*.quad9.net"
    or net.host in {"8.8.8.8","8.8.4.4","9.9.9.9","149.112.112.112","208.67.222.222"}

# Policy 4 — block risky non-HTTP outbound
- name: "Block dangerous outbound protocols"
  action: block
  condition: |
    net.port in {22, 23, 3389, 445, 1433, 3306, 5432, 6379, 27017}
    and net.direction == "outbound"
  # SSH, Telnet, RDP, SMB, SQL variants, Redis, MongoDB.
  # Exception: specific corporate bastions/DBs routed via Tunnel (Part 8).

# Policy 5 — block Tor, torrents, proxy apps
- name: "Block anonymiser / P2P"
  action: block
  condition: |
    net.app in {"Tor", "Bittorrent", "eDonkey", "UltraSurf", "Psiphon"}

# Policy 6 — block personal cloud storage
- name: "Block personal storage"
  action: block
  condition: |
    net.sni in {
      "www.icloud.com","*.mega.nz","*.terabox.com",
      "*.zippyshare.com","*.mediafire.com"
    }

# Policy 7 — block sanctioned countries
- name: "Block sanctioned country"
  action: block
  condition: |
    net.geo.country in {"IR","KP","CU","SY"}

# Policy 8 — identity-based admin geo-fence
- name: "Admin tools geo-fence"
  action: block
  condition: |
    identity.groups in {"Admin-Prod"}
    and net.sni matches "*.admin.prod.*"
    and not (net.geo.country in {"VN","SG","US"})

# Policy 9 — default allow
- name: "Default allow"
  action: allow
  condition: "true"

Security considerations

Trust model

  • Gateway side: Cloudflare validates policy-evaluation correctness.
  • Customer side: rule correctness, exception hygiene.
  • Endpoint integrity: a user with local admin can disable WARP → bypass. MDM must enforce WARP is running.

Blind spots

  • Outside WARP scope: split-tunnel exclusion lists, networks outside WARP (home IoT).
  • ECH / encrypted SNI: future-proofing — plan to block ECH attempts until a fingerprint is available.
  • VPN on top of WARP: a user running a VPN on top of WARP encrypts traffic before WARP sees it → Gateway can’t inspect. Block user-level VPN apps via app rules.
  • Non-CF proxied sites: in DNS-location mode, only DNS is visible.

Anti-bypass playbook

  • Block DoH/DoT resolver IPs + SNIs (Policy 3 above).
  • Block Tor + anonymisers (Policy 5).
  • Block VPN apps (NordVPN, ExpressVPN, etc.) via app rules.
  • MDM enforces WARP running + auto-start.
  • Alert on WARP disconnections > 5 minutes per user.
  • Identity-bound rules with posture checks (device compliance) — covered in Part 16.

Compliance mapping

  • ISO 27001 A.8.20 Network security.
  • NIST CSF PR.AC-5 (network integrity), DE.CM-1 (continuous monitoring).
  • PCI DSS 4.0 1.2.5 (permitted connections), 1.4.2 (anti-spoofing).
  • CIS 12.1 (secure network infrastructure), 13.4 (perform traffic filtering).

Operations and monitoring

Metrics

  • Blocked connections/s — baseline + spike alert.
  • Top blocked ports — 22/3389/445 = lateral-movement attempts.
  • Top blocked countries — reflects the geopolitical threat landscape.
  • DoH block count — trend. Spikes = endpoint compromise or a browser defaulting to DoH.
  • App rule hits — Tor/BitTorrent = policy violations.

Alerting

  • Spike of 10× baseline in 15 minutes = incident.
  • The same user hitting blocked outbound ≥ 3× per hour = SOC triage.
  • WARP disconnect > 10 minutes = endpoint issue or bypass attempt.
  • Unexpected country block (US → a random Russian IP connection) = possible C2.

Logs pipeline

L4 logs flow: Gateway network events → logs store → Logpush → SIEM. Fields: timestamp, user, source IP, dest IP/SNI, port, protocol, app, country, action, policy ID.

Important fields

{
  "Timestamp": "2026-05-14T10:15:42Z",
  "UserID": "u_abc",
  "Email": "alice@company.com",
  "DeviceID": "d_xyz",
  "SourceIP": "10.0.0.42",
  "DestinationIP": "8.8.8.8",
  "DestinationPort": 443,
  "Protocol": "TCP",
  "SNI": "dns.google",
  "App": "Google DNS",
  "DestinationCountry": "US",
  "DestinationASN": 15169,
  "Action": "block",
  "PolicyID": "p_block_doh",
  "PolicyName": "Block third-party DoH"
}

Dataset: gateway_network.

SIEM correlation

  • Correlate DNS + Network + HTTP logs per user to identify multi-layer attacks.
  • Example: a DNS log entry “malicious.com blocked” + 5 minutes later “direct IP 1.2.3.4 blocked” → the attacker tried DNS, fell back to IP.
  • Detection rules in SIEM (Splunk, Sentinel): pattern-match across datasets.

Common troubleshooting

”A developer says SSH to GitHub is failing”

$ git clone git@github.com:company/repo.git
Connection to github.com port 22 refused
  1. Logs → Network → filter by user + port 22.
  2. See a block hit on “Block outbound SSH to non-corporate”.
  3. Check: GitHub SSH for the dev workflow is legit. Add github.com + ssh.github.com to $approved_ssh_hosts.
  4. Test: retry clone → works.

Alternative: GitHub offers HTTPS clone — consider enforcing HTTPS-only.

”Redis monitoring from the jumpbox fails”

  • Port 6379 is blocked outbound.
  • Route Redis via Cloudflare Tunnel (Part 8) — the client talks to redis.corp.internal through Gateway.
  • Or add the source IP (jumpbox) exception to $internal_db_access.

”Zoom calls drop frequently”

  • Zoom uses non-standard UDP ports (8801–8810, TCP 80/443/3478).
  • Check: net.app == "Zoom" rule explicitly allows.
  • Add the Zoom app rule with precedence ahead of generic UDP blocks.

”ECH domains no longer show up in logs”

  • The browser upgraded to Encrypted ClientHello.
  • Gateway can’t read the SNI → falls back to IP-based matching.
  • Solution: block clients attempting ECH (via fingerprint) OR fully decrypt HTTPS (Part 12).
  • Track Cloudflare’s ECH-detection feature timeline.

”A legitimate DoH endpoint is blocked”

  • The corporate browser is using the vendor’s DoH instead of the company tenant.
  • Verify: browser config → enforce the enterprise DoH endpoint or disable it.
  • GPO/MDM: set Firefox network.trr.uri to the tenant endpoint.
  • Chrome: DnsOverHttpsMode = automatic + the company endpoint.

”Log volume is too high”

  • Network logs are verbose — every connection.
  • Sample 10% non-blocked, 100% blocked.
  • Cloudflare supports sampling at Logpush.

Trade-offs and design decisions

DecisionOption AOption BRecommendation
Block DoH comprehensivelyBlock all third-partyBlock majors, allow restBlock all third-party. Attackers use obscure DoH resolvers too. Allow only the tenant DoH.
Block outbound SSHHard blockAllow with auditHard block by default, whitelist specific. SSH is a ransomware vector.
App rule vs raw IPRaw IP/domain listApp rule (CF catalogue)App rule for common shadow IT. Raw for custom threat IoCs.
Country-block granularityWhole-country blockSpecific CIDRCountry initially (coverage), refine with CIDR for false positives.
Log sampling100%SampleSample non-blocked (10%), 100% of blocks. Balance storage vs forensics.
SNI inspect vs full decryptSNI only (privacy)Full decryptSNI + L4 is enough for most control. Full decrypt only for DLP/CASB needs.
ECH handlingAllow (future)Block attemptsBlock ECH until Cloudflare visibility catches up. Document for a future unblock.

Rollout playbook

Phase 1 — Audit (1–2 weeks)

  • Inventory the current L4 policy (existing firewall rules, existing blocks).
  • Traffic analysis: top ports, SNIs, countries from current logs.
  • Identify current gaps (DoH passing? Tor? SSH outbound allowed?).

Phase 2 — Log-only baseline (2 weeks)

  • Enable every candidate policy in log-only mode.
  • Measure the false-positive rate.
  • Identify legitimate services that hit rules (build the exception list).

Phase 3 — Progressive blocking

  • Start with the highest-confidence rules: DoH block, Tor block, sanctioned countries.
  • Monitor for 1 week per batch.
  • Next batch: non-HTTP outbound (SSH, RDP, SMTP block).
  • Final batch: app rules (BitTorrent, anonymisers), granular personal cloud storage.

Phase 4 — Continuous refinement

  • Monthly review: block hit rates, false-positive tickets, new threats.
  • Quarterly: refresh the country list, app-catalogue update, IoC feed integration.

Checklist — before L4 in production

Policy coverage:

  • Third-party DoH resolvers blocked.
  • DoT (port 853) blocked unless whitelisted.
  • Outbound SSH/RDP/SMTP/DB blocked except for the approved list.
  • Tor + P2P apps blocked.
  • Personal cloud storage blocked.
  • Sanctioned countries blocked.
  • Anonymiser/VPN apps blocked.

Enforcement:

  • WARP enrolled on all user devices.
  • MDM enforces WARP running + auto-connect.
  • Alert on WARP disconnects > 10 minutes.
  • Magic WAN for site egress (when applicable).
  • Guest wifi / IoT routed via DNS location (accept DNS-only coverage).

Logs & SIEM:

  • Logpush dataset gateway_network to SIEM.
  • Fields mapped: user, src IP, dst IP/SNI, port, action.
  • Retention ≥ 1 year.
  • SIEM correlation rules (DNS + Network + HTTP multi-layer).
  • Dashboard: top blocked, trend, geo.

Monitoring:

  • Baseline metrics: block rate, connection volume.
  • Alert on 10× baseline spikes.
  • Per-user block threshold → SOC triage.
  • Runbook: user-ticket resolution flow.

Operations:

  • Exception-request process documented.
  • Whitelist hygiene: quarterly review, remove stale entries.
  • Cert-pin exception list synced with the HTTP layer (Part 12).
  • Sanctioned-country list refresh quarterly.

Lessons from practice

  • DoH bypass is priority #1. Without a DoH block, most of the DNS filter is moot. Browser-default DoH is rising; the problem grows over time.
  • Blocking SSH breaks developer workflows instantly. Communicate ahead and provide alternatives (HTTPS git, Cloudflare Tunnel for internal SSH).
  • The app catalogue goes stale. When a new SaaS launches, Cloudflare may not have an entry yet. Fall back to manual SNI rules.
  • Users look for WARP bypasses. Mobile hotspots, disconnecting WARP. MDM enforcement + posture checks are critical.
  • Log volume explodes. The network layer is 3–5× more verbose than DNS. Sampling + retention tuning is necessary.
  • Week-one false positives run high. Legitimate services hit the rules. Two weeks of log-only is the minimum.
  • ECH is a ticking clock. When browsers default to ECH, SNI-based rules degrade. Plan a decrypt transition or an ECH block.
  • Geo-block is a blunt instrument. It covers 80% of country-based threats but misses VPN-hopping attackers. Combine with ASN + CIDR.

Summary

The network layer closes the Policy & Filtering block. Together with DNS (Part 11) and HTTP (Part 12) it forms a three-tier SWG:

  • DNS: broad, cheap, the first line.
  • Network (L4): closes the DoH gap, catches non-HTTP, direct-IP, and geo-based threats.
  • HTTP: granular URL, DLP, CASB, body inspection.

No single layer is sufficient on its own. Each handles a class of threats that the others can’t see. Skipping the network layer leaves a back door for experienced attackers.

One line to remember:

Network policy isn’t as glamorous as DLP or CASB, but without it, DNS + HTTP filters are trivial to bypass. Blocking DoH and controlling non-HTTP are the minimum bar for a production Gateway.

That closes the Policy & Filtering block (Parts 11–13). The next block covers Observability & Ops: the end-to-end logs pipeline, SIEM integration, DEX (Digital Experience Monitoring), and posture signals for continuous verification.


References

In this series: