
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
    <channel>
        <title><![CDATA[ The Cloudflare Blog ]]></title>
        <description><![CDATA[ Get the latest news on how products at Cloudflare are built, technologies used, and join the teams helping to build a better Internet. ]]></description>
        <link>https://blog.cloudflare.com</link>
        <atom:link href="https://blog.cloudflare.com/" rel="self" type="application/rss+xml"/>
        <language>en-us</language>
        <image>
            <url>https://blog.cloudflare.com/favicon.png</url>
            <title>The Cloudflare Blog</title>
            <link>https://blog.cloudflare.com</link>
        </image>
        <lastBuildDate>Fri, 10 Apr 2026 08:32:27 GMT</lastBuildDate>
        <item>
            <title><![CDATA[Resolving a Mutual TLS session resumption vulnerability]]></title>
            <link>https://blog.cloudflare.com/resolving-a-mutual-tls-session-resumption-vulnerability/</link>
            <pubDate>Fri, 07 Feb 2025 20:13:14 GMT</pubDate>
            <description><![CDATA[ Cloudflare patched a Mutual TLS (mTLS) vulnerability (CVE-2025-23419) reported via its Bug Bounty Program. The flaw in session resumption allowed client certificates to authenticate across different ]]></description>
            <content:encoded><![CDATA[ <p>On January 23, 2025, Cloudflare was notified via its <a href="https://www.cloudflare.com/en-gb/disclosure/"><u>Bug Bounty Program</u></a> of a vulnerability in Cloudflare’s <a href="https://www.cloudflare.com/en-gb/learning/access-management/what-is-mutual-tls/"><u>Mutual TLS</u></a> (mTLS) implementation. </p><p>The vulnerability affected customers who were using mTLS and involved a flaw in our session resumption handling. Cloudflare’s investigation revealed <b>no</b> evidence that the vulnerability was being actively exploited. And tracked as<a href="https://nvd.nist.gov/vuln/detail/CVE-2025-23419"> <u>CVE-2025-23419</u></a>, Cloudflare mitigated the vulnerability within 32 hours after being notified. Customers who were using Cloudflare’s API shield in conjunction with <a href="https://developers.cloudflare.com/waf/custom-rules/"><u>WAF custom rules</u></a> that validated the issuer's Subject Key Identifier (<a href="https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls_client_auth.cert_issuer_ski/"><u>SKI</u></a>) were not vulnerable. Access policies such as identity verification, IP address restrictions, and device posture assessments were also not vulnerable.</p>
    <div>
      <h2>Background</h2>
      <a href="#background">
        
      </a>
    </div>
    <p>The bug bounty report detailed that a client with a valid mTLS certificate for one Cloudflare zone could use the same certificate to resume a TLS session with another Cloudflare zone using mTLS, without having to authenticate the certificate with the second zone.</p><p>Cloudflare customers can implement mTLS through Cloudflare <a href="https://developers.cloudflare.com/api-shield/security/mtls/"><u>API Shield</u></a> with Custom Firewall Rules and the <a href="https://developers.cloudflare.com/cloudflare-one/identity/devices/access-integrations/mutual-tls-authentication/"><u>Cloudflare Zero Trust</u></a> product suite. Cloudflare establishes the TLS session with the client and forwards the client certificate to Cloudflare’s Firewall or Zero Trust products, where customer policies are enforced.</p><p>mTLS operates by extending the standard TLS handshake to require authentication from both sides of a connection - the client and the server. In a typical TLS session, a client connects to a server, which presents its <a href="https://www.cloudflare.com/application-services/products/ssl/">TLS certificate</a>. The client verifies the certificate, and upon successful validation, an encrypted session is established. However, with mTLS, the client also presents its own TLS certificate, which the server verifies before the connection is fully established. Only if both certificates are validated does the session proceed, ensuring bidirectional trust.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2FXDaK0R6cpH4IZwSlCyXk/e8f6764656d2672f9eadf4e60851614f/BLOG-2667_2.png" />
          </figure><p>mTLS is useful for <a href="https://developers.cloudflare.com/api-shield/security/mtls/"><u>securing API communications</u></a>, as it ensures that only legitimate and authenticated clients can interact with backend services. Unlike traditional authentication mechanisms that rely on credentials or <a href="https://www.cloudflare.com/en-gb/learning/access-management/token-based-authentication/"><u>tokens</u></a>, mTLS requires possession of a valid certificate and its corresponding private key.</p><p>To improve TLS connection performance, Cloudflare employs <a href="https://blog.cloudflare.com/tls-session-resumption-full-speed-and-secure/"><u>session resumption</u></a>. Session resumption speeds up the handshake process, reducing both latency and resource consumption. The core idea is that once a client and server have successfully completed a TLS handshake, future handshakes should be streamlined — assuming that fundamental parameters such as the cipher suite or TLS version remain unchanged.</p><p>There are two primary mechanisms for session resumption: session IDs and session tickets. With session IDs, the server stores the session context and associates it with a unique session ID. When a client reconnects and presents this session ID in its ClientHello message, the server checks its cache. If the session is still valid, the handshake is resumed using the cached state.</p><p>Session tickets function in a stateless manner. Instead of storing session data, the server encrypts the session context and sends it to the client as a session ticket. In future connections, the client includes this ticket in its ClientHello, which the server can then decrypt to restore the session, eliminating the need for the server to maintain session state.</p><p>A resumed mTLS session leverages previously established trust, allowing clients to reconnect to a protected application without needing to re-initiate an mTLS handshake.</p>
    <div>
      <h3>The mTLS resumption vulnerability</h3>
      <a href="#the-mtls-resumption-vulnerability">
        
      </a>
    </div>
    <p>In Cloudflare’s mTLS implementation, however, session resumption introduced an unintended behavior.  <a href="https://boringssl.googlesource.com/boringssl"><u>BoringSSL</u></a>, the TLS library that Cloudflare uses, will store the client certificate from the originating, full TLS handshake in the session. Upon resuming that session, the client certificate is not revalidated against the full chain of trust, and the original handshake's verification status is respected. To avoid this situation, BoringSSL provides an API to partition session caches/tickets between different “contexts” defined by the application. Unfortunately, Cloudflare’s use of this API was not correct, which allowed TLS sessions to be resumed when they shouldn’t have been. </p><p>To exploit this vulnerability, the security researcher first set up two zones on Cloudflare and configured them behind Cloudflare’s proxy with mTLS enabled. Once their domains were configured, the researcher authenticated to the first zone using a valid client certificate, allowing Cloudflare to issue a TLS session ticket against that zone. </p><p>The researcher then changed the TLS Server Name Indication (SNI) and HTTP Host header from the first zone (which they had authenticated with) to target the second zone (which they had <i>not</i> authenticated with). The researcher then presented the session ticket when handshaking with the second Cloudflare-protected mTLS zone. This resulted in Cloudflare resuming the session with the second zone and reporting verification status for the cached client certificate as successful,bypassing the mTLS authentication that would normally be required to initiate a session.</p><p>If you were using additional validation methods in your API Shield or Access policies – for example, checking the issuers SKI, identity verification, IP address restrictions, or device posture assessments – these controls continued to function as intended. However, due to the issue with TLS session resumption, the mTLS checks mistakenly returned a passing result without re-evaluating the full certificate chain.</p>
    <div>
      <h2>Remediation and next steps</h2>
      <a href="#remediation-and-next-steps">
        
      </a>
    </div>
    <p>We have disabled TLS session resumption for all customers that have mTLS enabled. As a result, Cloudflare will no longer allow resuming sessions that cache client certificates and their verification status.</p><p>We are exploring ways to bring back the performance improvements from TLS session resumption for mTLS customers.</p>
    <div>
      <h2>Further hardening</h2>
      <a href="#further-hardening">
        
      </a>
    </div>
    <p>Customers can further harden their mTLS configuration and add enhanced logging to detect future issues by using Cloudflare's <a href="https://developers.cloudflare.com/rules/transform/"><u>Transform Rules</u></a>, logging, and firewall features.</p><p>While Cloudflare has mitigated the issue by disabling session resumption for mTLS connections, customers may want to implement additional monitoring at their origin to enforce stricter authentication policies. All customers using mTLS can also enable additional request headers using our <a href="https://developers.cloudflare.com/rules/transform/managed-transforms/reference/#add-tls-client-auth-headers"><u>Managed Transforms</u></a> product. Enabling this feature allows us to pass additional metadata to your origin with the details of the client certificate that was used for the connection.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7eYFaZUrBYTESAZEQHsnHS/8bdb9135ab58648529cb8339c48ebb2b/BLOG-2667_3.png" />
          </figure><p>Enabling this feature allows you to see the following headers where mTLS is being utilized on a request.</p>
            <pre><code>{
  "headers": {
    "Cf-Cert-Issuer-Dn": "CN=Taskstar Root CA,OU=Taskstar\\, Inc.,L=London,ST=London,C=UK",
    "Cf-Cert-Issuer-Dn-Legacy": "/C=UK/ST=London/L=London/OU=Taskstar, Inc./CN=Taskstar Root CA",
    "Cf-Cert-Issuer-Dn-Rfc2253": "CN=Taskstar Root CA,OU=Taskstar\\, Inc.,L=London,ST=London,C=UK",
    "Cf-Cert-Issuer-Serial": "7AB07CC0D10C38A1B554C728F230C7AF0FF12345",
    "Cf-Cert-Issuer-Ski": "A5AC554235DBA6D963B9CDE0185CFAD6E3F55E8F",
    "Cf-Cert-Not-After": "Jul 29 10:26:00 2025 GMT",
    "Cf-Cert-Not-Before": "Jul 29 10:26:00 2024 GMT",
    "Cf-Cert-Presented": "true",
    "Cf-Cert-Revoked": "false",
    "Cf-Cert-Serial": "0A62670673BFBB5C9CA8EB686FA578FA111111B1B",
    "Cf-Cert-Sha1": "64baa4691c061cd7a43b24bccb25545bf28f1111",
    "Cf-Cert-Sha256": "528a65ce428287e91077e4a79ed788015b598deedd53f17099c313e6dfbc87ea",
    "Cf-Cert-Ski": "8249CDB4EE69BEF35B80DA3448CB074B993A12A3",
    "Cf-Cert-Subject-Dn": "CN=MB,OU=Taskstar Admins,O=Taskstar,L=London,ST=Essex,C=UK",
    "Cf-Cert-Subject-Dn-Legacy": "/C=UK/ST=Essex/L=London/O=Taskstar/OU=Taskstar Admins/CN=MB ",
    "Cf-Cert-Subject-Dn-Rfc2253": "CN=MB,OU=Taskstar Admins,O=Taskstar,L=London,ST=London,C=UK",
    "Cf-Cert-Verified": "true",
    "Cf-Client-Cert-Sha256": "083129c545d7311cd5c7a26aabe3b0fc76818495595cea92efe111150fd2da2",
    }
}
</code></pre>
            <p>Enterprise customers can also use our <a href="https://developers.cloudflare.com/logs/"><u>Cloudflare Log</u></a> products to add these headers via the Logs <a href="https://developers.cloudflare.com/logs/reference/custom-fields/"><u>Custom Fields</u></a> feature. For example:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3D864CsepB5U2wM1AWhYVu/ca7d3d1ca144bc4fb7ac7edddfdf5987/BLOG-2667_4.png" />
          </figure><p>This will add the following information to Cloudflare Logs.</p>
            <pre><code>"RequestHeaders": {
    "cf-cert-issuer-ski": "A5AC554235DBA6D963B9CDE0185CFAD6E3F55E8F",
    "cf-cert-sha256": "528a65ce428287e91077e4a79ed788015b598deedd53f17099c313e6dfbc87ea"
  },
</code></pre>
            <p>Customers already logging this information — either at their origin or via Cloudflare Logs — can retroactively check for unexpected certificate hashes or issuers that did not trigger any security policy.</p><p>Users are also able to use this information within their <a href="https://developers.cloudflare.com/learning-paths/application-security/firewall/custom-rules/"><u>WAF custom rules</u></a> to conduct additional checks. For example, checking the <a href="https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.tls_client_auth.cert_issuer_ski/"><u>Issuer's SKI</u></a> can provide an extra layer of security.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1YWZe9P1hhYEPJrWH4gpqi/b0a6f3c70a203032404c1ca0e2fc517c/BLOG-2667_5.png" />
          </figure><p>Customers who enabled this <a href="https://developers.cloudflare.com/api-shield/security/mtls/configure/#expression-builder"><u>additional check</u></a> were not vulnerable.</p>
    <div>
      <h2><b>Conclusion</b></h2>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>We would like to thank Sven Hebrok, Felix Cramer, Tim Storm, Maximilian Radoy, and Juraj Somorovsky of Paderborn University who responsibly disclosed this issue via our <a href="https://hackerone.com/cloudflare?type=team"><u>HackerOne Bug Bounty Program</u></a>, allowing us to identify and mitigate the vulnerability. We welcome further submissions from our community of researchers to continually improve our products' security.</p><p>Finally, we want to apologize to our mTLS customers. Security is at the core of everything we do at Cloudflare, and we deeply regret any concerns this issue may have caused. We have taken immediate steps to resolve the vulnerability and have implemented additional safeguards to prevent similar issues in the future. </p>
    <div>
      <h2><b>Timeline </b></h2>
      <a href="#timeline">
        
      </a>
    </div>
    <p><i>All timestamps are in UTC</i></p><ul><li><p><b>2025-01-23 15:40</b> – Cloudflare is notified of a vulnerability in Mutual TLS and the use of session resumption.</p></li><li><p><b>2025-01-23 16:02 to 21:06</b> – Cloudflare validates Mutual TLS vulnerability and prepares a release to disable session resumption for Mutual TLS.</p></li><li><p><b>2025-01-23 21:26</b> – Cloudflare begins rollout of remediation.</p></li><li><p><b>2025-01-24 20:15</b> – Rollout completed. Vulnerability is remediated.</p></li></ul><p></p> ]]></content:encoded>
            <category><![CDATA[Vulnerabilities]]></category>
            <category><![CDATA[WAF]]></category>
            <category><![CDATA[Zero Trust]]></category>
            <category><![CDATA[SASE]]></category>
            <category><![CDATA[TLS]]></category>
            <category><![CDATA[Network Services]]></category>
            <guid isPermaLink="false">4gJhafUsmUjkevKu55304a</guid>
            <dc:creator>Matt Bullock</dc:creator>
            <dc:creator>Rushil Mehra</dc:creator>
            <dc:creator>Alessandro Ghedini</dc:creator>
        </item>
        <item>
            <title><![CDATA[New standards for a faster and more private Internet]]></title>
            <link>https://blog.cloudflare.com/new-standards/</link>
            <pubDate>Wed, 25 Sep 2024 13:00:00 GMT</pubDate>
            <description><![CDATA[ Cloudflare's customers can now take advantage of Zstandard (zstd) compression, offering 42% faster compression than Brotli and 11.3% more efficiency than GZIP. We're further optimizing performance for our customers with HTTP/3 prioritization and BBR congestion control, and enhancing privacy through Encrypted Client Hello (ECH). ]]></description>
            <content:encoded><![CDATA[ <p>As the Internet grows, so do the demands for speed and security. At Cloudflare, we’ve spent the last 14 years simplifying the adoption of the latest web technologies, ensuring that our users stay ahead without the complexity. From being the first to offer <a href="https://www.cloudflare.com/application-services/products/ssl/">free SSL certificates</a> through <a href="https://blog.cloudflare.com/introducing-universal-ssl/"><u>Universal SSL</u></a> to quickly supporting innovations like <a href="https://blog.cloudflare.com/introducing-tls-1-3"><u>TLS 1.3</u></a>, <a href="https://blog.cloudflare.com/introducing-cloudflares-automatic-ipv6-gatewa/"><u>IPv6</u></a>, and <a href="https://blog.cloudflare.com/http-3-from-root-to-tip/"><u>HTTP/3</u></a>, we've consistently made it easy for everyone to harness cutting-edge advancements.</p><p>One of the most exciting recent developments in web performance is Zstandard (zstd) — a new compression algorithm that we have found compresses data 42% faster than Brotli while maintaining almost the same compression levels. Not only that, but Zstandard reduces file sizes by 11.3% compared to GZIP, all while maintaining comparable speeds. As compression speed and efficiency directly impact latency, this is a game changer for improving user experiences across the web.</p><p>We’re also re-starting the <a href="https://blog.cloudflare.com/announcing-encrypted-client-hello/"><u>rollout of Encrypted Client Hello (ECH)</u></a>, a <a href="https://datatracker.ietf.org/doc/draft-ietf-tls-esni/"><u>new proposed standard </u></a>that prevents networks from snooping on which websites a user is visiting. <a href="https://blog.cloudflare.com/encrypted-client-hello/"><u>Encrypted Client Hello (ECH) is a successor to ESNI</u></a> and masks the <a href="https://www.cloudflare.com/en-gb/learning/ssl/what-is-sni/"><u>Server Name Indication (SNI)</u></a> that is used to negotiate a TLS handshake. This means that whenever a user visits a website on Cloudflare that has ECH enabled, no one except for the user, Cloudflare, and the website owner will be able to determine which website was visited. Cloudflare is a big proponent of privacy for everyone and is excited about the prospects of bringing this technology to life.</p><p>In this post, we also further explore our work measuring the impact of HTTP/3 prioritization, and the development of Bottleneck Bandwidth and Round-trip propagation time (BBR) congestion control to further optimize network performance.</p>
    <div>
      <h2>Introducing Zstandard compression</h2>
      <a href="#introducing-zstandard-compression">
        
      </a>
    </div>
    <p><a href="https://github.com/facebook/zstd"><u>Zstandard</u></a>, an advanced compression algorithm, was developed by <a href="https://engineering.fb.com/2018/12/19/core-infra/zstandard/"><u>Yann Collet at Facebook</u></a> and open sourced in August 2016 to manage large-scale data processing.  It has gained popularity in recent years due to its impressive compression ratios and speed. The protocol was included in <a href="https://chromestatus.com/feature/6186023867908096"><u>Chromium-based browsers</u></a> and <a href="https://connect.mozilla.org/t5/ideas/add-support-for-zstd-compression/idi-p/52155"><u>Firefox</u></a> in March 2024 as a <a href="https://caniuse.com/zstd"><u>supported</u></a> compression algorithm. </p><p>Today, we are excited to announce that Zstandard compression between Cloudflare and browsers is now available to everyone. </p><p>Our testing shows that Zstandard compresses data up to 42% faster than <a href="https://github.com/google/brotli"><u>Brotli</u></a> while achieving nearly equivalent data compression. Additionally, Zstandard outperforms <a href="https://datatracker.ietf.org/doc/html/rfc1952"><u>GZIP</u></a> by approximately 11.3% in compression efficiency, all while maintaining similar compression speeds. This means Zstandard can compress files to the same size as Brotli but in nearly half the time, speeding up your website without sacrificing performance.

This is exciting because compression speed and file size directly impacts latency. When a browser requests a resource from the origin server, the server needs time to compress the data before it’s sent over the network. A faster compression algorithm, like Zstandard, reduces this initial processing time. By also reducing the size of files transmitted over the Internet, better compression means downloads take less time to complete, websites load quicker, and users ultimately get a better experience.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6HSjbMJGtBI4GJlBp2Jf35/e2f971157f078636c6702f40f2c03a70/image2.png" />
            
            </figure>
    <div>
      <h3>Why is compression so important?</h3>
      <a href="#why-is-compression-so-important">
        
      </a>
    </div>
    <p>Website performance is crucial to the success of online businesses. <a href="https://www2.deloitte.com/content/dam/Deloitte/ie/Documents/Consulting/Milliseconds_Make_Millions_report.pdf"><u>Study</u></a> after <a href="https://www.thinkwithgoogle.com/_qs/documents/4290/c676a_Google_MobileSiteSpeed_Playbook_v2.1_digital_4JWkGQT.pdf"><u>study</u></a> has shown that an increased load time <a href="https://www.cloudflare.com/learning/performance/more/website-performance-conversion-rates/"><u>directly affects sales</u></a>. In highly competitive markets, the performance of a website is crucial for success. Just like a physical shop situated in a remote area faces challenges in attracting customers, a slow website encounters similar difficulties in attracting traffic. 

Think about buying a piece of flat pack furniture such as a bookshelf. Instead of receiving the bookshelf fully assembled, which would be expensive and cumbersome to transport, you receive it in a compact, flat box with all the components neatly organized, ready for assembly. The parts are carefully arranged to take up the least amount of space, making the package much smaller and easier to handle. When you get the item, you simply follow the instructions to assemble it to its proper state. </p><p>This is similar to how data compression works. The data is “disassembled” and packed tightly to reduce its size before being transmitted. Once it reaches its destination, it’s “reassembled” to its original form. This compression process reduces the amount of data that needs to be sent, saving bandwidth, reducing costs, and speeding up the transfer, just like how flat pack furniture reduces shipping costs and simplifies delivery logistics.</p><p>However, with compression, there is a tradeoff: time to compress versus the overall compression ratio. A compression ratio is a measure of how much a file's size is reduced during compression. For example, a 10:1 compression ratio means that the compressed file is one-tenth the size of the original. Just like assembling flat-pack furniture takes time and effort, achieving higher compression ratios often requires more processing time. While a higher compression ratio significantly reduces file size — making data transmission faster and more efficient — it may take longer to compress and decompress the data. Conversely, quicker compression methods might produce larger files, leading to faster processing but at the cost of greater bandwidth usage. Balancing these factors is key to optimizing performance in data transmission.</p><p><a href="https://w3techs.com/technologies/details/ce-compression"><u>W3 Technologies</u></a> reports that as of September 12, 2024, 88.6% of websites rely on compression to optimize speed and reduce bandwidth usage. <a href="https://datatracker.ietf.org/doc/html/rfc1952"><u>GZIP</u></a>, introduced in 1996, remains the default algorithm for many, used by 57.0% of sites due to its reasonable compression ratios and fast compression speeds. <a href="https://datatracker.ietf.org/doc/html/rfc7932"><u>Brotli</u></a>, released by Google in 2016, delivers better <a href="https://blog.cloudflare.com/results-experimenting-brotli/"><u>compression ratios</u></a>, leading to smaller file sizes, especially for static assets like JavaScript and CSS, and is used by 45.5% of websites. However, this also means that 11.4% of websites still operate without any compression, missing out on crucial performance improvements.</p><p>As the Internet and its supporting infrastructure have evolved, so have user demands for faster, more efficient performance. This growing need for higher efficiency without compromising speed is where Zstandard comes into play.</p>
    <div>
      <h3>Enter Zstandard</h3>
      <a href="#enter-zstandard">
        
      </a>
    </div>
    <p>Zstandard offers higher compression ratios comparable to GZIP, but with significantly faster compression and decompression speeds than Brotli. This makes it ideal for real-time applications that require both speed and relatively high compression ratios.</p><p>To understand Zstandard's advantages, it's helpful to know about <a href="https://blog.cloudflare.com/cloudflare-fights-cancer/"><u>Zlib</u></a>. Zlib was developed in the mid-1990s based on the <a href="https://en.wikipedia.org/wiki/DEFLATE"><u>DEFLATE</u></a> compression algorithm, which combines <a href="https://www.cloudflare.com/en-gb/learning/performance/glossary/what-is-image-compression/"><u>LZ77 and Huffman coding</u></a> to reduce file sizes. While Zlib has been a compression standard since the mid-1990s and is used in Cloudflare’s <a href="https://blog.cloudflare.com/cloudflare-fights-cancer/"><u>open-source</u></a> GZIP implementation, its design is limited by a 32 KB sliding window — a constraint from the memory limitations of that era. This makes Zlib less efficient on modern hardware, which can access far more memory.</p><p>Zstandard enhances Zlib by leveraging modern innovations and hardware capabilities. Unlike Zlib’s fixed 32 KB window, Zstandard has no strict memory constraints and can theoretically address terabytes of memory. However,  in practice, it typically uses much less, around 1 MB at lower compression levels. This flexibility allows Zstandard to buffer large amounts of data, enabling it to identify and compress repeating patterns more effectively. Zstandard also employs <a href="https://engineering.fb.com/2016/08/31/core-infra/smaller-and-faster-data-compression-with-zstandard/#:~:text=Repcode%20modeling,within%20zlib/gzip."><u>repcode modeling</u></a> to efficiently compress structured data with repetitive sequences, further reducing file sizes and enhancing its suitability for modern compression needs.</p><p>Zstandard is optimized for modern CPUs, which can execute multiple tasks simultaneously using multiple Arithmetic Logic Units (ALUs) that are used to perform mathematical tasks. Zstandard achieves this by processing data in parallel streams, dividing it into multiple parts that are processed concurrently. <a href="https://chromium.googlesource.com/external/github.com/klauspost/compress/+/refs/heads/master/huff0/"><u>The Huffman decoder, Huff0</u></a>, can decode multiple symbols in parallel on a single CPU core, and when combined with multi-threading, this leads to substantial speed improvements during both compression and decompression.</p><p>Zstandard’s branchless design is a crucial innovation that enhances CPU efficiency, especially in modern processors. To understand its significance, consider how CPUs execute instructions.</p><p>Modern CPUs use pipelining, where different stages of an instruction are processed simultaneously—like a production line—keeping all parts of the processor busy. However, when CPUs encounter a branch, such as an 'if-else' decision, they must make a <a href="https://blog.cloudflare.com/branch-predictor/"><u>branch prediction</u></a> to guess the next step. If the prediction is wrong, the pipeline must be cleared and restarted, causing slowdowns.</p><p>Zstandard avoids this issue by eliminating conditional branching. Without relying on branch predictions, it ensures the CPU can execute instructions continuously, keeping the pipeline full and avoiding performance bottlenecks.</p><p>A key feature of Zstandard is its use of <a href="https://www.rfc-editor.org/rfc/rfc8478.html#section-4.1"><u>Finite State Entropy (FSE)</u></a>, an advanced compression method that encodes data more efficiently based on probability. FSE, built on the <a href="https://en.wikipedia.org/wiki/Asymmetric_numeral_systems"><u>Asymmetric Numeral System (ANS)</u></a>, allows Zstandard to use fractional bits for encoding, unlike traditional Huffman coding, which only uses whole bits. This allows heavily repeated data to be compressed more tightly without sacrificing efficiency.</p>
    <div>
      <h3>Zstandard findings</h3>
      <a href="#zstandard-findings">
        
      </a>
    </div>
    <p>In the third quarter of 2024, we conducted extensive tests on our new Zstandard compression module, focusing on a 24-hour period where we switched the default compression algorithm from Brotli to Zstandard across our Free plan traffic. This experiment spanned billions of requests, covering a wide range of file types and sizes, including HTML, CSS, and JavaScript. The results were very promising, with significant improvements in both compression speed and file size reduction, leading to faster load times and more efficient bandwidth usage.</p>
    <div>
      <h4>Compression ratios</h4>
      <a href="#compression-ratios">
        
      </a>
    </div>
    <p>In terms of compression efficiency, Zstandard delivers impressive results. Below are the average compression ratios we observed during our testing.</p><table><tr><td><p><b>Compression Algorithm</b></p></td><td><p><b>Average Compression Ratio</b></p></td></tr><tr><td><p>GZIP</p></td><td><p>2.56</p></td></tr><tr><td><p>Zstandard</p></td><td><p>2.86</p></td></tr><tr><td><p>Brotli</p></td><td><p>3.08</p></td></tr></table>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2EA8KkP7M3j4KiEArzmXVT/2a93b972f531f02f6b253e231f73ff40/image5.png" />
            
            </figure><p>As the table shows, Zstandard achieves an average compression ratio of <b>2.86:1</b>, which is notably higher than gzip's <b>2.56:1</b> and close to Brotli’s <b>3.08:1</b>. While Brotli slightly edges out Zstandard in terms of pure compression ratio, what is particularly exciting is that we are only using Zstandard’s default compression level of 3 (out of 22) on our traffic. In the fourth quarter of 2024, we plan to experiment with higher compression levels and multithreading capabilities to further enhance Zstandard’s performance and optimize results even more.</p>
    <div>
      <h4>Compression speeds</h4>
      <a href="#compression-speeds">
        
      </a>
    </div>
    <p>What truly sets Zstandard apart is its speed. Below are the average times to compress data from our traffic-based tests measured in milliseconds:</p><table><tr><td><p><b>Compression Algorithm</b></p></td><td><p><b>Average Time to Compress (ms)</b></p></td></tr><tr><td><p>GZIP</p></td><td><p>0.872</p></td></tr><tr><td><p>Zstandard</p></td><td><p>0.848</p></td></tr><tr><td><p>Brotli</p></td><td><p>1.544</p></td></tr></table>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/15AxPyO1PmyV6hDRRjBznu/9cf16cfdc146afddbf9a3332da29629a/image10.png" />
            
            </figure><p>Zstandard not only compresses data efficiently, but it also does so <b>42% faster</b> than Brotli, with an average compression time of <b>0.848 ms</b> compared to Brotli’s <b>1.544 ms</b>. It even outperforms gzip, which compresses at <b>0.872 ms</b> on average.</p><p>From our results, we have found Zstandard strikes an excellent balance between achieving a high compression ratio and maintaining fast compression speed, making it particularly well-suited for dynamic content such as HTML and non-cacheable sensitive data. Zstandard can compress these responses from the origin quickly and efficiently, saving time compared to Brotli while providing better compression ratios than GZIP.</p>
    <div>
      <h3>Implementing Zstandard at Cloudflare</h3>
      <a href="#implementing-zstandard-at-cloudflare">
        
      </a>
    </div>
    <p>To implement Zstandard compression at Cloudflare, we needed to build it into our Nginx-based service which already handles GZIP and Brotli compression. Nginx is modular by design, with each module performing a specific function, such as compressing a response. Our custom Nginx module leverages Nginx's function 'hooks' — specifically, the header filter and body filter — to implement Zstandard compression.</p>
    <div>
      <h4>Header filter</h4>
      <a href="#header-filter">
        
      </a>
    </div>
    <p>The header filter allows us to access and modify response headers. For example, Cloudflare only compresses responses above a certain size (50 bytes for Zstandard), which is enforced with this code:</p>
            <pre><code>if (r-&gt;headers_out.content_length_n != -1 &amp;&amp;
    r-&gt;headers_out.content_length_n &lt; conf-&gt;min_length) {
    return ngx_http_next_header_filter(r);
}</code></pre>
            <p>Here, we check the "Content-Length" header. If the content length is less than our minimum threshold, we skip compression and let Nginx execute the next module.</p><p>We also need to ensure the content is not already compressed by checking the "Content-Encoding" header:</p>
            <pre><code>if (r-&gt;headers_out.content_encoding &amp;&amp;
    r-&gt;headers_out.content_encoding-&gt;value.len) {
    return ngx_http_next_header_filter(r);
}</code></pre>
            <p>If the content is already compressed, the module is bypassed, and Nginx proceeds to the next header filter.</p>
    <div>
      <h4>Body filter</h4>
      <a href="#body-filter">
        
      </a>
    </div>
    <p>The body filter hook is where the actual processing of the response body occurs. In our case, this involves compressing the data with the Zstandard encoder and streaming the compressed data back to the client. Since responses can be very large, it's not feasible to buffer the entire response in memory, so we manage internal memory buffers carefully to avoid running out of memory.</p><p>The Zstandard library is well-suited for streaming compression and provides the <code>ZSTD_compressStream2</code> function:</p>
            <pre><code>ZSTDLIB_API size_t ZSTD_compressStream2(ZSTD_CCtx* cctx,
                                        ZSTD_outBuffer* output,
                                        ZSTD_inBuffer* input,
                                        ZSTD_EndDirective endOp);</code></pre>
            <p>This function can be called repeatedly with chunks of input data to be compressed. It accepts input and output buffers and an "operation" parameter (<code>ZSTD_EndDirective endOp</code>) that controls whether to continue feeding data, flush the data, or finalize the compression process.</p><p>Nginx uses a "flush" flag on memory buffers to indicate when data can be sent. Our module uses this flag to set the appropriate Zstandard operation:</p>
            <pre><code>switch (zstd_operation) {
    case ZSTD_e_continue: {
        if (flush) {
            zstd_operation = ZSTD_e_flush;
        }
    }
}
</code></pre>
            <p>This logic allows us to switch from the "ZSTD_e_continue" operation, which feeds more input data into the encoder, to "ZSTD_e_flush", which extracts compressed data from the encoder.</p>
    <div>
      <h4>Compression cycle</h4>
      <a href="#compression-cycle">
        
      </a>
    </div>
    <p>The compression module operates in the following cycle:</p><ol><li><p>Receive uncompressed data.</p></li><li><p>Locate an internal buffer to store compressed data.</p></li><li><p>Compress the data with Zstandard.</p></li><li><p>Send the compressed data back to the client.</p></li></ol><p>Once a buffer is filled with compressed data, it’s passed to the next Nginx module and eventually sent to the client. When the buffer is no longer in use, it can be recycled, avoiding unnecessary memory allocation. This process is managed as follows:</p>
            <pre><code>if (free) {
    // A free buffer is available, so use it
    buffer = free;
} else if (buffers_used &lt; maximum_buffers) {
    // No free buffers, but we're under the limit, so allocate a new one
    buffer = create_buf();
} else {
    // No free buffers and can't allocate more
    err = no_memory;
}
</code></pre>
            
    <div>
      <h4>Handling backpressure</h4>
      <a href="#handling-backpressure">
        
      </a>
    </div>
    <p>If no buffers are available, it can lead to backpressure — a situation where the Zstandard module generates compressed data faster than the client can receive it. This causes data to become "stuck" inside Nginx, halting further compression due to memory constraints. In such cases, we stop compression and send an empty buffer to the next Nginx module, allowing Nginx to attempt to send the data to the client again. When successful, this frees up memory buffers that our module can reuse, enabling continued streaming of the compressed response without buffering the entire response in memory.</p>
    <div>
      <h3>What's next? Compression dictionaries</h3>
      <a href="#whats-next-compression-dictionaries">
        
      </a>
    </div>
    <p>The future of Internet compression lies in the use of <a href="https://datatracker.ietf.org/doc/draft-ietf-httpbis-compression-dictionary/"><u>compression dictionaries</u></a>. Both Brotli and Zstandard support dictionaries, offering up to <a href="https://developer.chrome.com/blog/shared-dictionary-compression"><u>90% improvement</u></a> on compression levels compared to using static dictionaries. </p><p>Compression dictionaries store common patterns or sequences of data, allowing algorithms to compress information more efficiently by referencing these patterns rather than repeating them. This concept is akin to how an iPhone's predictive text feature works. For example, if you frequently use the phrase "On My Way," you can customize your iPhone’s dictionary to recognize the abbreviation "OMW" and automatically expand it to "On My Way" when you type it, saving the user from typing six extra letters.</p><table><tr><td><p>O</p></td><td><p>M</p></td><td><p>W</p></td><td><p></p></td><td><p></p></td><td><p></p></td><td><p></p></td><td><p></p></td><td><p></p></td></tr><tr><td><p>O</p></td><td><p>n</p></td><td><p>
</p></td><td><p>M</p></td><td><p>y</p></td><td><p>
</p></td><td><p>W</p></td><td><p>a</p></td><td><p>y</p></td></tr></table><p>Traditionally, compression algorithms use a static dictionary defined by its RFC that is shared between clients and origin servers. This static dictionary is designed to be broadly applicable, balancing size and compression effectiveness for general use. However, Zstandard and Brotli support custom dictionaries, tailored specifically to the content being sent to the client. For example, Cloudflare could create a specialized dictionary that focuses on frequently used terms like “Cloudflare”. This custom dictionary would compress these terms more efficiently, and a browser using the same dictionary could decode them accurately, leading to significant improvements in compression and performance.</p><p>In the future, we will enable users to leverage origin-generated dictionaries for Zstandard and Brotli to enhance compression. Another exciting area we're exploring is the use of AI to create these dictionaries dynamically without them needing to be generated at the origin. By analyzing data streams in real-time, Cloudflare could develop context-aware dictionaries tailored to the specific characteristics of the data being processed. This approach would allow users to significantly improve both compression ratios and processing speed for their applications.</p>
    <div>
      <h3>Compression Rules for everyone</h3>
      <a href="#compression-rules-for-everyone">
        
      </a>
    </div>
    <p>Today we’re also excited to announce the introduction of <a href="https://developers.cloudflare.com/rules/compression-rules/"><u>Compression Rules</u></a> for all our customers. By default, Cloudflare will automatically compress certain content types based on their <a href="https://developers.cloudflare.com/speed/optimization/content/brotli/content-compression"><u>Content-Type headers</u></a>. Customers can use compression rules to optimize how and what Cloudflare compresses. This feature was previously exclusive to our Enterprise plans.

Compression Rules is built on the same robust framework as our other rules products, such as Origin Rules, Custom Firewall Rules, and Cache Rules, with additional fields for Media Type and Extension Type. This allows you to easily specify the content you wish to compress, providing granular control over your site’s performance optimization.</p><p>Compression rules are now available on all our pay-as-you-go plans and will be added to free plans in October 2024. This feature was previously exclusive to our Enterprise customers. In the table below, you’ll find the updated limits, including an increase to 125 Compression Rules for Enterprise plans, aligning with our other rule products' quotas.</p><table><tr><td><p><b>Plan Type</b></p></td><td><p><b>Free*</b></p></td><td><p><b>Pro</b></p></td><td><p><b>Business</b></p></td><td><p><b>Enterprise</b></p></td></tr><tr><td><p>Available Compression Rules</p></td><td><p>10</p></td><td><p>25</p></td><td><p>50</p></td><td><p>125</p></td></tr></table>
    <div>
      <h3>Using Compression Rules to enable Zstandard</h3>
      <a href="#using-compression-rules-to-enable-zstandard">
        
      </a>
    </div>
    <p>To integrate our Zstandard module into our platform, we also added support for it within our Compression Rules framework. This means that customers can now specify Zstandard as their preferred compression method, and our systems will automatically enable the Zstandard module in Nginx, disabling other compression modules when necessary.</p><p>The <code>Accept-Encoding</code> header determines which compression algorithms a client supports. If a browser supports Zstandard (<code>zstd</code>), and both Cloudflare and the zone have enabled the feature, then Cloudflare will return a Zstandard compressed response.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/tRIwu8JItGU0zyVmeTp2e/232af3ea43893022e5879e8361ed42b7/image4.png" />
            
            </figure><p>If the client does not support Zstandard, then Cloudflare will automatically fall back to Brotli, GZIP, or serve the content uncompressed where no compression algorithm is supported, ensuring compatibility. 

To enable Zstandard for your entire site or specifically filter on certain file types, all Cloudflare users can deploy a simple compression rule.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2WiodFBfD02mlPASLABkz5/e9a66b552ba46e423f352e502792b398/image3.png" />
            
            </figure><p>Further details and examples of what can be accomplished with Compression Rules can be found in our <a href="https://developers.cloudflare.com/rules/compression-rules/"><u>developer documentation</u></a>.</p><p>Currently, we support Zstandard, Brotli, and GZIP as compression algorithms for traffic sent to clients, and support GZIP and Brotli (since <a href="https://blog.cloudflare.com/this-is-brotli-from-origin/"><u>2023</u></a>) compressed data from the origin. We plan to implement full end-to-end support for Zstandard in 2025, offering customers another effective way to reduce their egress costs.</p><p>Once Zstandard is enabled, you can view your browser’s <a href="https://developer.chrome.com/docs/devtools/network"><u>Network Activity</u></a> log to check the content-encoding headers of the response.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1CujaUsXiEFee79Ny27Zks/1f7ef23910d4bad47c203ad311866951/image11.png" />
            
            </figure><p></p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5JIvK4tNjlxd7uFlWyEJoc/e426053d2c895c980f4c1370379c7b2e/image1.png" />
            
            </figure>
    <div>
      <h3>Enable Zstandard now!</h3>
      <a href="#enable-zstandard-now">
        
      </a>
    </div>
    <p>Zstandard is now available to all Cloudflare customers through <a href="https://dash.cloudflare.com/?to=/:account/:zone/rules/compression-rules"><u>Compression Rules</u></a> on our Enterprise and pay as you go plans, with free plans gaining access in October 2024. Whether you're optimizing for speed or aiming to reduce bandwidth, <a href="https://dash.cloudflare.com/?to=/:account/:zone/rules/compression-rules"><u>Compression Rules</u></a> give all customers granular control over their site's performance.</p>
    <div>
      <h2>Encrypted Client Hello (ECH)</h2>
      <a href="#encrypted-client-hello-ech">
        
      </a>
    </div>
    
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4BFVDlJK6Mxn0P1yk5UdHK/e348084642480eeaec9861a76e32d5f2/image9.png" />
          </figure><p>While performance is crucial for delivering a fast user experience, ensuring privacy is equally important in today’s Internet landscape. As we optimize for speed with Zstandard, Cloudflare is also working to protect users' sensitive information from being exposed during data transmission. With web traffic growing more complex and interconnected, it's critical to keep both performance and privacy in balance. This is where technologies like Encrypted Client Hello (ECH) come into play, securing connections without sacrificing speed.</p><p>Ten years ago, we embarked on a mission to create a more secure and encrypted web. At the time, much of the Internet remained unencrypted, leaving user data vulnerable to interception. On September 27, 2014, we took a major step forward by enabling HTTPS for free for all Cloudflare customers. Overnight, we doubled the size of the encrypted web. This set the stage for a more secure Internet, ensuring that encryption was not a privilege limited by budget but a right accessible to everyone.</p><p>Since then, both Cloudflare and the broader community have helped encrypt more of the Internet. Projects like <a href="https://letsencrypt.org/"><u>Let's Encrypt</u></a> launched to make certificates free for everyone. Cloudflare invested to encrypt more of the connection, and future-proof that encryption from coming technologies like <a href="https://blog.cloudflare.com/post-quantum-for-all/"><u>quantum computers</u></a>. We've always believed that it was everyone's right, regardless of your budget, to have an encrypted Internet at no cost.</p><p>One of the last major challenges has been securing the SNI (Server Name Identifier), which remains exposed in plaintext during the TLS handshake. This is where Encrypted Client Hello (ECH) comes in, and today, we are proud to announce that we're closing that gap. </p><p>Cloudflare announced support for <a href="https://blog.cloudflare.com/announcing-encrypted-client-hello/"><u>Encrypted Client Hello (ECH)</u></a> in 2023 and has continued to enhance its implementation in collaboration with our Internet browser partners. During a TLS handshake, one of the key pieces of information exchanged is the <a href="https://www.cloudflare.com/learning/ssl/what-is-sni/"><u>Server Name Indication (SNI)</u></a>, which is used to initiate a secure connection. Unfortunately, the SNI is sent in plaintext, meaning anyone can read it. Imagine hand-delivering a letter — anyone following you can see where you're delivering it, even if they don’t know the contents. With ECH, it is like sending the same confidential letter to a P.O. Box. You place your sensitive letter in a sealed inner envelope with the actual address. Then, you put that envelope into a larger, standard envelope addressed to a public P.O. Box, trusted to securely forward your intended recipient. The larger envelope containing the non-sensitive information is visible to everyone, while the inner envelope holds the confidential details, such as the actual address and recipient. Just as the P.O. Box maintains the anonymity of the true recipient’s address, ECH ensures that the SNI remains protected. </p><p>While encrypting the SNI is a primary motivation for ECH, its benefits extend further. ECH encrypts the entire Client Hello, ensuring user privacy and enabling TLS to evolve without exposing sensitive connection data. By securing the full handshake, ECH allows for flexible, future-proof encryption designs that safeguard privacy as the Internet continues to grow.</p>
    <div>
      <h3>How ECH works</h3>
      <a href="#how-ech-works">
        
      </a>
    </div>
    <p>Encrypted Client Hello (ECH) introduces a layer of privacy by dividing the ClientHello message into two distinct parts: a ClientHelloOuter and a ClientHelloInner. </p><ul><li><p><b>ClientHelloOuter</b>: This part remains unencrypted and contains innocuous values for sensitive TLS extensions. It sets the SNI to Cloudflare’s public name, currently set to cloudflare-ech.com. Cloudflare manages this domain and possesses the necessary certificates to handle TLS negotiations for it.</p></li><li><p><b>ClientHelloInner</b>: This part is encrypted with a public key and includes the actual server name the client wants to visit, along with other sensitive TLS extensions. The encryption scheme ensures that this sensitive data can only be decrypted by the client-facing server, which in our case is Cloudflare.</p></li></ul><p>During the TLS handshake, the ClientHelloOuter reveals only the public name (e.g., cloudflare-ech.com), while the encrypted ClientHelloInner carries the real server name. As a result, intermediaries observing the traffic will only see cloudflare-ech.com in plaintext, concealing the actual destination.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5C7EUMmlYp3gmvfvnbeKul/ea62a3c648cd859bbb46bb6fe0761645/image13.png" />
          </figure><p>The design of ECH effectively addresses many challenges in securely deploying handshake encryption, thanks to the collaborative efforts within the <a href="https://datatracker.ietf.org/doc/draft-ietf-tls-esni/"><u>IETF community</u></a>. The key to ECH’s success is its integration with other IETF standards, including the new <a href="https://datatracker.ietf.org/doc/html/rfc9460"><u>HTTPS DNS resource record</u></a>, which enables HTTPS endpoints to advertise different TLS capabilities and simplifies key distribution. By using <a href="https://blog.cloudflare.com/dns-encryption-explained/"><u>Encrypted DNS</u></a> methods, browsers and clients can anonymously query these HTTPS records. These records contain the ECH parameters needed to initiate a secure connection. </p><p>ECH leverages the <a href="https://blog.cloudflare.com/hybrid-public-key-encryption/"><u>Hybrid Public Key Encryption (HPKE)</u></a> standard, which streamlines the handshake encryption process, making it more secure and easier to implement. Before initiating a layer 4 connection, the user’s browser makes a DNS request for an HTTPS record, and zones with ECH enabled will include an ECH configuration in the HTTPS record containing an encryption public key and some associated metadata. For example, looking at the zone cloudflare-ech.com, you can see the following record returned:</p>
            <pre><code>dig cloudflare-ech.com https +short


1 . alpn="h3,h2" ipv4hint=104.18.10.118,104.18.11.118 ech=AEX+DQBB2gAgACD1W1B+GxY3nZ53Rigpsp0xlL6+80qcvZtgwjsIs4YoOwAEAAEAAQASY2xvdWRmbGFyZS1lY2guY29tAAA= ipv6hint=2606:4700::6812:a76,2606:4700::6812:b76</code></pre>
            <p>Aside from the public key used by the client to encrypt ClientHelloInner and other <a href="https://www.ietf.org/archive/id/draft-ietf-tls-esni-20.html#name-encrypted-clienthello-confi"><u>parameters</u></a> that specify the ECH configuration, the configured public name is also present.</p>
            <pre><code>Y2xvdWRmbGFyZS1lY2guY29t</code></pre>
            <p>When the string is decoded it reveals:</p>
            <pre><code>cloudflare-ech.com</code></pre>
            <p>This public name is then used by the client in the ClientHelloOuter.</p>
    <div>
      <h3>Practical implications</h3>
      <a href="#practical-implications">
        
      </a>
    </div>
    <p>With ECH, any observer monitoring the traffic between the client and Cloudflare will see only uniform TLS handshakes that appear to be directed towards <code>cloudflare-ech.com</code>, regardless of the actual website being accessed. For instance, if a user visits <code>example.com</code>, intermediaries will not discern this specific destination but will only see <code>cloudflare-ech.com</code> in the visible handshake data. </p>
    <div>
      <h3>The problem with middleboxes</h3>
      <a href="#the-problem-with-middleboxes">
        
      </a>
    </div>
    <p>In a basic HTTPS connection, a browser (client) establishes a TLS connection directly with an origin server to send requests and download content. However, many connections on the Internet do not go directly from a browser to the server but instead pass through some form of proxy or middlebox (often referred to as a "monster-in-the-middle" or MITM). This routing through intermediaries can occur for various reasons, both benign and malicious.</p><p>One common type of HTTPS interceptor is the TLS-terminating forward proxy. This proxy sits between the client and the destination server, transparently forwarding and potentially modifying traffic. To perform this task, the proxy terminates the TLS connection from the client, decrypts the traffic, and then re-encrypts and forwards it to the destination server over a new TLS connection. To avoid browser certificate validation errors, these forward proxies typically require users to install a root certificate on their devices. This root certificate allows the proxy to generate and present a trusted certificate for the destination server, a process often managed by network administrators in corporate environments, as seen with <a href="https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/warp/"><u>Cloudflare WARP</u></a>. These services can help prevent sensitive company data from being transmitted to unauthorized destinations, safeguarding confidentiality.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2xfA7PB61KxnbZ96XRLahh/975153cfcd831f67f47f638ec9578cdb/image8.png" />
          </figure><p>However, TLS-terminating forward proxies may not be equipped to handle Encrypted Client Hello (ECH) correctly, especially if the MITM proxy and the client facing ECH server belong to different entities.  Because the MITM proxy will terminate the TLS connection without being ECH aware, it may provide a valid certificate for the public name (in our case, cloudflare-ech.com) without being able to decrypt the ClientHelloInner or provide a new public key for the client to use. In this case, the client considers ECH to be disabled, which means you lose out on both ECH and pay the cost of an extra round trip. </p><p>We also observed that specific Cloudflare setups, such as <a href="https://developers.cloudflare.com/dns/cname-flattening/"><u>CNAME Flattening</u></a> and <a href="https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/"><u>Orange-to-Orange configurations</u></a>, could cause ECH to break. This issue arose because the end destination for these connections did not support TLS 1.3, preventing ECH from being processed correctly. Fortunately, in close collaboration with our browser partners, we implemented a fallback in our <a href="https://boringssl.googlesource.com/boringssl/+/d274b1bacdca36f3941bf78e43dc38acf676a1a8"><u>BoringSSL</u></a> implementation that handles TLS terminations. This fallback allows browsers to retry connections over TLS 1.2 without ECH, ensuring that a connection can be established and not break.</p><p>As a result of these improvements, we have enabled ECH by default for all Free plans, while all other plan types can manually enable it through their <a href="https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates#ech-card"><u>Cloudflare dashboard</u></a> or via the API. We are excited to support ECH at scale, enhancing the privacy and security of users' browsing activities. ECH plays a crucial role in safeguarding online interactions from potential eavesdroppers and maintaining the confidentiality of web activities.</p>
    <div>
      <h2>HTTP/3 Prioritization and QUIC congestion control</h2>
      <a href="#http-3-prioritization-and-quic-congestion-control">
        
      </a>
    </div>
    <p>Two other areas we are investing in to improve performance for all our customers are <a href="https://blog.cloudflare.com/better-http-3-prioritization-for-a-faster-web/"><u>HTTP/3 Prioritization</u></a> and QUIC congestion control. </p><p>HTTP/3 Prioritization focuses on efficiently managing the order in which web assets are loaded, thereby improving web performance by ensuring critical assets are delivered faster. HTTP/3 Prioritization uses Extensible Priorities to simplify prioritization with two parameters: urgency (ranging from 0-7) and a true/false value indicating whether the resource can be processed progressively. This allows resources like HTML, CSS, and images to be prioritized based on importance.</p><p>On the other hand, QUIC congestion control aims to optimize the flow of data, preventing network bottlenecks and ensuring smooth, reliable transmission even under heavy traffic conditions. </p><p>Both of these improvements significantly impact how Cloudflare’s network serves requests to clients. Before deploying these technologies across our global network, which handles peak traffic volumes of over 80 million requests per second, we first developed a reliable method to measure their impact through rigorous experimentation.</p>
    <div>
      <h3>Measuring impact</h3>
      <a href="#measuring-impact">
        
      </a>
    </div>
    <p>Accurately measuring the impact of features implemented by Cloudflare for our customers is crucial for several reasons. These measurements ensure that optimizations related to performance, security, or reliability deliver the intended benefits without introducing new issues. Precise measurement validates the effectiveness of these changes, allowing Cloudflare to assess improvements in metrics such as load times, user experience, and overall site security. One of the best ways to measure performance changes is through aggregated real-world data.</p><p><a href="https://developers.cloudflare.com/pages/how-to/web-analytics/"><u>Cloudflare Web Analytics</u></a> offers free, privacy-first analytics for your website, helping you understand the performance of your web pages as experienced by your visitors. Real User Metrics (RUM) is a vital tool in web performance optimization, capturing data from real users interacting with a website, providing insights into site performance under real-world conditions. RUM tracks various metrics directly from the user's device, including load times, resource usage, and user interactions. This data is essential for understanding the actual user experience, as it reflects the diverse environments and conditions under which the site is accessed.</p><p>A key performance indicator measured through RUM is <a href="https://web.dev/articles/vitals#core-web-vitals"><u>Core Web Vitals (CWV)</u></a>, a set of metrics defined by Google that quantify crucial aspects of user experience on the web. CWV focuses on three main areas: loading performance, interactivity, and visual stability. The specific metrics include Largest Contentful Paint (LCP), which measures loading performance; First Input Delay (FID), which gauges interactivity; and Cumulative Layout Shift (CLS), which assesses visual stability. By using the CWV measurement in RUM, developers can monitor and optimize their applications to ensure a smoother, faster, and more stable user experience and track the impact of any changes they release.</p><p>Over the last three months we have developed the capability to include valuable information in Server-Timing response headers. When a page that uses Cloudflare Web Analytics is loaded in a browser, the privacy-first client-side script from Web Analytics collects browser metrics and server-timing headers, then sends back this performance data. This data is ingested, aggregated, and made available for querying. The server-timing header includes Layer 4 information, such as Round-Trip Time (RTT) and protocol type (TCP or QUIC). Combined with Core Web Vitals data, this allows us to determine whether an optimization has positively impacted a request compared to a control sample. This capability enables us to release large-scale changes such as HTTP/3 Prioritization or BBR with a clear understanding of their impact across our global network.</p><p>An example of this header contains several key properties that provide valuable information about the network performance as observed by the server:</p>
            <pre><code>server-timing: cfL4;desc="?proto=TCP&amp;rtt=7337&amp;sent=8&amp;recv=8&amp;lost=0&amp;retrans=0&amp;sent_bytes=3419&amp;recv_bytes=832&amp;delivery_rate=548023&amp;cwnd=25&amp;unsent_bytes=0&amp;cid=94dae6b578f91145&amp;ts=225</code></pre>
            <ul><li><p><b>proto</b>: Indicates the transport protocol used</p></li><li><p><b>rtt</b>: Round-Trip Time (RTT), representing the duration of the network round trip as measured by the layer 4 connection using a smoothing algorithm.</p></li><li><p><b>sent</b>: Number of packets sent.</p></li><li><p><b>recv</b>: Number of packets received.</p></li><li><p><b>lost</b>: Number of packets lost.</p></li><li><p><b>retrans</b>: Number of retransmitted packets.</p></li><li><p><b>sent_bytes</b>: Total number of bytes sent.</p></li><li><p><b>recv_bytes</b>: Total number of bytes received.</p></li><li><p><b>delivery_rate</b>: Rate of data delivery, an instantaneous measurement in bytes per second.</p></li><li><p><b>cwnd</b>: Congestion Window, an instantaneous measurement of packet or byte count depending on the protocol.</p></li><li><p><b>unsent_bytes</b>: Number of bytes not yet sent.</p></li><li><p><b>cid</b>: A 16-byte hexadecimal opaque connection ID.</p></li><li><p><b>ts</b>: Timestamp in milliseconds, representing when the data was captured.</p></li></ul><p>This real-time collection of performance data via RUM and Server-Timing headers allows Cloudflare to make data-driven decisions that directly enhance user experience. By continuously analyzing these detailed network and performance insights, we can ensure that future optimizations, such as HTTP/3 Prioritization or BBR deployment, are delivering tangible benefits for our customers.</p>
    <div>
      <h3>Enabling HTTP/3 Prioritization for all plans</h3>
      <a href="#enabling-http-3-prioritization-for-all-plans">
        
      </a>
    </div>
    <p>As part of our focus on improving <a href="https://www.cloudflare.com/learning/performance/what-is-observability/">observability</a> through the integration of the server-timing header, we implemented several minor changes to optimize QUIC handshakes. Notably, we observed positive improvements in our telemetry due to the Layer 4 observability enhancements provided by the server-timing header. These internal findings coincided with third-party measurements, which showed similar improvements in handshake performance.</p><p>In the fourth quarter of 2024, we will apply the same experimental methodology to the HTTP/3 Prioritization support announced during Speed Week 2023. <a href="https://blog.cloudflare.com/better-http-3-prioritization-for-a-faster-web/"><u>HTTP/3 Prioritization</u></a> is designed to enhance the efficiency and speed of loading web pages by intelligently managing the order in which web assets are delivered to users. This is crucial because modern web pages are composed of numerous elements — such as images, scripts, and stylesheets — that vary in importance. Proper prioritization ensures that critical elements, like primary content and layout, load first, delivering a faster and more seamless browsing experience.</p><p>We will use this testing framework to measure performance improvements before enabling the feature across all plan types. This process allows us not only to quantify the benefits but, most importantly, to ensure there are no performance regressions.</p>
    <div>
      <h3>Congestion control</h3>
      <a href="#congestion-control">
        
      </a>
    </div>
    <p>Following the completion of the HTTP/3 Prioritization experiments we will then begin testing different congestion control algorithms, specifically focusing on <a href="https://cloud.google.com/blog/products/networking/tcp-bbr-congestion-control-comes-to-gcp-your-internet-just-got-faster"><u>BBR</u></a> (Bottleneck Bandwidth and Round-trip propagation time) version 3. Congestion control is a crucial mechanism in network communication that aims to optimize data transfer rates while avoiding network congestion. When too much data is sent too quickly over a network, it can lead to congestion, causing packet loss, delays, and reduced overall performance. Think of a busy highway during rush hour. If too many cars (data packets) flood the highway at once, traffic jams occur, slowing everyone down.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1kR4Ekkg2eUPzO4Lj8CrjY/d002875b8f77f782d13bc0ef199ba931/image6.png" />
          </figure><p>Congestion control algorithms act like traffic managers, regulating the flow of data to prevent these “traffic jams,” ensuring that data moves smoothly and efficiently across the network. Each side of a connection runs an algorithm in real time, dynamically adjusting the flow of data based on the current and predicted network conditions.

BBR is an advanced congestion control algorithm, initially developed by Google. BBR seeks to estimate the actual available bandwidth and the minimum round-trip time (RTT) to determine the optimal data flow. This approach allows BBR to maintain high throughput while minimizing latency, leading to more efficient and stable network performance.</p><p><a href="https://github.com/google/bbr/blob/v3/README.md"><u>BBR v3</u></a>, the latest iteration, builds on the strengths of its predecessors BBRv1 and BBRv2 by further refining its bandwidth estimation techniques and enhancing its adaptability to varying network conditions. We found BBR v3 to be faster in several cases compared to our previous implementation of <a href="https://datatracker.ietf.org/doc/html/rfc8312"><u>CUBIC</u></a>. Most importantly, it reduced loss and retransmission rates in our <a href="https://blog.cloudflare.com/introducing-oxy/"><u>Oxy</u></a> proxy implementation.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/61VpPQXJWTHnrnlb7dz2um/f1aecca8fea1bbeced3074d46389c3db/image7.png" />
            
            </figure><p>With these promising results, we are excited to test various congestion control algorithms including BBRv3 for <a href="https://github.com/cloudflare/quiche"><u>quiche</u></a>, our QUIC implementation, across our HTTP/3 traffic. Combining the layer 4 server-timing information with experiments in this area will enable us to explicitly control and measure the impact on real-world metrics.</p>
    <div>
      <h2>The future</h2>
      <a href="#the-future">
        
      </a>
    </div>
    <p>The future of the Internet relies on continuous innovation to meet the growing demands for speed, security, and scalability. Technologies like Zstandard for compression, BBR for congestion control, HTTP/3 prioritization, and Encrypted Client Hello are setting new standards for performance and privacy. By implementing these protocols, web services can achieve faster page load times, more efficient bandwidth usage, and stronger protections for user data.</p><p>These advancements don't just offer incremental improvements, they provide a significant leap forward in optimizing the user experience and safeguarding online interactions. At Cloudflare, we are committed to making these technologies accessible to everyone, empowering businesses to deliver better, faster, and more secure services. </p><p>Stay tuned for more developments as we continue to push the boundaries of what's possible on the web and if you’re passionate about building and implementing the latest Internet innovations, we’re <a href="https://www.cloudflare.com/careers/jobs/"><u>hiring</u></a>!</p> ]]></content:encoded>
            <category><![CDATA[Birthday Week]]></category>
            <category><![CDATA[Privacy]]></category>
            <category><![CDATA[Compression]]></category>
            <category><![CDATA[TLS]]></category>
            <guid isPermaLink="false">6YLU1FUKD4lioSrbpOnb5r</guid>
            <dc:creator>Matt Bullock</dc:creator>
            <dc:creator>Maciej Lechowski</dc:creator>
            <dc:creator>Rushil Mehra</dc:creator>
        </item>
        <item>
            <title><![CDATA[Encrypted Client Hello - the last puzzle piece to privacy]]></title>
            <link>https://blog.cloudflare.com/announcing-encrypted-client-hello/</link>
            <pubDate>Fri, 29 Sep 2023 13:00:52 GMT</pubDate>
            <description><![CDATA[ We're excited to announce a contribution to improving privacy for everyone on the Internet. Encrypted Client Hello, a new standard that prevents networks from snooping on which websites a user is visiting, is now available on all Cloudflare plans.  ]]></description>
            <content:encoded><![CDATA[ <p></p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4tab7Qbtn2MGjXuTbcAsux/c40ac1cfda644402d4022573129a588b/image2-29.png" />
            
            </figure><p>Today we are excited to announce a contribution to improving privacy for everyone on the Internet. Encrypted Client Hello, a <a href="https://datatracker.ietf.org/doc/draft-ietf-tls-esni/">new proposed standard</a> that prevents networks from snooping on which websites a user is visiting, is now available on all Cloudflare plans.  </p><p>Encrypted Client Hello (ECH) is a successor to <a href="https://www.cloudflare.com/learning/ssl/what-is-encrypted-sni/">ESNI</a> and masks the Server Name Indication (SNI) that is used to negotiate a TLS handshake. This means that whenever a user visits a website on Cloudflare that has ECH enabled, no one except for the user, Cloudflare, and the website owner will be able to determine which website was visited. Cloudflare is a big proponent of privacy for everyone and is excited about the prospects of bringing this technology to life.</p>
    <div>
      <h3>Browsing the Internet and your privacy</h3>
      <a href="#browsing-the-internet-and-your-privacy">
        
      </a>
    </div>
    <p>Whenever you visit a website, your browser sends a request to a web server. The web server responds with content and the website starts loading in your browser. Way back in the early days of the Internet this happened in 'plain text', meaning that your browser would just send bits across the network that everyone could read: the corporate network you may be browsing from, the Internet Service Provider that offers you Internet connectivity and any network that the request traverses before it reaches the web server that hosts the website. Privacy advocates have long been concerned about how much information could be seen in "plain text":  If any network between you and the web server can see your traffic, that means they can also see exactly what you are doing. If you are initiating a bank transfer any intermediary can see the destination and the amount of the transfer.</p><p>So how to start making this data more private? To prevent eavesdropping, encryption was introduced in the form of <a href="https://www.cloudflare.com/learning/ssl/what-is-ssl/">SSL</a> and later <a href="https://www.cloudflare.com/learning/ssl/transport-layer-security-tls/">TLS</a>. These are amazing protocols that safeguard not only your privacy but also ensure that no intermediary can tamper with any of the content you view or upload. But encryption only goes so far.</p><p>While the actual content (which particular page on a website you're visiting and any information you upload) is encrypted and shielded from intermediaries, there are still ways to determine what a user is doing. For example, the DNS request to determine the address (IP) of the website you're visiting and the <a href="https://www.cloudflare.com/learning/ssl/what-is-sni/">SNI</a> are both common ways for intermediaries to track usage.</p><p>Let's start with <a href="https://www.cloudflare.com/learning/dns/what-is-dns/">DNS</a>. Whenever you visit a website, your operating system needs to know which IP address to connect to. This is done through a DNS request. DNS by default is unencrypted, meaning anyone can see which website you're asking about. To help users shield these requests from intermediaries, Cloudflare introduced <a href="/dns-encryption-explained/">DNS over HTTPS</a> (DoH) in 2019. In 2020, we went one step further and introduced <a href="/oblivious-dns/">Oblivious DNS over HTTPS</a> which prevents even Cloudflare from seeing which websites a user is asking about.</p><p>That leaves SNI as the last unencrypted bit that intermediaries can use to determine which website you're visiting. After performing a DNS query, one of the first things a browser will do is perform a <a href="https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/">TLS handshake</a>. The handshake constitutes several steps, including which cipher to use, which TLS version and which certificate will be used to verify the web server's identity. As part of this handshake, the browser will indicate the name of the server (website) that it intends to visit: the Server Name Indication.</p><p>Due to the fact that the session is not encrypted yet, and the server doesn't know which certificate to use, the browser must transmit this information in plain text. Sending the SNI in plaintext means that any intermediary can view which website you’re visiting simply by checking the first packet for a connection:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/74acW9qWQyuJFltzJagc2S/5693f381e386d44283121cdd9dd65106/pasted-image-0--8--2.png" />
            
            </figure><p>This means that despite the amazing efforts of TLS and DoH, which websites you’re visiting on the Internet still isn't truly private. Today, we are adding the final missing piece of the puzzle with ECH. With ECH, the browser performs a TLS handshake with Cloudflare, but not a customer-specific hostname. This means that although intermediaries will be able to see that you are visiting <i>a</i> website on Cloudflare, they will never be able to determine which one.</p>
    <div>
      <h3>How does ECH work?</h3>
      <a href="#how-does-ech-work">
        
      </a>
    </div>
    <p>In order to explain how ECH works, it helps to first understand how TLS handshakes are performed. A TLS handshake starts with a <a href="https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/">ClientHello</a> part, which allows a client to say which ciphers to use, which TLS version and most importantly, which server it's trying to visit (the SNI).</p><p>With ECH, the ClientHello message part is split into two separate messages: an inner part and an outer part. The outer part contains the non-sensitive information such as which ciphers to use and the TLS version. It also includes an "outer SNI". The inner part is encrypted and contains an "inner SNI".</p><p>The outer SNI is a common name that, in our case, represents that a user is trying to visit an encrypted website on Cloudflare. We chose cloudflare-ech.com as the SNI that all websites will share on Cloudflare. Because Cloudflare controls that domain we have the appropriate certificates to be able to negotiate a TLS handshake for that server name.</p><p>The inner SNI contains the actual server name that the user is trying to visit. This is encrypted using a public key and can only be read by Cloudflare. Once the handshake completes the web page is loaded as normal, just like any other website loaded over TLS.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/MOw4dKZFQbisxTiD3PIrD/6b173801a10ece203e82d8bf3ed28c0b/pasted-image-0-8.png" />
            
            </figure><p>In practice, this means that any intermediary that is trying to establish which website you’re visiting will simply see normal TLS handshakes with one caveat: any time you visit an ECH enabled website on Cloudflare the server name will look the same. Every TLS handshake will appear identical in that it looks like it's trying to load a website for cloudflare-ech.com, as opposed to the actual website. We've solved the last puzzle-piece in preserving privacy for users that don't like intermediaries seeing which websites they are visiting.</p><p>Visist our introductory blog for full details on the nitty-gritty of <a href="/encrypted-client-hello/">ECH technology</a>.</p>
    <div>
      <h3>The future of privacy</h3>
      <a href="#the-future-of-privacy">
        
      </a>
    </div>
    <p>We're excited about what this means for privacy on the Internet. Browsers like <a href="https://chromestatus.com/feature/6196703843581952">Google Chrome</a> and <a href="https://groups.google.com/a/mozilla.org/g/dev-platform/c/uv7PNrHUagA/m/BNA4G8fOAAAJ">Firefox</a> are starting to ramp up support for ECH already. If you're a website, and you care about users visiting your website in a fashion that doesn't allow any intermediary to see what users are doing, enable ECH today on Cloudflare. We've enabled ECH for all free zones already. If you're an existing paying customer, just head on over to the Cloudflare dashboard and <a href="https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates">apply for the feature</a>. We’ll be enabling this for everyone that signs up over the coming few weeks.</p><p>Over time, we hope others will follow our footsteps, leading to a more private Internet for everyone. The more providers that offer ECH, the harder it becomes for anyone to listen in on what users are doing on the Internet. Heck, we might even solve privacy for good.</p><p>If you're looking for more information on ECH, how it works and how to enable it head on over to our <a href="https://developers.cloudflare.com/ssl/edge-certificates/ech/">developer documentation on ECH</a>.</p> ]]></content:encoded>
            <category><![CDATA[Birthday Week]]></category>
            <category><![CDATA[Product News]]></category>
            <category><![CDATA[Encrypted SNI]]></category>
            <category><![CDATA[Research]]></category>
            <guid isPermaLink="false">3qwZPNqFZ0Cj1noi8cSLG9</guid>
            <dc:creator>Achiel van der Mandele</dc:creator>
            <dc:creator>Alessandro Ghedini</dc:creator>
            <dc:creator>Christopher Wood</dc:creator>
            <dc:creator>Rushil Mehra</dc:creator>
        </item>
        <item>
            <title><![CDATA[mTLS client certificate revocation vulnerability with TLS Session Resumption]]></title>
            <link>https://blog.cloudflare.com/mtls-client-certificate-revocation-vulnerability-with-tls-session-resumption/</link>
            <pubDate>Mon, 03 Apr 2023 13:00:00 GMT</pubDate>
            <description><![CDATA[ This blog post outlines the root cause analysis and solution for a bug found in Cloudflare’s mTLS implementation ]]></description>
            <content:encoded><![CDATA[ <p></p><p>On December 16, 2022, Cloudflare discovered a bug where, in limited circumstances, some users with revoked certificates may not have been blocked by Cloudflare firewall settings. Specifically, Cloudflare’s <a href="https://developers.cloudflare.com/firewall/">Firewall Rules solution</a> did not block some users with revoked certificates from resuming a session via <a href="https://www.cloudflare.com/learning/access-management/what-is-mutual-tls/">mutual transport layer security (mTLS)</a>, even if the customer had configured Firewall Rules to do so. This bug has been mitigated, and we have no evidence of this being exploited. We notified any customers that may have been impacted in an abundance of caution, so they can check their own logs to determine if an mTLS protected resource was accessed by entities holding a revoked certificate.</p>
    <div>
      <h3>What happened?</h3>
      <a href="#what-happened">
        
      </a>
    </div>
    <p>One of Cloudflare Firewall Rules’ features, introduced in March 2021, lets customers revoke or block a client certificate, preventing it from being used to authenticate and establish a session. For example, a customer may use Firewall Rules to protect a service by requiring clients to provide a client certificate through the mTLS authentication protocol. Customers could also revoke or disable a client certificate, after which it would no longer be able to be used to authenticate a party initiating an encrypted session via mTLS.</p><p>When Cloudflare receives traffic from an end user, a service at the edge is responsible for terminating the incoming TLS connection. From there, this service is <a href="https://www.cloudflare.com/en-gb/learning/cdn/glossary/reverse-proxy/">a reverse proxy</a>, and it is responsible for acting as a bridge between the end user and various upstreams. Upstreams might include other services within Cloudflare such as Workers or Caching, or may travel through Cloudflare to an external server such as an origin hosting content. Sometimes, you may want to restrict access to an endpoint, ensuring that only authorized actors can access it. Using client certificates is a common way of authenticating users. This is referred to as <i>mutual TLS</i>, because both the server and client provide a certificate. When mTLS is enabled for a specific hostname, this service at the edge is responsible for parsing the incoming client certificate and converting that into metadata that is attached to HTTP requests that are forwarded to upstreams. The upstreams can process this metadata and make the decision whether the client is authorized or not.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2TvrmqDG2SgLoVONCkuao6/37eae4dafac44d112dcc4ca8bcfb4baf/image1-12.png" />
            
            </figure><p>Customers can use the Cloudflare dashboard to <a href="https://developers.cloudflare.com/ssl/client-certificates/revoke-client-certificate/">revoke existing client certificates</a>. Instead of immediately failing handshakes involving revoked client certificates, revocation is optionally enforced via Firewall Rules, which take effect at the HTTP request level. This leaves the decision to enforce revocation with the customer.</p><p>So how exactly does this service determine whether a client certificate is revoked?</p><p>When we see a client certificate presented as part of the TLS handshake, we store the entire certificate chain on the TLS connection. This means that for every HTTP request that is sent on the connection, the client certificate chain is available to the application. When we receive a request, we look at the following fields related to a client certificate chain:</p><ol><li><p>Leaf certificate Subject Key Identifier (SKI)</p></li><li><p>Leaf certificate Serial Number (SN)</p></li><li><p>Issuer certificate SKI</p></li><li><p>Issuer certificate SN</p></li></ol><p>Some of these values are used for upstream processing, but the issuer SKI and leaf certificate SN are used to query our internal data stores for revocation status. The data store indexes on an issuer SKI, and stores a collection of revoked leaf certificate serial numbers. If we find the leaf certificate in this collection, we set the relevant metadata for consumption in Firewall Rules.</p><p>But what does this have to do with TLS session resumption?</p><p>To explain this, let’s first discuss how session resumption works. At a high level, session resumption grants the ability for clients and servers to expedite the handshake process, saving both time and resources. The idea is that if a client and server successfully handshake, then future handshakes are more or less redundant, assuming nothing about the handshake needs to change at a fundamental level (e.g. cipher suite or TLS version).</p><p>Traditionally, there are two mechanisms for session resumption - session IDs and session tickets. In both cases, the TLS server will handle encrypting the context of the session, which is basically a snapshot of the acquired TLS state that is built up during the handshake process. <b>Session IDs</b> work in a stateful fashion, meaning that the server is responsible for saving this state, somewhere, and keying against the session ID. When a client provides a session ID in the client hello, the server checks to see if it has a corresponding session cached. If it does, then the handshake process is expedited and the cached session is restored. In contrast, <b>session tickets</b> work in a stateless fashion, meaning that the server has no need to store the encrypted session context. Instead, the server sends the client the encrypted session context (AKA a session ticket). In future handshakes, the client can send the session ticket in the client hello, which the server can decrypt in order to restore the session and expedite the handshake.</p><p>Recall that when a client presents a certificate, we store the certificate chain on the TLS connection. It was discovered that when sessions were resumed, the code to store the client certificate chain in application data did not run. As a result, we were left with an empty certificate chain, meaning we were unable to check the revocation status and pass this information to firewall rules for further processing.</p><p>To illustrate this, let's use an example where mTLS is used for api.example.com. Firewall Rules are configured to block revoked certificates, and all certificates are revoked. We can reconstruct the client certificate checking behavior using a two-step process. First we use OpenSSL's s_client to perform a handshake using the revoked certificate (recall that revocation has nothing to do with the success of the handshake - it only affects HTTP requests <i>on</i> the connection), and dump the session’s context into a "session.txt" file. We then issue an HTTP request on the connection, which fails with a 403 status code response because the certificate is revoked.</p>
            <pre><code>❯ echo -e "GET / HTTP/1.1\r\nHost:api.example.com\r\n\r\n" | openssl s_client -connect api.example.com:443 -cert cert2.pem -key key2.pem -ign_eof  -sess_out session.txt | grep 'HTTP/1.1'
depth=2 C=IE, O=Baltimore, OU=CyberTrust, CN=Baltimore CyberTrust Root
verify return:1
depth=1 C=US, O=Cloudflare, Inc., CN=Cloudflare Inc ECC CA-3
verify return:1
depth=0 C=US, ST=California, L=San Francisco, O=Cloudflare, Inc., CN=sni.cloudflaressl.com
verify return:1
HTTP/1.1 403 Forbidden
^C⏎</code></pre>
            <p>Now, if we reuse "session.txt" to perform session resumption and then issue an identical HTTP request, the request succeeds. This shouldn't happen. We should fail both requests because they both use the same revoked client certificate.</p>
            <pre><code>❯ echo -e "GET / HTTP/1.1\r\nHost:api.example.com\r\n\r\n" | openssl s_client -connect api.example.com:443 -cert cert2.pem -key key2.pem -ign_eof -sess_in session.txt | grep 'HTTP/1.1'
HTTP/1.1 200 OK</code></pre>
            
    <div>
      <h3>How we addressed the problem</h3>
      <a href="#how-we-addressed-the-problem">
        
      </a>
    </div>
    <p>Upon realizing that session resumption led to the inability to properly check revocation status, our first reaction was to disable session resumption for all mTLS connections. This blocked the vulnerability immediately.</p><p>The next step was to figure out how to safely re-enable resumption for mTLS. To do so, we need to remove the requirement of depending on data stored within the TLS connection state. Instead, we can use an API call that will grant us access to the leaf certificate in both session resumption and non session resumption cases. Two pieces of information are necessary: the leaf certificate serial number and the issuer SKI. The issuer SKI is actually included in the leaf certificate, also known as the Authority Key Identifier (AKI). Similar to how one would obtain the SKI for a certificate, <code>X509_get0_subject_key_id</code>, we can use <code>X509_get0_authority_key_id</code> to get the AKI.</p>
    <div>
      <h3>Detailed timeline</h3>
      <a href="#detailed-timeline">
        
      </a>
    </div>
    <p><i>All timestamps are in UTC</i></p><p>In March 2021 we introduced a new feature in Firewall Rules that allows customers to block traffic from revoked mTLS certificates.</p><p>2022-12-16 21:53 - Cloudflare discovers that the vulnerability resulted from a bug whereby certificate revocation status was not checked for session resumptions. Cloudflare begins working on a fix to disable session resumption for all mTLS connections to the edge.2022-12-17 02:20 - Cloudflare validates the fix and starts to roll out a fix globally.2022-12-17 21:07 - Rollout is complete, mitigating the vulnerability.2023-01-12 16:40 - Cloudflare starts to roll out a fix that supports both session resumption and revocation.2023-01-18 14:07 - Rollout is complete.</p><p>In conclusion: once Cloudflare identified the vulnerability, a remediation was put into place quickly. A fix that correctly supports session resumption and revocation has been fully rolled out as of 2023-01-18. After reviewing the logs, Cloudflare has not seen any evidence that this vulnerability has been exploited in the wild.</p> ]]></content:encoded>
            <category><![CDATA[TLS]]></category>
            <category><![CDATA[Bugs]]></category>
            <guid isPermaLink="false">1c0CkT5im0RxAvfTT5PMiA</guid>
            <dc:creator>Rushil Mehra</dc:creator>
        </item>
    </channel>
</rss>