100 punten op internet.nl

100% scoren op internet.nl met Cloudflare

Deze handleiding helpt je om de maximale score te halen op internet.nl, met de nieuwe TLS richtlijnen van het NCSC (2025), wanneer je website achter Cloudflare zit. Welke score je kunt halen hangt af van je TLS-configuratie.

Minimum TLS 1.3

De makkelijkste manier om 100% te scoren is simpelweg de minimale TLS-versie op 1.3 te zetten. Op deze manier heb je ook geen Advanced Certificate Manager (ACM) of aangepaste cipher suite configuratie nodig.

De afweging: clients die alleen TLS 1.2 ondersteunen (oudere apparaten, sommige bots) kunnen geen verbinding meer maken. Alle moderne browsers en besturingssystemen ondersteunen TLS 1.3.

100% haalbaar met minimum TLS 1.3 โ€” geen ACM nodig.

Minimum TLS 1.2 met ACM

Wanneer je TLS 1.2 clients moet ondersteunen, kun je op dit moment niet de volledige 100% halen. Cloudflare accepteert namelijk verbindingen waarbij de client alleen SHA-1 als signature-algoritme aanbiedt (ยง3.3.5 van de NCSC richtlijnen).

De impact hiervan is in de praktijk minimaal: SHA-1 wordt alleen gebruikt als de client geen sterkere algoritmes zoals SHA-256 adverteert. De server kiest er dan voor om de verbinding toch te laten slagen in plaats van af te breken. Voor clients die alleen TLS 1.2 ondersteunen is upgraden naar TLS 1.3 de belangrijkste stap โ€” dat biedt meer veiligheidswinst dan het uitsluiten van SHA-1.

Als onderdeel van Cloudflare's strategie om zoveel mogelijk verkeer af te handelen door middel van moderne, veilige Rust code (zie Cloudflare just got faster and more secure, powered by Rust), zal ook het TLS sessie afhandeling systeem (gebaseerd op NGINX) gemigreerd worden. Dit zal gefaseerd gebeuren en een vaste tijdslijn is er op dit moment niet.

Om de overige cipher suite tests te halen moet Cloudflare geconfigureerd worden met de Modern cipher suite lijst. Hiervoor is Advanced Certificate Manager (ACM) nodig (een betaalde feature).

98% is op dit moment de maximale score met minimum TLS 1.2 en ACM.

๐Ÿ“ž 100% nodig maar TLS 1.2 vereist?

Heeft jouw organisatie een strikte verplichting om 100% te scoren maar kun je TLS 1.2 niet uitschakelen? Neem dan contact op met je Cloudflare-accountteam โ€” er zijn opties beschikbaar, maar deze vereisen aanvullende architectuurkeuzes en begeleiding.

Minimum TLS 1.2 zonder ACM

De standaard lijst met cipher suites die gebruikt wordt met Universal SSL is het zgn. "Legacy" security niveau. Deze lijst bevat cipher suites die onvoldoende zijn volgens de NCSC richtlijnen.

95% is de maximale score zonder ACM (met de standaard Legacy cipher suite lijst).

Post-quantum cryptografie (PQC)

Helaas ondersteunt internet.nl nog geen rapportage op ondersteuning van hybride sleuteluitwisselingsalgoritmes (waarin 'klassieke' en 'quantumveilige' algoritmes gecombineerd worden). Websites achter Cloudflare ondersteunen dit echter automatisch, zonder verdere configuratie: Post-quantum cryptography.

Cloudflare Radar biedt ook een tool aan om te checken of een website al een hybride sleuteluitwisselingsalgoritme ondersteunt: Radar PQC checker.

Instructies

Hieronder volgen de instructies om Cloudflare op de juiste manier in te stellen. Deze instructies zijn bewust in het Engels.

๐Ÿง  Tip: gebruik een AI-agent

Laat je LLM deze pagina lezen (de site serveert ook markdown) en gebruik de Cloudflare Skills om je zone automatisch te configureren.

Scoring 100% on internet.nl with Cloudflare

This guide helps you achieve the maximum score on internet.nl, with the new NCSC TLS guidelines (2025), when your website is behind Cloudflare. The score you can achieve depends on your TLS configuration.

Minimum TLS 1.3

The easiest way to score 100% is to simply set the minimum TLS version to 1.3. This way you also don't need Advanced Certificate Manager (ACM) or custom cipher suite configuration.

The tradeoff: clients that only support TLS 1.2 (older devices, some bots) will no longer be able to connect. All modern browsers and operating systems support TLS 1.3.

100% achievable with minimum TLS 1.3 โ€” no ACM needed.

Minimum TLS 1.2 with ACM

When you need to support TLS 1.2 clients, you currently cannot achieve the full 100%. Cloudflare accepts connections where the client only offers SHA-1 as a signature algorithm (ยง3.3.5 of the NCSC guidelines).

The practical impact is minimal: SHA-1 is only used when the client doesn't advertise stronger algorithms like SHA-256. The server then chooses to allow the connection rather than dropping it. For clients still on TLS 1.2, upgrading to TLS 1.3 is the most impactful step โ€” it provides far greater security benefits than eliminating SHA-1.

As part of Cloudflare's strategy to handle as much traffic as possible using modern, secure Rust code (see Cloudflare just got faster and more secure, powered by Rust), the TLS session handling system (based on NGINX) will also be migrated. This will happen in phases and there is no fixed timeline at this point.

To pass the remaining cipher suite tests, Cloudflare must be configured with the Modern cipher suite list. This requires Advanced Certificate Manager (ACM) (a paid feature).

98% is currently the maximum score with minimum TLS 1.2 and ACM.

๐Ÿ“ž Need 100% but require TLS 1.2?

Does your organization have a strict requirement to score 100% but cannot disable TLS 1.2? Contact your Cloudflare account team โ€” there are options available, but they require additional architecture decisions and guidance.

Minimum TLS 1.2 without ACM

The default cipher suite list used with Universal SSL is the so-called "Legacy" security level. This list contains cipher suites that are insufficient according to the NCSC guidelines.

95% is the maximum score without ACM (using the default Legacy cipher suite list).

Post-quantum cryptography (PQC)

Unfortunately, internet.nl does not yet report on support for hybrid key exchange algorithms (combining 'classical' and 'quantum-safe' algorithms). Websites behind Cloudflare automatically support this, without any configuration: Post-quantum cryptography.

Cloudflare Radar also offers a tool to check whether a website already supports a hybrid key exchange algorithm: Radar PQC checker.

๐Ÿง  Tip: use an AI agent

Point your LLM at this page (the site also serves markdown) and use the Cloudflare Skills to configure your zone automatically.

Configuration instructions

Prerequisites

๐Ÿ’ฐ Advanced Certificate Manager (ACM) โ€” only needed with minimum TLS 1.2

ACM ($10/zone/month) is required when using minimum TLS 1.2. Without it, you cannot restrict cipher suites to the Modern preset โ€” the Legacy preset includes CBC, 3DES, and static-RSA ciphers that fail the NCSC-NL TLS guidelines. If you set minimum TLS version to 1.3, ACM is not needed.

All API examples below use $ZONE_ID and $CF_API_TOKEN. Set them in your shell:

export ZONE_ID="<your zone id>"
export CF_API_TOKEN="<token>"

Token permissions needed: Zone Settings Write, SSL and Certificates Write, DNS Write, Zone Rulesets Write.

IPv6 Automatic

Nameserver and web server reachability over IPv6.

Nameserver IPv6

Cloudflare's *.ns.cloudflare.com nameservers are dual-stack and covered by AS13335 ROAs. Passes automatically when your registrar delegates to Cloudflare nameservers.

Web server IPv6

For any proxied (orange-cloud) record, Cloudflare automatically serves AAAA responses. The IPv6 Compatibility setting must be enabled (it is by default).

Network โ†’ IPv6 Compatibility โ†’ On
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/ipv6" \
  -X PATCH \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  --json '{"value":"on"}'

DNSSEC Configuration needed

Domain signature validation. Requires both enabling at Cloudflare and adding the DS record at your registrar.

DNS โ†’ Settings โ†’ DNSSEC โ†’ Enable DNSSEC

A modal will display the DS record values (Algorithm 13, ECDSA P-256/SHA-256, Digest Type 2). Copy these values to your registrar.

# Enable zone signing
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dnssec" \
  -X PATCH \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  --json '{"status":"active"}'

# Retrieve the DS record to add at your registrar
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dnssec" \
  -H "Authorization: Bearer $CF_API_TOKEN"

โš ๏ธ Registrar action required

Paste the DS record into your registrar's control panel. Without the DS at the parent zone, DNSSEC validation fails.

๐Ÿšจ Migration warning

If migrating a zone to Cloudflare, disable DNSSEC at the old provider first. Leaving an old DS record during a nameserver swap breaks DNS resolution.

HTTPS & TLS Configuration needed

Covers 12 internet.nl subtests: HTTPS redirect, HSTS, TLS versions, key exchange, compression, renegotiation, 0-RTT, OCSP, EMS, and certificate validation.

HTTPS redirect & SSL mode

Enable Always Use HTTPS and set the encryption mode to Full (strict).

SSL/TLS โ†’ Overview โ†’ Full (strict)
SSL/TLS โ†’ Edge Certificates โ†’ Always Use HTTPS โ†’ On
SSL/TLS โ†’ Edge Certificates โ†’ Automatic HTTPS Rewrites โ†’ On
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/ssl" \
  -X PATCH \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  --json '{"value":"strict"}'

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/always_use_https" \
  -X PATCH \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  --json '{"value":"on"}'

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/automatic_https_rewrites" \
  -X PATCH \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  --json '{"value":"on"}'

๐Ÿ“œ Origin certificate

Full (strict) requires your origin to present a valid certificate on port 443. Use a Cloudflare Origin CA certificate or a public CA cert.

HSTS

Required: max-age โ‰ฅ 31,536,000 (1 year), with includeSubDomains and preload.

SSL/TLS โ†’ Edge Certificates โ†’ HTTP Strict Transport Security (HSTS) โ†’ Enable

Set: Max Age = 12 months, Include subdomains = On, Preload = On, No-Sniff = On.

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/security_header" \
  -X PATCH \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  --json '{
    "value": {
      "strict_transport_security": {
        "enabled": true,
        "max_age": 31536000,
        "include_subdomains": true,
        "preload": true,
        "nosniff": true
      }
    }
  }'

TLS version

โ„น๏ธ Minimum TLS 1.3 vs 1.2

Your choice of minimum TLS version determines both the maximum internet.nl score and whether you need ACM:

  • Minimum TLS 1.3 โ†’ 100% score possible. No ACM or cipher suite changes needed โ€” TLS 1.3 cipher suites are compliant by default. Older TLS 1.2-only clients will be dropped.
  • Minimum TLS 1.2 โ†’ 98% score (currently). Requires ACM to set cipher suites to Modern. The SHA-1 hash function limitation prevents 100%.

If you previously configured custom cipher suites (e.g. the Modern preset via ACM), you must first reset them to the default (Legacy) before you can change the minimum TLS version to 1.3. Cloudflare does not allow custom cipher suite configuration combined with minimum TLS 1.3.

Option A: Minimum TLS 1.3 (for 100%)

If you have custom cipher suites configured, reset them first, then set minimum TLS version to 1.3.

SSL/TLS โ†’ Edge Certificates โ†’ Cipher suites โ†’ Configure โ†’ By security level โ†’ Legacy โ†’ Save

(Only needed if you previously changed cipher suites. Skip if they are already on the default.)

SSL/TLS โ†’ Edge Certificates โ†’ Minimum TLS Version โ†’ TLS 1.3
# Reset cipher suites to default (only if previously customized)
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/ciphers" \
  -X PATCH \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  --json '{"value":[]}'

# Set minimum TLS version to 1.3
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/min_tls_version" \
  -X PATCH \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  --json '{"value":"1.3"}'

Option B: Minimum TLS 1.2 (for 98%, requires ACM)

Set minimum TLS version to 1.2 and enable TLS 1.3. Then configure cipher suites to Modern (see Cipher suites section below). Do not set TLS 1.3 to "zrt" โ€” that enables 0-RTT.

SSL/TLS โ†’ Edge Certificates โ†’ Minimum TLS Version โ†’ TLS 1.2
SSL/TLS โ†’ Edge Certificates โ†’ TLS 1.3 โ†’ On
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/min_tls_version" \
  -X PATCH \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  --json '{"value":"1.2"}'

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/tls_1_3" \
  -X PATCH \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  --json '{"value":"on"}'

0-RTT (must be off)

Internet.nl requires 0-RTT to be disabled. It is off by default โ€” just confirm.

Speed โ†’ Settings โ†’ Protocol Optimization โ†’ 0-RTT Connection Resumption โ†’ Off
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/0rtt" \
  -X PATCH \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  --json '{"value":"off"}'

Automatic subtests (no configuration needed)

These subtests pass automatically on Cloudflare's edge:

SubtestWhy it passes
Cipher suite orderCloudflare enforces server cipher preference
Key exchange parametersOnly ECDHE (X25519, P-256, P-384); no finite-field DHE
Hash functions for key exchangeSee note below
TLS compressionBoringSSL never offers compression (CRIME mitigated)
Secure renegotiationRFC 5746 supported; client-initiated renegotiation disabled
OCSP staplingHigh-Reliability OCSP Stapling on all edge certs
Extended Master SecretRFC 7627 EMS advertised by BoringSSL
Certificate chainUniversal SSL/ACM certs are publicly-trusted, RSA โ‰ฅ 2048 or ECDSA P-256+

๐Ÿ”’ Hash function for key exchange โ€” TLS 1.2 limitation

This only applies when minimum TLS version is set to 1.2. If you use minimum TLS 1.3, this limitation does not affect you and you can score 100%.

Internet.nl tests whether the server accepts a TLS 1.2 handshake where the client only offers SHA-1 signature algorithms. Cloudflare accepts such connections and falls back to SHA-1 for the ServerKeyExchange signature. This causes the "insufficiently secure hash function" failure.

In practice, the impact is limited: SHA-1 is only used when the client doesn't advertise stronger algorithms. The server chooses to continue the connection rather than dropping it. TLS 1.3 clients (all modern browsers) are unaffected โ€” they use only SHA-256+ and also benefit from post-quantum key exchange. For clients still on TLS 1.2, upgrading to TLS 1.3 provides far greater security benefits than addressing this specific hash function fallback.

This is not configurable through any Cloudflare zone setting, cipher suite selection, or certificate type while keeping TLS 1.2 support. This is a Cloudflare platform behavior that cannot currently be resolved at the zone level for TLS 1.2 connections.

Organizations with strict compliance requirements (e.g. public sector) that need to achieve 100% while maintaining TLS 1.2 support can contact their Cloudflare account team to discuss available options โ€” these involve architectural tradeoffs and are not self-service.

HTTP compression (recommended, not scored)

Brotli/gzip are applied by default. Internet.nl issues an orange warning about BREACH but it does not affect the score.

Cipher suites Configuration needed

Only AEAD ciphers (GCM, ChaCha20-Poly1305) with ECDHE key exchange pass. No CBC, no static-RSA, no 3DES, no SHA-1 HMAC.

๐Ÿ’ฐ Advanced Certificate Manager (ACM) required

Cipher suite customization requires ACM ($10/zone/month). Without ACM, the Legacy preset includes 14 non-compliant ciphers (CBC, 3DES, static-RSA) and cannot pass the internet.nl cipher suite test.

SSL/TLS โ†’ Edge Certificates โ†’ Cipher suites โ†’ Configure

Select By security level โ†’ Modern โ†’ Save. The "Modern" option only appears if ACM is active.

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/settings/ciphers" \
  -X PATCH \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  --json '{
    "value": [
      "ECDHE-ECDSA-AES128-GCM-SHA256",
      "ECDHE-ECDSA-CHACHA20-POLY1305",
      "ECDHE-RSA-AES128-GCM-SHA256",
      "ECDHE-RSA-CHACHA20-POLY1305",
      "ECDHE-ECDSA-AES256-GCM-SHA384",
      "ECDHE-RSA-AES256-GCM-SHA384"
    ]
  }'

These 6 ciphers are exactly the Cloudflare "Modern" preset. All are ECDHE + AEAD, covering both ECDSA and RSA leaf certificates. TLS 1.3 ciphers are always enabled automatically.

Security headers Configuration needed

X-Frame-Options, X-Content-Type-Options, Referrer-Policy, and Content-Security-Policy.

X-Frame-Options, X-Content-Type-Options, Referrer-Policy

These three headers are handled by the Cloudflare Managed Transform "Add security headers". One toggle, no custom rules needed.

Rules โ†’ Settings โ†’ Managed Transforms โ†’ HTTP response headers โ†’ Add security headers โ†’ On

This sets:

  • X-Frame-Options: SAMEORIGIN
  • X-Content-Type-Options: nosniff
  • Referrer-Policy: same-origin
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/managed_headers" \
  -X PATCH \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  --json '{
    "managed_request_headers": [],
    "managed_response_headers": [
      {"id": "add_security_headers", "enabled": true},
      {"id": "remove_x-powered-by_header", "enabled": true}
    ]
  }'

Content-Security-Policy (CSP)

CSP is not included in the Managed Transform. You need a separate Transform Rule. Internet.nl requires a restrictive default-src, explicit frame-ancestors, form-action, and base-uri.

โš ๏ธ CSP pitfalls

'unsafe-inline', 'unsafe-eval', bare https:, and mixing 'none' with other sources all fail internet.nl. Keep it strict.

Rules โ†’ Transform Rules โ†’ Create rule โ†’ Modify Response Header

Expression: true (all requests). Add a Set static header:

  • Header name: Content-Security-Policy
  • Value: default-src 'self'; frame-ancestors 'none'; form-action 'self'; base-uri 'self'; object-src 'none'; upgrade-insecure-requests
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/phases/http_response_headers_transform/entrypoint" \
  -X PUT \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  --json '{
    "rules": [{
      "expression": "true",
      "action": "rewrite",
      "description": "Set CSP header for internet.nl compliance",
      "action_parameters": {
        "headers": {
          "Content-Security-Policy": {
            "operation": "set",
            "value": "default-src '\''self'\''; frame-ancestors '\''none'\''; form-action '\''self'\''; base-uri '\''self'\''; object-src '\''none'\''; upgrade-insecure-requests"
          }
        }
      }
    }]
  }'

๐Ÿ”ง Adapt CSP to your site

If your site loads external scripts, fonts, or images, add specific sources. Avoid 'unsafe-inline' โ€” use hashes or nonces instead.

security.txt Configuration needed

RFC 9116 vulnerability disclosure file at /.well-known/security.txt.

Cloudflare serves security.txt directly from the edge via the Security Center feature. Required fields: Contact: (โ‰ฅ1) and Expires: (within ~1 year).

Security โ†’ Settings โ†’ Security.txt โ†’ Configure

Fill in: Contact (mailto: URI), Expires (date), Canonical, Preferred-Languages. Save.

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/security-center/securitytxt" \
  -X PUT \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  --json '{
    "enabled": true,
    "contact": ["mailto:security@example.com"],
    "expires": "2027-04-21T00:00:00Z",
    "preferred_languages": "en, nl",
    "canonical": ["https://example.com/.well-known/security.txt"]
  }'

RPKI Automatic

Route Origin Authorization for web server and nameserver IPs.

Cloudflare operates AS13335 with ROAs covering all announced prefixes. All proxied host IPs and nameserver IPs are covered. No configuration needed.

For unproxied (grey-cloud) origins, your hosting provider must publish a ROA. Most major providers (AWS, GCP, Azure, Hetzner, etc.) already do.

SPF Configuration needed

Sender Policy Framework. Record must be present, valid syntax, โ‰ค10 DNS lookups, policy -all or ~all.

๐Ÿ“ง Email Routing

If you enable Cloudflare Email Routing, the SPF record is created automatically with include:_spf.mx.cloudflare.net ~all.

DNS โ†’ Records โ†’ Add record

Type: TXT, Name: @, Content: v=spf1 include:_spf.mx.cloudflare.net ~all

Replace the include: with your mail provider's SPF mechanism (e.g. include:_spf.google.com for Google Workspace).

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
  -X POST \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  --json '{
    "type": "TXT",
    "name": "example.com",
    "content": "v=spf1 include:_spf.mx.cloudflare.net ~all",
    "ttl": 3600
  }'

DKIM Configuration needed

DomainKeys Identified Mail. At least one valid DKIM public-key TXT record required.

๐Ÿ“ง Email Routing

If you enable Cloudflare Email Routing, a DKIM record is created automatically at cf2024-1._domainkey.

DNS โ†’ Records โ†’ Add record

Type: TXT, Name: <selector>._domainkey, Content: the v=DKIM1; k=rsa; p=... value from your mail provider.

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
  -X POST \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  --json '{
    "type": "TXT",
    "name": "selector._domainkey.example.com",
    "content": "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEB...",
    "ttl": 3600
  }'

For a non-sending (parked) domain, publish a wildcard null key: *._domainkey.example.com TXT "v=DKIM1; p="

DMARC Configuration needed

Policy must be p=quarantine or p=reject. p=none fails.

Email โ†’ DMARC Management โ†’ Enable

Cloudflare's DMARC Management creates the record and sets up aggregate reporting to @dmarc-reports.cloudflare.net. Important: DMARC Management defaults to p=none (monitoring mode). For internet.nl you must change the policy to p=reject by editing the TXT record.

DNS โ†’ Records โ†’ Edit _dmarc TXT record

Change the content to:

v=DMARC1; p=reject; sp=reject; adkim=s; aspf=s; fo=1; rua=mailto:<your-id>@dmarc-reports.cloudflare.net

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
  -X POST \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  --json '{
    "type": "TXT",
    "name": "_dmarc.example.com",
    "content": "v=DMARC1; p=reject; sp=reject; adkim=s; aspf=s; fo=1; rua=mailto:dmarc@example.com",
    "ttl": 3600
  }'

โš ๏ธ p=none will fail

Internet.nl requires p=quarantine or p=reject. If you use Cloudflare DMARC Management, it starts with p=none for monitoring. Upgrade the policy once you've verified legitimate mail is aligned.

STARTTLS & DANE Provider-dependent

TLS on SMTP port 25 and DANE (TLSA records) for mail servers.

STARTTLS

All TLS subtests (version, ciphers, key exchange, compression, etc.) must pass on every MX host. This is your mail provider's responsibility โ€” you cannot configure these settings on Cloudflare Email Routing's MX servers.

๐Ÿ”’ Email Routing MX servers โ€” platform limitations

Cloudflare's Email Routing MX servers (route*.mx.cloudflare.net) have the same two platform limitations as the web edge:

  • Cipher suites: The MX servers offer legacy ciphers (static-RSA, CBC, 3DES) that fail internet.nl. There is no ACM equivalent for Email Routing โ€” you cannot restrict MX cipher suites.
  • Hash function for key exchange: SHA-1 is accepted as a fallback, same as the website test.

These cost ~3% on the mail test. With Email Routing, the maximum mail score is 97%.

Providers known to pass all STARTTLS subtests: Google Workspace, Microsoft 365, Mailbox.org, Posteo, Migadu, Fastmail.

DANE

Requires a TLSA record at _25._tcp.<mx-host> with DNSSEC on the MX host's parent zone.

โœ… Cloudflare Email Routing supports DANE

Cloudflare publishes TLSA records and DNSSEC-signs mx.cloudflare.net. DANE existence, validity, and rollover all pass automatically โ€” no configuration needed on your part.

If you use a different mail provider and control the MX host, you need to publish a TLSA record yourself:

DNS โ†’ Records โ†’ Add record

Type: TLSA, Name: _25._tcp.mail, Usage: 3 (DANE-EE), Selector: 1 (SPKI), Matching: 1 (SHA-256), Certificate: SHA-256 hash of SPKI.

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
  -X POST \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  --json '{
    "type": "TLSA",
    "name": "_25._tcp.mail.example.com",
    "data": {
      "usage": 3, "selector": 1, "matching_type": 1,
      "certificate": "<sha256-hex>"
    },
    "ttl": 3600
  }'