
<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>Mon, 13 Apr 2026 14:42:36 GMT</lastBuildDate>
        <item>
            <title><![CDATA[How Workers powers our internal maintenance scheduling pipeline]]></title>
            <link>https://blog.cloudflare.com/building-our-maintenance-scheduler-on-workers/</link>
            <pubDate>Mon, 22 Dec 2025 14:00:00 GMT</pubDate>
            <description><![CDATA[ Physical data center maintenance is risky on a global network. We built a maintenance scheduler on Workers to safely plan disruptive operations, while solving scaling challenges by viewing the state of our infrastructure through a graph interface on top of multiple data sources and metrics pipelines. ]]></description>
            <content:encoded><![CDATA[ <p>Cloudflare has data centers in over <a href="https://www.cloudflare.com/network/"><u>330 cities globally</u></a>, so you might think we could easily disrupt a few at any time without users noticing when we plan data center operations. However, the reality is that <a href="https://developers.cloudflare.com/support/disruptive-maintenance/"><u>disruptive maintenance</u></a> requires careful planning, and as Cloudflare grew, managing these complexities through manual coordination between our infrastructure and network operations specialists became nearly impossible.</p><p>It is no longer feasible for a human to track every overlapping maintenance request or account for every customer-specific routing rule in real time. We reached a point where manual oversight alone couldn't guarantee that a routine hardware update in one part of the world wouldn't inadvertently conflict with a critical path in another.</p><p>We realized we needed a centralized, automated "brain" to act as a safeguard — a system that could see the entire state of our network at once. By building this scheduler on <a href="https://workers.cloudflare.com/"><u>Cloudflare Workers</u></a>, we created a way to programmatically enforce safety constraints, ensuring that no matter how fast we move, we never sacrifice the reliability of the services on which our customers depend.</p><p>In this blog post, we’ll explain how we built it, and share the results we’re seeing now.</p>
    <div>
      <h2>Building a system to de-risk critical maintenance operations</h2>
      <a href="#building-a-system-to-de-risk-critical-maintenance-operations">
        
      </a>
    </div>
    <p>Picture an edge router that acts as one of a small, redundant group of gateways that collectively connect the public Internet to the many Cloudflare data centers operating in a metro area. In a populated city, we need to ensure that the multiple data centers sitting behind this small cluster of routers do not get cut off because the routers were all taken offline simultaneously. </p><p>Another maintenance challenge comes from our Zero Trust product, Dedicated CDN Egress IPs, which allows customers to choose specific data centers from which their user traffic will exit Cloudflare and be sent to their geographically close origin servers for low latency. (For the purpose of brevity in this post, we'll refer to the Dedicated CDN Egress IPs product as "Aegis," which was its former name.) If all the data centers a customer chose are offline at once, they would see higher latency and possibly 5xx errors, which we must avoid. </p><p>Our maintenance scheduler solves problems like these. We can make sure that we always have at least one edge router active in a certain area. And when scheduling maintenance, we can see if the combination of multiple scheduled events would cause all the data centers for a customer’s Aegis pools to be offline at the same time.</p><p>Before we created the scheduler, these simultaneous disruptive events could cause downtime for customers. Now, our scheduler notifies internal operators of potential conflicts, allowing us to propose a new time to avoid overlapping with other related data center maintenance events.</p><p>We define these operational scenarios, such as edge router availability and customer rules, as maintenance constraints which allow us to plan more predictable and safe maintenance.</p>
    <div>
      <h2>Maintenance constraints</h2>
      <a href="#maintenance-constraints">
        
      </a>
    </div>
    <p>Every constraint starts with a set of proposed maintenance items, such as a network router or list of servers. We then find all the maintenance events in the calendar that overlap with the proposed maintenance time window.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2vHCauxOGRXzhrO6DNDr2S/cf38b93ac9b812e5e064f800e537e549/image4.png" />
          </figure><p>Next, we aggregate product APIs, such as a list of Aegis customer IP pools. Aegis returns a set of IP ranges where a customer requested egress out of specific data center IDs, shown below.</p>
            <pre><code>[
    {
      "cidr": "104.28.0.32/32",
      "pool_name": "customer-9876",
      "port_slots": [
        {
          "dc_id": 21,
          "other_colos_enabled": true,
        },
        {
          "dc_id": 45,
          "other_colos_enabled": true,
        }
      ],
      "modified_at": "2023-10-22T13:32:47.213767Z"
    },
]</code></pre>
            <p>In this scenario, data center 21 and data center 45 relate to each other because we need at least one data center online for the Aegis customer 9876 to receive egress traffic from Cloudflare. If we tried to take data centers 21 and 45 down simultaneously, our coordinator would alert us that there would be unintended consequences for that customer workload.</p><p>We initially had a naive solution to load all data into a single Worker. This included all server relationships, product configurations, and metrics for product and infrastructure health to compute constraints. Even in our proof of concept phase, we ran into problems with “out of memory” errors.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1v4Q6bXsZLBXLbrbRrcW3o/00d291ef3db459e99ae9b620965b6bc7/image2.png" />
          </figure><p>We needed to be more cognizant of Workers’ <a href="https://developers.cloudflare.com/workers/platform/limits/"><u>platform limits</u></a>. This required loading only as much data as was absolutely necessary to process the constraint’s business logic. If a maintenance request for a router in Frankfurt, Germany, comes in, we almost certainly do not care what is happening in Australia since there is no overlap across regions. Thus, we should only load data for neighboring data centers in Germany. We needed a more efficient way to process relationships in our dataset.</p>
    <div>
      <h2>Graph processing on Workers</h2>
      <a href="#graph-processing-on-workers">
        
      </a>
    </div>
    <p>As we looked at our constraints, a pattern emerged where each constraint boiled down to two concepts: objects and associations. In graph theory, these components are known as vertices and edges, respectively. An object could be a network router and an association could be the list of Aegis pools in the data center that requires the router to be online. We took inspiration from Facebook’s <a href="https://research.facebook.com/publications/tao-facebooks-distributed-data-store-for-the-social-graph/"><u>TAO</u></a> research paper to establish a graph interface on top of our product and infrastructure data. The API looks like the following:</p>
            <pre><code>type ObjectID = string

interface MainTAOInterface&lt;TObject, TAssoc, TAssocType&gt; {
  object_get(id: ObjectID): Promise&lt;TObject | undefined&gt;

  assoc_get(id1: ObjectID, atype: TAssocType): AsyncIterable&lt;TAssoc&gt;
}</code></pre>
            <p>The core insight is that associations are typed. For example, a constraint would call the graph interface to retrieve Aegis product data.</p>
            <pre><code>async function constraint(c: AppContext, aegis: TAOAegisClient, datacenters: string[]): Promise&lt;Record&lt;string, PoolAnalysis&gt;&gt; {
  const datacenterEntries = await Promise.all(
    datacenters.map(async (dcID) =&gt; {
      const iter = aegis.assoc_get(c, dcID, AegisAssocType.DATACENTER_INSIDE_AEGIS_POOL)
      const pools: string[] = []
      for await (const assoc of iter) {
        pools.push(assoc.id2)
      }
      return [dcID, pools] as const
    }),
  )

  const datacenterToPools = new Map&lt;string, string[]&gt;(datacenterEntries)
  const uniquePools = new Set&lt;string&gt;()
  for (const pools of datacenterToPools.values()) {
    for (const pool of pools) uniquePools.add(pool)
  }

  const poolTotalsEntries = await Promise.all(
    [...uniquePools].map(async (pool) =&gt; {
      const total = aegis.assoc_count(c, pool, AegisAssocType.AEGIS_POOL_CONTAINS_DATACENTER)
      return [pool, total] as const
    }),
  )

  const poolTotals = new Map&lt;string, number&gt;(poolTotalsEntries)
  const poolAnalysis: Record&lt;string, PoolAnalysis&gt; = {}
  for (const [dcID, pools] of datacenterToPools.entries()) {
    for (const pool of pools) {
      poolAnalysis[pool] = {
        affectedDatacenters: new Set([dcID]),
        totalDatacenters: poolTotals.get(pool),
      }
    }
  }

  return poolAnalysis
}</code></pre>
            <p>We use two association types in the code above:</p><ol><li><p>DATACENTER_INSIDE_AEGIS_POOL, which retrieves the Aegis customer pools that a data center resides in.</p></li><li><p>AEGIS_POOL_CONTAINS_DATACENTER, which retrieves the data centers an Aegis pool needs to serve traffic.</p></li></ol><p>The associations are inverted indices of one another. The access pattern is exactly the same as before, but now the graph implementation has much more control of how much data it queries. Before, we needed to load all Aegis pools into memory and filter inside constraint business logic. Now, we can directly fetch only the data that matters to the application.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4b68YLIHiOPt5EeyTUTeBt/5f624f0d0912e7dfd0e308a3427d194c/unnamed.png" />
          </figure><p>The interface is powerful because our graph implementation can improve performance behind the scenes without complicating the business logic. This lets us use the scalability of Workers and Cloudflare’s CDN to fetch data from our internal systems very quickly.</p>
    <div>
      <h2>Fetch pipeline</h2>
      <a href="#fetch-pipeline">
        
      </a>
    </div>
    <p>We switched to using the new graph implementation, sending more targeted API requests. Response sizes dropped by 100x overnight, switching from loading a few massive requests to many tiny requests.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/71aDOicyippmUbj4ypXKw/73dacdf16ca0ac422efdfec9e86e9dbf/image5.png" />
          </figure><p>While this solves the issue of loading too much into memory, we now have a subrequest problem because instead of a few large HTTP requests, we make an order of magnitude more of small requests. Overnight, we started consistently breaching subrequest limits.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/36KjfOU8xIuUkwF7QOlNkK/e2275a50ff1bef497cdb201c2d3a6249/image3.png" />
          </figure><p>In order to solve this problem, we built a smart middleware layer between our graph implementation and the <code>fetch</code> API.</p>
            <pre><code>export const fetchPipeline = new FetchPipeline()
  .use(requestDeduplicator())
  .use(lruCacher({
    maxItems: 100,
  }))
  .use(cdnCacher())
  .use(backoffRetryer({
    retries: 3,
    baseMs: 100,
    jitter: true,
  }))
  .handler(terminalFetch);</code></pre>
            <p>If you’re familiar with Go, you may have seen the <a href="https://pkg.go.dev/golang.org/x/sync/singleflight"><u>singleflight</u></a> package before. We took inspiration from this idea and the first middleware component in the fetch pipeline deduplicates inflight HTTP requests, so they all wait on the same Promise for data instead of producing duplicate requests in the same Worker. Next, we use a lightweight Least Recently Used (LRU) cache to internally cache requests that we have already seen before.</p><p>Once both of those are complete, we use Cloudflare’s <code>caches.default.match</code> function to cache all GET requests in the region that the Worker is running. Since we have multiple data sources with different performance characteristics, we choose time to live (TTL) values carefully. For example, real-time data is only cached for 1 minute. Relatively static infrastructure data could be cached for 1–24 hours depending on the type of data. Power management data might be changed manually and infrequently, so we can cache it for longer at the edge.</p><p>In addition to those layers, we have the standard exponential backoff, retries and jitter. This helps reduce wasted <code>fetch</code> calls where a downstream resource might be unavailable temporarily. By backing off slightly, we increase the chance that we fetch the next request successfully. Conversely, if the Worker sends requests constantly without backoff, it will easily breach the subrequest limit when the origin starts returning 5xx errors.</p><p>Putting it all together, we saw ~99% cache hit rate. <a href="https://www.cloudflare.com/learning/cdn/what-is-a-cache-hit-ratio/"><u>Cache hit rate</u></a> is the percentage of HTTP requests served from Cloudflare’s fast cache memory (a "hit") versus slower requests to data sources running in our control plane (a "miss"), calculated as (hits / (hits + misses)). A high rate means better HTTP request performance and lower costs because querying data from cache in our Worker is an order of magnitude faster than fetching from an origin server in a different region. After tuning settings, for our in memory and CDN caches, hit rates have increased dramatically. Since much of our workload is real-time, we will never have a 100% hit rate as we must request fresh data at least once per minute.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1jifI33QpBkQPd7tE5Tapi/186a74b922faac3abe091b79f03d640b/image1.png" />
          </figure><p>We have talked about improving the fetching layer, but not about how we made origin HTTP requests faster. Our maintenance coordinator needs to react in real-time to network degradation and failure of machines in data centers. We use our distributed <a href="https://blog.cloudflare.com/how-cloudflare-runs-prometheus-at-scale/"><u>Prometheus</u></a> query engine, Thanos, to deliver performant metrics from the edge into the coordinator.</p>
    <div>
      <h2>Thanos in real-time</h2>
      <a href="#thanos-in-real-time">
        
      </a>
    </div>
    <p>To explain how our choice in using the graph processing interface affected our real-time queries, let’s walk through an example. In order to analyze the health of edge routers, we could send the following query:</p>
            <pre><code>sum by (instance) (network_snmp_interface_admin_status{instance=~"edge.*"})</code></pre>
            <p>Originally, we asked our Thanos service, which stores Prometheus metrics, for a list of each edge router’s current health status and would manually filter for routers relevant to the maintenance inside the Worker. This is suboptimal for many reasons. For example, Thanos returned multi-MB responses which it needed to decode and encode. The Worker also needed to cache and decode these large HTTP responses only to filter out the majority of the data while processing a specific maintenance request. Since TypeScript is single-threaded and parsing JSON data is CPU-bound, sending two large HTTP requests means that one is blocked waiting for the other to finish parsing.</p><p>Instead, we simply use the graph to find targeted relationships such as the interface links between edge and spine routers, denoted as <code>EDGE_ROUTER_NETWORK_CONNECTS_TO_SPINE</code>.</p>
            <pre><code>sum by (lldp_name) (network_snmp_interface_admin_status{instance=~"edge01.fra03", lldp_name=~"spine.*"})</code></pre>
            <p>The result is 1 Kb on average instead of multiple MBs, or approximately 1000x smaller. This also massively reduces the amount of CPU required inside the Worker because we offload most of the deserialization to Thanos. As we explained before, this means we need to make a higher number of these smaller fetch requests, but load balancers in front of Thanos can spread the requests evenly to increase throughput for this use case. </p><p>Our graph implementation and fetch pipeline successfully tamed the 'thundering herd' of thousands of tiny real-time requests. However, historical analysis presents a different I/O challenge. Instead of fetching small, specific relationships, we need to scan months of data to find conflicting maintenance windows. In the past, Thanos would issue a massive amount of random reads to our object store, <a href="https://www.cloudflare.com/developer-platform/products/r2/">R2</a>. To solve this massive bandwidth penalty without losing performance, we adopted a new approach the Observability team developed internally this year.</p>
    <div>
      <h2>Historical data analysis</h2>
      <a href="#historical-data-analysis">
        
      </a>
    </div>
    <p>There are enough maintenance use cases that we must rely on historical data to tell us if our solution is accurate and will scale with the growth of Cloudflare’s network. We do not want to cause incidents, and we also want to avoid blocking proposed physical maintenance unnecessarily. In order to balance these two priorities, we can use time series data about maintenance events that happened two months or even a year ago to tell us how often a maintenance event is violating one of our constraints, e.g. edge router availability or Aegis. We blogged earlier this year about using Thanos to <a href="https://blog.cloudflare.com/safe-change-at-any-scale/"><u>automatically release and revert software</u></a> to the edge.</p><p>Thanos primarily fans out to Prometheus, but when Prometheus' retention is not enough to answer the query it has to download data from object storage — R2 in our case. Prometheus TSDB blocks were originally designed for local SSDs, relying on random access patterns that become a bottleneck when moved to object storage. When our scheduler needs to analyze months of historical maintenance data to identify conflicting constraints, random reads from object storage incur a massive I/O penalty. To solve this, we implemented a conversion layer that transforms these blocks into <a href="https://parquet.apache.org/"><u>Apache Parquet</u></a> files. Parquet is a columnar format native to big data analytics that organizes data by column rather than row, which — together with rich statistics — allows us to only fetch what we need.</p><p>Furthermore, since we are rewriting TSDB blocks into Parquet files, we can also store the data in a way that allows us to read the data in just a few big sequential chunks.</p>
            <pre><code>sum by (instance) (hmd:release_scopes:enabled{dc_id="45"})</code></pre>
            <p>In the example above we would choose the tuple “(__name__, dc_id)” as a primary sorting key so that metrics with the name “hmd:release_scopes:enabled” and the same value for “dc_id” get sorted close together.</p><p>Our Parquet gateway now issues precise R2 range requests to fetch only the specific columns relevant to the query. This reduces the payload from megabytes to kilobytes. Furthermore, because these file segments are immutable, we can aggressively cache them on the Cloudflare CDN.</p><p>This turns R2 into a low-latency query engine, allowing us to backtest complex maintenance scenarios against long-term trends instantly, avoiding the timeouts and high tail latency we saw with the original TSDB format. The graph below shows a recent load test, where Parquet reached up to 15x the P90 performance compared to the old system for the same query pattern.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6lVj6W4W4MMUy6cEsDpk5G/21614b7ac003a86cb5162a2ba75f4c42/image8.png" />
          </figure><p>To get a deeper understanding of how the Parquet implementation works, you can watch this talk at PromCon EU 2025, <a href="https://www.youtube.com/watch?v=wDN2w2xN6bA&amp;list=PLoz-W_CUquUlHOg314_YttjHL0iGTdE3O&amp;index=16"><u>Beyond TSDB: Unlocking Prometheus with Parquet for Modern Scale</u></a>.</p>
    <div>
      <h2>Building for scale</h2>
      <a href="#building-for-scale">
        
      </a>
    </div>
    <p>By leveraging Cloudflare Workers, we moved from a system that ran out of memory to one that intelligently caches data and uses efficient observability tooling to analyze product and infrastructure data in real time. We built a maintenance scheduler that balances network growth with product performance.</p><p>But “balance” is a moving target.</p><p>Every day, we add more hardware around the world, and the logic required to maintain it without disrupting customer traffic gets exponentially harder with more products and types of maintenance operations. We’ve worked through the first set of challenges, but now we’re staring down more subtle, complex ones that only appear at this massive scale.</p><p>We need engineers who aren't afraid of hard problems. Join our <a href="https://www.cloudflare.com/careers/jobs/?department=Infrastructure"><u>Infrastructure team</u></a> and come build with us.</p> ]]></content:encoded>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[Prometheus]]></category>
            <category><![CDATA[Infrastructure]]></category>
            <guid isPermaLink="false">5pdspiP2m71MeIoVL8wv1i</guid>
            <dc:creator>Kevin Deems</dc:creator>
            <dc:creator>Michael Hoffmann</dc:creator>
        </item>
        <item>
            <title><![CDATA[Vulnerability transparency: strengthening security through responsible disclosure]]></title>
            <link>https://blog.cloudflare.com/vulnerability-transparency-strengthening-security-through-responsible/</link>
            <pubDate>Fri, 16 May 2025 15:00:00 GMT</pubDate>
            <description><![CDATA[ In line with CISA’s Secure By Design pledge, Cloudflare shares its vulnerability disclosure process, CVE issuance criteria, and CNA duties.  ]]></description>
            <content:encoded><![CDATA[ <p>In an era where digital threats evolve faster than ever, cybersecurity isn't just a back-office concern — it's a critical business priority. At Cloudflare, we understand the responsibility that comes with operating in a connected world. As part of our ongoing commitment to security and transparency, Cloudflare is proud to have joined the <a href="https://www.cisa.gov/"><u>United States Cybersecurity and Infrastructure Security Agency’s (CISA)</u></a> <a href="https://www.cisa.gov/securebydesign/pledge"><u>“Secure by Design” pledge</u></a> in May 2024. </p><p>By signing this pledge, Cloudflare joins a growing coalition of companies committed to strengthening the resilience of the digital ecosystem. This isn’t just symbolic — it's a concrete step in aligning with cybersecurity best practices and our commitment to protect our customers, partners, and data. </p><p>A central goal in CISA’s Secure by Design pledge is promoting transparency in vulnerability reporting. This initiative underscores the importance of proactive security practices and emphasizes transparency in vulnerability management — values that are deeply embedded in Cloudflare’s Product Security program. ​We believe that openness around vulnerabilities is foundational to earning and maintaining the trust of our customers, partners, and the broader security community.</p>
    <div>
      <h2>Why transparency in vulnerability reporting matters</h2>
      <a href="#why-transparency-in-vulnerability-reporting-matters">
        
      </a>
    </div>
    <p>Transparency in vulnerability reporting is essential for building trust between companies and customers. In 2008, Linus Torvalds <a href="https://lkml.org/lkml/2008/7/15/293"><u>noted</u></a> that disclosure is inherently tied to resolution: “<i>So as far as I'm concerned, disclosing is the fixing of the bug</i>”, emphasizing that resolution must start with visibility. While this mindset might apply well to open-source projects and communities familiar with code and patches, it doesn’t scale easily to non-expert users and enterprise users who require structured, validated, and clearly communicated disclosures regarding a vulnerability’s impact. Today’s threat landscape demands not only rapid remediation of vulnerabilities but also clear disclosure of their nature, impact and resolution. This builds trust with the customer and contributes to the broader collective understanding of common vulnerability classes and emerging systemic flaws.</p>
    <div>
      <h3>What is a CVE?</h3>
      <a href="#what-is-a-cve">
        
      </a>
    </div>
    <p>Common Vulnerabilities and Exposures (CVE) is a catalog of publicly disclosed vulnerabilities and exposures. Each CVE includes a unique identifier, summary, associated metadata like the Common Weakness Enumeration (CWE) and Common Platform Enumeration (CPE), and a severity score that can range from None to Critical. </p><p>The format of a CVE ID consists of a fixed prefix, the year of the disclosure and an arbitrary sequence number ​​like<b> </b>CVE-2017-0144. Memorable names such as "EternalBlue"  (<a href="https://www.cve.org/CVERecord?id=CVE-2017-0144"><u>CVE-2017-0144</u></a>)  are often associated with high-profile exploits to enhance recall.</p>
    <div>
      <h3>What is a CNA?</h3>
      <a href="#what-is-a-cna">
        
      </a>
    </div>
    <p>As an authorized <a href="https://www.cve.org/ResourcesSupport/Glossary#glossaryCNA"><u>CVE Numbering Authority (CNA)</u></a>, Cloudflare can assign CVE identifiers for vulnerabilities discovered within our products and ecosystems. Cloudflare has been actively involved with MITRE's <a href="https://www.cve.org"><u>CVE program</u></a> since its founding in 2009. As a CNA, Cloudflare assumes the responsibility to manage disclosure timelines ensuring they are accurate, complete, and valuable to the broader industry. </p>
    <div>
      <h3>Cloudflare CVE issuance process</h3>
      <a href="#cloudflare-cve-issuance-process">
        
      </a>
    </div>
    <p>Cloudflare issues CVEs for vulnerabilities discovered internally and through our <a href="https://hackerone.com/cloudflare"><u>Bug Bounty program</u></a> when they affect <b>open source software</b> and/or our <b>distributed closed source products</b>.</p><p>The findings are triaged based on real-world exploitability and impact. Vulnerabilities without a plausible exploitation path, in addition to findings related to test repositories or exposed credentials like API keys, typically do not qualify for CVE issuance.</p><p>We recognize that CVE issuance involves nuance, particularly for sophisticated security issues in a complex codebase (for example, the <a href="https://www.youtube.com/watch?v=Rg_VPMT0XXw"><u>Linux kernel</u></a>). Issuance relies on impact to users and the likelihood of the exploit, which depends on the complexity of executing an attack. The growing number of CVEs issued industry-wide reflects a broader effort to balance theoretical vulnerabilities against real-world risk. </p><p>In scenarios where Cloudflare was impacted by a vulnerability, but the root cause was within another CNA’s scope of products, Cloudflare will not assign the CVE. Instead, Cloudflare may choose other mediums of disclosure, like blog posts.</p>
    <div>
      <h3>How does Cloudflare disclose a CVE?</h3>
      <a href="#how-does-cloudflare-disclose-a-cve">
        
      </a>
    </div>
    <p>Our disclosure process begins with internal evaluation of severity and scope, and any potential privacy or compliance impacts. When necessary, we engage our Legal and Security Incident Response Teams (SIRT). For vulnerabilities reported to Cloudflare by external entities via our Bug Bounty program, our standard disclosure timeline is within 90 days. This timeline allows us to ensure proper remediation, thorough testing, and responsible coordination with affected parties. While we are committed to transparent disclosure, we believe addressing and validating fixes before public release is essential to protect users and uphold system security. For open source projects, we also issue security advisories on the relevant GitHub repositories. Additionally, we encourage external researchers to publish/blog about their findings after issues are remediated. Full details and process of Cloudflare’s external researcher/entity disclosure policy can be found via our <a href="https://hackerone.com/cloudflare?type=team#:~:text=the%20next%20level!-,Disclosure,-Cloudflare%20strongly%20supports"><u>Bug Bounty program</u></a> policy page</p>
    <div>
      <h2>Outcomes</h2>
      <a href="#outcomes">
        
      </a>
    </div>
    <p>To date, Cloudflare has issued and disclosed<b> </b>multiple<b> </b>CVEs. Because of the security platforms and products that Cloudflare builds, vulnerabilities have primarily been in the areas of denial of service, local privilege escalation, logical flaws, and improper input validation. Cloudflare also believes in collaboration and open sources of some of our software stack, therefore CVEs in these repositories are also promptly disclosed.</p><p>Cloudflare disclosures can be found <a href="https://www.cve.org/CVERecord/SearchResults?query=Cloudflare"><u>here</u></a>. Below are some of the most notable vulnerabilities disclosed by Cloudflare:</p>
    <div>
      <h3><a href="https://www.cve.org/CVERecord?id=CVE-2024-1765"><u>CVE-2024-1765</u></a>: quiche: Memory Exhaustion Attack using post-handshake CRYPTO frames</h3>
      <a href="#quiche-memory-exhaustion-attack-using-post-handshake-crypto-frames">
        
      </a>
    </div>
    <p><a href="https://github.com/cloudflare/quiche"><u>Cloudflare quiche</u></a> (through version 0.19.1/0.20.0) was affected by an unlimited resource allocation vulnerability causing rapid increase of memory usage of the system running a quiche server or client.</p><p>A remote attacker could take advantage of this vulnerability by repeatedly sending an unlimited number of 1-RTT CRYPTO frames after previously completing the QUIC handshake.</p><p>Exploitation was possible for the duration of the connection, which could be extended by the attacker.</p><p>quiche 0.19.2 and 0.20.1 are the earliest versions containing the fix for this issue.</p>
    <div>
      <h3><a href="https://www.cve.org/CVERecord?id=CVE-2024-0212"><u>CVE-2024-0212</u></a>: Cloudflare WordPress plugin enables information disclosure of Cloudflare API (for low-privilege users)</h3>
      <a href="#cloudflare-wordpress-plugin-enables-information-disclosure-of-cloudflare-api-for-low-privilege-users">
        
      </a>
    </div>
    <p>The <a href="https://github.com/cloudflare/Cloudflare-WordPress"><u>Cloudflare WordPress</u></a> plugin was found to be vulnerable to improper authentication. The vulnerability enables attackers with a lower privileged account to access data from the Cloudflare API.</p><p>The issue has been fixed in version &gt;= 4.12.3 of the plugin</p>
    <div>
      <h3><a href="https://www.cve.org/CVERecord?id=CVE-2023-2754"><u>CVE-2023-2754</u></a> - Plaintext transmission of DNS requests in Windows 1.1.1.1 WARP client</h3>
      <a href="#plaintext-transmission-of-dns-requests-in-windows-1-1-1-1-warp-client">
        
      </a>
    </div>
    <p>The Cloudflare WARP client for Windows assigns loopback IPv4 addresses for the DNS servers, since WARP acts as a local DNS server that performs DNS queries securely. However, if a user is connected to WARP over an IPv6-capable network, the WARP client did not assign loopback IPv6 addresses but rather Unique Local Addresses, which under certain conditions could point towards unknown devices in the same local network, enabling an attacker to view DNS queries made by the device.</p><p>This issue was patched in version 2023.7.160.0 of the WARP client (Windows).</p>
    <div>
      <h3><a href="https://www.cve.org/CVERecord?id=CVE-2025-0651"><u>CVE-2025-0651</u></a> - Improper privilege management allows file manipulations </h3>
      <a href="#improper-privilege-management-allows-file-manipulations">
        
      </a>
    </div>
    <p>An improper privilege management vulnerability in Cloudflare WARP for Windows allowed file manipulation by low-privilege users. Specifically, a user with limited system permissions could create symbolic links within the <code>C:\ProgramData\Cloudflare\warp-diag-partials</code> directory. When the "Reset all settings" feature is triggered, the WARP service — running with SYSTEM-level privileges — followed these symlinks and may delete files outside the intended directory, potentially including files owned by the SYSTEM user.</p><p>This vulnerability affected versions of WARP prior to 2024.12.492.0.</p>
    <div>
      <h3><a href="https://www.cve.org/CVERecord/SearchResults?query=CVE-2025-23419"><u>CVE-2025-23419</u></a>: TLS client authentication can be bypassed due to ticket resumption (disclosed Cloudflare impact via blog post)</h3>
      <a href="#tls-client-authentication-can-be-bypassed-due-to-ticket-resumption-disclosed-cloudflare-impact-via-blog-post">
        
      </a>
    </div>
    <p>Cloudflare’s <a href="https://www.cloudflare.com/en-gb/learning/access-management/what-is-mutual-tls/"><u>mutual TLS</u></a> implementation caused a vulnerability in the session resumption handling. The underlying issue originated from <a href="https://github.com/google/boringssl"><u>BoringSSL</u></a>’s process to resume TLS sessions. BoringSSL stored client certificates, which were reused from the original session (without revalidating the full certificate chain) and the original handshake's verification status was not re-validated. </p><p>While Cloudflare was impacted by the vulnerability, the root cause was within NGINX's implementation, making F5 the appropriate CNA to assign the CVE. This is an example of alternate mediums of disclosure that Cloudflare sometimes opt for. This issue was fixed as per guidance from the respective CVE — please see our <a href="https://blog.cloudflare.com/resolving-a-mutual-tls-session-resumption-vulnerability/"><u>blog post</u></a> for more details.</p>
    <div>
      <h2>Conclusion</h2>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>Irrespective of the industry, if your organization builds software, we encourage you to familiarize yourself with <a href="https://www.cisa.gov/securebydesign"><u>CISA’s “Secure by Design” principles</u></a> and create a plan to implement them in your company. The CISA Secure by Design pledge is built around seven security goals, prioritizing the security of customers, and challenges organizations to think differently about security. </p><p>As we continue to enhance our security posture, Cloudflare remains committed to enhancing our internal practices, investing in tooling and automation, and sharing knowledge with the community. CVE transparency is not a one-time initiative — it’s a sustained effort rooted in openness, discipline, and technical excellence. By embedding these values in how we design, build and secure our products, we aim to meet and exceed expectations set out in the CISA pledge and make the Internet more secure, faster and reliable!</p><p>For more updates on our CISA progress, review our related <a href="https://blog.cloudflare.com/tag/cisa/"><u>blog posts</u></a>. Cloudflare has delivered five of the seven CISA Secure by Design pledge goals, and we aim to complete the remainder of the pledge goals in May 2025.</p> ]]></content:encoded>
            <category><![CDATA[CISA]]></category>
            <category><![CDATA[Policy & Legal]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[Security]]></category>
            <category><![CDATA[CVE]]></category>
            <guid isPermaLink="false">1Ni8ekT7qEWe5PVydsDP1m</guid>
            <dc:creator>Sri Pulla</dc:creator>
            <dc:creator>Martin Schwarzl</dc:creator>
            <dc:creator>Trishna</dc:creator>
        </item>
        <item>
            <title><![CDATA[Scaling with safety: Cloudflare's approach to global service health metrics and software releases]]></title>
            <link>https://blog.cloudflare.com/safe-change-at-any-scale/</link>
            <pubDate>Mon, 05 May 2025 14:00:00 GMT</pubDate>
            <description><![CDATA[ Learn how Cloudflare tackles the challenge of scaling global service health metrics to safely release new software across our global network. ]]></description>
            <content:encoded><![CDATA[ <p>Has your browsing experience ever been disrupted by this error page? Sometimes Cloudflare returns <a href="https://developers.cloudflare.com/support/troubleshooting/cloudflare-errors/troubleshooting-cloudflare-5xx-errors/#error-500-internal-server-error"><u>"Error 500"</u></a> when our servers cannot respond to your web request. This inability to respond could have several potential causes, including problems caused by a bug in one of the services that make up Cloudflare's software stack.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1rIrBE5GP2IJwbn2k6mVTV/fd796ed1ef591fb8bd95395aa8f604d1/1.png" />
          </figure><p>We know that our testing platform will inevitably miss <a href="https://blog.cloudflare.com/pipefail-how-a-missing-shell-option-slowed-cloudflare-down/"><u>some software bugs</u></a>, so we built guardrails to gradually and safely release new code before a feature reaches all users. Health Mediated Deployments (HMD) is Cloudflare’s data-driven solution to automating software updates across our <a href="https://www.cloudflare.com/network/"><u>global network</u></a>. HMD works by querying <a href="https://thanos.io/"><u>Thanos</u></a>, a system for storing and scaling <a href="https://blog.cloudflare.com/how-cloudflare-runs-prometheus-at-scale/"><u>Prometheus</u></a> metrics. Prometheus collects detailed data about the performance of our services, and Thanos makes that data accessible across our distributed network. HMD uses these metrics to determine whether new code should continue to roll out, pause for further evaluation, or be automatically reverted to prevent widespread issues.</p><p>Cloudflare engineers configure signals from their service, such as alerting rules or <a href="https://sre.google/workbook/implementing-slos/"><u>Service Level Objectives (SLOs)</u></a>. For example, the following Service Level Indicator (SLI) checks the rate of HTTP 500 errors over 10 minutes returned from a service in our software stack.</p>
            <pre><code>sum(rate(http_request_count{code="500"}[10m])) / sum(rate(http_request_count[10m]))</code></pre>
            <p>An SLO is a combination of an SLI and an objective threshold. For example, the service returns 500 errors &lt;0.1% of the time.</p><p>If the success rate is unexpectedly decreasing where the new code is running, HMD reverts the change in order to stabilize the system, reacting before humans even know what Cloudflare service was broken. Below, HMD recognizes the degradation in signal in an early release stage and reverts the code back to the prior version to limit the blast radius.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2O6gCfhZsoU1QCf3lu0QMl/bb4377cccbf982b607ce3564e4bf9fbd/2.png" />
          </figure><p>
Cloudflare’s network serves millions of requests per second across diverse geographies. How do we know that HMD will react quickly the next time we accidentally release code that contains a bug? HMD performs a testing strategy called <a href="https://en.wikipedia.org/wiki/Backtesting"><u>backtesting</u></a>, outside the release process, which uses historical incident data to test how long it would take to react to degrading signals in a future release.</p><p>We use Thanos to join thousands of small Prometheus deployments into a single unified query layer while keeping our monitoring reliable and cost-efficient. To backfill historical incident metric data that has fallen out of Prometheus’ retention period, we use our <a href="https://www.cloudflare.com/developer-platform/products/r2/">object storage solution</a>, R2.</p><p>Today, we store 4.5 billion distinct time series for a year of retention, which results in roughly 8 petabytes of data in 17 million objects distributed all over the globe.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5TlfqQIPqS7TVxFB38PztG/65dc562db7af5304562b3fed9ab6486d/3.png" />
          </figure>
    <div>
      <h2>Making it work at scale</h2>
      <a href="#making-it-work-at-scale">
        
      </a>
    </div>
    <p>To give a sense of scale, we can estimate the impact of a batch of backtests:</p><ul><li><p>Each backtest run is made up of multiple SLOs to evaluate a service's health.</p></li><li><p>Each SLO is evaluated using multiple queries containing batches of data centers.</p></li><li><p>Each data center issues anywhere from tens to thousands of requests to R2.</p></li></ul><p>Thus, in aggregate, a batch can translate to hundreds of thousands of <a href="https://prometheus.io/docs/prometheus/latest/querying/basics/"><u>PromQL queries</u></a> and millions of requests to R2. Initially, batch runs would take about 30 hours to complete but through blood, sweat, and tears, we were able to cut this down to 2 hours.</p><p>Let’s review how we made this processing more efficient.</p>
    <div>
      <h3>Recording rules</h3>
      <a href="#recording-rules">
        
      </a>
    </div>
    <p>HMD slices our fleet of machines across multiple dimensions. For the purposes of this post, let’s refer to them as “tier” and “color”. Given a pair of tier and color, we would use the following PromQL expression to find the machines that make up this combination:</p>
            <pre><code>group by (instance, datacenter, tier, color) (
  up{job="node_exporter"}
  * on (datacenter) group_left(tier) datacenter_metadata{tier="tier3"}
  * on (instance) group_left(color) server_metadata{color="green"}
  unless on (instance) (machine_in_maintenance == 1)
  unless on (datacenter) (datacenter_disabled == 1)
)</code></pre>
            <p>Most of these series have a cardinality of approximately the number of machines in our fleet. That’s a substantial amount of data we need to fetch from <a href="https://www.cloudflare.com/learning/cloud/what-is-object-storage/">object storage</a> and transmit home for query evaluation, as well as a significant number of series we need to decode and join together.</p><p>Since this is a fairly common query that is issued in every HMD run, it makes sense to precompute it. In the Prometheus ecosystem, this is commonly done with <a href="https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/"><u>recording rules</u></a>:</p>
            <pre><code>hmd:release_scopes:info{tier="tier3", color="green"}</code></pre>
            <p>Aside from looking much cleaner, this also reduces the load at query time significantly. Since all the joins involved can only have matches within a data center, it is well-defined to evaluate those rules directly in the Prometheus instances inside the data center itself.</p><p>Compared to the original query, the cardinality we need to deal with now scales with the size of the release scope instead of the size of the entire fleet.</p><p>This is significantly cheaper and also less likely to be affected by network issues along the way, which in turn reduces the amount that we need to retry the query, on average. </p>
    <div>
      <h3>Distributed query processing</h3>
      <a href="#distributed-query-processing">
        
      </a>
    </div>
    
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2X1dlDO1DYXfFo29DRIBeX/c2d8a7f88d24dc4b562d068a4774a6dd/4.png" />
          </figure><p>HMD and the Thanos Querier, depicted above, are stateless components that can run anywhere, with highly available deployments in North America and Europe. Let us quickly recap what happens when we evaluate the SLI expression from HMD in our introduction:</p>
            <pre><code>sum(rate(http_request_count{code="500"}[10m]))
/ 
sum(rate(http_request_count[10m]))</code></pre>
            <p>Upon receiving this query from HMD, the Thanos Querier will start requesting raw time series data for the “http_requests_total” metric from its connected <a href="https://thanos.io/v0.4/components/sidecar/"><u>Thanos Sidecar</u></a> and <a href="https://thanos.io/tip/components/store.md/"><u>Thanos Store</u></a> instances all over the world, wait for all the data to be transferred to it, decompress it, and finally compute its result:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4jcK7cvQfMtqeQMeuFnTMz/3bdca2132a4e700050512dc15d823ef3/5.png" />
          </figure><p>While this works, it is not optimal for several reasons. We have to wait for raw data from thousands of data sources all over the world to arrive in one location before we can even start to decompress it, and then we are limited by all the data being processed by one instance. If we double the number of data centers, we also need to double the amount of memory we allocate for query evaluation.</p><p>Many SLIs come in the form of simple aggregations, typically to boil down some aspect of the service's health to a number, such as the percentage of errors. As with the aforementioned recording rule, those aggregations are often distributive — we can evaluate them inside the data center and coalesce the sub-aggregations again to arrive at the same result.</p><p>To illustrate, if we had a recording rule per data center, we could rewrite our example like this:</p>
            <pre><code>sum(datacenter:http_request_count:rate10m{code="500"})
/ 
sum(datacenter:http_request_count:rate10m)</code></pre>
            <p>This would solve our problems, because instead of requesting raw time series data for high-cardinality metrics, we would request pre-aggregated query results. Generally, these pre-aggregated results are an order of magnitude less data that needs to be sent over the network and processed into a final result.</p><p>However, recording rules come with a steep write-time cost in our architecture, evaluated frequently across thousands of Prometheus instances in production, just to speed up a less frequent ad-hoc batch process. Scaling recording rules alongside our growing set of service health SLIs quickly would be unsustainable. So we had to go back to the drawing board.</p><p>It would be great if we could evaluate data center-scoped queries remotely and coalesce their result back again — for arbitrary queries and at runtime. To illustrate, we would like to evaluate our example like this:</p>
            <pre><code>(sum(rate(http_requests_total{status="500", datacenter="dc1"}[10m])) + ...)
/
(sum(rate(http_requests_total{datacenter="dc1"}[10m])) + ...)</code></pre>
            <p>This is exactly what Thanos’ <a href="https://thanos.io/tip/proposals-done/202301-distributed-query-execution.md/"><u>distributed query engine</u></a> is capable of doing. Instead of requesting raw time series data, we request data center scoped aggregates and only need to send those back home where they get coalesced back again into the full query result:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/41XYc4JFFrNsmr3p0nYD2h/e3719dbe8fb8055cbb8f72c88729dfd9/6.png" />
          </figure><p>Note that we ensure all the expensive data paths are as short as possible by utilizing R2 <a href="https://developers.cloudflare.com/r2/reference/data-location/#location-hints"><u>location hints</u></a> to specify the primary access region.
</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6H31Ad1XCjJWpuAQGPYSlt/ddaa971e4fa59bffdf283e10d0be0b8c/7.png" />
          </figure>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1kxTrCfN0wZiNu90MNaOm8/8c3df56f9b8724b0ec01e6e9270bb989/8.png" />
          </figure><p>To measure the effectiveness of this approach, we used <a href="https://cloudprober.org/"><u>Cloudprober</u></a> and wrote probes that evaluate the relatively cheap, but still global, query <code>count(node_uname_info)</code>.</p>
            <pre><code>sum(thanos_cloudprober_latency:rate6h{component="thanos-central"})
/
sum(thanos_cloudprober_latency:rate6h{component="thanos-distributed"})</code></pre>
            <p>In the graph below, the y-axis represents the speedup of the distributed execution deployment relative to the centralized deployment. On average, distributed execution responds 3–5 times faster to probes.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1FzUb7uthpVG0yeSEFQxnd/6061eb1bc585565a47017ed9ddddae0a/9.png" />
          </figure><p>Anecdotally, even slightly more complex queries quickly time out or even crash our centralized deployment, but they still can be comfortably computed by the distributed one. For a slightly more expensive query like <code>count(up)</code> for about 17 million scrape jobs, we had difficulty getting the centralized querier to respond and had to scope it to a single region, which took about 42 seconds:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3lhd497YLjRAhmSz55jGlG/2b258c6f634dc8a435f78703e38ec56c/10.png" />
          </figure><p>Meanwhile, our distributed queriers were able to return the full result in about 8 seconds:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4tr2sKnLeKrzXLnMsfRViZ/675a2aade0d922548fc07a0bd8ad5fc5/11.png" />
          </figure>
    <div>
      <h3>Congestion control</h3>
      <a href="#congestion-control">
        
      </a>
    </div>
    <p>HMD batch processing leads to spiky load patterns that are hard to provision for. In a perfect world, it would issue a steady and predictable stream of queries. At the same time, HMD batch queries have lower priority to us than the queries that on-call engineers issue to triage production problems. We tackle both of those problems by introducing an adaptive priority-based concurrency control mechanism. After reading Netflix’s work on <a href="https://netflixtechblog.medium.com/performance-under-load-3e6fa9a60581"><u>adaptive concurrency limits</u></a>, we implemented a similar proxy to dynamically limit batch request flow when Thanos SLOs start to degrade. For example, one such SLO is its cloudprober failure rate over the last minute:</p>
            <pre><code>sum(thanos_cloudprober_fail:rate1m)
/
(sum(thanos_cloudprober_success:rate1m) + sum(thanos_cloudprober_fail:rate1m))</code></pre>
            <p>We apply jitter, a random delay, to smooth query spikes inside the proxy. Since batch processing prioritizes overall query throughput over individual query latency, jitter helps HMD send a burst of queries, while allowing Thanos to process queries gradually over several minutes. This reduces instantaneous load on Thanos, improving overall throughput, even if individual query latency increases. Meanwhile, HMD encounters fewer errors, minimizing retries and boosting batch efficiency.</p><p>Our solution simulates how TCP’s congestion control algorithm, <a href="https://en.wikipedia.org/wiki/Additive_increase/multiplicative_decrease"><u>additive increase/multiplicative decrease</u></a>, works. When the proxy server receives a successful request from Thanos, it allows one more concurrent request through next time. If backpressure signals breach defined thresholds, the proxy limits the congestion window proportional to the failure rate.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4M4s0lmq8h3bmZumLPUfXu/c3a967d51b367d155c26f4d95c673cd1/12.png" />
          </figure><p>As the failure rate increases past the “warn” threshold, approaching the “emergency” threshold, the proxy gets exponentially closer to allowing zero additional requests through the system. However, to prevent bad signals from halting all traffic, we cap the loss with a configured minimum request rate.</p>
    <div>
      <h3>Columnar experiments</h3>
      <a href="#columnar-experiments">
        
      </a>
    </div>
    <p>Because Thanos deals with Prometheus TSDB blocks that were never designed for being read over a slow medium like object storage, it does a lot of random I/O. Inspired by <a href="https://www.youtube.com/watch?v=V8Y4VuUwg8I"><u>this excellent talk</u></a>, we started storing our time series data in <a href="https://parquet.apache.org/"><u>Parquet</u></a> files, with some promising preliminary results. This project is still too early to draw any robust conclusions, but we wanted to share our implementation with the Prometheus community, so we are publishing our experimental object storage gateway as <a href="https://github.com/cloudflare/parquet-tsdb-poc"><u>parquet-tsdb-poc</u></a> on GitHub.</p>
    <div>
      <h2>Conclusion</h2>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>We built Health Mediated Deployments (HMD) to enable safe and reliable software releases while pushing the limits of our <a href="https://www.cloudflare.com/learning/performance/what-is-observability/">observability</a> infrastructure. Along the way, we significantly improved Thanos’ ability to handle high-load queries, reducing batch runtimes by 15x.</p><p>But this is just the beginning. We’re excited to continue working with the observability, resiliency, and R2 teams to push our infrastructure to its limits — safely and at scale. As we explore new ways to enhance observability, one exciting frontier is optimizing time series storage for object storage.</p><p>We’re sharing this work with the community as an open-source proof of concept. If you’re interested in exploring Parquet-based time series storage and its potential for large-scale observability, check out the GitHub project linked above.</p> ]]></content:encoded>
            <category><![CDATA[R2]]></category>
            <category><![CDATA[Prometheus]]></category>
            <category><![CDATA[Reliability]]></category>
            <guid isPermaLink="false">5D2xgj0sJ6yj8oOh6qrNUb</guid>
            <dc:creator>Harshal Brahmbhatt</dc:creator>
            <dc:creator>Kevin Deems</dc:creator>
            <dc:creator>Nina Giunta</dc:creator>
            <dc:creator>Michael Hoffmann</dc:creator>
        </item>
        <item>
            <title><![CDATA[Demonstrating reduction of vulnerability classes: a key step in CISA’s “Secure by Design” pledge]]></title>
            <link>https://blog.cloudflare.com/cisa-pledge-commitment-reducing-vulnerability/</link>
            <pubDate>Tue, 14 Jan 2025 14:00:00 GMT</pubDate>
            <description><![CDATA[ Cloudflare strengthens its commitment to cybersecurity by joining CISA's "Secure by Design" pledge. In line with this, we're reducing the prevalence of vulnerability classes across our products. ]]></description>
            <content:encoded><![CDATA[ <p>In today’s rapidly evolving digital landscape, securing software systems has never been more critical. Cyber threats continue to exploit systemic vulnerabilities in widely used technologies, leading to widespread damage and disruption. That said, the <a href="https://www.cisa.gov/"><u>United States Cybersecurity and Infrastructure Agency (CISA)</u></a> helped shape best practices for the technology industry with their <a href="https://www.cisa.gov/securebydesign/pledge"><u>Secure-by-Design pledge</u></a>. <a href="https://blog.cloudflare.com/secure-by-design-principles/"><u>Cloudflare signed this pledge</u></a> on May 8, 2024, reinforcing our commitment to creating resilient systems where security is not just a feature, but a foundational principle.</p><p>We’re excited to share an update aligned with one of CISA’s goals in the pledge: <i>To reduce entire classes of vulnerabilities</i>. This goal aligns with the Cloudflare Product Security program’s initiatives to continuously automate proactive detection and vigorously prevent vulnerabilities at scale.   </p><p>Cloudflare’s commitment to the CISA pledge reflects our dedication to transparency and accountability to our customers. This blog post outlines why we prioritized certain vulnerability classes, the steps we took to further eliminate vulnerabilities, and the measurable outcomes of our work.</p>
    <div>
      <h3>The core philosophy that continues: prevent, not patch</h3>
      <a href="#the-core-philosophy-that-continues-prevent-not-patch">
        
      </a>
    </div>
    <p>Cloudflare’s core security philosophy is to prevent security vulnerabilities from entering production environments. One of the goals for Cloudflare’s Product Security team is to champion this philosophy and ensure secure-by-design approaches are part of product and platform development. Over the last six months, the Product Security team aggressively added both new and customized rulesets aimed at completely eliminating secrets and injection code vulnerabilities. These efforts have enhanced detection precision, reducing false positives, while enabling the proactive detection and blocking of these two vulnerability classes. Cloudflare’s security practice to block vulnerabilities before they are introduced into code at merge or code changes serves to maintain a high security posture and aligns with CISA’s pledge around proactive security measures.</p><p>Injection vulnerabilities are a critical vulnerability class, irrespective of the product or platform. These occur when code and data are improperly mixed due to lack of clear boundaries as a result of inadequate validation, unsafe functions, and/or improper sanitization. Injection vulnerabilities are considered high impact as they lead to compromise of confidentiality, integrity, and availability of the systems involved. Some of the ways Cloudflare continuously detects and prevents these risks is through security reviews, secure code scanning, and vulnerability testing. Additionally, ongoing efforts to institute improved precision serve to reduce false positives and aggressively detect and block these vulnerabilities at the source if engineers accidentally introduce these into code.</p><p>Secrets in code is another vulnerability class of high impact, as it presents significant risk related to confidential information leaks, potentially leading to unauthorized access and insider threat challenges. In 2023, Cloudflare prioritized tuning our security tools and systems to further improve the detection and reduction of secrets within code. Through audits and usage patterns analysis across all Cloudflare repositories, we further decreased the probability of the reintroduction of these vulnerabilities into new code by writing and enabling enhanced secrets detection rules.</p><p>Cloudflare is committed to elimination of these vulnerability classes regardless of their criticality. By addressing these vulnerabilities at their source, Cloudflare has significantly reduced the attack surface and the potential for exploitation in production environments. This approach established secure defaults by enabling developers to rely on frameworks and tools that inherently separate data or secrets from code, minimizing the need for reactive fixes. Additionally, resolving these vulnerabilities at the code level “future-proofs” applications, ensuring they remain resilient as the threat landscape evolves. </p>
    <div>
      <h3>Cloudflare’s techniques for addressing these vulnerabilities</h3>
      <a href="#cloudflares-techniques-for-addressing-these-vulnerabilities">
        
      </a>
    </div>
    <p>To address both injection and embedded secrets vulnerabilities, Cloudflare focused on building secure defaults, leveraging automation, and empowering developers. To establish secure default configurations, Cloudflare uses frameworks designed to inherently separate data from code. We also increased reliance on secure storage systems and secret management tools, integrating them seamlessly into the development pipeline.</p><p><i>Continuous automation played a critical role in our strategy.</i> Static analysis tools integration with DevOps process were enhanced with customized rule sets to block issues based on observed patterns and trends. Additionally, along with security scans running on every pull and merge request, software quality assurance measures of “build break”  and “stop the code” were enforced. This prevented risks from entering production when true positive vulnerabilities were detected across all Cloudflare development activities, irrespective of criticality and impacted product. This proactive approach has further reduced the likelihood of these vulnerabilities reaching production environments. </p><p><i>Developer enablement was another key pillar</i>. Priority was placed on bolstering existing continuous education and training for engineering teams by providing additional guidance and best practices on preventing security vulnerabilities, and leveraging our centralized secrets platform in an automated way. Embedding these principles into daily workflows has fostered a culture of shared responsibility for security across the organization.</p>
    <div>
      <h3>The role of custom rulesets and “build break” </h3>
      <a href="#the-role-of-custom-rulesets-and-build-break">
        
      </a>
    </div>
    <p>To operationalize the more aggressive detection and blocking capabilities, Cloudflare’s Product Security team wrote new detection rulesets for its <a href="https://en.wikipedia.org/wiki/Static_application_security_testing"><u>static application security testing (SAST)</u></a> tool integrated in <a href="https://www.cloudflare.com/learning/serverless/glossary/what-is-ci-cd/">CI/CD workflows</a> and hardened the security criteria for code releases to production. Using the SAST tooling with both default and custom rulesets allows the security team to perform comprehensive scans for secure code, secrets, and software supply chain vulnerabilities, virtually eliminating injection vulnerabilities and secrets from source code. It also enables the security team to identify and address issues early while systematically enforcing security policies.</p><p>Cloudflare’s expansion of the security tool suite played a critical role in the company’s secure product strategy. Initially, rules were enabled in “monitoring only” mode to understand trends and potential false positives. Then rules were fine-tuned to enforce and adjust priorities without disrupting development workflows. Leveraging internal threat models, the team writes custom rules tailored to Cloudflare’s infrastructure. Every <a href="https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests"><u>pull request (PR)</u></a> and <a href="https://github.com/diffblue/gitlab/blob/master/doc/user/project/merge_requests/creating_merge_requests.md"><u>merge request (MR)</u></a> was scanned against these specific rule sets, including those targeting injection and secrets. The fine-tuned rules, optimized for high precision, are then activated in blocking mode, which leads to breaking the build when detected. This process provides vulnerability remediation at the PR/MR stage.</p><p>Hardening these security checks directly into the CI/CD pipeline enforces a proactive security assurance strategy in the development lifecycle. This approach ensures vulnerabilities are detected and addressed early in the development process before reaching production. The detection and blocking of these issues early reduces remediation efforts, minimizes risk, and strengthens the overall security of our products and systems.</p>
    <div>
      <h3>Outcomes</h3>
      <a href="#outcomes">
        
      </a>
    </div>
    <p>Cloudflare continues to follow a culture of transparency as it provides increased visibility into the root cause of an issue and consequently allowing us to improve the process/product at scale. As a result, these efforts have yielded tangible results and continue to strengthen the security posture of all Cloudflare products.</p><p>In the second half of 2024, the team aggressively added new rulesets that helped detect and remove new secrets introduced into code repositories. This led to a 79% reduction of secrets in code over the previous quarter, underscoring Cloudflare’s commitment to safeguarding the company's codebase and protecting sensitive information. Following a similar approach, the team also introduced new rulesets in blocking mode, irrespective of the criticality level for all injection vulnerabilities. These improvements led to an additional 44% reduction of potential SQL injection and code injection vulnerabilities.</p><p>While security tools may produce false positives, customized rulesets with high-confidence true positives remain a key step in order to methodically evaluate and address the findings. These reductions reflect the effectiveness of proactive security measures in reducing entire vulnerability classes at scale. </p>
    <div>
      <h3>Future plans</h3>
      <a href="#future-plans">
        
      </a>
    </div>
    <p>Cloudflare will continue to mature the current practices and enforce secure-by-design principles. Some other security practices we will continue to mature include: providing secure frameworks, threat modeling at scale, integration of automated security tooling in every stage of the software development lifecycle (SDLC), and ongoing role based developer training on leading edge security standards. All of these strategies help reduce, or eliminate, entire classes of vulnerabilities.</p>
    <div>
      <h3>Conclusion</h3>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>Irrespective of the industry, if your organization builds software, we encourage you to familiarize yourself with <a href="https://www.cisa.gov/securebydesign"><u>CISA’s ‘Secure by Design’ principles</u></a> and create a plan to implement them in your company. The commitment is built around seven security goals, prioritizing the security of customers.</p><p>The CISA Secure by Design pledge challenges organizations to think differently about security. By addressing vulnerabilities at their source, Cloudflare has demonstrated measurable progress in reducing systemic risks.</p><p>Cloudflare’s continued focus on addressing vulnerability classes through prevention mechanisms outlined above serves as a critical foundation. These efforts ensure the security of Cloudflare systems, employees, and customers. Cloudflare is invested in continuous innovation and building a safe digital world. </p><p>You can also find more updates on our <a href="https://blog.cloudflare.com/"><u>blog</u></a> as we build our roadmap to meet all seven CISA Secure by Design pledge goals by May 2025, such as our post about reaching <a href="https://blog.cloudflare.com/cisa-pledge-commitment-bug-bounty-vip/"><u>Goal #5 of the pledge</u></a>.</p><p>As a cybersecurity company, Cloudflare considers product security an integral part of its DNA. We strongly believe in CISA’s principles issued in the <a href="https://www.cisa.gov/securebydesign/pledge"><u>Secure by Design pledge</u></a>, and will continue to uphold these principles in the work we do.</p> ]]></content:encoded>
            <category><![CDATA[CISA]]></category>
            <category><![CDATA[Policy & Legal]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[Security]]></category>
            <guid isPermaLink="false">4j7FBBC7QJi59ZFzmAG5Sx</guid>
            <dc:creator>Sri Pulla</dc:creator>
            <dc:creator>Trishna</dc:creator>
            <dc:creator>Jordan Lilly</dc:creator>
        </item>
        <item>
            <title><![CDATA[Improving platform resilience at Cloudflare through automation]]></title>
            <link>https://blog.cloudflare.com/improving-platform-resilience-at-cloudflare/</link>
            <pubDate>Wed, 09 Oct 2024 13:00:00 GMT</pubDate>
            <description><![CDATA[ We realized that we need a way to automatically heal our platform from an operations perspective, and designed and built a workflow orchestration platform to provide these self-healing capabilities   ]]></description>
            <content:encoded><![CDATA[ <p>Failure is an expected state in production systems, and no predictable failure of either software or hardware components should result in a negative experience for users. The exact failure mode may vary, but certain remediation steps must be taken after detection. A common example is when an error occurs on a server, rendering it unfit for production workloads, and requiring action to recover.</p><p>When operating at Cloudflare’s scale, it is important to ensure that our platform is able to recover from faults seamlessly. It can be tempting to rely on the expertise of world-class engineers to remediate these faults, but this would be manual, repetitive, unlikely to produce enduring value, and not scaling. In one word: toil; not a viable solution at our scale and rate of growth.</p><p>In this post we discuss how we built the foundations to enable a more scalable future, and what problems it has immediately allowed us to solve.</p>
    <div>
      <h2>Growing pains</h2>
      <a href="#growing-pains">
        
      </a>
    </div>
    <p>The Cloudflare <a href="https://en.wikipedia.org/wiki/Site_reliability_engineering"><u>Site Reliability Engineering (SRE)</u></a> team builds and manages the platform that helps product teams deliver our extensive suite of offerings to customers. One important component of this platform is the collection of servers that power critical products such as Durable Objects, Workers, and DDoS mitigation. We also build and maintain foundational software services that power our product offerings, such as configuration management, provisioning, and IP address allocation systems.</p><p>As part of tactical operations work, we are often required to respond to failures in any of these components to minimize impact to users. Impact can vary from lack of access to a specific product feature, to total unavailability. The level of response required is determined by the priority, which is usually a reflection of the severity of impact on users. Lower-priority failures are more common — a server may run too hot, or experience an unrecoverable hardware error. Higher-priority failures are rare and are typically resolved via a well-defined incident response process, requiring collaboration with multiple other teams.</p><p>The commonality of lower-priority failures makes it obvious when the response required, as defined in runbooks, is “toilsome”. To reduce this toil, we had previously implemented a plethora of solutions to automate runbook actions such as manually-invoked shell scripts, cron jobs, and ad-hoc software services. These had grown organically over time and provided solutions on a case-by-case basis, which led to duplication of work, tight coupling, and lack of context awareness across the solutions.</p><p>We also care about how long it takes to resolve any potential impact on users. A resolution process which involves the manual invocation of a script relies on human action, increasing the Mean-Time-To-Resolve (MTTR) and leaving room for human error. This risks increasing the amount of errors we serve to users and degrading trust.</p><p>These problems proved that we needed a way to automatically heal these platform components. This especially applies to our servers, for which failure can cause impact across multiple product offerings. While we have <a href="https://blog.cloudflare.com/unimog-cloudflares-edge-load-balancer"><u>mechanisms to automatically steer traffic away</u></a> from these degraded servers, in some rare cases the breakage is sudden enough to be visible.</p>
    <div>
      <h2>Solving the problem</h2>
      <a href="#solving-the-problem">
        
      </a>
    </div>
    <p>To provide a more reliable platform, we needed a new component that provides a common ground for remediation efforts. This would remove duplication of work, provide unified context-awareness and increase development speed, which ultimately saves hours of engineering time and effort.</p><p>A good solution would not allow only the SRE team to auto-remediate, it would empower the entire company. The key to adding self-healing capability was a generic interface for all teams to self-service and quickly remediate failures at various levels: machine, service, network, or dependencies.</p><p>A good way to think about auto-remediation is in terms of workflows. A workflow is a sequence of steps to get to a desired outcome. This is not dissimilar to a manual shell script which executes what a human would otherwise do via runbook instructions. Because of this logical fit with workflows and durable execution, we decided to adopt an open-source platform called <a href="https://github.com/temporalio/temporal"><u>Temporal</u></a>. </p><p>The concept of durable execution is useful to gracefully manage infrastructure failures such as network outages and transient failures in external service endpoints. This capability meant we only needed to build a way to schedule “workflow” tasks and have the code provide reliability guarantees by default, using Temporal. This allowed us to focus on building out the orchestration system to support the control and flow of workflow execution in our data centers. </p><p><a href="https://learn.temporal.io/getting_started/go/first_program_in_go/"><u>Temporal’s documentation</u></a> provides a good introduction to writing Temporal workflows.</p>
    <div>
      <h2>Building an Automatic Remediation System</h2>
      <a href="#building-an-automatic-remediation-system">
        
      </a>
    </div>
    <p>Below, we describe how our automatic remediation system works. It is essentially a way to schedule tasks across our global network with built-in reliability guarantees. With this system, teams can serve their customers more reliably. An unexpected failure mode can be recognized and immediately mitigated, while the root cause can be determined later via a more detailed analysis.</p>
    <div>
      <h3>Step one: we need a coordinator</h3>
      <a href="#step-one-we-need-a-coordinator">
        
      </a>
    </div>
    
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/FOpkEE13QcgwHJ9vhcIZj/5b0c5328ee5326794329a4a07c5db065/Building_on_Temporal_process.png" />
          </figure><p>After our initial testing of Temporal, it was now possible to write workflows. But we needed a way to schedule workflow tasks from other internal services. The coordinator was built to serve this purpose, and became the primary mechanism for the authorisation and scheduling of workflows. </p><p>The most important roles of the coordinator are authorisation, workflow task routing, and safety constraints enforcement. Each consumer is authorized via <a href="https://www.cloudflare.com/learning/access-management/what-is-mutual-tls/"><u>mTLS authentication</u></a>, and the coordinator uses an ACL to determine whether to permit the execution of a workflow. An ACL configuration looks like the following example.</p>
            <pre><code>server_config {
    enable_tls = true
    [...]
    route_rule {
      name  = "global_get"
      method = "GET"
      route_patterns = ["/*"]
      uris = ["spiffe://example.com/worker-admin"]
    }
    route_rule {
      name = "global_post"
      method = "POST"
      route_patterns = ["/*"]
      uris = ["spiffe://example.com/worker-admin"]
      allow_public = true
    }
    route_rule {
      name = "public_access"
      method = "GET"
      route_patterns = ["/metrics"]
      uris = []
      allow_public = true
      skip_log_match = true
    }
}
</code></pre>
            <p>Each workflow specifies two key characteristics: where to run the tasks and the safety constraints, using an <a href="https://github.com/hashicorp/hcl"><u>HCL</u></a> configuration file. Example constraints could be whether to run on only a specific node type (such as a database), or if multiple parallel executions are allowed: if a task has been triggered too many times, that is a sign of a wider problem that might require human intervention. The coordinator uses the Temporal <a href="https://docs.temporal.io/visibility"><u>Visibility API</u></a> to determine the current state of the executions in the Temporal cluster.</p><p>An example of a configuration file is shown below:</p>
            <pre><code>task_queue_target = "&lt;target&gt;"

# The following entries will ensure that
# 1. This workflow is not run at the same time in a 15m window.
# 2. This workflow will not run more than once an hour.
# 3. This workflow will not run more than 3 times in one day.
#
constraint {
    kind = "concurency"
    value = "1"
    period = "15m"
}

constraint {
    kind = "maxExecution"
    value = "1"
    period = "1h"
}

constraint {
    kind = "maxExecution"
    value = "3"
    period = "24h"
    is_global = true
}
</code></pre>
            
    <div>
      <h3>Step two: Task Routing is amazing</h3>
      <a href="#step-two-task-routing-is-amazing">
        
      </a>
    </div>
    
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4wOIwKfkKzp7k46Z6tPuhW/f35667a65872cf7a90fc9c03f38a48d5/Task_Routing_is_amazing_process.png" />
          </figure><p>An unforeseen benefit of using a central Temporal cluster was the discovery of Task Routing. This feature allows us to schedule a Workflow/Activity on any server that has a running Temporal Worker, and further segment by the type of server, its location, etc. For this reason, we have three primary task queues — the general queue in which tasks can be executed by any worker in the datacenter, the node type queue in which tasks can only be executed by a specific node type in the datacenter, and the individual node queue where we target a specific node for task execution.</p><p>We rely on this heavily to ensure the speed and efficiency of automated remediation. Certain tasks can be run in datacenters with known low latency to an external resource, or a node type with better performance than others (due to differences in the underlying hardware). This reduces the amount of failure and latency we see overall in task executions. Sometimes we are also constrained by certain types of tasks that can only run on a certain node type, such as a database.</p><p>Task Routing also means that we can configure certain task queues to have a higher priority for execution, although this is not a feature we have needed so far. A drawback of task routing is that every Workflow/Activity needs to be registered to the target task queue, which is a common gotcha. Thankfully, it is possible to catch this failure condition with proper testing.</p>
    <div>
      <h3>Step three: when/how to self-heal?</h3>
      <a href="#step-three-when-how-to-self-heal">
        
      </a>
    </div>
    <p>None of this would be relevant if we didn’t put it to good use. A primary design goal for the platform was to ensure we had easy, quick ways to trigger workflows on the most important failure conditions. The next step was to determine what the best sources to trigger the actions were. The answer to this was simple: we could trigger workflows from anywhere as long as they are properly authorized and detect the failure conditions accurately.</p><p>Example triggers are an alerting system, a log tailer, a health check daemon, or an authorized engineer via a chatbot. Such flexibility allows a high level of reuse, and permits to invest more in workflow quality and reliability.</p><p>As part of the solution, we built a daemon that is able to poll a signal source for any unwanted condition and trigger a configured workflow. We have initially found <a href="https://blog.cloudflare.com/how-cloudflare-runs-prometheus-at-scale"><u>Prometheus</u></a> useful as a source because it contains both service-level and hardware/system-level metrics. We are also exploring more event-based trigger mechanisms, which could eliminate the need to use precious system resources to poll for metrics.</p><p>We already had internal services that are able to detect widespread failure conditions for our customers, but were only able to page a human. With the adoption of auto-remediation, these systems are now able to react automatically. This ability to create an automatic feedback loop with our customers is the cornerstone of these self-healing capabilities, and we continue to work on stronger signals, faster reaction times, and better prevention of future occurrences.</p><p>The most exciting part, however, is the future possibility. Every customer cares about any negative impact from Cloudflare. With this platform we can onboard several services (especially those that are foundational for the critical path) and ensure we react quickly to any failure conditions, even before there is any visible impact.</p>
    <div>
      <h3>Step four: packaging and deployment</h3>
      <a href="#step-four-packaging-and-deployment">
        
      </a>
    </div>
    <p>The whole system is written in <a href="https://go.dev/"><u>golang</u></a>, and a single binary can implement each role. We distribute it as an apt package or a container for maximum ease of deployment.</p><p>We deploy a Temporal-based worker to every server we intend to run tasks on, and a daemon in datacenters where we intend to automatically trigger workflows based on the local conditions. The coordinator is more nuanced since we rely on task routing and can trigger from a central coordinator, but we have also found value in running coordinators locally in the datacenters. This is especially useful in datacenters with less capacity or degraded performance, removing the need for a round-trip to schedule the workflows.</p>
    <div>
      <h3>Step five: test, test, test</h3>
      <a href="#step-five-test-test-test">
        
      </a>
    </div>
    <p>Temporal provides native mechanisms to test an entire workflow, via a <a href="https://docs.temporal.io/develop/go/testing-suite"><u>comprehensive test suite</u></a> that supports end-to-end, integration, and unit testing, which we used extensively to prevent regressions while developing. We also ensured proper test coverage for all the critical platform components, especially the coordinator.</p><p>Despite the ease of written tests, we quickly discovered that they were not enough. After writing workflows, engineers need an environment as close as possible to the target conditions. This is why we configured our staging environments to support quick and efficient testing. These environments receive the latest changes and point to a different (staging) Temporal cluster, which enables experimentation and easy validation of changes.</p><p>After a workflow is validated in the staging environment, we can then do a full release to production. It seems obvious, but catching simple configuration errors before releasing has saved us many hours in development/change-related-task time.</p>
    <div>
      <h2>Deploying to production</h2>
      <a href="#deploying-to-production">
        
      </a>
    </div>
    <p>As you can guess from the title of this post, we put this in production to automatically react to server-specific errors and unrecoverable failures. To this end, we have a set of services that are able to detect single-server failure conditions based on analyzed traffic data. After deployment, we have successfully mitigated potential impact by taking any errant single sources of failure out of production.</p><p>We have also created a set of workflows to reduce internal toil and improve efficiency. These workflows can automatically test pull requests on target machines, wipe and reset servers after experiments are concluded, and take away manual processes that cost many hours in toil.</p><p>Building a system that is maintained by several SRE teams has allowed us to iterate faster, and rapidly tackle long-standing problems. We have set ambitious goals regarding toil elimination and are on course to achieve them, which will allow us to scale faster by eliminating the human bottleneck.</p>
    <div>
      <h2>Looking to the future</h2>
      <a href="#looking-to-the-future">
        
      </a>
    </div>
    <p>Our immediate plans are to leverage this system to provide a more reliable platform for our customers and drastically reduce operational toil, freeing up engineering resources to tackle larger-scale problems. We also intend to leverage more Temporal features such as <a href="https://docs.temporal.io/develop/go/versioning"><u>Workflow Versioning</u></a>, which will simplify the process of making changes to workflows by ensuring that triggered workflows run expected versions. </p><p> We are also interested in how others are solving problems using durable execution platforms such as Temporal, and general strategies to eliminate toil. If you would like to discuss this further, feel free to reach out on the <a href="https://community.cloudflare.com"><u>Cloudflare Community</u></a> and start a conversation!</p><p>If you’re interested in contributing to projects that help build a better Internet, <a href="https://www.cloudflare.com/en-gb/careers/jobs/?department=Engineering&amp;location=default"><u>our engineering teams are hiring</u></a>.</p> ]]></content:encoded>
            <category><![CDATA[Edge]]></category>
            <category><![CDATA[Engineering]]></category>
            <category><![CDATA[Serverless]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Go]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[Speed & Reliability]]></category>
            <guid isPermaLink="false">2i9tHkPAfy7GxYAioGM100</guid>
            <dc:creator>Opeyemi Onikute</dc:creator>
        </item>
        <item>
            <title><![CDATA[Changing the industry with CISA’s Secure by Design principles]]></title>
            <link>https://blog.cloudflare.com/secure-by-design-principles/</link>
            <pubDate>Mon, 04 Mar 2024 14:00:56 GMT</pubDate>
            <description><![CDATA[ Security considerations should be an integral part of software’s design, not an afterthought. Explore how Cloudflare adheres to CISA’s Secure by Design principles to shift the industry ]]></description>
            <content:encoded><![CDATA[ <p></p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/69sko7A68LpSgodcAbWNKk/84a79ab3e02de76023c119ca4d14c132/Cloudflare-Aligns-with-CISA-Secure-by-Design-Principles--Helps-Drive-the-Shift-of-Security-Responsibilities-from-User-to-Sof.png" />
            
            </figure><p>The United States Cybersecurity and Infrastructure Agency (CISA) and seventeen international partners are helping shape best practices for the technology industry with their ‘<a href="https://www.cisa.gov/sites/default/files/2023-10/SecureByDesign_1025_508c.pdf">Secure by Design</a>’ principles. The aim is to encourage software manufacturers to not only make security an integral part of their products’ development, but to also design products with strong security capabilities that are configured by default.</p><p>As a cybersecurity company, Cloudflare considers product security an integral part of its DNA. We strongly believe in CISA’s principles and will continue to uphold them in the work we do. We’re excited to share stories about how Cloudflare has baked secure by design principles into the products we build and into the services we make available to all of our customers.</p>
    <div>
      <h2>What do “secure by design” and “secure by default” mean?</h2>
      <a href="#what-do-secure-by-design-and-secure-by-default-mean">
        
      </a>
    </div>
    <p>Secure by design describes a product where the security is ‘baked in’ rather than ‘bolted on’. Rather than manufacturers addressing security measures reactively, they take actions to mitigate any risk beforehand by building products in a way that reasonably protects against attackers successfully gaining access to them.</p><p>Secure by default means products are built to have the necessary security configurations come as a default, without additional charges.</p><p>CISA outlines the following three software product security principles:</p><ul><li><p>Take ownership of customer security outcomes</p></li><li><p>Embrace radical transparency and accountability</p></li><li><p>Lead from the top</p></li></ul><p>In its <a href="https://www.cisa.gov/sites/default/files/2023-10/SecureByDesign_1025_508c.pdf">documentation</a>, CISA provides comprehensive guidance on how to achieve its principles and what security measures a manufacturer should follow. Adhering to these guidelines not only enhances security benefits to customers and boosts the developer’s brand reputation, it also reduces long term maintenance and patching costs for manufacturers.</p>
    <div>
      <h2>Why does it matter?</h2>
      <a href="#why-does-it-matter">
        
      </a>
    </div>
    <p>Technology undeniably plays a significant role in our lives, automating numerous everyday tasks. The world’s dependence on technology and Internet-connected devices has significantly increased in the last few years, in large part <a href="https://datareportal.com/reports/digital-2022-time-spent-with-connected-tech">due to Covid-19</a>. During the outbreak, individuals and companies moved online as they complied with the public health measures that limited physical interactions.</p><p>While Internet connectivity makes our lives easier, bringing opportunities for online learning and remote work, it also creates an opportunity for attackers to benefit from such activities. Without proper safeguards, sensitive data such as user information, financial records, and login credentials can all be compromised and used for malicious activities.</p><p>Systems vulnerabilities can also impact entire industries and economies. In 2023, hackers from North Korea were suspected of being <a href="https://finance.yahoo.com/news/north-korea-linked-lazarus-group-130000746.html?cf_history_state=%7B%22guid%22%3A%22C255D9FF78CD46CDA4F76812EA68C350%22%2C%22historyId%22%3A13%2C%22targetId%22%3A%222168179FD2D36545B7494CB31CA686CB%22%7D&amp;_guc_consent_skip=1708084501">responsible for over 20% of crypto losses</a>, exploiting software vulnerabilities and stealing more than $300 million from individuals and companies around the world.</p><p>Despite the potentially devastating consequences of insecure software, too many vendors place the onus of security on their customers — a fact that CISA underscores in their guidelines. While a level of care from customers is expected, the majority of risks should be handled by manufacturers and their products. Only then can we have more secure and trusting online interactions. The ‘Secure by Design’ principles are essential to bridge that gap and change the industry.</p>
    <div>
      <h2>How does Cloudflare support secure by design principles?</h2>
      <a href="#how-does-cloudflare-support-secure-by-design-principles">
        
      </a>
    </div>
    
    <div>
      <h3>Taking ownership of customer security outcomes</h3>
      <a href="#taking-ownership-of-customer-security-outcomes">
        
      </a>
    </div>
    <p>CISA explains that in order to take ownership of customer security outcomes, software manufacturers should invest in product security efforts that include application hardening, application features, and application default settings. At Cloudflare, we always have these product security efforts top of mind and a few examples are shared below.</p>
    <div>
      <h4>Application hardening</h4>
      <a href="#application-hardening">
        
      </a>
    </div>
    <p>At Cloudflare, our developers follow a defined software development life cycle (SDLC) management process with checkpoints from our security team. We proactively address known vulnerabilities before they can be exploited and fix any exploited vulnerabilities for <i>all</i> of our customers. For example, we are committed to memory safe programming languages and use them where possible. Back in 2021, Cloudflare rewrote the <a href="/new-cloudflare-waf/">Cloudflare WAF</a> from Lua into the memory safe Rust. More recently, Cloudflare introduced a <a href="/how-we-built-pingora-the-proxy-that-connects-cloudflare-to-the-internet">new in-house built HTTP proxy named Pingora</a>, that moved us from memory unsafe C to memory safe Rust as well. Both of these projects were extra large undertakings that would not have been possible without executive support from our technical leadership team.</p>
    <div>
      <h4>Zero Trust Security</h4>
      <a href="#zero-trust-security">
        
      </a>
    </div>
    <p>By default, we align with CISA’s <a href="https://www.cisa.gov/zero-trust-maturity-model">Zero Trust Maturity Model</a> through the use of Cloudflare’s <a href="https://www.cloudflare.com/en-gb/learning/security/glossary/what-is-zero-trust/">Zero Trust Security suite of services</a>, to prevent unauthorized access to Cloudflare data, development resources, and other services. We minimize trust assumptions and require strict identity verification for every person and device trying to access any Cloudflare resources, whether self-hosted or in the cloud.</p><p>At Cloudflare, we believe that Zero Trust Security is a must-have security architecture in today’s environment, where cyber security attacks are rampant and hybrid work environments are the new normal. To help protect small businesses today, we have a <a href="https://www.cloudflare.com/plans/zero-trust-services/">Zero Trust plan</a> that provides the essential security controls needed to keep employees and apps protected online available free of charge for up to 50 users.</p>
    <div>
      <h4>Application features</h4>
      <a href="#application-features">
        
      </a>
    </div>
    <p>We not only provide users with many essential security tools for free, but we have helped push the entire industry to provide better security features by default since our early days.</p><p>Back in 2014, during Cloudflare's birthday week, we announced that we were making encryption free for all our customers by introducing <a href="/introducing-universal-ssl">Universal SSL</a>. Then in 2015, we went one step further and provided <a href="/universal-ssl-encryption-all-the-way-to-the-origin-for-free">full encryption</a> of all data from the browser to the origin, for free. Now, the rest of the industry has followed our lead and encryption by default has become the standard for Internet applications.</p><p>During Cloudflare’s seventh Birthday Week in 2017, we were incredibly proud to announce <a href="/unmetered-mitigation">unmetered DDoS mitigation</a>. The service absorbs and mitigates large-scale DDoS attacks without charging customers for the excess bandwidth consumed during an attack. With such announcement we eliminated the industry standard of ‘surge pricing’ for DDoS attacks</p><p>In 2021, we announced a protocol called <a href="/privacy-preserving-compromised-credential-checking/">MIGP</a> ("Might I Get Pwned") that allows users to check whether their credentials have been compromised without exposing any unnecessary information in the process. Aside from a bucket ID derived from a prefix of the hash of your email, your credentials stay on your device and are never sent (even encrypted) over the Internet. Before that, using credential checking services could turn out to be a vulnerability in itself, leaking sensitive information while you are checking whether or not your credentials have been compromised.</p><p>A year later, in 2022, Cloudflare again disrupted the industry when we announced <a href="/waf-for-everyone/">WAF (Web Application Firewall) Managed Rulesets free of charge for all Cloudflare plans</a>. <a href="https://developers.cloudflare.com/waf/glossary/">WAF</a> is a service responsible for protecting web applications from malicious attacks. Such attacks have a major impact across the Internet regardless of the size of an organization. By making WAF free, we are making the Internet safe for everyone.</p><p>Finally, at the end of 2023, we were excited to help lead the industry by making <a href="/post-quantum-to-origins">post-quantum cryptography</a> available free of charge to all of our customers irrespective of plan levels.</p>
    <div>
      <h4>Application default settings</h4>
      <a href="#application-default-settings">
        
      </a>
    </div>
    <p>To further protect our customers, we ensure our default settings provide a robust security posture right from the start. Once users are comfortable, they can change and configure any settings the way they prefer. For example, Cloudflare automatically deploys the <a href="/waf-for-everyone/">Free Cloudflare Managed Ruleset</a> to any new Cloudflare zone. The managed ruleset includes Log4j rules, Shellshock rules, rules matching very common WordPress exploits, and others. Customers are able to disable the ruleset, if necessary, or configure the traffic filter or individual rules. To provide an even more secure-by-default system, we also created the <a href="/stop-attacks-before-they-are-known-making-the-cloudflare-waf-smarter/">ML-computed WAF Attack Score</a> that uses AI to detect bypasses of existing managed rules and can detect software exploits before they are made public.</p><p>As another example, all Cloudflare accounts come with unmetered DDoS mitigation services to protect applications from many of the Internet's most common and hard to handle attacks, by default.</p><p>As yet another example, when customers use our <a href="https://www.cloudflare.com/en-gb/developer-platform/r2/">R2 storage</a>, all the stored objects are encrypted at rest. Both encryption and decryption is automatic, does not require user configuration to enable, and does not impact the performance of R2.</p><p>Cloudflare also provides all of our customers with robust audit logs. <a href="https://developers.cloudflare.com/fundamentals/setup/account/account-security/review-audit-logs/">Audit logs</a> summarize the history of changes made within your Cloudflare account. Audit logs include account level actions like login, as well as zone configuration changes. Audit Logs are available on all plan types and are captured for both individual users and for multi-user organizations. Our audit logs are available across all plan levels for 18 months.</p>
    <div>
      <h3>Embracing radical transparency and accountability</h3>
      <a href="#embracing-radical-transparency-and-accountability">
        
      </a>
    </div>
    <p>To embrace radical transparency and accountability means taking pride in delivering safe and secure products. Transparency and sharing information are crucial for improving and evolving the security industry, fostering an environment where companies learn from each other and make the online world safer. Cloudflare shows transparency in multiple ways, as outlined below.</p>
    <div>
      <h4>The Cloudflare blog</h4>
      <a href="#the-cloudflare-blog">
        
      </a>
    </div>
    <p>On the <a href="/">Cloudflare blog</a>, you can find the latest information about our features and improvements, but also about zero-day attacks that are relevant to the entire industry, like the historic <a href="/technical-breakdown-http2-rapid-reset-ddos-attack">HTTP/2 Rapid Reset attacks</a> detected last year. We are transparent and write about important security incidents, such as the <a href="/thanksgiving-2023-security-incident/">Thanksgiving 2023 security incident</a>, where we go in detail about what happened, why it happened, and the steps we took to resolve it. We have also made a conscious effort to embrace radical transparency from Cloudflare’s inception about incidents impacting our services, and continue to embrace this important principle as one of our core <a href="https://www.cloudflare.com/careers/">values</a>. We hope that the information we share can assist others in enhancing their software practices.</p>
    <div>
      <h4>Cloudflare System Status</h4>
      <a href="#cloudflare-system-status">
        
      </a>
    </div>
    <p><a href="https://www.cloudflarestatus.com/">Cloudflare System Status</a> is a page to inform website owners about the status of Cloudflare services. It provides information about the current status of services and whether they are operating as expected. If there are any ongoing incidents, the status page notes which services were affected, as well as details about the issue. Users can also find information about scheduled maintenance that may affect the availability of some services.</p>
    <div>
      <h4>Technical transparency for code integrity</h4>
      <a href="#technical-transparency-for-code-integrity">
        
      </a>
    </div>
    <p>We believe in the importance of using cryptography as a technical means for transparently verifying identity and data integrity. For example, in 2022, we <a href="/cloudflare-verifies-code-whatsapp-web-serves-users/">partnered with WhatsApp</a> to provide a system for WhatsApp that assures users they are running the correct, untampered code when visiting the web version of the service by enabling the <a href="https://chrome.google.com/webstore/detail/code-verify/llohflklppcaghdpehpbklhlfebooeog/?cf_history_state=%7B%22guid%22:%22C255D9FF78CD46CDA4F76812EA68C350%22,%22historyId%22:14,%22targetId%22:%22135202E37AE255A706ECF9E58DB17616%22%7D">code verify extension</a> to confirm hash integrity automatically. It’s this process, and the fact that is automated on behalf of the user, that helps provide transparency in a scalable way. If users had to manually fetch, compute, and compare the hashes themselves, detecting tampering would likely only be done by a small fraction of technical users.</p>
    <div>
      <h4>Transparency report and warrant canaries</h4>
      <a href="#transparency-report-and-warrant-canaries">
        
      </a>
    </div>
    <p>We also believe that an essential part of earning and maintaining the trust of our customers is being transparent about the requests we receive from law enforcement and other governmental entities. To this end, Cloudflare publishes semi-annual updates to our <a href="https://cf-assets.www.cloudflare.com/slt3lc6tev37/Q1INAiyBubYSlfGdUhthU/8cc0e3de0f160e2765af4f514991ef6c/Transparency-Report-H2-2022.pdf?_gl=1*1y467q5*_ga*MTEyMzg0OTg5MC4xNjc3Nzg2MDk2*_ga_SQCRB0TXZW*MTcwOTA2NTM5OS4yNDIuMS4xNzA5MDY2NjYyLjAuMC4w">Transparency Report</a> on the requests we have received to disclose information about our customers.</p><p>An important part of Cloudflare’s transparency report is our warrant canaries. Warrant canaries are a method to implicitly inform users that we have not taken certain actions or received certain requests from government or law enforcement authorities, such as turning over our encryption or authentication keys or our customers' encryption or authentication keys to anyone. Through these means we are able to let our users know just how private and secure their data is while adhering to orders from law enforcement that prohibit disclosing some of their requests. You can read Cloudflare’s warrant canaries <a href="https://www.cloudflare.com/transparency/">here</a>.</p><p>While transparency reports and warrant canaries are not explicitly mentioned in CISA’s secure by design principles, we think they are an important aspect in a technology company being transparent about their practices.</p>
    <div>
      <h4>Public bug bounties</h4>
      <a href="#public-bug-bounties">
        
      </a>
    </div>
    <p>We invite you to contribute to our security efforts by participating in our <a href="https://hackerone.com/cloudflare?view_policy=true">public bug bounty</a> hosted by HackerOne, where you can report Cloudflare vulnerabilities and receive financial compensation in return for your help.</p>
    <div>
      <h3>Leading from the top</h3>
      <a href="#leading-from-the-top">
        
      </a>
    </div>
    <p>With this principle, security is deeply rooted inside Cloudflare’s business goals. Because of the tight relationship of security and quality, by improving a product's default security, the quality of the overall product also improves.</p><p>At Cloudflare, our dedication to security is reflected in the company’s structure. Our Chief Security Officer reports directly to our CEO, and presents at every board meeting. That allows for board members well-informed about the current cybersecurity landscape and emphasizes the importance of the company's initiatives to improve security.</p><p>Additionally, our security engineers are a part of the main R&amp;D organization, with their work being as integral to our products as that of our system engineers. This means that our security engineers can bake security into the SDLC instead of bolting it on as an afterthought.</p>
    <div>
      <h2>How can you help?</h2>
      <a href="#how-can-you-help">
        
      </a>
    </div>
    <p>If you are a software manufacturer, we encourage you to familiarize yourself with CISA’s ‘Secure by Design’ principles and create a plan to implement them in your company.</p><p>As an individual, we encourage you to participate in bug bounty programs (such as <a href="https://hackerone.com/cloudflare?type=team&amp;view_policy=true">Cloudflare’s HackerOne</a> public bounty) and promote cybersecurity awareness in your community.</p><p>Let’s help build a better Internet together.</p> ]]></content:encoded>
            <category><![CDATA[Security Week]]></category>
            <category><![CDATA[Policy & Legal]]></category>
            <category><![CDATA[API Security]]></category>
            <category><![CDATA[CISA]]></category>
            <category><![CDATA[Reliability]]></category>
            <guid isPermaLink="false">S9si8dmzOmPd8vlxjvLNl</guid>
            <dc:creator>Kristina Galicova</dc:creator>
            <dc:creator>Edo Royker</dc:creator>
        </item>
        <item>
            <title><![CDATA[Hardening Workers KV]]></title>
            <link>https://blog.cloudflare.com/workers-kv-restoring-reliability/</link>
            <pubDate>Wed, 02 Aug 2023 13:05:42 GMT</pubDate>
            <description><![CDATA[ A deep dive into the recent incidents relating to Workers KV, and how we’re going to fix them ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Over the last couple of months, Workers KV has suffered from a series of incidents, culminating in three back-to-back incidents during the week of July 17th, 2023. These incidents have directly impacted customers that rely on KV — and this isn’t good enough.</p><p>We’re going to share the work we have done to understand why KV has had such a spate of incidents and, more importantly, share in depth what we’re doing to dramatically improve how we deploy changes to KV going forward.</p>
    <div>
      <h3>Workers KV?</h3>
      <a href="#workers-kv">
        
      </a>
    </div>
    <p><a href="https://www.cloudflare.com/developer-platform/workers-kv/">Workers KV</a> — or just “KV” — is a key-value service for storing data: specifically, data with high read throughput requirements. It’s especially useful for user configuration, service routing, small assets and/or authentication data.</p><p>We use KV extensively inside Cloudflare too, with <a href="https://www.cloudflare.com/zero-trust/products/access/">Cloudflare Access</a> (part of our Zero Trust suite) and <a href="https://pages.cloudflare.com/">Cloudflare Pages</a> being some of our highest profile internal customers. Both teams benefit from KV’s ability to keep regularly accessed key-value pairs close to where they’re accessed, as well its ability to scale out horizontally without any need to become an expert in operating KV.</p><p>Given Cloudflare’s extensive use of KV, it wasn’t just external customers impacted. Our own internal teams felt the pain of these incidents, too.</p>
    <div>
      <h3>The summary of the post-mortem</h3>
      <a href="#the-summary-of-the-post-mortem">
        
      </a>
    </div>
    <p>Back in June 2023, we announced the move to a new architecture for KV, which is designed to address two major points of customer feedback we’ve had around KV: high latency for infrequently accessed keys (or a key accessed in different regions), and working to ensure the upper bound on KV’s eventual consistency model for writes is 60 seconds — not “mostly 60 seconds”.</p><p>At the time of the blog, we’d already been testing this internally, including early access with our community champions and running a small % of production traffic to validate stability and performance expectations beyond what we could emulate within a staging environment.</p><p>However, in the weeks between mid-June and culminating in the series of incidents during the week of July 17th, we would continue to increase the volume of new traffic onto the new architecture. When we did this, we would encounter previously unseen problems (many of these customer-impacting) — then immediately roll back, fix bugs, and repeat. Internally, we’d begun to identify that this pattern was becoming unsustainable — each attempt to cut traffic onto the new architecture would surface errors or behaviors we hadn’t seen before and couldn’t immediately explain, and thus we would roll back and assess.</p><p>The issues at the root of this series of incidents proved to be significantly challenging to track and observe. Once identified, the two causes themselves proved to be quick to fix, but an (1) observability gap in our error reporting and (2) a mutation to local state that resulted in an unexpected mutation of global state were both hard to observe and reproduce over the days following the customer-facing impact ending.</p>
    <div>
      <h3>The detail</h3>
      <a href="#the-detail">
        
      </a>
    </div>
    <p>One important piece of context to understand before we go into detail on the post-mortem: Workers KV is composed of two separate Workers scripts – internally referred to as the Storage Gateway Worker and SuperCache. SuperCache is an optional path in the Storage Gateway Worker workflow, and is the basis for KV's new (faster) backend (refer to the blog).</p><p>Here is a timeline of events:</p>
<table>
<thead>
  <tr>
    <th><span>Time</span></th>
    <th><span>Description</span></th>
  </tr>
</thead>
<tbody>
  <tr>
    <td><span>2023-07-17 21:52 UTC</span></td>
    <td><span>Cloudflare observes alerts showing 500 HTTP status codes in the MEL01 data-center (Melbourne, AU) and begins investigating.</span><br /><span>We also begin to see a small set of customers reporting HTTP 500s being returned via multiple channels. It is not immediately clear if this is a data-center-wide issue or KV specific, as there had not been a recent KV deployment, and the issue directly correlated with three data-centers being brought back online.</span></td>
  </tr>
  <tr>
    <td><span>2023-07-18 00:09 UTC</span></td>
    <td><span>We disable the new backend for KV in MEL01 in an attempt to mitigate the issue (noting that there had not been a recent deployment or change to the % of users on the new backend).</span></td>
  </tr>
  <tr>
    <td><span>2023-07-18 05:42 UTC</span></td>
    <td><span>Investigating alerts showing 500 HTTP status codes in VIE02 (Vienna, AT) and JNB01 (Johannesburg, SA).</span></td>
  </tr>
  <tr>
    <td><span>2023-07-18 13:51 UTC</span></td>
    <td><span>The new backend is disabled globally after seeing issues in VIE02 (Vienna, AT) and JNB01 (Johannesburg, SA) data-centers, similar to MEL01. In both cases, they had also recently come back online after maintenance, but it remained unclear as to why KV was failing.</span></td>
  </tr>
  <tr>
    <td><span>2023-07-20 19:12 UTC</span></td>
    <td><span>The new backend is inadvertently re-enabled while deploying the update due to a misconfiguration in a deployment script. </span></td>
  </tr>
  <tr>
    <td><span>2023-07-20 19:33 UTC</span></td>
    <td><span>The new backend is (re-) disabled globally as HTTP 500 errors return.</span></td>
  </tr>
  <tr>
    <td><span>2023-07-20 23:46 UTC</span></td>
    <td><span>Broken Workers script pipeline deployed as part of gradual rollout due to incorrectly defined pipeline configuration in the deployment script.</span><br /><span>Metrics begin to report that a subset of traffic is being black-holed.</span></td>
  </tr>
  <tr>
    <td><span>2023-07-20 23:56 UTC</span></td>
    <td><span>Broken pipeline rolled back; errors rates return to pre-incident (normal) levels.</span></td>
  </tr>
</tbody>
</table><p><i>All timestamps referenced are in Coordinated Universal Time (UTC).</i></p><p>We initially observed alerts showing 500 HTTP status codes in the MEL01 data-center (Melbourne, AU) at 21:52 UTC on July 17th, and began investigating. We also received reports from a small set of customers reporting HTTP 500s being returned via multiple channels. This correlated with three data centers being brought back online, and it was not immediately clear if it related to the data centers or was KV-specific — especially given there had not been a recent KV deployment. On 05:42, we began investigating alerts showing 500 HTTP status codes in VIE02 (Vienna) and JNB02 (Johannesburg) data-centers; while both had recently come back online after maintenance, it was still unclear why KV was failing. At 13:51 UTC, we made the decision to disable the new backend globally.</p><p>Following the incident on July 18th, we attempted to deploy an allow-list configuration to reduce the scope of impacted accounts. However, while attempting to roll out a change for the Storage Gateway Worker at 19:12 UTC on July 20th, an older configuration was progressed causing the new backend to be enabled again, leading to the third event. As the team worked to fix this and deploy this configuration, they attempted to manually progress the deployment at 23:46 UTC, which resulted in the passing of a malformed configuration value that caused traffic to be sent to an invalid Workers script configuration.</p><p>After all deployments and the broken Workers configuration (pipeline) had been rolled back at 23:56 on the 20th July, we spent the following three days working to identify the root cause of the issue. We lacked <a href="https://www.cloudflare.com/learning/performance/what-is-observability/">observability</a> as KV's Worker script (responsible for much of KV's logic) was throwing an unhandled exception very early on in the request handling process. This was further exacerbated by prior work to disable error reporting in a disabled data-center due to the noise generated, which had previously resulted in logs being rate-limited upstream from our service.</p><p>This previous mitigation prevented us from capturing meaningful logs from the Worker, including identifying the exception itself, as an uncaught exception terminates request processing. This has raised the priority of improving how unhandled exceptions are reported and surfaced in a Worker (see Recommendations, below, for further details). This issue was exacerbated by the fact that KV's Worker script would fail to re-enter its "healthy" state when a Cloudflare data center was brought back online, as the Worker was mutating an environment variable perceived to be in request scope, but that was in global scope and persisted across requests. This effectively left the Worker “frozen” with the previous, invalid configuration for the affected locations.</p><p>Further, the introduction of a new progressive release process for Workers KV, designed to de-risk rollouts (as an action from a prior incident), prolonged the incident. We found a bug in the deployment logic that led to a broader outage due to an incorrectly defined configuration.</p><p>This configuration effectively caused us to drop a single-digit % of traffic until it was rolled back 10 minutes later. This code is untested at scale, and we need to spend more time hardening it before using it as the default path in production.</p><p>Additionally: although the root cause of the incidents was limited to three Cloudflare data-centers (Melbourne, Vienna, and Johannesburg), traffic across these regions still uses these data centers to route reads and writes to our system of record. Because these three data centers participate in KV’s new backend as regional tiers, a portion of traffic across the Oceania, Europe, and African regions was affected. Only a portion of keys from enrolled namespaces use any given data center as a regional tier in order to limit a single (regional) point of failure, so while traffic across <i>all</i> data centers in the region was impacted, nowhere was <i>all</i> traffic in a given data center affected.</p><p>We estimated the affected traffic to be 0.2-0.5% of KV's global traffic (based on our error reporting), however we observed some customers with error rates approaching 20% of their total KV operations. The impact was spread across KV namespaces and keys for customers within the scope of this incident.</p><p>Both KV’s high total traffic volume and its role as a critical dependency for many customers amplify the impact of even small error rates. In all cases, once the changes were rolled back, errors returned to normal levels and did not persist.</p>
    <div>
      <h3>Thinking about risks in building software</h3>
      <a href="#thinking-about-risks-in-building-software">
        
      </a>
    </div>
    <p>Before we dive into what we’re doing to significantly improve how we build, test, deploy and observe Workers KV going forward, we think there are lessons from the real world that can equally apply to how we improve the safety factor of the software we ship.</p><p>In traditional engineering and construction, there is an extremely common procedure known as a   “JSEA”, or <a href="https://en.wikipedia.org/wiki/Job_safety_analysis">Job Safety and Environmental Analysis</a> (sometimes just “JSA”). A JSEA is designed to help you iterate through a list of tasks, the potential hazards, and most importantly, the controls that will be applied to prevent those hazards from damaging equipment, injuring people, or worse.</p><p>One of the most critical concepts is the “hierarchy of controls” — that is, what controls should be applied to mitigate these hazards. In most practices, these are elimination, substitution, engineering, administration and personal protective equipment. Elimination and substitution are fairly self-explanatory: is there a different way to achieve this goal? Can we eliminate that task completely? Engineering and administration ask us whether there is additional engineering work, such as changing the placement of a panel, or using a horizontal boring machine to lay an underground pipe vs. opening up a trench that people can fall into.</p><p>The last and lowest on the hierarchy, is personal protective equipment (PPE). A hard hat can protect you from severe injury from something falling from above, but it’s a last resort, and it certainly isn’t guaranteed. In engineering practice, any hazard that <i>only</i> lists PPE as a mitigating factor is unsatisfactory: there must be additional controls in place. For example, instead of only wearing a hard hat, we should <i>engineer</i> the floor of scaffolding so that large objects (such as a wrench) cannot fall through in the first place. Further, if we require that all tools are attached to the wearer, then it significantly reduces the chance the tool can be dropped in the first place. These controls ensure that there are multiple degrees of mitigation — defense in depth — before your hard hat has to come into play.</p><p>Coming back to software, we can draw parallels between these controls: engineering can be likened to improving automation, gradual rollouts, and detailed metrics. Similarly, personal protective equipment can be likened to code review: useful, but code review cannot be the only thing protecting you from shipping bugs or untested code. Automation with linters, more robust testing, and new metrics are all vastly <i>safer</i> ways of shipping software.</p><p>As we spent time assessing where to improve our existing controls and how to put new controls in place to mitigate risks and improve the reliability (safety) of Workers KV, we took a similar approach: eliminating unnecessary changes, engineering more resilience into our codebase, automation, deployment tooling, and only then looking at human processes.</p>
    <div>
      <h3>How we plan to get better</h3>
      <a href="#how-we-plan-to-get-better">
        
      </a>
    </div>
    <p>Cloudflare is undertaking a larger, more structured review of KV's observability tooling, release infrastructure and processes to mitigate not only the contributing factors to the incidents within this report, but recent incidents related to KV. Critically, we see tooling and automation as the most powerful mechanisms for preventing incidents, with process improvements designed to provide an additional layer of protection. Process improvements alone cannot be the only mitigation.</p><p>Specifically, we have identified and prioritized the below efforts as the most important next steps towards meeting our own availability SLOs, and (above all) make KV a service that customers building on Workers can rely on for storing configuration and service data in the hot path of their traffic:</p><ul><li><p>Substantially improve the existing observability tooling for unhandled exceptions, both for internal teams and customers building on Workers. This is especially critical for high-volume services, where traditional logging alone can be too noisy (and not specific enough) to aid in tracking down these cases. The existing ongoing work to land this will be prioritized further. In the meantime, we have directly addressed the specific uncaught exception with KV's primary Worker script.</p></li><li><p>Improve the safety around the mutation of environmental variables in a Worker, which currently operate at "global" (per-isolate) scope, but can appear to be per-request. Mutating an environmental variable in request scope mutates the value for all requests transiting that same isolate (in a given location), which can be unexpected. Changes here will need to take backwards compatibility in mind.</p></li><li><p>Continue to expand KV’s test coverage to better address the above issues, in parallel with the aforementioned observability and tooling improvements, as an additional layer of defense. This includes allowing our test infrastructure to simulate traffic from any source data-center, which would have allowed us to more quickly reproduce the issue and identify a root cause.</p></li><li><p>Improvements to our release process, including how KV changes and releases are reviewed and approved, going forward. We will enforce a higher level of scrutiny for future changes, and where possible, reduce the number of changes deployed at once. This includes taking on new infrastructure dependencies, which will have a higher bar for both design and testing.</p></li><li><p>Additional logging improvements, including sampling, throughout our request handling process to improve troubleshooting &amp; debugging. A significant amount of the challenge related to these incidents was due to the lack of logging around specific requests (especially non-2xx requests)</p></li><li><p>Review and, where applicable, improve alerting thresholds surrounding error rates. As mentioned previously in this report, sub-% error rates at a global scale can have severe negative impact on specific users and/or locations: ensuring that errors are caught and not lost in the noise is an ongoing effort.</p></li><li><p>Address maturity issues with our progressive deployment tooling for Workers, which is net-new (and will eventually be exposed to customers directly).</p></li></ul><p>This is not an exhaustive list: we're continuing to expand on preventative measures associated with these and other incidents. These changes will not only improve KVs reliability, but other services across Cloudflare that KV relies on, or that rely on KV.</p><p>We recognize that KV hasn’t lived up to our customers’ expectations recently. Because we rely on KV so heavily internally, we’ve felt that pain first hand as well. The work to fix the issues that led to this cycle of incidents is already underway. That work will not only improve KV’s reliability but also improve the reliability of any software written on the Cloudflare Workers developer platform, whether by our customers or by ourselves.</p> ]]></content:encoded>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[Post Mortem]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <guid isPermaLink="false">6sRjpTRuwGjPJmHgwHlg7u</guid>
            <dc:creator>Matt Silverlock</dc:creator>
            <dc:creator>Charles Burnett</dc:creator>
            <dc:creator>Rob Sutter</dc:creator>
            <dc:creator>Kris Evans</dc:creator>
        </item>
        <item>
            <title><![CDATA[How we scaled and protected Eurovision 2023 voting with Pages and Turnstile]]></title>
            <link>https://blog.cloudflare.com/how-cloudflare-scaled-and-protected-eurovision-2023-voting/</link>
            <pubDate>Fri, 23 Jun 2023 13:00:55 GMT</pubDate>
            <description><![CDATA[ More than 162 million fans tuned in to the 2023 Eurovision Song Contest, the first year that non-participating countries could also vote. Cloudflare helped scale and protect the voting application based.io, built by once.net using our rapid DNS infrastructure, CDN, Cloudflare Pages and Turnstile ]]></description>
            <content:encoded><![CDATA[ <p></p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3EL1K1PkflEKz4BN5RvvVl/9caa639fcc20faba71edc840a70a6ad6/image3-27.png" />
            
            </figure><p>2023 was the first year that non-participating countries could vote for their favorites during the Eurovision Song Contest, adding millions of additional viewers and voters to an already impressive 162 million tuning in from the participating countries. It became a truly global event with a potential for disruption from multiple sources. To prepare for anything, Cloudflare helped scale and protect the voting application, used by millions of dedicated fans around the world to choose the winner.</p><p>In this blog we will cover how <a href="https://once.net">once.net</a> built their platform <a href="https://www.based.io/">based.io</a> to monitor, manage and scale the Eurovision voting application to handle all traffic using many Cloudflare services. The speed with which DNS changes made through the Cloudflare API propagate globally allowed them to scale their backend within seconds. At the same time, Cloudflare Pages was ready to serve any amount of traffic to the voting landing page so fans didn’t miss a beat. And to cap it off, by combining Cloudflare CDN, <a href="https://www.cloudflare.com/ddos/">DDoS protection</a>, WAF, and Turnstile, they made sure that attackers didn’t steal any of the limelight.</p>
    <div>
      <h3>The unsung heroes</h3>
      <a href="#the-unsung-heroes">
        
      </a>
    </div>
    <p>Based.io is a resilient live data platform built by the <a href="https://once.net">once.net</a> team, with the capability to scale up to 400 million concurrent connected users. It’s built from the ground up for speed and performance, consisting of an observable real time graph database, <a href="https://www.cloudflare.com/learning/network-layer/what-is-the-network-layer/">networking layer</a>, cloud functions, analytics and infrastructure orchestration. Since all system information, traffic analysis and disruptions are monitored in real time, it makes the platform instantly responsive to variable demand, which enables real time scaling of your infrastructure during spikes, outages and attacks.</p><p>Although the based.io platform on its own is currently in closed beta, it is already serving a few flagship customers in production assisted by the software and services of the once.net team. One such customer is Tally, a platform used by multiple broadcasters in Europe to add live interaction to traditional television. Over 100 live shows have been performed using the platform. Another is Airhub, a startup that handles and logs automatic drone flights. And of course the star of this blog post, the Eurovision Song Contest.</p>
    <div>
      <h3>Setting the stage</h3>
      <a href="#setting-the-stage">
        
      </a>
    </div>
    <p>The Eurovision Song Contest is one of the world’s most popular broadcasted contests, and this year it reached 162 million people across 38 broadcasting countries. In addition, on TikTok the three live shows were viewed 4.8 million times, while 7.6 million people watched the Grand Final live on YouTube. With such an audience, it is no surprise that Cloudflare sees the impact of it on the Internet. Last year, we wrote <a href="/eurovision-2022-internet-trends/">a blog post</a> where we showed lower than average traffic during, and higher than average traffic after the grand final. This year, the traffic from participating countries showed an even more remarkable surge:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3gO2U4Z3Qg4GOcNKZ6MIwe/d4fbd14cabdefb4e3764d7f4bc70c893/image1-39.png" />
            
            </figure><p>HTTP Requests per Second from Norway, with a similar pattern visible in countries such as the UK, Sweden and France. Internet traffic spiked at 21:20 UTC, when voting started.</p><p>Such large amounts of traffic are nothing new to the Eurovision Song Contest. Eurovision has relied on Cloudflare’s services for over a decade now and Cloudflare has helped to protect Eurovision.tv and improve its performance through noticeable faster load time to visitors from all corners of the world. Year after year, the team of Eurovision continued to use our services more, discovering additional features to improve performance and reliability further, with increasingly fine-grained control over their traffic flows. Eurovision.tv uses Page Rules to cache additional content on Cloudflare’s edge, speeding up delivery without sacrificing up-to-the-minute updates during the global event. Finally, to protect their backend and content management system, the team has placed their admin portals behind Cloudflare Zero Trust to delegate responsibilities down to individual levels.</p><p>Since then the contest itself has also evolved – sometimes by choice, sometimes by force. During the COVID-19 pandemic in-person cheering became impossible for many people due to a reduced live audience, resulting in the Eurovision Song Contest asking once.net to build a new iOS and Android application in which fans could cheer virtually. The feature was an instant hit, and it was clear that it would become part of this year’s contest as well.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3r33qBRnXFsgoKlqwH8Hly/5a087ff5295ac331344e548f2f7bd0ee/Screenshot-2023-06-23-at-12.05.08.png" />
            
            </figure><p>A screenshot of the official Eurovision Song Contest application showing the real-time number of connected fans (1) and allowing them to cheer (2) for their favorites.</p><p>In 2023, once.net was also asked to handle the paid voting from the regions where phone and SMS voting was not possible. It was the first time that Eurovision allowed voting online. The challenge that had to be overcome was the extreme peak demand on the platform when the show was live, and especially when the voting window started.</p><p>Complicating it further, was the fact that during last year’s show, there had been a large number of targeted and coordinated attacks.</p><p>To prepare for these spikes in demand and determined adversaries, once.net needed a platform that isn’t only resilient and highly scalable, but could also act as a mitigation layer in front of it. once.net selected Cloudflare for this functionality and integrated Cloudflare deeply with its <a href="https://www.cloudflare.com/application-services/solutions/app-performance-monitoring/">real-time monitoring</a> and management platform. To understand how and why, it’s essential to understand based.io underlying architecture.</p>
    <div>
      <h3>The based.io platform</h3>
      <a href="#the-based-io-platform">
        
      </a>
    </div>
    <p>Instead of relying on network or HTTP load balancers, based.io uses a client-side service discovery pattern, selecting the most suitable server to connect to and leveraging Cloudflare's fast cache propagation infrastructure to handle spikes in traffic (both malicious and benign).</p><p>First, each server continuously registers a unique access key that has an expiration of 15 seconds, which must be used when a client connects to the server. In addition, the backend servers register their health (such as active connections, CPU, memory usage, requests per second, etc.) to the service registry every 300 milliseconds. Clients then request the optimal server URL and associated access key from a central discovery registry and proceed to establish a long lived connection with that server. When a server gets overloaded it will disconnect a certain amount of clients and those clients will go through the discovery process again.</p><p>The central discovery registry would normally be a huge bottleneck and attack target. based.io resolves this by putting the registry behind Cloudflare's global network with a cache time of three seconds. Since the system relies on real-time stats to distribute load and uses short lived access keys, it is crucial that the cache updates fast and reliably. This is where Cloudflare’s infrastructure proved its worth, both due to the fast updating cache and reducing load with <a href="/introducing-regional-tiered-cache/">Tiered Caching</a>.</p><p>Not using <a href="https://www.cloudflare.com/learning/performance/what-is-load-balancing/">load balancers</a> means the based.io system allows clients to connect to the backend servers through Cloudflare, resulting in  better performance and a more resilient infrastructure by eliminating the load balancers as potential attack surface. It also results in a better distribution of connections, using the real-time information of server health, amount of active connections, active subscriptions.</p><p>Scaling up the platform happens automatically under load by deploying additional machines that can each handle 40,000 connected users. These are spun up in batches of a couple of hundred and as each machine spins up, it reaches out directly to the Cloudflare API to configure its own <a href="https://www.cloudflare.com/learning/dns/dns-records/">DNS record</a> and proxy status. Thanks to <a href="/dns-build-improvement/">Cloudflare’s high speed DNS system</a>, these changes are then propagated globally within seconds, resulting in a total machine turn-up time of around three seconds. This means faster discovery of new servers and faster dynamic rebalancing from the clients. And since the voting window of the Eurovision Song Contest is only 45 minutes, with the main peak within minutes after the window opens, every second counts!</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2Q8phs7FFGD11xvymotWjf/d911f35b6d8521dbad6f0e5fb27b6adb/image4-22.png" />
            
            </figure><p>High level architecture of the based.io platform used for the 2023 Eurovision Song Contest‌ ‌</p><p>To vote, users of the mobile app and viewers globally were pointed to the voting landing page, <a href="https://www.esc.vote">esc.vote</a>. Building a frontend web application able to handle this kind of an audience is a challenge in itself. Although hosting it yourself and putting a <a href="https://www.cloudflare.com/learning/cdn/what-is-a-cdn/">CDN</a> in front seems straightforward, this still requires you to own, configure and manage your origin infrastructure. once.net decided to leverage Cloudflare’s infrastructure directly by hosting the voting landing page on Cloudflare Pages. Deploying was as quick as a commit to their Git repository, and they never had to worry about reachability or scaling of the webpage.</p><p>once.net also used <a href="/turnstile-private-captcha-alternative/">Cloudflare Turnstile</a> to protect their payment <a href="https://www.cloudflare.com/learning/security/api/what-is-api-endpoint/">API endpoints</a> that were used to validate online votes. They used the invisible Turnstile widget to make sure the request was not coming from emulated browsers (e.g. Selenium). And best of all, using the invisible Turnstile widget the user did not have to go through extra steps, which allowed for a better user experience and better conversion.</p>
    <div>
      <h3>Cloudflare Pages stealing the show!</h3>
      <a href="#cloudflare-pages-stealing-the-show">
        
      </a>
    </div>
    <p>After the two semi-finals went according to plan with approximately 200,000 concurrent users during each,May 13 brought the Grand Final. The once.net team made sure that there were enough machines ready to take the initial load, jumped on a call with Cloudflare to monitor and started looking at the number of concurrent users slowly increasing. During the event, there were a few attempts to <a href="https://www.cloudflare.com/learning/ddos/what-is-a-ddos-attack/">DDoS</a> the site, which were automatically and instantaneously mitigated without any noticeable impact to any visitors.</p><p>The based.io discovery registry server also got some attention. Since the cache TTL was set quite low at five seconds, a high rate of distributed traffic to it could still result in a significant load. Luckily, on its own, the highly optimized based.io server can already handle around 300,000 requests per second. Still, it was great to see that during the event the cache hit ratio for normal traffic was 20%, and during one significant attack the <a href="https://www.cloudflare.com/learning/cdn/what-is-a-cache-hit-ratio/">cache hit ratio</a> peaked towards 80%. This showed how easy it is to leverage a combination of Cloudflare CDN and DDoS protection to mitigate such attacks, while still being able to serve dynamic and real time content.</p><p>When the curtains finally closed, 1.3 million concurrent users connected to the based.io platform at peak. The based.io platform handled a total of 350 million events and served seven million unique users in three hours. The voting landing page hosted by Cloudflare Pages served 2.3 million requests per second at peak, and made sure that the voting payments were by real human fans using Turnstile. Although the Cloudflare platform didn’t blink for such a flood of traffic, it is no surprise that it shows up as a short crescendo in our traffic statistics:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5huk3IzNOj2l5bBB9gyPJK/adbabc5972b3d2e713de82b42ab26803/image5-15.png" />
            
            </figure>
    <div>
      <h3>Get in touch with us</h3>
      <a href="#get-in-touch-with-us">
        
      </a>
    </div>
    <p>If you’re also working on or with an application that would benefit from Cloudflare’s speed and security, but don’t know where to start, reach <a href="https://www.cloudflare.com/plans/enterprise/contact/">out</a> and we’ll work together.</p> ]]></content:encoded>
            <category><![CDATA[Speed Week]]></category>
            <category><![CDATA[Cloudflare Pages]]></category>
            <category><![CDATA[Turnstile]]></category>
            <category><![CDATA[Customers]]></category>
            <category><![CDATA[Customer Success]]></category>
            <category><![CDATA[DNS]]></category>
            <category><![CDATA[Speed]]></category>
            <category><![CDATA[Reliability]]></category>
            <guid isPermaLink="false">7jlSeSTqS7MOjIXIa5Bwy6</guid>
            <dc:creator>Dirk-Jan van Helmond</dc:creator>
            <dc:creator>Michiel Appelman</dc:creator>
            <dc:creator>Jim de Beer (Guest Author)</dc:creator>
        </item>
        <item>
            <title><![CDATA[SLP: a new DDoS amplification vector in the wild]]></title>
            <link>https://blog.cloudflare.com/slp-new-ddos-amplification-vector/</link>
            <pubDate>Tue, 25 Apr 2023 13:07:56 GMT</pubDate>
            <description><![CDATA[ Researchers have recently published the discovery of a new DDoS reflection/amplification attack vector leveraging the SLP protocol. Cloudflare expects the prevalence of SLP-based DDoS attacks to rise in the coming weeks ]]></description>
            <content:encoded><![CDATA[ 
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3I71ArpV1rGLMEvmAECNwa/1307863c865f182b789b3a3e1ea4f078/image13-1-4.png" />
            
            </figure><p>Earlier today, April 25, 2023, researchers Pedro Umbelino at <a href="https://www.bitsight.com/blog/new-high-severity-vulnerability-cve-2023-29552-discovered-service-location-protocol-slp">Bitsight</a> and Marco Lux at <a href="https://curesec.com/blog/article/CVE-2023-29552-Service-Location-Protocol-Denial-of-Service-Amplification-Attack-212.html">Curesec</a> published their discovery of CVE-2023-29552, a new <a href="https://www.cisa.gov/news-events/alerts/2014/01/17/udp-based-amplification-attacks">DDoS reflection/amplification attack vector</a> leveraging the SLP protocol. If you are a Cloudflare customer, your services are already protected from this new attack vector.</p><p><a href="https://en.wikipedia.org/wiki/Service_Location_Protocol">Service Location Protocol</a> (SLP) is a “service discovery” protocol invented by Sun Microsystems in 1997. Like other service discovery protocols, it was designed to allow devices in a local area network to interact without prior knowledge of each other. SLP is a relatively obsolete protocol and has mostly been supplanted by more modern alternatives like UPnP, mDNS/Zeroconf, and WS-Discovery. Nevertheless, many commercial products still offer support for SLP.</p><p>Since SLP has no method for authentication, it should never be exposed to the public Internet. However, Umbelino and Lux have discovered that upwards of 35,000 Internet endpoints have their devices’ SLP service exposed and accessible to anyone. Additionally, they have discovered that the UDP version of this protocol has an <a href="/reflections-on-reflections/">amplification factor</a> of up to 2,200x, which is the third largest discovered to-date.</p><p>Cloudflare expects the prevalence of SLP-based DDoS attacks to rise significantly in the coming weeks as malicious actors learn how to exploit this newly discovered attack vector.</p>
    <div>
      <h3>Cloudflare customers are protected</h3>
      <a href="#cloudflare-customers-are-protected">
        
      </a>
    </div>
    <p>If you are a Cloudflare customer, our <a href="/deep-dive-cloudflare-autonomous-edge-ddos-protection/">automated DDoS protection system</a> already protects your services from these SLP amplification attacks.To avoid being exploited to launch the attacks, if you are a network operator, you should ensure that you are not exposing the SLP protocol directly to the public Internet. You should consider blocking UDP port 427 via access control lists or other means. This port is rarely used on the public Internet, meaning it is relatively safe to block without impacting legitimate traffic. Cloudflare <a href="https://developers.cloudflare.com/magic-transit/">Magic Transit</a> customers can use the <a href="https://developers.cloudflare.com/magic-firewall/">Magic Firewall</a> to craft and deploy such rules.</p> ]]></content:encoded>
            <category><![CDATA[CVE]]></category>
            <category><![CDATA[Vulnerabilities]]></category>
            <category><![CDATA[DDoS]]></category>
            <category><![CDATA[Attacks]]></category>
            <category><![CDATA[Mitigation]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[Security]]></category>
            <guid isPermaLink="false">5wnL1ufYrN0dZqE5GMsDZ8</guid>
            <dc:creator>Alex Forster</dc:creator>
            <dc:creator>Omer Yoachimik</dc:creator>
        </item>
        <item>
            <title><![CDATA[Oxy: Fish/Bumblebee/Splicer subsystems to improve reliability]]></title>
            <link>https://blog.cloudflare.com/oxy-fish-bumblebee-splicer-subsystems-to-improve-reliability/</link>
            <pubDate>Thu, 20 Apr 2023 13:00:00 GMT</pubDate>
            <description><![CDATA[ We split a proxy application into multiple services to improve development agility and reliability. This blog also shares some common patterns we are leveraging to design a system supporting zero-downtime restart ]]></description>
            <content:encoded><![CDATA[ <p></p><p>At Cloudflare, we are building proxy applications on top of <a href="/introducing-oxy/">Oxy</a> that must be able to handle a <i>huge</i> amount of traffic. Besides high performance requirements, the applications must also be resilient against crashes or reloads. As the framework evolves, the complexity also increases. While migrating WARP to support soft-unicast (<a href="/cloudflare-servers-dont-own-ips-anymore/">Cloudflare servers don't own IPs anymore</a>), we needed to add different functionalities to our proxy framework. Those additions increased not only the code size but also resource usage and states required to be <a href="/oxy-the-journey-of-graceful-restarts/">preserved between process upgrades</a>.</p><p>To address those issues, we opted to split a big proxy process into smaller, specialized services. Following the Unix philosophy, each service should have a single responsibility, and it must do it well. In this blog post, we will talk about how our proxy interacts with three different services - Splicer (which pipes data between sockets), Bumblebee (which upgrades an IP flow to a TCP socket), and Fish (which handles layer 3 egress using soft-unicast IPs). Those three services help us to improve system reliability and efficiency as we migrated WARP to support soft-unicast.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7BnvngSFKAe8Lo7PrjUbIQ/770f180a0fd67ad8ad7c5914046614f8/image2-8.png" />
            
            </figure>
    <div>
      <h3>Splicer</h3>
      <a href="#splicer">
        
      </a>
    </div>
    <p>Most transmission tunnels in our proxy forward <a href="https://www.cloudflare.com/learning/network-layer/what-is-a-packet/">packets</a> without making any modifications. In other words, given two sockets, the proxy just relays the data between them: read from one socket and write to the other. This is a common pattern within Cloudflare, and we reimplement very similar functionality in separate projects. These projects often have their own tweaks for buffering, flushing, and terminating connections, but they also have to coordinate long-running proxy tasks with their process restart or upgrade handling, too.</p><p>Turning this into a service allows other applications to send a long-running proxying task to Splicer. The applications pass the two sockets to Splicer and they will not need to worry about keeping the connection alive when restart. After finishing the task, Splicer will return the two original sockets and the original metadata attached to the request, so the original application can inspect the final state of the sockets - <a href="/when-tcp-sockets-refuse-to-die/">for example using TCP_INFO</a> - and finalize audit logging if required.</p>
    <div>
      <h3>Bumblebee</h3>
      <a href="#bumblebee">
        
      </a>
    </div>
    <p>Many of Cloudflare’s on-ramps are IP-based (layer 3) but most of our services operate on <a href="https://www.cloudflare.com/learning/ddos/glossary/tcp-ip/">TCP</a> or <a href="https://www.cloudflare.com/learning/ddos/glossary/user-datagram-protocol-udp/">UDP</a> sockets (layer 4). To handle TCP termination, we want to create a <i>kernel</i> TCP socket from IP packets received from the client (and we can later forward this socket and an upstream socket to Splicer to proxy data between the eyeball and origin). Bumblebee performs the upgrades by spawning a thread in an anonymous network namespace with <a href="https://man7.org/linux/man-pages/man2/unshare.2.html">unshare</a> syscall, NAT-ing the IP packets, and using a tun device there to perform TCP three-way handshakes to a listener. You can find a more detailed write-up on how we upgrade an IP flows to a TCP stream <a href="/from-ip-packets-to-http-the-many-faces-of-our-oxy-framework/">here</a>.</p><p>In short, other services just need to pass a socket carrying the IP flow, and Bumblebee will upgrade it to a TCP socket, no user-space TCP stack involved! After the socket is created, Bumblebee will return the socket to the application requesting the upgrade. Again, the proxy can restart without breaking the connection as Bumblebee pipes the IP socket while Splicer handles the TCP ones.</p>
    <div>
      <h3>Fish</h3>
      <a href="#fish">
        
      </a>
    </div>
    <p>Fish forwards IP packets using <a href="/cloudflare-servers-dont-own-ips-anymore/">soft-unicast</a> IP space without upgrading them to layer 4 sockets. We previously implemented packet forwarding on shared IP space using iptables and conntrack. However, IP/port mapping management is not simple when you have many possible IPs to egress from and variable port assignments. Conntrack is highly configurable, but applying configuration through iptables rules requires careful coordination and debugging iptables execution can be challenging. Plus, relying on configuration when sending a packet through the network stack results in arcane failure modes when conntrack is unable to rewrite a packet to the exact IP or port range specified.</p><p>Fish attempts to overcome this problem by rewriting the packets and configuring conntrack using the netlink protocol. Put differently, a proxy application sends a socket containing IP packets from the client, together with the desired soft-unicast IP and port range, to Fish. Then, Fish will ensure to forward those packets to their destination. The client’s choice of IP address does not matter; Fish ensures that egressed IP packets have a unique five-tuple within the root network namespace and performs the necessary packet rewriting to maintain this isolation. Fish’s internal state is also survived across restarts.</p>
    <div>
      <h3>The Unix philosophy, manifest</h3>
      <a href="#the-unix-philosophy-manifest">
        
      </a>
    </div>
    <p>To sum up what we are having so far: instead of adding the functionalities directly to the proxy application, we create smaller and reusable services. It becomes possible to understand the failure cases present in a smaller system and design it to exhibit reliable behavior. Then if we can remove the subsystems of a larger system, we can apply this logic to those subsystems. By focusing on making the smaller service work correctly, we improve the whole system's reliability and development agility.</p><p>Although those three services’ business logics are different, you can notice what they do in common: receive sockets, or file descriptors, from other applications to allow them to restart. Those services can be restarted without dropping the connection too. Let’s take a look at how graceful restart and file descriptor passing work in our cases.</p>
    <div>
      <h3>File descriptor passing</h3>
      <a href="#file-descriptor-passing">
        
      </a>
    </div>
    <p>We use Unix Domain Sockets for interprocess communication. This is a common pattern for inter-process communication. Besides sending raw data, unix sockets also allow passing file descriptors between different processes. This is essential for our architecture as well as graceful restarts.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/43M4QXoTMDFZLlb9idMPbs/5f9ea51f3c055e0b7ee8723c97c9188a/image4-6.png" />
            
            </figure><p>There are two main ways to transfer a file descriptor: using pid_getfd syscall or <a href="/know-your-scm_rights/">SCM_RIGHTS</a>. The latter is the better choice for us here as the use cases gear toward the proxy application “giving” the sockets instead of the microservices “taking” them. Moreover, the first method would require special permission and a way for the proxy to signal which file descriptor to take.</p><p>Currently we have our own internal library named hot-potato to pass the file descriptors around as we use stable Rust in production. If you are fine with using nightly Rust, you may want to consider the <a href="https://doc.rust-lang.org/std/os/unix/net/struct.SocketAncillary.html">unix_socket_ancillary_data</a> feature. The linked blog post above about SCM_RIGHTS also explains how that can be implemented. Still, we also want to add some “interesting” details you may want to know before using your SCM_RIGHTS in production:</p><ul><li><p>There is a maximum number of file descriptors you can pass per messageThe limit is defined by the constant SCM_MAX_FD in the kernel. This is set to 253 since kernel version 2.6.38</p></li><li><p>Getting the peer credentials of a socket may be quite useful for observability in multi-tenant settings</p></li><li><p>A SCM_RIGHTS ancillary data forms a message boundary.</p></li><li><p>It is possible to send any file descriptors, not only socketsWe use this trick together with memfd_create to get around the maximum buffer size without implementing something like length-encoded frames. This also makes zero-copy message passing possible.</p></li></ul>
    <div>
      <h3>Graceful restart</h3>
      <a href="#graceful-restart">
        
      </a>
    </div>
    <p>We explored the general strategy for graceful restart in “<a href="/oxy-the-journey-of-graceful-restarts/">Oxy: the journey of graceful restarts</a>” blog. Let’s dive into how we leverage tokio and file descriptor passing to migrate all important states in the old process to the new one. We can terminate the old process almost instantly without leaving any connection behind.</p>
    <div>
      <h3>Passing states and file descriptors</h3>
      <a href="#passing-states-and-file-descriptors">
        
      </a>
    </div>
    <p>Applications like NGINX can be reloaded with no downtime. However, if there are pending requests then there will be lingering processes that handle those connections before they terminate. This is not ideal for observability. It can also cause performance degradation when the old processes start building up after consecutive restarts.</p><p>In three micro-services in this blog post, we use the state-passing concept, where the pending requests will be paused and transferred to the new process. The new process will pick up both new requests and the old ones immediately on start. This method indeed requires a higher complexity than keeping the old process running. At a high level, we have the following extra steps when the application receives an upgrade request (usually SIGHUP): pause all tasks, wait until all tasks (in groups) are paused, and send them to the new process.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4JKw9eZUPQspxBsmCKcwm6/5a83e36bcc5fb03531a89cd75da73158/Graceful-restart.png" />
            
            </figure>
    <div>
      <h3>WaitGroup using JoinSet</h3>
      <a href="#waitgroup-using-joinset">
        
      </a>
    </div>
    <p>Problem statement: we dynamically spawn different concurrent tasks, and each task can spawn new child tasks. We must wait for some of them to complete before continuing.</p><p>In other words, tasks can be managed as groups. In Go, waiting for a collection of tasks to complete is a solved problem with WaitGroup. We discussed a way to implement WaitGroup in Rust using channels in a <a href="/oxy-the-journey-of-graceful-restarts/">previous blog</a>. There also exist crates like waitgroup that simply use AtomicWaker. Another approach is using JoinSet, which may make the code more readable. Considering the below example, we group the requests using a JoinSet.</p>
            <pre><code>    let mut task_group = JoinSet::new();

    loop {
        // Receive the request from a listener
        let Some(request) = listener.recv().await else {
            println!("There is no more request");
            break;
        };
        // Spawn a task that will process request.
        // This returns immediately
        task_group.spawn(process_request(request));
    }

    // Wait for all requests to be completed before continue
    while task_group.join_next().await.is_some() {}</code></pre>
            <p>However, an obvious problem with this is if we receive a lot of requests then the JoinSet will need to keep the results for all of them. Let’s change the code to clean up the JoinSet as the application processes new requests, so we have lower memory pressure</p>
            <pre><code>    loop {
        tokio::select! {
            biased; // This is optional

            // Clean up the JoinSet as we go
            // Note: checking for is_empty is important ?
            _task_result = task_group.join_next(), if !task_group.is_empty() =&gt; {}

            req = listener.recv() =&gt; {
                let Some(request) = req else {
                    println!("There is no more request");
                    break;
                };
                task_group.spawn(process_request(request));
            }
        }
    }

    while task_group.join_next().await.is_some() {}</code></pre>
            
    <div>
      <h3>Cancellation</h3>
      <a href="#cancellation">
        
      </a>
    </div>
    <p>We want to pass the pending requests to the new process as soon as possible once the upgrade signal is received. This requires us to pause all requests we are processing. In other terms, to be able to implement graceful restart, we need to implement graceful shutdown. The <a href="https://tokio.rs/tokio/topics/shutdown">official tokio tutorial</a> already covered how this can be achieved by using channels. Of course, we must guarantee the tasks we are pausing are cancellation-safe. The paused results will be collected into the JoinSet, and we just need to pass them to the new process using file descriptor passing.</p><p>For example, in Bumblebee, a paused state will include the environment’s file descriptors, client socket, and the socket proxying IP flow. We also need to transfer the current NAT table to the new process, which could be larger than the socket buffer. So the NAT table state is encoded into an anonymous file descriptor, and we just need to pass the file descriptor to the new process.</p>
    <div>
      <h3>Conclusion</h3>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>We considered how a complex proxy app can be divided into smaller components. Those components can run as new processes, allowing different life-times. Still, this type of architecture does incur additional costs: distributed tracing and inter-process communication. However, the costs are acceptable nonetheless considering the performance, maintainability, and reliability improvements. In the upcoming blog posts, we will talk about different debug tricks we learned when working with a large codebase with complex service interactions using tools like strace and eBPF.</p> ]]></content:encoded>
            <category><![CDATA[Proxying]]></category>
            <category><![CDATA[Rust]]></category>
            <category><![CDATA[Edge]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[Oxy]]></category>
            <guid isPermaLink="false">3xNFwkSFuO8BXQtaddgoVq</guid>
            <dc:creator>Quang Luong</dc:creator>
            <dc:creator>Chris Branch</dc:creator>
        </item>
        <item>
            <title><![CDATA[Accelerate building resiliency into systems with Cloudflare Workers]]></title>
            <link>https://blog.cloudflare.com/accelerate-building-resiliency-into-systems-with-cloudflare-workers/</link>
            <pubDate>Wed, 08 Mar 2023 14:00:00 GMT</pubDate>
            <description><![CDATA[ In this blog post we’ll discuss how Cloudflare Workers enabled us to quickly improve the resiliency of a legacy system ]]></description>
            <content:encoded><![CDATA[ <p></p><p>In this blog post we’ll discuss how Cloudflare Workers enabled us to quickly improve the resiliency of a legacy system. In particular, we’ll discuss how we prevented the email notification systems within Cloudflare from outages caused by external vendors.</p>
    <div>
      <h3>Email notification services</h3>
      <a href="#email-notification-services">
        
      </a>
    </div>
    <p>At Cloudflare, we send email notifications to customers such as billing invoices, password resets, OTP logins and certificate status updates. We rely on external Email Service Providers (ESPs) to deliver these emails to customers.</p><p>The following diagram shows how the system looks. Multiple services in our control plane dispatch emails through an external email vendor. They use HTTP Transmission APIs and also SMTP to send messages to the vendor. If dispatching an email fails, they are retried with exponential back-off mechanisms. Even when our ESP has outages, the retry mechanisms in place guarantee that we don’t lose any messages.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7blNZOkW5ujnoqJDm6ZR3W/c66afc080f8854fb3ae791b873f1b31f/image6.jpg" />
            
            </figure>
    <div>
      <h3>Why did we need to improve resilience?</h3>
      <a href="#why-did-we-need-to-improve-resilience">
        
      </a>
    </div>
    <p>In some cases, it isn’t sufficient to just deliver the email to the customer; it must be delivered on time. For example, OTP login emails are extremely time sensitive; their validity is short-lived such that a delay in sending them is as bad as not sending them at all. If the ESP is down, all emails including the critical ones will be delayed.</p><p>Some time ago our ESP suffered an outage; both the HTTP API and SMTP were unavailable and we couldn’t send emails to customers for a few hours. Several thousand emails couldn’t be delivered immediately and were queued.  This led to a delay in clearing out the backlogged messages in the retry queue in addition to sending new messages.</p><p>Critical emails not being sent is a major incident for us. A major incident impacts our customers, our business, and also our reputation. We take serious measures to prevent it from happening again in the future. Hence improving the resiliency of this system was our top priority.</p><p>Our concrete action items to reduce the failure possibilities were to improve availability by onboarding another email vendor and, when ESP has an outage, mitigate downtime by failing over from one vendor to another.</p><p>We wanted to achieve the above as quickly as possible so that our customers are not impacted again.</p>
    <div>
      <h3>Step 1 - Improve Availability</h3>
      <a href="#step-1-improve-availability">
        
      </a>
    </div>
    <p>Introducing a new vendor gives us the option to failover. But before we introduced it we had to consider another key component of email deliverability, which is the email sender reputation.  ISPs assign a sending score to any organization that sends emails. The higher the score, the higher the probability that the email sent by the organization reaches your inbox. Similarly the lower the score, the higher the probability it reaches your spam folder.</p><p>Adding a new vendor means emails will be delivered from a new IP address. Mailbox providers (such as Gmail or Hotmail) view new IP addresses as suspicious until they achieve a positive sending reputation. A positive sending reputation is determined by answering the question “did the recipient want this email?”. This is calculated differently for different mailbox providers, but the simplest measure would be that the recipient opened it, and perhaps clicked a link within. To build this reputation, it's recommended to use an IP warm-up strategy. This usually involves increasing e-mail volume slowly over a matter of days and weeks.</p><p>Using this new vendor “only” during failovers would increase the probability of emails reaching our customer’s spam folder for the reasons outlined above. To avoid this and establish a positive sending reputation we want to send a constant stream of traffic between the two vendors.</p>
    <div>
      <h3>Solution</h3>
      <a href="#solution">
        
      </a>
    </div>
    <p>We came up with a weighted traffic routing module, an algorithm to <a href="https://www.cloudflare.com/learning/email-security/what-is-email-routing/">route emails</a> to the ESPs based on the ratio of weights assigned to them. This is how the algorithm works roughly:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5orLJeAifKo7LQh0jaRWAi/e4e4486ca02f6f57ac61b667f4bcfaee/Screenshot-2023-03-08-at-13.21.04.png" />
            
            </figure><p>This algorithm solves the problem of maintaining a constant stream of traffic between the two vendors and to failover when outages happen.</p><p>Our next big question was “where” to implement this module? How should this be implemented so that we can build, deploy, and test as quickly as possible? Since there are multiple teams involved, how can we make it quicker for all of them? This leads to a perfect segue to our next step.</p>
    <div>
      <h3>Step 2 - Mitigate downtime</h3>
      <a href="#step-2-mitigate-downtime">
        
      </a>
    </div>
    <p>Let’s discuss a few approaches on where to build this logic. Should this just be a library? Or should it be a service in itself? Or do we have an even better way?</p>
    <div>
      <h3>Design 1 - A simple solution</h3>
      <a href="#design-1-a-simple-solution">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1NwMOz8SFMyDz8YsjjHXvf/0514a4c8b6ce0dc043c57f9e7ff32228/image5.jpg" />
            
            </figure><p>In this proposed solution, we would implement the weighted traffic routing module in a library and import it in every service. The pros of this approach is that there are no major changes to the overall existing architecture. However, it does come with quite a few drawbacks.  Firstly, All of the services require a major code change and a considerable amount of development effort would  have to be spent on this integration and testing end-to-end. Furthermore, updating libraries can be slow and there is no guarantee that teams would update in a timely manner. This means we may see teams still sending only to the old ESP during an incident, and we have not solved the problem we set out to.</p>
    <div>
      <h3>Design 2 - Extract email routing decisions to its own microservice</h3>
      <a href="#design-2-extract-email-routing-decisions-to-its-own-microservice">
        
      </a>
    </div>
    <p>The first approach is simple and doesn’t disrupt the architecture, but is not a sustainable solution in the long run. This naturally leads to our next design.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/75jQKklNlVsDZ1QwxCumKj/41458408349c2197d1dc0d9756b702b9/image1.jpg" />
            
            </figure><p>In this iteration, the weighted-traffic-routing module is extracted to its own service. This service decides where to route emails. Although it’s better than the previous approach, it is not without its drawbacks.</p><p>Firstly, the positives. This approach requires no major code changes in each service. As long as we honor the original ESP contract, team’s should simply need to update the base URL. Furthermore, we achieve the Single Responsibility Principle. When outages happen, the configurations have to be changed only in the weighted-traffic-routing service and this is the only service to be modified.  Finally, we have much more control over retry semantics as they are implemented in a single place.</p><p>Some of the drawbacks of taking this approach are the time involved in spinning up a new service from scratch -  building, testing, and shipping it is not insignificant. Secondly, we are adding an additional network hop; previously the email-notification-services talked directly to the email service providers, now we are proxying it through another service. Furthermore, since all the upstream requests are funneled through this service, it has to be load-balanced and scaled according to the incoming traffic and we need to ensure we service every request.</p>
    <div>
      <h3>Design 3 - The Workers way</h3>
      <a href="#design-3-the-workers-way">
        
      </a>
    </div>
    <p>The final design we considered; Implementing the weighted traffic routing module in a Cloudflare Worker.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/qwjWyomY40JtIvkaTBIr2/9ba18633c6c0f19ad263e890fc9741ab/image4.jpg" />
            
            </figure><p>There are a lot of positives to doing it this way.</p><p>Firstly, minimal code changes are required in each service. In fact, nothing beyond the environment variables need to be updated. As with the previous design, when email vendor outages happen, only the Email Weighted Traffic Router Worker configuration has to be changed. One positive of using a Cloudflare Worker is when an environment variable is changed and deployed, it’s deployed in all of Cloudflare’s network in a few milliseconds. This is a significant advantage for us because it means the failover process takes only a few milliseconds; time-critical emails will reach our customers’ inbox on time, preventing major incidents.</p><p>Secondly, As the email traffic increases, we don’t have to care about scaling or load balancing the weighted-traffic-routing module. A Worker automatically takes care of it.</p><p>Finally, the operational overhead to building and running this is incredibly low. We don’t have to spend time on spinning up new containers, configuring and deploying them. The majority of the work is just to programme the algorithm that we discussed earlier.</p><p>There are still some drawbacks here though.We are still introducing a new service and an additional network hop. However, we can make use of the templates available <a href="https://developers.cloudflare.com/workers/wrangler/">here</a> to make bootstrapping as efficient as possible.</p>
    <div>
      <h3>Building it the Workers way</h3>
      <a href="#building-it-the-workers-way">
        
      </a>
    </div>
    <p>Weighing the pros and cons of the above approaches, we went with implementing it in a Cloudflare Worker.</p><p>The Email Traffic Router Worker sits in between the Cloudflare control plane and the ESPs and proxies requests between them. We stream raw responses from the upstream; the internal service is completely agnostic of multiple ESPs, and how the traffic is routed.</p><p>We configure the percentage of traffic we want to send to each vendor using environment variables. Cloudflare Workers provide environment variables which is a convenient way to configure a worker application.</p>
            <pre><code>addEventListener('fetch', async (event: FetchEvent) =&gt; {
try {
    const finalInstance = ratioBasedRandPicker(
      parseFloat(VENDOR1_TO_VENDOR2_RATIO),
      API_ENDPOINT_VENDOR1,
      API_ENDPOINT_VENDOR2,
    )
    // stream request and response
    return doRequest(request, finalInstance)
  } catch (err) {
       // handle errors
    }
})  </code></pre>
            
            <pre><code>export const ratioBasedRandPicker = (
  ratio: number,
  VENDOR1: string,
  VENDOR2: string,
  generator: () =&gt; number = Math.random,
): string =&gt; {
  if (isNaN(ratio) || ratio &lt; 0 || ratio &gt; 1) throw new ConfigurationError(`invalid ratio ${ratio}`)
  return generator() &lt; ratio ? VENDOR1 : VENDOR2  
}</code></pre>
            <p>The Email Weighted Traffic Router Worker generates a random number between 0 (inclusive) and 1 with approximately uniform distribution over the range. When the ratio is set to <code>1</code>, vendor 1 will be picked always, and similarly when it’s set to <code>0</code> vendor 2 will be picked all the time. For any values in between, the vendor is picked based on the weights assigned. Thus, when all the traffic has to be routed to vendor 1 we set the ratio to 1; the random numbers generated are always less than <code>1</code>, hence vendor 1 will always be selected.</p><p>Doing a failover is as simple as updating the <code>vendor1_to_vendor2</code> environment variable. In general, an environment variable for a Cloudflare Worker can be updated in one of the following ways:</p><p><b>Using Cloudflare Dashboard:</b> All Worker environment variables are available to be configured in the Cloudflare Dashboard. Navigate to Workers -&gt; Settings -&gt; Variables -&gt; Edit Variables and update the value</p><p><b>Using Wrangler</b> (if your Worker is managed by wrangler): edit the environment variable in the wrangler.toml file and execute wrangler publish for the new values to kick in.</p><p>Once the variable is updated using one of the above methods, the Email Traffic Router Worker is deployed immediately in all Cloudflare data centers with this value. Hence all our emails will now be routed by the healthy vendor.</p><p>Now, we have built and shipped our weighted-traffic-routing logic in a Worker and building it in a Worker really accelerated our process of improving the resiliency.</p><p>The module is shipped, now what happens when the ESP is suffering an outage or a degraded performance? Let me conclude with a success story.</p>
    <div>
      <h3>When an ESP outage happened</h3>
      <a href="#when-an-esp-outage-happened">
        
      </a>
    </div>
    <p>After deploying this Email Traffic Router Worker to production, we saw an outage declared by one of our vendors. We immediately configured our Traffic Router to send all traffic to the healthy vendor. Changing this configuration took about a few seconds, and deploying the change was even faster. Within a few milliseconds all the traffic was routed to the healthy instance, and all the critical emails reached their corresponding inboxes on time!</p><p>Looking at some timelines:</p><p>18:45 UTC - we get alerted that message delivery is slow/degraded from email provider 1. The other provider is not impacted</p><p>18:47 UTC - Teams within Cloudflare confirmed that their message outbound is experiencing delays</p><p>18:47 UTC - we decide to failover</p><p>18:50 UTC - we configured the Email Traffic Router Worker to dispatch all the traffic to the healthy email provider, deployed the changes</p><p>Starting 18:50 we saw a steady decrease in requests to email provider 1 and a steady uptick in the requests to the provider 2 instance.</p><p>Here’s our metrics dashboard:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2E8kywz4Y85sIWrVG10Ero/cda9deddbc94156c4787c0bcd745451a/image7.png" />
            
            </figure>
    <div>
      <h3>Next steps</h3>
      <a href="#next-steps">
        
      </a>
    </div>
    <p>Currently, the failover step is manual. Our next step is to automate this process. Once we get notified that one of the vendors is experiencing outages, the Email Traffic Router Worker will failover automatically to the healthy vendor.</p>
    <div>
      <h3>Conclusion</h3>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>To reiterate our goals, we wanted to make our email notification systems resilient by</p><ol><li><p>adding another vendor</p></li><li><p>having a simple and fast mechanism to failover when vendor outages happen</p></li><li><p>achieving the above two objectives as quickly as possible to reduce customer impact</p></li></ol><p>Thus our email systems are more reliable, and more resilient to any outages or failures of our email service providers. Cloudflare Worker makes it easy and simple to build and ship a production-ready service in no time; it also makes failovers possible without any code changes or downtime. It’s powerful that multiple services/teams within Cloudflare can rely on one place, the Email Traffic Router Worker, for uninterrupted email delivery.</p> ]]></content:encoded>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <category><![CDATA[Developers]]></category>
            <guid isPermaLink="false">30hn1PU05oglGgzFBbYYJQ</guid>
            <dc:creator>Revathy Ramasundaram</dc:creator>
        </item>
        <item>
            <title><![CDATA[Cloudflare and COVID-19: Project Fair Shot Update]]></title>
            <link>https://blog.cloudflare.com/cloudflare-and-covid-19-project-fair-shot-update/</link>
            <pubDate>Thu, 29 Jul 2021 13:00:43 GMT</pubDate>
            <description><![CDATA[ Cloudflare Waiting Room helping organizations around the world to stifle COVID-19 and aid with easy rapid vaccinations. ]]></description>
            <content:encoded><![CDATA[ 
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/oMc5oJGNvoM3zY9UMJf7X/7ff04e8e12c8d19b33a7cd67d12b459b/image1-40.png" />
            
            </figure><p>In February 2021, Cloudflare launched <a href="/project-fair-shot/">Project Fair Shot</a> — a program that gave our Waiting Room product free of charge to any government, municipality, private/public business, or anyone responsible for the scheduling and/or dissemination of the COVID-19 vaccine.</p><p>By having our <a href="/cloudflare-waiting-room/">Waiting Room</a> technology in front of the vaccine scheduling application, it ensured that:</p><ul><li><p>Applications would remain available, reliable, and resilient against massive spikes of traffic for users attempting to get their vaccine appointment scheduled.</p></li><li><p>Visitors could wait for their long-awaited vaccine with confidence, arriving at a branded queuing page that provided accurate, estimated wait times.</p></li><li><p>Vaccines would get distributed equitably, and not just to folks with faster reflexes or Internet connections.</p></li></ul><p>Since February, we’ve seen a good number of participants in Project Fair Shot. To date, we have helped more than 100 customers across more than 10 countries to schedule approximately 100 million vaccinations. Even better, these vaccinations went smoothly, with customers like the County of San Luis Obispo regularly dealing with more than 20,000 appointments in a day.  “The bottom line is Cloudflare saved lives today. Our County will forever be grateful for your participation in getting the vaccine to those that need it most in an elegant, efficient and ethical manner” — Web Services Administrator for the <a href="https://www.cloudflare.com/case-studies/county-of-san-luis-obispo/">County of San Luis Obispo</a>.</p><p>We are happy to have helped not just in the US, but worldwide as well. In Canada, we partnered with a number of organizations and the Canadian government to increase access to the vaccine. One partner stated: “Our relationship with Cloudflare went from ‘Let's try Waiting Room’ to ‘Unless you have this, we're not going live with that public-facing site.'” — CEO of <a href="https://www.cloudflare.com/case-studies/verto/">Verto Health</a>. In another country in Europe, we saw over three million people go through the Waiting Room in less than 24 hours, leading to a significantly smoother and less stressful experience. Cities in Japan, — working closely with our partner, <a href="https://classmethod.jp/news/202106-cloudflare-en/">Classmethod</a> — have been able to vaccinate over 40 million people and are on track to complete their vaccination process across 317 cities. If you want more stories from Project Fair Shot, check out <a href="https://www.cloudflare.com/case-studies/?product=Waiting+Room">our case studies</a>.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3JW3zznYeLCU0J8N1MDYcd/327e638ae0b710f938a93d8cd2207643/image2-28.png" />
            
            </figure><p>A European customer seeing very high amounts of traffic during a vaccination event</p><p>We are continuing to add more customers to Project Fair Shot every day to ensure we are doing all that we can to help distribute more vaccines. With the emergence of the Delta variant and others, vaccine distribution (and soon, booster shots) is still very much a real problem to keep everyone healthy and resilient. Because of these new developments, Cloudflare will be extending Project Fair Shot until at least July 1, 2022. Though we are not excited to see the pandemic continue, we are humbled to be able to provide our services and be a critical part in helping us collectively move towards a better tomorrow.</p> ]]></content:encoded>
            <category><![CDATA[Impact Week]]></category>
            <category><![CDATA[Waiting Room]]></category>
            <category><![CDATA[COVID-19]]></category>
            <category><![CDATA[Project Fair Shot]]></category>
            <category><![CDATA[Reliability]]></category>
            <guid isPermaLink="false">5HBc7sJzo5x35fCSj9DBji</guid>
            <dc:creator>Brian Batraski</dc:creator>
        </item>
        <item>
            <title><![CDATA[Automatic Remediation of Kubernetes Nodes]]></title>
            <link>https://blog.cloudflare.com/automatic-remediation-of-kubernetes-nodes/</link>
            <pubDate>Thu, 15 Jul 2021 12:59:42 GMT</pubDate>
            <description><![CDATA[ In Cloudflare’s core data centers, we are using Kubernetes to run many of the diverse services that help us control Cloudflare’s edge. We are automating some aspects of node remediation to keep the Kubernetes clusters healthy. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>We use <a href="https://kubernetes.io/">Kubernetes</a> to run many of the diverse services that help us control Cloudflare’s edge. We have five geographically diverse clusters, with hundreds of nodes in our largest cluster. These clusters are self-managed on bare-metal machines which gives us a good amount of power and flexibility in the software and integrations with Kubernetes. However, it also means we don’t have a cloud provider to rely on for virtualizing or managing the nodes. This distinction becomes even more prominent when considering all the different reasons that nodes degrade. With self-managed bare-metal machines, the list of reasons that cause a node to become unhealthy include:</p><ul><li><p>Hardware failures</p></li><li><p>Kernel-level software failures</p></li><li><p>Kubernetes cluster-level software failures</p></li><li><p>Degraded network communication</p></li><li><p>Software updates are required</p></li><li><p>Resource exhaustion<sup>1</sup></p></li></ul>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/59IDEspjCRavbrtH1Rtu4r/a5f057aa79b2aae10fc0073b8f3b5573/image2-5.png" />
            
            </figure>
    <div>
      <h2>Unhappy Nodes</h2>
      <a href="#unhappy-nodes">
        
      </a>
    </div>
    <p>We have plenty of examples of failures in the aforementioned categories, but one example has been particularly tedious to deal with. It starts with the following log line from the kernel:</p>
            <pre><code>unregister_netdevice: waiting for lo to become free. Usage count = 1</code></pre>
            <p>The issue is further observed with the number of network interfaces on the node owned by the Container Network Interface (CNI) plugin getting out of proportion with the number of running pods:</p>
            <pre><code>$ ip link | grep cali | wc -l
1088</code></pre>
            <p>This is unexpected as it shouldn't exceed the maximum number of pods allowed on a node (we use the default limit of 110). While this issue is interesting and perhaps worthy of a whole separate blog, the short of it is that the Linux network interfaces owned by the CNI are not getting cleaned up after a pod terminates.</p><p>Some history on this can be read in a <a href="https://github.com/moby/moby/issues/5618">Docker GitHub issue</a>. We found this seems to plague nodes with a longer uptime, and after rebooting the node it would be fine for about a month. However, with a significant number of nodes, this was happening multiple times per day. Each instance would need rebooting, which means going through our worker reboot procedure which looked like this:</p><ol><li><p>Cordon off the affected node to prevent new workloads from scheduling on it.</p></li><li><p>Collect any diagnostic information for later investigation.</p></li><li><p>Drain the node of current workloads.</p></li><li><p>Reboot and wait for the node to come back.</p></li><li><p>Verify the node is healthy.</p></li><li><p>Re-enable scheduling of new workloads to the node.</p></li></ol><p>While solving the underlying issue would be ideal, we needed a mitigation to avoid toil in the meantime — an automated node remediation process.</p>
    <div>
      <h2>Existing Detection and Remediation Solutions</h2>
      <a href="#existing-detection-and-remediation-solutions">
        
      </a>
    </div>
    <p>While not complicated, the manual remediation process outlined previously became tedious and distracting, as we had to reboot nodes multiple times a day. Some manual intervention is unavoidable, but for cases matching the following, we wanted automation:</p><ul><li><p>Generic worker nodes</p></li><li><p>Software issues confined to a given node</p></li><li><p>Already researched and diagnosed issues</p></li></ul><p>Limiting automatic remediation to generic worker nodes is important as there are other node types in our clusters where more care is required. For example, for control-plane nodes the process has to be augmented to check <a href="https://etcd.io/">etcd</a> cluster health and ensure proper redundancy for components servicing the Kubernetes API. We are also going to limit the problem space to known software issues confined to a node where we expect automatic remediation to be the right answer (as in our ballooning network interface problem). With that in mind, we took a look at existing solutions that we could use.</p>
    <div>
      <h3>Node Problem Detector</h3>
      <a href="#node-problem-detector">
        
      </a>
    </div>
    <p><a href="https://github.com/kubernetes/node-problem-detector">Node problem detector</a> is a daemon that runs on each node that detects problems and reports them to the Kubernetes API. It has a pluggable problem daemon system such that one can add their own logic for detecting issues with a node. Node problems are distinguished between temporary and permanent problems, with the latter being persisted as status conditions on the Kubernetes node resources.<sup>2</sup></p>
    <div>
      <h3>Draino and Cluster-Autoscaler</h3>
      <a href="#draino-and-cluster-autoscaler">
        
      </a>
    </div>
    <p><a href="https://github.com/planetlabs/draino">Draino</a> as its name implies, drains nodes but does so based on Kubernetes node conditions. It is meant to be used with <a href="https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler">cluster-autoscaler</a> which then can add or remove nodes via the cluster plugins to scale node groups.</p>
    <div>
      <h3>Kured</h3>
      <a href="#kured">
        
      </a>
    </div>
    <p><a href="https://github.com/weaveworks/kured">Kured</a> is a daemon that looks at the presence of a file on the node to initiate a drain, reboot and uncordon of the given node. It uses a locking mechanism via the Kubernetes API to ensure only a single node is acted upon at a time.</p>
    <div>
      <h3>Cluster-API</h3>
      <a href="#cluster-api">
        
      </a>
    </div>
    <p>The <a href="https://github.com/kubernetes/community/tree/master/sig-cluster-lifecycle">Kubernetes cluster-lifecycle SIG</a> has been working on the <a href="https://github.com/kubernetes-sigs/cluster-api">cluster-api</a> project to enable declaratively defining clusters to simplify provisioning, upgrading, and operating multiple Kubernetes clusters. It has a concept of machine resources which back Kubernetes node resources and furthermore has a concept of <a href="https://cluster-api.sigs.k8s.io/tasks/healthcheck.html">machine health checks</a>. Machine health checks use node conditions to determine unhealthy nodes and then the cluster-api provider is then delegated to replace that machine via create and delete operations.</p>
    <div>
      <h2>Proof of Concept</h2>
      <a href="#proof-of-concept">
        
      </a>
    </div>
    <p>Interestingly, with all the above except for Kured, there is a theme of pluggable components centered around Kubernetes node conditions. We wanted to see if we could build a proof of concept using the existing theme and solutions. For the existing solutions, draino with cluster-autoscaler didn’t make sense in a non-cloud environment like our bare-metal set up. The cluster-api health checks are interesting, however they require a more complete investment into the cluster-api project to really make sense. That left us with node-problem-detector and kured. Deploying node-problem-detector was simple, and we ended up testing a <a href="https://github.com/kubernetes/node-problem-detector/blob/master/docs/custom_plugin_monitor.md">custom-plugin-monitor</a> like the following:</p>
            <pre><code>apiVersion: v1
kind: ConfigMap
metadata:
  name: node-problem-detector-config
data:
  check_calico_interfaces.sh: |
    #!/bin/bash
    set -euo pipefail
    
    count=$(nsenter -n/proc/1/ns/net ip link | grep cali | wc -l)
    
    if (( $count &gt; 150 )); then
      echo "Too many calico interfaces ($count)"
      exit 1
    else
      exit 0
    fi
  cali-monitor.json: |
    {
      "plugin": "custom",
      "pluginConfig": {
        "invoke_interval": "30s",
        "timeout": "5s",
        "max_output_length": 80,
        "concurrency": 3,
        "enable_message_change_based_condition_update": false
      },
      "source": "calico-custom-plugin-monitor",
      "metricsReporting": false,
      "conditions": [
        {
          "type": "NPDCalicoUnhealthy",
          "reason": "CalicoInterfaceCountOkay",
          "message": "Normal amount of interfaces"
        }
      ],
      "rules": [
        {
          "type": "permanent",
          "condition": "NPDCalicoUnhealthy",
          "reason": "TooManyCalicoInterfaces",
          "path": "/bin/bash",
          "args": [
            "/config/check_calico_interfaces.sh"
          ],
          "timeout": "3s"
        }
      ]
    }</code></pre>
            <p>Testing showed that when the condition became true, a condition would be updated on the associated Kubernetes node like so:</p>
            <pre><code>kubectl get node -o json worker1a | jq '.status.conditions[] | select(.type | test("^NPD"))'
{
  "lastHeartbeatTime": "2020-03-20T17:05:17Z",
  "lastTransitionTime": "2020-03-20T17:05:16Z",
  "message": "Too many calico interfaces (154)",
  "reason": "TooManyCalicoInterfaces",
  "status": "True",
  "type": "NPDCalicoUnhealthy"
}</code></pre>
            <p>With that in place, the actual remediation needed to happen. Kured seemed to do most everything we needed, except that it was looking at a file instead of Kubernetes node conditions. We hacked together a patch to change that and tested it successfully end to end — we had a working proof of concept!</p>
    <div>
      <h2>Revisiting Problem Detection</h2>
      <a href="#revisiting-problem-detection">
        
      </a>
    </div>
    <p>While the above worked, we found that node-problem-detector was unwieldy because we were replicating our existing monitoring into shell scripts and node-problem-detector configuration. A <a href="https://www.infoq.com/news/2017/10/monitoring-cloudflare-prometheus/">2017 blog post</a> describes Cloudflare’s monitoring stack, although some things have changed since then. What hasn’t changed is our extensive usage of <a href="https://prometheus.io/">Prometheus</a> and <a href="https://github.com/prometheus/alertmanager">Alertmanager</a>.</p><p>For the network interface issue and other issues we wanted to address, we already had the necessary exported metrics and alerting to go with them. Here is what our already existing alert looked like<sup>3</sup>:</p>
            <pre><code>- alert: CalicoTooManyInterfaces
  expr: sum(node_network_info{device=~"cali.*"}) by (node) &gt;= 200
  for: 1h
  labels:
    priority: "5"
    notify: chat-sre-core chat-k8s</code></pre>
            <p>Note that we use a “notify” label to drive the routing logic in Alertmanager. However, that got us asking, could we just route this to a Kubernetes node condition instead?</p>
    <div>
      <h2>Introducing Sciuro</h2>
      <a href="#introducing-sciuro">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2Hx2xX6FXjjTsCdZZFmn7O/1e8be40972f81d59b9be18a1e60c68c4/image1-6.png" />
            
            </figure><p>Sciuro is our open-source replacement of node-problem-detector that has one simple job: synchronize Kubernetes node conditions with currently firing alerts in Alertmanager. Node problems can be defined with a more holistic view and using already existing exporters such as <a href="https://github.com/prometheus/node_exporter">node exporter</a>, <a href="https://github.com/google/cadvisor">cadvisor</a> or <a href="https://github.com/google/mtail">mtail</a>. It also doesn’t run on affected nodes which allows us to rely on out-of-band remediation techniques. Here is a high level diagram of how Sciuro works:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2TF20JXIsXxWApKN9yyEcy/fe4d2244e860fe8e0c1477e06ae24c30/image4-3.png" />
            
            </figure><p>Starting from the top, nodes are scraped by Prometheus, which collects those metrics and fires relevant alerts to Alertmanager. Sciuro polls Alertmanager for alerts with a matching receiver, matches them with a corresponding node resource in the Kubernetes API and updates that node’s conditions accordingly.</p><p>In more detail, we can start by defining an alert in Prometheus like the following:</p>
            <pre><code>- alert: CalicoTooManyInterfacesEarly
  expr: sum(node_network_info{device=~"cali.*"}) by (node) &gt;= 150
  labels:
    priority: "6"
    notify: node-condition-k8s</code></pre>
            <p>Note the two differences from the previous alert. First, we use a new name with a more sensitive trigger. The idea is that we want automatic node remediation to try fixing the node first as soon as possible, but if the problem worsens or automatic remediation is failing, humans will still get notified to act. The second difference is that instead of notifying chat rooms, we route to a target called “node-condition-k8s”.</p><p>Sciuro then comes into play, polling the Altertmanager API for alerts matching the “node-condition-k8s” receiver. The following shows the equivalent using <a href="https://github.com/prometheus/alertmanager/tree/master/cmd/amtool">amtool</a>:</p>
            <pre><code>$ amtool alert query -r node-condition-k8s
Alertname                 	Starts At            	Summary                                                               	 
CalicoTooManyInterfacesEarly  2021-05-11 03:25:21 UTC  Kubernetes node worker1a has too many Calico interfaces  </code></pre>
            <p>We can also check the labels for this alert:</p>
            <pre><code>$ amtool alert query -r node-condition-k8s -o json | jq '.[] | .labels'
{
  "alertname": "CalicoTooManyInterfacesEarly",
  "cluster": "a.k8s",
  "instance": "worker1a",
  "node": "worker1a",
  "notify": "node-condition-k8s",
  "priority": "6",
  "prometheus": "k8s-a"
}</code></pre>
            <p>Note the node and instance labels which Sciuro will use for matching with the corresponding Kubernetes node. Sciuro uses the excellent <a href="https://github.com/kubernetes-sigs/controller-runtime">controller-runtime</a> to keep track of and update node sources in the Kubernetes API. We can observe the updated node condition on the status field via kubectl:</p>
            <pre><code>$ kubectl get node worker1a -o json | jq '.status.conditions[] | select(.type | test("^AlertManager"))'
{
  "lastHeartbeatTime": "2021-05-11T03:31:20Z",
  "lastTransitionTime": "2021-05-11T03:26:53Z",
  "message": "[P6] Kubernetes node worker1a has too many Calico interfaces",
  "reason": "AlertIsFiring",
  "status": "True",
  "type": "AlertManager_CalicoTooManyInterfacesEarly"
}</code></pre>
            <p>One important note is Sciuro added the AlertManager_ prefix to the node condition type to prevent conflicts with other node condition types. For example, DiskPressure, a kubelet managed condition, could also be an alert name. Sciuro will also properly update heartbeat and transition times to reflect when it first saw the alert and its last update. With node conditions synchronized by Sciuro, remediation can take place via one of the existing tools. As mentioned previously we are using a modified version of Kured for now.</p><p>We’re happy to announce that we’ve open sourced Sciuro, and it can be found on <a href="https://github.com/cloudflare/sciuro">GitHub</a> where you can read the code, find the deployment instructions, or open a Pull Request for changes.</p>
    <div>
      <h2>Managing Node Uptime</h2>
      <a href="#managing-node-uptime">
        
      </a>
    </div>
    <p>While we began using automatic node remediation for obvious problems, we’ve expanded its purpose to additionally keep node uptime low. Low node uptime is desirable to further reduce drift on nodes, keep the node initialization process well-oiled, and encourage the best deployment practices on the Kubernetes clusters. To expand on the last point, services that are deployed with best practices and in a high availability fashion should see negligible impact when a single node leaves the cluster. However, services that are not deployed with best practices will most likely have problems especially if they rely on singleton pods. By draining nodes more frequently, it introduces regular chaos that encourages best practices. To enable this with automatic node remediation the following alert was defined:</p>
            <pre><code>- alert: WorkerUptimeTooHigh
  expr: |
    (
      (
        (
              max by(node) (kube_node_role{role="worker"})
            - on(node) group_left()
              (max by(node) (kube_node_role{role!="worker"}))
          or on(node)
            max by(node) (kube_node_role{role="worker"})
        ) == 1
      )
    * on(node) group_left()
      (
        (time() - node_boot_time_seconds) &gt; (60 * 60 * 24 * 7)
      )
    )
  labels:
    priority: "9"
    notify: node-condition-k8s</code></pre>
            <p>There is a bit of juggling with the kube_node_roles metric in the above to isolate the alert to generic worker nodes, but at a high level it looks at node_boot_time_seconds, a metric from <a href="https://github.com/prometheus/node_exporter">prometheus node_exporter</a>. Again the notify label is configured to send to node conditions which kicks off the automatic node remediation. One further detail is the priority here is set to “9” which is of lower precedence than our other alerts. Note that the message field of the node condition is prefixed with the alert priority in brackets. This allows the remediation process to take priority into account when choosing which node to remediate first, which is important because Kured uses a lock to act on a single node at a time.</p>
    <div>
      <h2>Wrapping Up</h2>
      <a href="#wrapping-up">
        
      </a>
    </div>
    <p>In the past 30 days, we’ve used the above automatic node remediation process to action 571 nodes. That has saved our humans a considerable amount of time. We’ve also been able to reduce the time to repair for some issues as automatic remediation can act at all times of the day and with a faster response time.</p><p>As mentioned before, we’re open sourcing Sciuro and its code can be found on <a href="https://github.com/cloudflare/sciuro">GitHub</a>. We’re open to issues, suggestions, and pull requests. We do have some ideas for future improvements. For Sciuro, we may look to reduce latency which is mainly due to polling and potentially add a push model from Altermanager although this isn’t a need we’ve had yet.  For the larger node remediation story, we hope to do an overhaul of the remediating component. As mentioned previously, we are currently using a fork of kured, but a future replacement component should include the following:</p><ul><li><p>Use out-of-band management interfaces to be able to shut down and power on nodes without a functional operating system.</p></li><li><p>Move from decentralized architecture to a centralized one that can integrate more complicated logic. This might include being able to act on entire failure domains in parallel.</p></li><li><p>Handle specialized nodes such as masters or storage nodes.</p></li></ul><p>Finally, we’re looking for more people passionate about Kubernetes to <a href="https://boards.greenhouse.io/cloudflare/jobs/816059?gh_jid=816059">join our team</a>. Come help us push Kubernetes to the next level to serve Cloudflare’s many needs!</p><hr /><p><sup>1</sup>Exhaustion can be applied to hardware resources, kernel resources, or logical resources like the amount of logging being produced.</p><p><sup>2</sup>Nearly all Kubernetes objects have <a href="https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/">spec and status fields</a>. The status field is used to describe the current state of an object. For node resources, typically the kubelet manages a conditions field under the status field for reporting things like if the node is ready for servicing pods.
<sup>3</sup>The format of the following alert is documented on <a href="https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/">Prometheus Alerting Rules</a>.</p> ]]></content:encoded>
            <category><![CDATA[Kubernetes]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[Monitoring]]></category>
            <guid isPermaLink="false">76X316XLhCYnEUO7ZQR8CO</guid>
            <dc:creator>Andrew DeMaria</dc:creator>
        </item>
        <item>
            <title><![CDATA[Encrypt it or lose it: how encrypted SNI works]]></title>
            <link>https://blog.cloudflare.com/encrypted-sni/</link>
            <pubDate>Mon, 24 Sep 2018 12:01:00 GMT</pubDate>
            <description><![CDATA[ Today we announced support for encrypted SNI, an extension to the TLS 1.3 protocol that improves privacy of Internet users. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Today we announced <a href="/esni">support for encrypted SNI</a>, <a href="https://tools.ietf.org/html/draft-ietf-tls-esni">an extension</a> to the <a href="/rfc-8446-aka-tls-1-3/">TLS 1.3</a> protocol that improves privacy of Internet users by preventing on-path observers, including ISPs, coffee shop owners and firewalls, from intercepting the TLS Server Name Indication (SNI) extension and using it to determine which websites users are visiting.</p><p>Encrypted SNI, together with other Internet security features already offered by Cloudflare for free, will make it harder to censor content and track users on the Internet. Read on to learn how it works.</p>
    <div>
      <h3>SNWhy?</h3>
      <a href="#snwhy">
        
      </a>
    </div>
    <p>The TLS Server Name Indication (SNI) extension, <a href="https://tools.ietf.org/html/rfc3546">originally standardized back in 2003</a>, lets servers host multiple TLS-enabled websites on the same set of IP addresses, by requiring clients to specify which site they want to connect to during the initial TLS handshake. Without SNI the server wouldn’t know, for example, which certificate to serve to the client, or which configuration to apply to the connection.</p><p>The client adds the SNI extension containing the hostname of the site it’s connecting to to the ClientHello message. It sends the ClientHello to the server during the TLS handshake. Unfortunately the ClientHello message is sent unencrypted, due to the fact that client and server don’t share an encryption key at that point.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/15sFb2PJWXZn3WBxjYOa7p/0f42a188a08641aaee1e18b82ce160a9/tls13_unencrypted_server_name_indication-2.png" />
            
            </figure><p><i>TLS 1.3 with Unencrypted SNI</i></p><p>This means that an on-path observer (say, an ISP, coffee shop owner, or a firewall) can intercept the plaintext ClientHello message, and determine which website the client is trying to connect to. That allows the observer to track which sites a user is visiting.</p><p>But with SNI encryption the client encrypts the SNI even though the rest of the ClientHello is sent in plaintext.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/596ebAAHizuuRJ4B7kuFEq/9cba63e4141b47dd0f5d0e8941157b58/tls13_encrypted_server_name_indication-1.png" />
            
            </figure><p><i>TLS 1.3 with Encrypted SNI</i></p><p>So how come the original SNI couldn’t be encrypted before, but now it can? Where does the encryption key come from if client and server haven’t negotiated one yet?</p>
    <div>
      <h3>If the chicken must come before the egg, where do you put the chicken?</h3>
      <a href="#if-the-chicken-must-come-before-the-egg-where-do-you-put-the-chicken">
        
      </a>
    </div>
    <p>As with <a href="https://datatracker.ietf.org/meeting/101/materials/slides-101-dnsop-sessa-the-dns-camel-01">many other Internet features</a> the answer is simply “DNS”.</p><p>The server publishes a <a href="https://en.wikipedia.org/wiki/Public-key_cryptography">public key</a> on a well-known DNS record, which can be fetched by the client before connecting (as it already does for A, AAAA and other records). The client then replaces the SNI extension in the ClientHello with an “encrypted SNI” extension, which is none other than the original SNI extension, but encrypted using a symmetric encryption key derived using the server’s public key, as described below. The server, which owns the private key and can derive the symmetric encryption key as well, can then decrypt the extension and therefore terminate the connection (or forward it to a backend server). Since only the client, and the server it’s connecting to, can derive the encryption key, the encrypted SNI cannot be decrypted and accessed by third parties.</p><p>It’s important to note that this is an extension to TLS version 1.3 and above, and doesn’t work with previous versions of the protocol. The reason is very simple: one of the changes introduced by TLS 1.3 (<a href="/you-get-tls-1-3-you-get-tls-1-3-everyone-gets-tls-1-3/">not without problems</a>) meant moving the Certificate message sent by the server to the encrypted portion of the TLS handshake (before 1.3, it was sent in plaintext). Without this fundamental change to the protocol, an attacker would still be able to determine the identity of the server by simply observing the plaintext certificate sent on the wire.</p><p>The underlying cryptographic machinery involves using the <a href="https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange">Diffie-Hellman key exchange algorithm</a> which allows client and server to generate a shared encryption key over an untrusted channel. The encrypted SNI encryption key is thus calculated on the client-side by using the server’s public key (which is actually the public portion of a Diffie-Hellman semi-static key share) and the private portion of an ephemeral Diffie-Hellman share generated by the client itself on the fly and discarded immediately after the ClientHello is sent to the server. Additional data (such as some of the cryptographic parameters sent by the client as part of its ClientHello message) is also mixed into the cryptographic process for good measure.</p><p>The client’s ESNI extension will then include, not only the actual encrypted SNI bits, but also the client’s public key share, the cipher suite it used for encryption and the digest of the server’s ESNI DNS record. On the other side, the server uses its own private key share, and the public portion of the client’s share to generate the encryption key and decrypt the extension.</p><p>While this may seem overly complicated, this ensures that the encryption key is cryptographically tied to the specific TLS session it was generated for, and cannot be reused across multiple connections. This prevents an attacker able to observe the encrypted extension sent by the client from simply capturing it and replaying it to the server in a separate session to unmask the identity of the website the user was trying to connect to (this is known as “cut-and-paste” attack).</p><p>However a compromise of the server’s private key would put all ESNI symmetric keys generated from it in jeopardy (which would allow observers to decrypt previously collected encrypted data), which is why Cloudflare’s own SNI encryption implementation rotates the server’s keys every hour to improve forward secrecy, but keeps track of the keys for the previous few hours to allow for DNS caching and replication delays, so that clients with slightly outdated keys can still use ESNI without problems (but eventually all keys are discarded and forgotten).</p>
    <div>
      <h3>But wait, DNS? For real?</h3>
      <a href="#but-wait-dns-for-real">
        
      </a>
    </div>
    <p>The observant reader might have realized that simply using <a href="https://www.cloudflare.com/learning/dns/what-is-dns/">DNS</a> (which is, by default, unencrypted) would make the whole encrypted SNI idea completely pointless: an on-path observer would be able to determine which website the client is connecting to by simply observing the plaintext DNS queries sent by the client itself, whether encrypted SNI was used or not.</p><p>But with the introduction of DNS features such as DNS over TLS (DoT) and DNS over HTTPS (DoH), and of public DNS resolvers that provide those features to their users (such as Cloudflare’s own <a href="/announcing-1111/">1.1.1.1</a>), DNS queries can now be encrypted and protected by the prying eyes of censors and trackers alike.</p><p>However, while responses from DoT/DoH DNS resolvers can be trusted, to a certain extent (evil resolvers notwithstanding), it might still be possible for a determined attacker to poison the resolver’s cache by intercepting its communication with the authoritative DNS server and injecting malicious data. That is, unless both the authoritative server and the resolver support <a href="https://www.cloudflare.com/dns/dnssec/">DNSSEC</a><sub>[1]</sub>. Incidentally, Cloudflare’s authoritative DNS servers can sign responses returned to resolvers, and the 1.1.1.1 resolver can verify them.</p>
    <div>
      <h3>What about the IP address?</h3>
      <a href="#what-about-the-ip-address">
        
      </a>
    </div>
    <p>While both DNS queries and the TLS SNI extensions can now be protected by on-path attackers, it might still be possible to determine which websites users are visiting by simply looking at the destination IP addresses on the traffic originating from users’ devices. Some of our customers are protected by this to a certain degree thanks to the fact that many Cloudflare domains share the same sets of addresses, but this is not enough and more work is required to protect end users to a larger degree. Stay tuned for more updates from Cloudflare on the subject in the future.</p>
    <div>
      <h3>Where do I sign up?</h3>
      <a href="#where-do-i-sign-up">
        
      </a>
    </div>
    <p>Encrypted SNI is now enabled for free on all Cloudflare zones using our name servers, so you don’t need to do anything to enable it on your Cloudflare website. On the browser side, our friends at Firefox tell us that they expect to add encrypted SNI support this week to <a href="https://www.mozilla.org/firefox/channel/desktop/">Firefox Nightly</a> (keep in mind that the encrypted SNI spec is still under development, so it’s not stable just yet).</p><p>By visiting <a href="https://encryptedsni.com">encryptedsni.com</a> you can check how secure your browsing experience is. Are you using secure DNS? Is your resolver validating DNSSEC signatures? Does your browser support TLS 1.3? Did your browser encrypt the SNI? If the answer to all those questions is “yes” then you can sleep peacefully knowing that your browsing is protected from prying eyes.</p>
    <div>
      <h3>Conclusion</h3>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>Encrypted SNI, along with TLS 1.3, DNSSEC and DoT/DoH, plugs one of the few remaining holes that enable surveillance and censorship on the Internet. More work is still required to get to a surveillance-free Internet, but we are (slowly) getting there.</p><p>[1]: It's important to mention that DNSSEC could be disabled by BGP route hijacking between a DNS resolver and the TLD server. Last week we <a href="/rpki/">announced</a> our commitment to RPKI and if DNS resolvers and <a href="https://www.cloudflare.com/learning/dns/top-level-domain/">TLDs</a> also implement RPKI, this type of hijacking will be much more difficult.</p><p><a href="/subscribe/"><i>Subscribe to the blog</i></a><i> for daily updates on all our Birthday Week announcements.</i></p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4J9GqS6QbKbhfEaYr5EO0a/a524c0ca04e9a919cc052e55eb670c17/Cloudflare-Birthday-Week-3.png" />
            
            </figure><p></p> ]]></content:encoded>
            <category><![CDATA[Birthday Week]]></category>
            <category><![CDATA[Product News]]></category>
            <category><![CDATA[Cryptography]]></category>
            <category><![CDATA[Security]]></category>
            <category><![CDATA[TLS]]></category>
            <category><![CDATA[TLS 1.3]]></category>
            <category><![CDATA[DNS]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[Speed & Reliability]]></category>
            <guid isPermaLink="false">377BXgmPj3EgsOPaOyf1oG</guid>
            <dc:creator>Alessandro Ghedini</dc:creator>
        </item>
        <item>
            <title><![CDATA[Encrypting SNI: Fixing One of the Core Internet Bugs]]></title>
            <link>https://blog.cloudflare.com/esni/</link>
            <pubDate>Mon, 24 Sep 2018 12:00:00 GMT</pubDate>
            <description><![CDATA[ Cloudflare launched on September 27, 2010. Since then, we've considered September 27th our birthday. This Thursday we'll be turning 8 years old.
Ever since our first birthday, we've used the occasion  ]]></description>
            <content:encoded><![CDATA[ 
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2KlxHjVa3dQkN8o9aUwBhS/8e02971c49b45811314c1393b0f5a761/Cloudflare-Birthday-Week-2.png" />
            
            </figure><p>Cloudflare <a href="https://www.youtube.com/watch?v=bAc_5gMwzuM">launched</a> on September 27, 2010. Since then, we've considered September 27th our birthday. This Thursday we'll be turning 8 years old.</p><p>Ever since our first birthday, we've used the occasion to launch new products or services. Over the years we came to the conclusion that the right thing to do to celebrate our birthday wasn't so much about launching products that we could make money from but instead to do things that were gifts back to our users and the Internet in general. My cofounder Michelle <a href="/cloudflare-turns-8/">wrote about this tradition in a great blog post yesterday</a>.</p><p>Personally, one of my proudest moments at Cloudflare came on our birthday in 2014 when we made <a href="/introducing-universal-ssl/">HTTPS support free for all our users</a>. At the time, people called us crazy — literally and repeatedly. Frankly, internally we had significant debates about whether we were crazy since encryption was the primary reason why people upgraded from a free account to a paid account.</p><p>But it was the right thing to do. The fact that encryption wasn't built into the web from the beginning was, in our mind, a bug. Today, almost exactly four years later, the web is nearly 80% encrypted thanks to leadership from great projects like Let's Encrypt, the browser teams at Google, Apple, Microsoft, and Mozilla, and the fact that more and more hosting and SaaS providers have built in support for HTTPS at no cost. I'm proud of the fact that we were a leader in helping start that trend.</p><p>Today is another day I expect to look back on and be proud of because today we hope to help start a new trend to make the encrypted web more private and secure. To understand that, you have to understand a bit about why the encrypted web as exists today still leaks a lot of your browsing history.</p>
    <div>
      <h2>How Private Is Your Browsing History?</h2>
      <a href="#how-private-is-your-browsing-history">
        
      </a>
    </div>
    <p>The expectation when you visit a site over HTTPS is that no one listening on the line between you and where your connection terminates can see what you're doing. And to some extent, that's true. If you visit your bank's website, HTTPS is effective at keeping the contents sent to or from the site (for example, your username and password or the balance of your bank account) from being leaked to your ISP or anyone else monitoring your network connection.</p><p>While the contents sent to or received from a HTTPS site are protected, the fact that you visited the site can be observed easily in a couple of ways. Traditionally, one of these has been via <a href="https://www.cloudflare.com/learning/dns/what-is-dns/">DNS</a>. DNS queries are, by default, unencrypted so your ISP or anyone else can see where you're going online. That's why last April, we launched <a href="https://one.one.one.one/">1.1.1.1</a> — a free (and <a href="https://www.dnsperf.com/#!dns-resolvers">screaming fast</a>) public DNS resolver with support for DNS over TLS and DNS over HTTPS.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4fWcc2LzN2BjMRcEisXaNq/bfe31ed6b02c14c773ff21e0ef3efefd/Cloudflare_resolver-1111-april-to-sept-2018.png" />
            
            </figure><p><a href="https://one.one.one.one/">1.1.1.1</a> has been a huge success and we've significantly increased the percentage of DNS queries sent over an encrypted connection. Critics, however, rightly pointed out that the identity of the sites that you visit still can leak in other ways. The most problematic is something called the Server Name Indication (SNI) extension.</p>
    <div>
      <h2>Why SNI?</h2>
      <a href="#why-sni">
        
      </a>
    </div>
    <p>Fundamentally, SNI exists in order to allow you to host multiple encrypted websites on a single IP address. Early browsers didn't include the SNI extension. As a result, when a request was made to establish a HTTPS connection the web server didn't have much information to go on and could only hand back a single <a href="https://www.cloudflare.com/application-services/products/ssl/">SSL certificate</a> per IP address the web server was listening on.</p><p>One solution to this problem was to create certificates with multiple Subject Alternative Names (SANs). These certificates would encrypt traffic for multiple domains that could all be hosted on the same IP. This is how Cloudflare handles HTTPS traffic from older browsers that don't support SNI. We limit that feature to our paying customers, however, for the same reason that SANs aren't a great solution: they're a hack, a pain to manage, and can slow down performance if they include too many domains.</p><p>The more scalable solution was SNI. The analogy that makes sense to me is to think of a postal mail envelope. The contents inside the envelope are protected and can't be seen by the postal carrier. However, outside the envelope is the street address which the postal carrier uses to bring the envelope to the right building. On the Internet, a web server's IP address is the equivalent of the street address.</p><p>However, if you live in a multi-unit building, a street address alone isn't enough to get the envelope to the right recipient. To supplement the street address you include an apartment number or recipient's name. That's the equivalent of SNI. If a web server hosts multiple domains, SNI ensures that a request is routed to the correct site so that the right SSL certificate can be returned to be able to encrypt and decrypt any content.</p>
    <div>
      <h2>Nosey Networks</h2>
      <a href="#nosey-networks">
        
      </a>
    </div>
    <p>The specification for SNI was introduced by the IETF in 2003 and browsers rolled out support over the next few years. At the time, it seemed like an acceptable tradeoff. The vast majority of Internet traffic was unencrypted. Adding a TLS extension that made it easier to support encryption seemed like a great trade even if that extension itself wasn't encrypted.</p><p>But, today, as HTTPS covers nearly 80% of all web traffic, the fact that SNI leaks every site you go to online to your ISP and anyone else listening on the line has become a glaring privacy hole. Knowing what sites you visit can build a very accurate picture of who you are, creating both privacy and security risks.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/c8iRSUxulX6UwI9piOFPV/b474340b44191a2f633cbb3c8c4efcd3/Cloudflare_https_with_plaintext_dns_tls12_plaintext_sni.png" />
            
            </figure><p>In the United States, ISPs were briefly restricted in their ability to gather customer browsing data under FCC rules passed at the end of the Obama administration. ISPs, however, lobbied Congress and, in April 2017, President Trump signed a Congressional Resolution repealing those protections. As ISPs increasingly <a href="https://arstechnica.com/information-technology/2017/06/oath-verizon-completes-4-5-billion-buy-of-yahoo-and-merges-it-with-aol/">acquire media companies</a> and <a href="https://www.appnexus.com/company/pressroom/att-to-acquire-appnexus">ad targeting businesses</a>, being able to mine the data flowing through their pipes is an increasingly attractive business for them and an increasingly troubling privacy threat to all of us.</p>
    <div>
      <h2>Closing the SNI Privacy Hole</h2>
      <a href="#closing-the-sni-privacy-hole">
        
      </a>
    </div>
    <p>On May 3, about a month after we launched <a href="https://one.one.one.one/">1.1.1.1</a>, I was reading a review of our new service. While the article praised the fact that <a href="https://one.one.one.one/">1.1.1.1</a> was privacy-oriented, it somewhat nihilistically concluded that it was all for naught because ISPs could still spy on you by monitoring SNI. Frustrated, I dashed off an email to some of Cloudflare's engineers and the senior team at Mozilla, who we'd been working on a project to help encrypt DNS. I concluded my email:</p><blockquote><p>My simple PRD: if Firefox connects to a Cloudflare IP then we'd give you a public key to use to encrypt the SNI entry before sending it to us. How does it scale to other providers? Dunno, but we have to start somewhere. Rough consensus and running code, right?</p></blockquote><p>It turned out to be <a href="/encrypted-sni">a bit more complex than that</a>. However, today I'm proud to announce that Encrypted SNI (ESNI) is live across Cloudflare's network. Later this week we expect Mozilla's Firefox to become the first browser to support the new protocol in their Nightly release. In the months to come, the plan is for it go mainstream. And it's not just Mozilla. There's been significant interest from all the major browser makers and I'm hopeful they'll all add support for ESNI over time.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6m8eyH5dCGo5BQfLPfexbz/92ef550e0368ec79ce665f492d083234/Cloudflare_https_with_secure_dns_tls13_encrytped_sni-1.png" />
            
            </figure>
    <div>
      <h2>Hoping to Start Another Trend</h2>
      <a href="#hoping-to-start-another-trend">
        
      </a>
    </div>
    <p>While we're the first to support ESNI, we haven't done this alone. We worked on ESNI with great teams from Apple, Fastly, Mozilla, and others across the industry who, like us, are concerned about Internet privacy. While Cloudflare is the first content network to support ESNI, this isn't a proprietary protocol. It's being worked on as an <a href="https://datatracker.ietf.org/doc/draft-ietf-tls-esni/?include_text=1">IETF Draft RFC</a> and we are hopeful others will help us formalize the draft and implement the standard as well. If you're curious about the technical details behind ESNI, you can learn more from the <a href="/encrypted-sni/">great blog post just published by my colleague Alessandro Ghedini</a>. Finally, when browser support starts to launch later this week you can test this from our <a href="https://encryptedsni.com">handy ESNI testing tool</a>.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/XTA8EuEynvYfTJQCyRATk/53384a3abb066250e9437b24f8cfcbb8/Cloudflare_esni-2.png" />
            
            </figure><p>Four years ago I'm proud that we helped start a trend that today has led to nearly all the web being encrypted. Today, I hope we are again helping start a trend — this time to make the encrypted web even more private and secure.</p><p><a href="/subscribe/"><i>Subscribe to the blog</i></a><i> for daily updates on all our Birthday Week announcements.</i></p> ]]></content:encoded>
            <category><![CDATA[Birthday Week]]></category>
            <category><![CDATA[Product News]]></category>
            <category><![CDATA[Security]]></category>
            <category><![CDATA[Privacy]]></category>
            <category><![CDATA[HTTPS]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[1.1.1.1]]></category>
            <category><![CDATA[DNS]]></category>
            <guid isPermaLink="false">217e9J3VWa9ZTuRMrfi0Tj</guid>
            <dc:creator>Matthew Prince</dc:creator>
        </item>
        <item>
            <title><![CDATA[Expanding DNSSEC Adoption]]></title>
            <link>https://blog.cloudflare.com/automatically-provision-and-maintain-dnssec/</link>
            <pubDate>Tue, 18 Sep 2018 13:00:00 GMT</pubDate>
            <description><![CDATA[ Cloudflare first started talking about DNSSEC in 2014 and at the time, Nick Sullivan wrote: “DNSSEC is a valuable tool for improving the trust and integrity of DNS, the backbone of the modern Internet.” ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Cloudflare first started talking about <a href="https://www.cloudflare.com/dns/dnssec/universal-dnssec/">DNSSEC</a> in <a href="/dnssec-an-introduction/">2014</a> and at the time, <a href="https://twitter.com/grittygrease">Nick Sullivan</a> wrote: “DNSSEC is a valuable tool for improving the trust and integrity of <a href="https://www.cloudflare.com/learning/dns/what-is-dns/">DNS</a>, the backbone of the modern Internet.”</p><p>Over the past four years, it has become an even more critical part of securing the internet. While <a href="/chrome-not-secure-for-http/">HTTPS</a> has gone a long way in preventing user sessions from being hijacked and maliciously (or innocuously) redirected, not all internet traffic is HTTPS. A safer Internet should secure every possible layer between a user and the origin they are intending to visit.</p><p>As a quick refresher, DNSSEC allows a user, application, or recursive resolver to trust that the answer to their DNS query is what the domain owner intends it to be. Put another way: DNSSEC proves authenticity and integrity (though not confidentiality) of a response from the authoritative nameserver. Doing so makes it much harder for a bad actor to inject malicious DNS records into the resolution path through <a href="/bgp-leaks-and-crypto-currencies/">BGP Leaks</a> and cache poisoning. Trust in DNS matters even more when a domain is publishing <a href="/additional-record-types-available-with-cloudflare-dns/">record types</a> that are used to declare trust for other systems. As a specific example, DNSSEC is helpful for preventing malicious actors from obtaining fraudulent certificates for a domain. <a href="https://blog.powerdns.com/2018/09/10/spoofing-dns-with-fragments/">Research</a> has shown how DNS responses can be spoofed for domain validation.</p><p>This week we are announcing our full support for CDS and CDNSKEY from <a href="https://datatracker.ietf.org/doc/rfc8078/">RFC 8078</a>. Put plainly: this will allow for setting up of DNSSEC without requiring the user to login to their <a href="https://www.cloudflare.com/learning/dns/glossary/what-is-a-domain-name-registrar/">registrar</a> to upload a DS record. Cloudflare customers on supported registries will be able to enable DNSSEC with the click of one button in the Cloudflare dashboard.</p>
    <div>
      <h3>Validation by Resolvers</h3>
      <a href="#validation-by-resolvers">
        
      </a>
    </div>
    <p>DNSSEC’s largest problem has been adoption. The number of DNS queries validated by recursive resolvers for DNSSEC has remained flat. Worldwide, less than 14% of DNS requests have DNSSEC validated by the resolver according to our friends at <a href="https://stats.labs.apnic.net/dnssec/XA?c=XA&amp;x=1&amp;g=1&amp;r=1&amp;w=7&amp;g=0">APNIC</a>. The blame here falls on the shoulders of the default DNS providers that most devices and users receive from DHCP via their ISP or network provider. Data shows that some countries do considerably better: Sweden, for example, has over <a href="https://stats.labs.apnic.net/dnssec/XE?o=cXAw7x1g1r1">80% of their requests validated</a>, showing that the default DNS resolvers in those countries validate the responses as they should. APNIC also has a fun <a href="https://stats.labs.apnic.net/dnssec">interactive map</a> so you can see how well your country does.</p><p>So what can we do? To ensure your resolver supports DNSSEC, visit <a href="http://brokendnssec.net/">brokendnssec.net</a> in your browser. If the page <b>loads,</b> you are not protected by a DNSSEC validating resolver and should <a href="https://1.1.1.1/#setup-instructions">switch your resolver</a>. However, in order to really move the needle across the internet, Cloudflare encourages network providers to either turn on the validation of DNSSEC in their software or switch to publicly available resolvers that validate DNSSEC by default. Of course we have <a href="https://one.one.one.one">a favourite</a>, but there are other fine choices as well.</p>
    <div>
      <h3>Signing of Zones</h3>
      <a href="#signing-of-zones">
        
      </a>
    </div>
    <p>Validation handles the user side, but another problem has been the signing of the zones themselves. Initially, there was concern about adoption at the <a href="https://www.cloudflare.com/learning/dns/top-level-domain/">TLD</a> level given that TLD support is a requirement for DNSSEC to work. This is now largely a non-issue with over 90% of TLDs signed with DS records in the root zone, as of <a href="http://stats.research.icann.org/dns/tld_report/">2018-08-27</a>.</p><p>It’s a different story when it comes to the individual domains themselves. Per <a href="https://usgv6-deploymon.antd.nist.gov/cgi-bin/generate-com">NIST data</a>, a woefully low 3% of the Fortune 1000 sign their primary domains. Some of this is due to apathy by the domain owners. However, some large DNS operators do not yet support the option at all, requiring domain owners who want to protect their users to move to another provider altogether. If you are on a service that does not support DNSSEC, we encourage you to switch to one that does and let them know that was the reason for the switch. Other large operators, such as GoDaddy, charge for DNSSEC. Our stance here is clear: DNSSEC should be available and included at all DNS operators for free.</p>
    <div>
      <h3>The DS Parent Issue</h3>
      <a href="#the-ds-parent-issue">
        
      </a>
    </div>
    <p>In December of 2017, APNIC wrote about <a href="https://blog.apnic.net/2017/12/06/dnssec-deployment-remains-low/">why DNSSEC deployment remains so low</a> and that remains largely true today. One key point was that the number of domain owners who attempt DNSSEC activation but do not complete it is very high. Using Cloudflare as an example, APNIC measured that 40% of those who enabled DNSSEC in the Cloudflare Dash (evidenced by the presence of a DNSKEY record) were actually successful in serving a DS key from the registry. Current data over a recent 90 day period is slightly better: we are seeing just over 50% of all zones which attempted to enable DNSSEC were able to complete the process with the registry (Note: these domains still resolve, they are just still not secured). Of our most popular TLDs, .be and .nl have success rates of over 70%, but these numbers are still not where we would want them to be in an ideal world. The graph below shows the specific rates for the most popular TLDs (most popular from left to right).</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/20XNgbCpC85y8X91Bpo7zS/2e85b5a9563fbe1d9e726141989d01df/Graph.png" />
            
            </figure><p>This end result is likely not surprising to anyone who has tried to add a DS record to their registrar. Locating the part of the registrar UI that houses DNSSEC can be problematic, as can the UI of adding the record itself. Additional factors such as varying degrees of technical knowledge amongst users and simply having to manage multiple logins and roles can also explain the lack of completion in the process. Finally, varying levels of DNSSEC compatibility amongst registrars may prevent even knowledgeable users from creating DS records in the parent.</p><p>As an example, at Cloudflare, we took a minimalist UX approach for adding DS records for delegated child domains. A novice user may not understand the fields and requirements for the DS record:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5uBtcWkLicobwesLsEJ1MF/68a4051c4b0746cfafb08fc93c4c0f0a/pasted-image-0.png" />
            
            </figure>
    <div>
      <h3></h3>
      <a href="#">
        
      </a>
    </div>
    <p>CDS and CDNSKEY</p><p>As mentioned in the aforementioned APNIC blog, Cloudflare is supportive of <a href="https://datatracker.ietf.org/doc/rfc8078/">RFC 8078</a> and the CDS and CDNSKEY records. This should come as no surprise given that our own <a href="https://twitter.com/OGudm">Olafur Gudmundsson</a> is a co-author of the RFC. CDS and CDNSKEY are records that mirror the DS and DNSKEY record types but are designated to signal the parent/registrar that the child domain wishes to enable DNSSEC and have a DS record presented by the registry. We have been pushing for automated solutions in this space for <a href="/updating-the-dns-registration-model-to-keep-pace-with-todays-internet/">years</a> and are encouraging the industry to move with us.</p><p>Today, we are announcing General Availability and full support for CDS and CDNSKEY records for all Cloudflare managed domains that enable DNSSEC in the Cloudflare dash.</p>
    <div>
      <h3>How It Works</h3>
      <a href="#how-it-works">
        
      </a>
    </div>
    <p>Cloudflare will publish CDS and CDNSKEY records for all domains who enable DNSSEC. Parent registries should scan the nameservers of the  domains under their purview and check for these rrsets. The presence of a CDS key for a domain delegated to Cloudflare indicates that a verified Cloudflare user has enabled DNSSEC within their dash and that the parent operator (a registrar or the registry itself) should take the CDS record content and create the requisite DS record to start signing the domain. TLDs .ch and .cz already support this automated method through Cloudflare and any other DNS operators that choose to support RFC8078. The registrar <a href="https://www.gandi.net/">Gandi</a> and a number of TLDs have indicated support in the near future.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6NWwLVYnosedEpsDH0NNQS/36198c65294dbdcce40045262c5f61a9/Flow.png" />
            
            </figure><p>Cloudflare also supports CDS0 for the removal of the DS record in the case that the user <a href="https://www.cloudflare.com/learning/dns/how-to-transfer-a-domain-name/">transfers</a> their domain off of Cloudflare or otherwise disables DNSSEC.</p>
    <div>
      <h3>Best Practices for Parent Operators</h3>
      <a href="#best-practices-for-parent-operators">
        
      </a>
    </div>
    <p>Below are a number of suggested procedures that parent registries may take to provide for the best experience for our users:</p><ul><li><p><i>Scan Selection</i> - Parent Operators should only scan their child domains who have nameservers pointed at Cloudflare (or other DNS operators who adopt RFC8078). Cloudflare nameservers are indicated *.ns.cloudflare.com.</p></li><li><p><i>Scan Regularly</i> - Parent Operators should scan at regular intervals for the presence and change of CDS records. A scan every 12 hours should be sufficient, though faster is better.</p></li><li><p><i>Notify Domain Contacts</i> - Parent Operators should notify their designated contacts through known channels (such as email and/or SMS) for a given child domain upon detection of a new CDS record and an impending change of their DS record. The Parent Operator may also wish to provide a standard delay (24 hours) before changing the DS record to allow the domain contact to cancel or otherwise change the operation.</p></li><li><p><i>Verify Success</i> - Parent Operators must ensure that the domain continues to resolve after being signed. Should the domain fail to resolve immediately after changing the DS record, the Parent Operator must fall back to the previous functional state and should notify designated contacts.</p></li></ul>
    <div>
      <h3>What Does This All Mean and What’s Next?</h3>
      <a href="#what-does-this-all-mean-and-whats-next">
        
      </a>
    </div>
    <p>For Cloudflare customers, this means an easier implementation of DNSSEC once your registry/registrar supports CDS and CDNSKEY. Customers can also enable DNSSEC for free on Cloudflare and manually enter the DS to the parent. To check your domain’s DNSSEC status, <a href="http://dnsviz.net/d/cloudflare.com/dnssec/">DNSViz (example cloudflare.com</a>) has one of the most standards compliant tools online.</p><p>For registries and registrars, we are taking this step with the hope that more providers support RFC8078 and help increase the global adoption of technology that helps end users be less vulnerable to DNS attacks on the internet.</p><p>For other DNS operators, we encourage you to join us in supporting this method as the more major DNS operators that publish CDS and CDNSKEY, the more likely it will be that the registries will start looking for and use them.</p><p>Cloudflare will continue pushing down this path and has plans to create and open source additional tools to help registries and operators push and consume records. If this sounds interesting to you, we are <a href="https://www.cloudflare.com/careers/">hiring</a>.</p><p><a href="/subscribe/"><i>Subscribe to the blog</i></a><i> for daily updates on our announcements.</i></p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4SOBfg9SIxbV23r9vS1Vlt/072c7daa0d365194497c3c11f0d6c807/Crypto-Week-1-1-1.png" />
            
            </figure><p></p> ]]></content:encoded>
            <category><![CDATA[Crypto Week]]></category>
            <category><![CDATA[Security]]></category>
            <category><![CDATA[DNSSEC]]></category>
            <category><![CDATA[DNS]]></category>
            <category><![CDATA[Product News]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[Cryptography]]></category>
            <guid isPermaLink="false">7FVga47DKN7yhAMwIAvQrV</guid>
            <dc:creator>Sergi Isasi</dc:creator>
            <dc:creator>Vicky Shrestha</dc:creator>
        </item>
        <item>
            <title><![CDATA[Welcome to Crypto Week]]></title>
            <link>https://blog.cloudflare.com/crypto-week-2018/</link>
            <pubDate>Mon, 17 Sep 2018 13:00:00 GMT</pubDate>
            <description><![CDATA[ The Internet isn’t perfect. It was put together piecemeal through publicly funded research, private investment, and organic growth that has left us with an imperfect tapestry. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>The Internet is an amazing invention. We marvel at how it connects people, connects ideas, and makes the world smaller. But the Internet isn’t perfect. It was put together piecemeal through publicly funded research, private investment, and organic growth that has left us with an imperfect tapestry. It’s also evolving. People are constantly developing creative applications and finding new uses for existing Internet technology. Issues like privacy and security that were afterthoughts in the early days of the Internet are now supremely important. People are being tracked and monetized, websites and web services are being attacked in interesting new ways, and the fundamental system of trust the Internet is built on is showing signs of age. The Internet needs an upgrade, and one of the tools that can make things better is cryptography.</p><p>Every day this week, Cloudflare will be announcing support for a new technology that uses cryptography to make the Internet better (hint: <a href="/subscribe/">subscribe to the blog</a> to make sure you don't miss any of the news). Everything we are announcing this week is free to use and provides a meaningful step towards supporting a new capability or structural reinforcement. So why are we doing this? Because it’s good for the users and good for the Internet. Welcome to Crypto Week!</p>
    <div>
      <h3>Day 1: Distributed Web Gateway</h3>
      <a href="#day-1-distributed-web-gateway">
        
      </a>
    </div>
    <ul><li><p><a href="/distributed-web-gateway/">Cloudflare goes InterPlanetary - Introducing Cloudflare’s IPFS Gateway</a></p></li><li><p><a href="/e2e-integrity/">End-to-End Integrity with IPFS</a></p></li></ul>
    <div>
      <h3>Day 2: DNSSEC</h3>
      <a href="#day-2-dnssec">
        
      </a>
    </div>
    <ul><li><p><a href="/automatically-provision-and-maintain-dnssec/">Expanding DNSSEC Adoption</a></p></li></ul>
    <div>
      <h3>Day 3: RPKI</h3>
      <a href="#day-3-rpki">
        
      </a>
    </div>
    <ul><li><p><a href="/rpki/">RPKI - The required cryptographic upgrade to BGP routing</a></p></li><li><p><a href="/rpki-details/">RPKI and BGP: our path to securing Internet Routing</a></p></li></ul>
    <div>
      <h3>Day 4: Onion Routing</h3>
      <a href="#day-4-onion-routing">
        
      </a>
    </div>
    <ul><li><p><a href="/cloudflare-onion-service/">Introducing the Cloudflare Onion Service</a></p></li></ul>
    <div>
      <h3>Day 5: Roughtime</h3>
      <a href="#day-5-roughtime">
        
      </a>
    </div>
    <ul><li><p><a href="/roughtime/">Roughtime: Securing Time with Digital Signatures</a></p></li></ul>
    <div>
      <h2>A more trustworthy Internet</h2>
      <a href="#a-more-trustworthy-internet">
        
      </a>
    </div>
    <p>Everything we do online depends on a relationship between users, services, and networks that is supported by some sort of trust mechanism. These relationships can be physical (I plug my router into yours), contractual (I paid a <a href="https://www.cloudflare.com/learning/dns/glossary/what-is-a-domain-name-registrar/">registrar</a> for this <a href="https://www.cloudflare.com/learning/dns/glossary/what-is-a-domain-name/">domain name</a>), or reliant on a trusted third party (I sent a message to my friend on iMessage via Apple). The simple act of visiting a website involves hundreds of trust relationships, some explicit and some implicit. The sheer size of the Internet and number of parties involved make trust online incredibly complex. Cryptography is a tool that can be used to encode and enforce, and most importantly scale these trust relationships.</p><p>To illustrate this, let’s break down what happens when you visit a website. But before we can do this, we need to know the jargon.</p><ul><li><p><b>Autonomous Systems (100 thousand or so active)</b>: An AS corresponds to a network provider connected to the Internet. Each has a unique Autonomous System Number (ASN).</p></li><li><p><b>IP ranges (1 million or so)</b>: Each AS is assigned a set of numbers called IP addresses. Each of these IP addresses can be used by the AS to identify a computer on its network when connecting to other networks on the Internet. These addresses are assigned by the Regional Internet Registries (RIR), of which there are 5. Data sent from one IP address to another hops from one AS to another based on a “route” that is determined by a protocol called BGP.</p></li><li><p><b>Domain names (&gt;1 billion)</b>: Domain names are the human-readable names that correspond to Internet services (like “cloudflare.com” or “mail.google.com”). These Internet services are accessed via the Internet by connecting to their IP address, which can be obtained from their domain name via the <a href="https://www.cloudflare.com/learning/dns/what-is-dns/">Domain Name System (DNS)</a>.</p></li><li><p><b>Content (infinite)</b>: The main use case of the Internet is to enable the transfer of specific pieces of data from one point on the network to another. This data can be of any form or type.</p></li></ul>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7wDRty2HT3gbpxOlTNAgm5/98e8e5b4168678a79bb091946813a845/name-to-asn-_3.5x.png" />
            
            </figure><p>When you type a website such as blog.cloudflare.com into your browser, a number of things happen. First, a (recursive) DNS service is contacted to get the IP address of the site. This DNS server configured by your ISP when you connect to the Internet, or it can be a public service such as 1.1.1.1 or 8.8.8.8. A query to the DNS service travels from network to network along a path determined by BGP announcements. If the recursive DNS server does not know the answer to the query, then it contacts the appropriate authoritative DNS services, starting with a root DNS server, down to a top level domain server (such as com or org), down to the DNS server that is authoritative for the domain. Once the DNS query has been answered, the browser sends an HTTP request to its IP address (traversing a sequence of networks), and in response, the server sends the content of the website.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2JHDdXKcnw2lce7hUVVvjP/a76212811897165d5e081bdc56be32a4/colorful-crypto-overview--copy-3_3.5x.png" />
            
            </figure><p>So what’s the problem with this picture? For one, every DNS query and every network hop needs to be trusted in order to trust the content of the site. Any DNS query could be modified, a network could advertise an IP that belongs to another network, and any machine along the path could modify the content. When the Internet was small, there were mechanisms to combat this sort of subterfuge. Network operators had a personal relationship with each other and could punish bad behavior, but given the number of networks in existence <a href="https://www.cidr-report.org/as2.0/autnums.html">almost 400,000 as of this week</a> this is becoming difficult to scale.</p><p>Cryptography is a tool that can encode these trust relationships and make the whole system reliant on hard math rather than physical handshakes and hopes.</p>
    <div>
      <h3>Building a taller tower of turtles</h3>
      <a href="#building-a-taller-tower-of-turtles">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4thrwRrwuZ1ctzlstdLLqv/4e0c8c5b89d4faa9f8ff3c5d76251f01/turtles.jpg" />
            
            </figure><p><a href="https://www.flickr.com/photos/wwarby/2499825928">Attribution 2.0 Generic (CC BY 2.0)</a></p><p>The two main tools that cryptography provides to help solve this problem are cryptographic hashes and digital signatures.</p><p>A hash function is a way to take any piece of data and transform it into a fixed-length string of data, called a digest or hash. A hash function is considered cryptographically strong if it is computationally infeasible (read: very hard) to find two inputs that result in the same digest, and that changing even one bit of the input results in a completely different digest. The most popular hash function that is considered secure is SHA-256, which has 256-bit outputs. For example, the SHA-256 hash of the word “crypto” is</p><p><code>DA2F073E06F78938166F247273729DFE465BF7E46105C13CE7CC651047BF0CA4</code></p><p>And the SHA-256 hash of “crypt0” is</p><p><code>7BA359D3742595F38347A0409331FF3C8F3C91FF855CA277CB8F1A3A0C0829C4</code></p><p>The other main tool is digital signatures. A digital signature is a value that can only be computed by someone with a private key, but can be verified by anyone with the corresponding public key. Digital signatures are way for a private key holder to “sign,” or attest to the authenticity of a specific message in a way that anyone can validate it.</p><p>These two tools can be combined to solidify the trust relationships on the Internet. By giving private keys to the trusted parties who are responsible for defining the relationships between ASs, IPs, domain names and content, you can create chains of trust that can be publicly verified. Rather than hope and pray, these relationships can be validated in real time at scale.</p><p>Let’s take our webpage loading example and see where digital signatures can be applied.</p><p><b>Routing</b>. Time-bound delegation of trust is defined through a system called the RPKI. RPKI defines an object called a Resource Certificate, an attestation that states that a given IP range belongs to a specific ASN for this period of time, digitally signed by the RIR responsible for assigning the IP range. Networks share routes via BGP, and if a route is advertised for an IP that does not conform the the Resource Certificate, the network can choose not to accept it.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2GgcQBjG2ecuqivy9h7SCe/f6bea1c0abb365d2cab805c221d00ae6/roas_3x.png" />
            
            </figure><p><b>DNS.</b> Adding cryptographic assurance to routing is powerful, but if a network adversary can change the content of the data (such as the DNS responses), then the system is still at risk. DNSSEC is a system built to provide a trusted link between names and IP addresses. The root of trust in DNSSEC is the DNS root key, which is managed with an <a href="https://www.iana.org/dnssec/ceremonies">elaborate signing ceremony</a>.</p><p><b>HTTPS</b>. When you connect to a site, not only do you want it to be coming from the right host, you also want the content to be private. The Web PKI is a system that issues certificates to sites, allowing you to bind the domain name to a time-bounded private key. Because there are many CAs, additional accountability systems like <a href="/introducing-certificate-transparency-and-nimbus/">certificate transparency</a> need to be involved to help keep the system in check.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6oSYpHOMRKf2EtzXWvcTbE/5b1100ad17540b9946cdbf91604a72fc/connection-to-asn_3.5x.png" />
            
            </figure><p>This cryptographic scaffolding turns the Internet into an encoded system of trust. With these systems in place, Internet users no longer need to trust every network and party involved in this diagram, they only need to trust the RIRs, DNSSEC and the CAs (and know the correct time).</p><p>This week we’ll be making some announcements that help strengthen this system of accountability.</p>
    <div>
      <h2>Privacy and integrity with friends</h2>
      <a href="#privacy-and-integrity-with-friends">
        
      </a>
    </div>
    <p>The Internet is great because it connects us to each other, but the details of how it connects us are important. The technical choices made when Internet was designed come with some interesting human implications.</p><p>One implication is <b>trackability</b>. Your IP address is contained on every packet you send over the Internet. This acts as a unique identifier for anyone (corporations, governments, etc.) to track what you do online. Furthermore, if you connect to a server, that server’s identity is sent in plaintext on the request <b>even over HTTPS</b>, revealing your browsing patterns to any intermediary who cares to look.</p><p>Another implication is <b>malleability</b>. Resources on the Internet are defined by <i>where</i> they are, not <i>what</i> they are. If you want to go to CNN or BBC, then you connect to the server for cnn.com or bbc.co.uk and validate the certificate to make sure it’s the right site. But once you’ve made the connection, there’s no good way to know that the actual content is what you expect it to be. If the server is hacked, it could send you anything, including dangerous malicious code. HTTPS is a secure pipe, but there’s no inherent way to make sure what gets sent through the pipe is what you expect.</p><p>Trackability and malleability are not inherent features of interconnectedness. It is possible to design networks that don’t have these downsides. It is also possible to build new networks with better characteristic on top of the existing Internet. The key ingredient is cryptography.</p>
    <div>
      <h3>Tracking-resilient networking</h3>
      <a href="#tracking-resilient-networking">
        
      </a>
    </div>
    <p>One of the networks built on top of the Internet that provides good privacy properties is Tor. The Tor network is run by a group of users who allow their computers to be used to route traffic for other members of the network. Using cryptography, it is possible to route traffic from one place to another without points along the path knowing both the source and the destination at the same time. This is called <a href="https://en.wikipedia.org/wiki/Onion_routing">onion routing</a> because it involves multiple layers of encryption, like an onion. Traffic coming out of the Tor network is “anonymous” because it could have come from anyone connected to the network. Everyone just blends in, making it hard to track individuals.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/68kxhYzrB1vuZ1FogJ2MgK/e11e433e5f39a95cd6ef9ed4009b5c8b/Tor-Onion-Cloudflare.png" />
            
            </figure><p>Similarly, web services can use onion routing to serve content inside the Tor network without revealing their location to visitors. Instead of using a hostname to identify their network location, so-called onion services use a cryptographic public key as their address. There are hundreds of onion services in use, including the one <a href="/welcome-hidden-resolver/">we use for 1.1.1.1</a> or the one in <a href="https://en.wikipedia.org/wiki/Facebookcorewwwi.onion">use by Facebook</a>.</p><p>Troubles occur at the boundary between Tor network and the rest of the Internet. This is especially true for user is attempting to access services that rely on abuse prevention mechanisms based on reputation. Since Tor is used by both privacy-conscious users and malicious bots, connections from both get lumped together and as the expression goes, one bad apple ruins the bunch. This unfortunately exposes legitimate visitors to anti-abuse mechanisms like CAPTCHAs. Tools like <a href="/cloudflare-supports-privacy-pass/">Privacy Pass</a> help reduce this burden but don’t eliminate it completely. This week we’ll be announcing a new way to improve this situation.</p>
    <div>
      <h3>Bringing integrity to content delivery</h3>
      <a href="#bringing-integrity-to-content-delivery">
        
      </a>
    </div>
    <p>Let’s revisit the issue of malleability: the fact that you can’t always trust the other side of a connection to send you the content you expect. There are technologies that allow users to insure the integrity of content without trusting the server. One such technology is a feature of HTML called <a href="https://www.w3.org/TR/SRI/">Subresource Integrity (SRI)</a>. SRI allows a webpage with sub-resources (like a script or stylesheet) to embed a unique cryptographic hash into the page so that when the sub-resource is loaded, it is checked to see that is matches the expected value. This protects the site from loading unexpected scripts from third parties, <a href="/an-introduction-to-javascript-based-ddos/">a known attack vector</a>.</p><p>Another idea is to flip this on its head: what if instead of fetching a piece of content from a specific location on the network, you asked the network to find piece of content that matches a given hash? By assigning resources based on their actual content rather than by location it’s possible to create a network in which you can fetch content from anywhere on the network and still know it’s authentic. This idea is called <i>content addressing</i> and there are networks built on top of the Internet that use it. These content addressed networks, based on protocols such <a href="https://ipfs.io/">IPFS</a> and <a href="https://datproject.org/">DAT</a>, are blazing a trail new trend in Internet applications called the Distributed Web. With the Distributed Web applications, malleability is no longer an issue, opening up a new set of possibilities.</p>
    <div>
      <h3>Combining strengths</h3>
      <a href="#combining-strengths">
        
      </a>
    </div>
    <p>Networks based on cryptographic principles, like Tor and IPFS, have one major downside compared to networks based on names: usability. Humans are exceptionally bad at remembering or distinguishing between cryptographically-relevant numbers. Take, for instance, the New York Times’ onion address:</p><p><code>https://www.nytimes3xbfgragh.onion/</code></p><p>This is would easily confused with similar-looking onion addresses, such as</p><p><code>https://www.nytimes3xfkdbgfg.onion/</code></p><p>which may be controlled by a malicious actor.</p><p>Content addressed networks are even worse from the perspective of regular people. For example, there is a snapshot of the Turkish version of Wikipedia on IPFS with the hash:</p><p><code>QmT5NvUtoM5nWFfrQdVrFtvGfKFmG7AHE8P34isapyhCxX</code></p><p>Try typing this hash into your browser without making a mistake.</p><p>These naming issues are things Cloudflare is perfectly positioned to help solve.First, by putting the hash address of an IPFS site in the DNS (and adding DNSSEC for trust) you can give your site a traditional hostname while maintaining a chain of trust.</p><p>Second, by enabling browsers to use a traditional DNS name to access the web through onion services, you can provide safer access to your site for Tor user with the added benefit of being better able to distinguish between bots and humans.With Cloudflare as the glue, is is possible to connect both standard internet and tor users to web sites and services on both the traditional web with the distributed web.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/rzDTSMsIy1c5frGel8Eff/ea82dba88874f5772d6f7bdc3cc54776/bowtie-diagram-crypto-week-2018-v02_medium-1.gif" />
            
            </figure><p>This is the promise of Crypto Week: using cryptographic guarantees to make a stronger, more trustworthy and more private internet without sacrificing usability.</p>
    <div>
      <h2>Happy Crypto Week</h2>
      <a href="#happy-crypto-week">
        
      </a>
    </div>
    <p>In conclusion, we’re working on many cutting-edge technologies based on cryptography and applying them to <a href="https://blog.cloudflare.com/50-years-of-the-internet-work-in-progress-to-a-better-internet/">make the Internet better</a>. The first announcement today is the launch of Cloudflare's <a href="/distributed-web-gateway/">Distributed Web Gateway</a> and <a href="/e2e-integrity/">browser extension</a>. Keep tabs on the Cloudflare blog for exciting updates as the week progresses.</p><p>I’m very proud of the team’s work on Crypto Week, which was made possible by the work of a dedicated team, including several brilliant interns. If this type of work is interesting to you, Cloudflare is hiring for the <a href="https://boards.greenhouse.io/cloudflare/jobs/634967?gh_jid=634967">crypto team</a> and <a href="https://www.cloudflare.com/careers/">others</a>!</p> ]]></content:encoded>
            <category><![CDATA[Crypto Week]]></category>
            <category><![CDATA[Security]]></category>
            <category><![CDATA[IPFS]]></category>
            <category><![CDATA[HTTPS]]></category>
            <category><![CDATA[Tor]]></category>
            <category><![CDATA[DNS]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[Cryptography]]></category>
            <guid isPermaLink="false">2NzZFGM5fxcJ3xnCx2v7jD</guid>
            <dc:creator>Nick Sullivan</dc:creator>
        </item>
        <item>
            <title><![CDATA[Fixing an old hack - why we are bumping the IPv6 MTU]]></title>
            <link>https://blog.cloudflare.com/increasing-ipv6-mtu/</link>
            <pubDate>Mon, 10 Sep 2018 09:21:25 GMT</pubDate>
            <description><![CDATA[ Back in 2015 we deployed ECMP routing - Equal Cost Multi Path - within our datacenters. This technology allowed us to spread traffic heading to a single IP address across multiple physical servers. ]]></description>
            <content:encoded><![CDATA[ <p>Back in 2015 we deployed <a href="https://en.wikipedia.org/wiki/Equal-cost_multi-path_routing">ECMP routing</a> - Equal Cost Multi Path - within our datacenters. This technology allowed us to spread traffic heading to a single IP address across multiple physical servers.</p><p>You can think about it as a third layer of load balancing.</p><ul><li><p>First we split the traffic across multiple IP addresses with DNS.</p></li><li><p>Then we split the traffic across <a href="https://www.cloudflare.com/learning/cdn/glossary/anycast-network/">multiple datacenters with Anycast</a>.</p></li><li><p>Finally, we split the traffic across multiple servers with ECMP.</p></li></ul>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6brB6jYvBwnIHL5UyGZZpq/dbc2f52a7ba7056bebc36eb90ec98c55/5799659266_28038df72f_b.jpg" />
            
            </figure><p><a href="https://www.flickr.com/photos/superlatif/5799659266/">photo</a> by <a href="https://www.flickr.com/photos/superlatif/">Sahra</a> by-sa/2.0</p><p>When deploying ECMP we hit a problem with Path MTU discovery. The ICMP packets destined to our Anycast IP's were being dropped. You can read more about that (and the solution) in the 2015 blog post <a href="/path-mtu-discovery-in-practice/">Path MTU Discovery in practice</a>.</p><p>To solve the problem we created a small piece of software, called <code>pmtud</code> (<a href="https://github.com/cloudflare/pmtud">https://github.com/cloudflare/pmtud</a>). Since deploying <code>pmtud</code>, our ECMP setup has been working smoothly.</p>
    <div>
      <h3>Hardcoding IPv6 MTU</h3>
      <a href="#hardcoding-ipv6-mtu">
        
      </a>
    </div>
    <p>During that initial ECMP rollout things were broken. To keep services running until <code>pmtud</code> was done, we deployed a quick hack. We reduced the MTU of  IPv6 traffic to the minimal possible value: 1280 bytes.</p><p>This was done as a tag on a default route. This is how our routing table used to look:</p>
            <pre><code>$ ip -6 route show
...
default via 2400:xxxx::1 dev eth0 src 2400:xxxx:2  metric 1024  mtu 1280</code></pre>
            <p>Notice the <code>mtu 1280</code> in the default route.</p><p>With this setting our servers never transmitted IPv6 packets larger than 1280 bytes, therefore "fixing" the issue. Since all IPv6 routers must have an MTU of at least 1280, we could expect that no ICMP Packet-Too-Big message would ever be sent to us.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/WoQ4atXDbAlJ1mhDnXDcf/0e2df496f1184bf35217d2be59f255b8/ECMP-hashing-ICMP.png" />
            
            </figure><p>Remember - the original problem introduced by ECMP was that ICMP routed back to our Anycast addresses could go to a wrong machine within the ECMP group. Therefore we became ICMP black holes. Cloudflare would send large packets, they would be dropped with ICMP PTB packet flying back to us. Which, in turn would fail to be delivered to the right machine due to ECMP.</p><p>But why did this problem not appear for IPv4 traffic? We believe the same issue exists on IPv4, but it's less damaging due to the different nature of the network. IPv4 is more mature and the great majority of end-hosts support either MTU 1500 or have their MSS option well configured - or clamped by some middle box. This is different in IPv6 where a large proportion of  users use tunnels, have Path MTU strictly smaller than 1500 and use incorrect MSS settings in the TCP header. Finally, Linux implements <a href="https://tools.ietf.org/html/rfc4821">RFC4821</a> for IPv4 but not IPv6. RFC4821 (PLPMTUD) has its disadvantages, but does slightly help to alleviate the ICMP blackhole issue.</p><p>Our "fix" - reducing the MTU to 1280 - was serving us well and we had no pressing reason to revert it.</p><p>Researchers did notice though. We were caught red-handed twice:</p><ul><li><p><a href="https://blog.apnic.net/2016/11/15/scoring-dns-root-server-system/">In 2017 Geoff Huston noticed (pdf)</a> that we sent DNS fragments of 1280 only (<a href="https://blog.apnic.net/2016/11/15/scoring-dns-root-server-system/">older blog post</a>).</p></li><li><p>In June 2018 the paper <a href="http://tma.ifip.org/2018/wp-content/uploads/sites/3/2018/06/tma2018_paper57.pdf">"Exploring usable Path MTU in the Internet" (pdf)</a> mentioned our weird setting - where we can accept 1500 bytes just fine, but transmit is limited to 1280.</p></li></ul>
    <div>
      <h3>When small MTU is too small</h3>
      <a href="#when-small-mtu-is-too-small">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3yo93AUS4hONJUarTUlGP/1c9fd02139519ea6f947b61a39da9d8b/6545737741_077583ca1f_b-1.jpg" />
            
            </figure><p><a href="https://www.flickr.com/photos/nh53/6545737741/">photo</a> by <a href="https://www.flickr.com/photos/nh53">NH53</a> by/2.0</p><p>This changed recently, when we started working on <a href="/spectrum/">Cloudflare Spectrum</a> support for UDP. Spectrum is a terminating proxy, able to handle protocols other than HTTP. Getting Spectrum to <a href="/how-we-built-spectrum/">forward TCP was relatively straightforward</a> (barring couple of <a href="/mmproxy-creative-way-of-preserving-client-ips-in-spectrum/">awesome hacks</a>). UDP is different.</p><p>One of the major issues we hit was related to the MTU on our servers.</p><p>During tests we wanted to forward UDP VPN packets through Spectrum. As you can imagine, any VPN would encapsulate a packet in another packet. Spectrum received packets like this:</p>
            <pre><code> +---------------------+------------------------------------------------+
 +  IPv6 + UDP header  |  UDP payload encapsulating a 1280 byte packet  |
 +---------------------+------------------------------------------------+</code></pre>
            <p>It's pretty obvious, that our edge servers supporting IPv6 packets of max 1280 bytes won't be able to handle this type of traffic. We are going to need at least 1280+40+8 bytes MTU! Hardcoding MTU=1280 in IPv6 may be acceptable solution if you are an end-node on the internet, but is definitely too small when forwarding tunneled traffic.</p>
    <div>
      <h3>Picking a new MTU</h3>
      <a href="#picking-a-new-mtu">
        
      </a>
    </div>
    <p>But what MTU value should we use instead? Let's see what other major internet companies do. Here is a couple of examples of advertised MSS values in TCP SYN+ACK packets over IPv6:</p>
            <pre><code>+---- site -----+- MSS --+- estimated MTU -+
| google.com    |  1360  |    1420         |
+---------------+--------+-----------------+
| facebook.com  |  1410  |    1470         |
+---------------+--------+-----------------+
| wikipedia.org |  1440  |    1500         |
+---------------+--------+-----------------+</code></pre>
            <p>I believe Google and Facebook adjust their MTU due to their use of L4 load balancers. Their implementations do IP-in-IP encapsulation so need a bit of space for the header. Read more:</p><ul><li><p>Google - <a href="https://ai.google/research/pubs/pub44824">Maglev</a></p></li><li><p>Facebook - <a href="https://code.fb.com/open-source/open-sourcing-katran-a-scalable-network-load-balancer/">Katran</a></p></li></ul><p>There may be other reasons for having a smaller MTU. A reduced value may decrease the probability of the Path MTU detection algorithm kicking in (ie: relying on ICMP PTB). We can theorize that for the misconfigured eyeballs:</p><ul><li><p>MTU=1280 will never run Path MTU detection</p></li><li><p>MTU=1500 will always run it.</p></li><li><p>In-between values would have increasing different chances of hitting the problem.</p></li></ul><p>But just what is the chance of that?</p><p>A quick unscientific study of the MSS values we encountered from eyeballs shows the following distributions. For connections going over IPv4:</p>
            <pre><code>IPv4 eyeball advertised MSS in SYN:
 value |-------------------------------------------------- count cummulative
  1300 |                                                 *  1.28%   98.53%
  1360 |                                              ****  4.40%   95.68%
  1370 |                                                 *  1.15%   91.05%
  1380 |                                               ***  3.35%   89.81%
  1400 |                                          ********  7.95%   84.79%
  1410 |                                                 *  1.17%   76.66%
  1412 |                                              ****  4.58%   75.49%
  1440 |                                            ******  6.14%   65.71%
  1452 |                                      ************ 11.50%   58.94%
  1460 |************************************************** 47.09%   47.34%</code></pre>
            <p>Assuming the majority of clients have MSS configured right, we can say that 89.8% of connections advertised MTU=1380+40=1420 or higher. 75% had MTU &gt;= 1452.</p><p>For IPv6 connections we saw:</p>
            <pre><code>IPv6 eyeball advertised MSS in SYN:
 value |-------------------------------------------------- count cummulative
  1220 |                                               ***  4.21%   99.96%
  1340 |                                                **  3.11%   93.23%
  1362 |                                                 *  1.31%   87.70%
  1368 |                                               ***  3.38%   86.36%
  1370 |                                               ***  4.24%   82.98%
  1380 |                                               ***  3.52%   78.65%
  1390 |                                                 *  2.11%   75.10%
  1400 |                                               ***  3.89%   72.25%
  1412 |                                               ***  3.64%   68.21%
  1420 |                                                 *  2.02%   64.54%
  1440 |************************************************** 54.31%   54.34%</code></pre>
            <p>On IPv6 87.7% connections had MTU &gt;= 1422 (1362+60). 75% had MTU &gt;= 1450. (See also: <a href="https://blog.apnic.net/2016/05/19/fragmenting-ipv6/">MTU distribution of DNS  servers</a>).</p>
    <div>
      <h3>Interpretation</h3>
      <a href="#interpretation">
        
      </a>
    </div>
    <p>Before we move on it's worth reiterating the original problem. Each connection from an eyeball to our Anycast network has three numbers related to it:</p><ul><li><p>Client advertised MTU - seen in MSS option in TCP header</p></li><li><p>True Path MTU value - generally unknown until measured</p></li><li><p>Our Edge server MTU - value we are trying to optimize in this exercise</p></li></ul><p>(This is a slight simplification, paths on the internet aren't symmetric so the path from eyeball to Cloudflare could have different Path MTU than the reverse path.)</p><p>In order for the connection to misbehave, three conditions must be met:</p><ul><li><p>Client advertised MTU must be "wrong", that is: larger than True Path MTU</p></li><li><p>Our edge server must be willing to send such large packets: Edge server MTU &gt;= True Path MTU</p></li><li><p>The ICMP PTB messages must fail to be delivered to our edge server - preventing Path MTU detection from working.</p></li></ul><p>The last condition could occur for one of the reasons:</p><ul><li><p>the routers on the path are misbehaving and perhaps firewalling ICMP</p></li><li><p>due to the asymmetric nature of the internet the ICMP back is routed to the wrong Anycast datacenter</p></li><li><p>something is wrong on our side, for example <code>pmtud</code> process fails</p></li></ul><p>In the past we limited our Edge Server MTU value to the smallest possible, to make sure we never encounter the problem. Due to the development of Spectrum UDP support we must increase the Edge Server MTU, while still minimizing the probability of the issue happening.</p><p>Finally, relying on ICMP PTB messages for a large fraction of traffic is a bad idea. It's easy to imagine the cost this induces: even with Path MTU detection working fine, the affected connection will suffer a hiccup. A couple of large packets will be dropped before the reverse ICMP will get through and reconfigure the saved Path MTU value. This is not optimal for latency.</p>
    <div>
      <h3>Progress</h3>
      <a href="#progress">
        
      </a>
    </div>
    <p>In recent days we increased the IPv6 MTU. As part of the process we could have chosen 1300, 1350, or 1400. We choose 1400 because we think it's the next best value to use after 1280. With 1400 we believe 93.2% of IPv6 connections will not need to rely on Path MTU Detection/ICMP. In the near future we plan to increase this value further. We won't settle on 1500 though - we want to leave a couple of bytes for IPv4 encapsulation, to allow the most popular tunnels to keep working without suffering poor latency when Path MTU Detection kicks in.</p><p>Since the rollout we've been monitoring <code>Icmp6InPktTooBigs</code> counters:</p>
            <pre><code>$ nstat -az | grep Icmp6InPktTooBigs
Icmp6InPktTooBigs               738748             0.0</code></pre>
            <p>Here is a chart of the ICMP PTB packets we received over last 7 days. You can clearly see that when the rollout started, we saw a large increase in PTB ICMP messages (Y label - packet count - deliberately obfuscated):</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/64aFjrP5OwJLKlbMfwIofg/abc284d8d6f8b2b0c7441277cfea12cc/Screen-Shot-2018-09-06-at-2.12.28-PM.png" />
            
            </figure><p>Interestingly the majority of the ICMP packets are concentrated in our Frankfurt datacenter:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7rwp7vqya4hZUVtqgALCo0/70c29ca328859bd7330a9399305d7d79/Screen-Shot-2018-09-06-at-2.11.53-PM.png" />
            
            </figure><p>We estimate that in our Frankfurt datacenter, we receive ICMP PTB message on 2 out of every 100 IPv6 TCP connections. These seem to come from only a handful of ASNs:</p><ul><li><p>AS6830 - Liberty Global Operations B.V.</p></li><li><p>AS20825- Unitymedia NRW GmbH</p></li><li><p>AS31334 - Vodafone Kabel Deutschland GmbH</p></li><li><p>AS29562 - Kabel BW GmbH</p></li></ul><p>These networks send to us ICMP PTB messages, usually informing that their MTU is 1280. For example:</p>
            <pre><code>$ sudo tcpdump -tvvvni eth0 icmp6 and ip6[40+0]==2 
IP6 2a02:908:xxx &gt; 2400:xxx ICMP6, packet too big, mtu 1280, length 1240
IP6 2a02:810d:xx &gt; 2400:xxx ICMP6, packet too big, mtu 1280, length 1240
IP6 2001:ac8:xxx &gt; 2400:xxx ICMP6, packet too big, mtu 1390, length 1240</code></pre>
            
    <div>
      <h3>Final thoughts</h3>
      <a href="#final-thoughts">
        
      </a>
    </div>
    <p>Finally, if you are an IPv6 user with a weird MTU and have misconfigured MSS - basically if you are doing tunneling - please let us know of any issues. We know that debugging MTU issues is notoriously hard. To aid that we created <a href="/ip-fragmentation-is-broken/">an online fragmentation and ICMP delivery test</a>. You can run it:</p><ul><li><p>IPv6 version: <a href="http://icmpcheckv6.popcount.org">http://icmpcheckv6.popcount.org</a></p></li><li><p>(for completeness, we also have an <a href="http://icmpcheck.popcount.org">IPv4 version</a>)</p></li></ul><p>If you are a server operator running IPv6 applications, you should not worry. In most cases leaving the MTU at default 1500 is a good choice and should work for the majority of connections.  Just remember to allow ICMP PTB packets on the firewall and you should be good. If you serve variety of IPv6 users and need to optimize latency, you may consider choosing a slightly smaller MTU for outbound packets, to reduce the risk of relying on Path MTU Detection / ICMP.</p><p><i>Low level network tuning sound interesting? Join our </i><a href="https://boards.greenhouse.io/cloudflare/jobs/589572"><i>world famous team</i></a><i> in London, Austin, San Francisco, Champaign and our elite office in Warsaw, Poland.</i></p> ]]></content:encoded>
            <category><![CDATA[IPv6]]></category>
            <category><![CDATA[DNS]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[Security]]></category>
            <category><![CDATA[Anycast]]></category>
            <category><![CDATA[Load Balancing]]></category>
            <guid isPermaLink="false">4jilwfKi5MVWxnIA3ErwZ8</guid>
            <dc:creator>Marek Majkowski</dc:creator>
        </item>
        <item>
            <title><![CDATA[Protection from Struts Remote Code Execution Vulnerability (S2-057)]]></title>
            <link>https://blog.cloudflare.com/apache-struts-s2-057/</link>
            <pubDate>Wed, 05 Sep 2018 14:58:32 GMT</pubDate>
            <description><![CDATA[ On August 22 a new vulnerability in the Apache Struts framework was announced. We quickly deployed a mitigation to protect customers. ]]></description>
            <content:encoded><![CDATA[ <p>On August 22 a new vulnerability in the Apache Struts framework was <a href="https://cwiki.apache.org/confluence/display/WW/S2-057">announced.</a> It allows unauthenticated attackers to perform Remote Code Execution (RCE) on vulnerable hosts.</p><p>As security researcher Man Yue Mo <a href="https://lgtm.com/blog/apache_struts_CVE-2018-11776">explained</a>, the vulnerability has similarities with previous Apache Struts vulnerabilities. The Cloudflare WAF already mitigated these so adjusting our rules to handle the new vulnerability was simple. Within hours of the disclosure we deployed a mitigation with no customer action required.</p>
    <div>
      <h3>OGNL, again</h3>
      <a href="#ognl-again">
        
      </a>
    </div>
    <p>Apache Struts RCE payloads often come in the form of Object-Graph Navigation Library (OGNL) expressions. OGNL is a language for interacting with the properties and functions of Java classes and Apache Struts supports it in many contexts.</p><p>For example, the snippet below uses OGNL to dynamically insert the value "5" into a webpage by calling a function.</p>
            <pre><code>&lt;s:property value="%{getSum(2,3)}" /&gt;</code></pre>
            <p>OGNL expressions can also be used for more general code execution:</p>
            <pre><code>${
    #_memberAccess["allowStaticMethodAccess"]=true,
    @java.lang.Runtime@getRuntime().exec('calc')
}</code></pre>
            <p>Which means if you can find a way to make Apache Struts execute a user supplied OGNL expression, you've found an RCE vulnerability. Security researchers have found a significant number of vulnerabilities where this was the root cause.</p>
    <div>
      <h3>What’s different this time?</h3>
      <a href="#whats-different-this-time">
        
      </a>
    </div>
    <p>The major difference between the various OGNL related Struts vulnerabilities is where the payload can be supplied.</p><p>For example <a href="https://cwiki.apache.org/confluence/display/WW/S2-003">S2-003</a>, <a href="https://cwiki.apache.org/confluence/display/WW/S2-005">S2-005</a> and <a href="https://cwiki.apache.org/confluence/display/WW/S2-009">S2-009</a> allowed OGNL expressions to be included in HTTP Parameters. In <a href="https://cwiki.apache.org/confluence/display/WW/S2-045">S2-045</a>, expressions could be supplied via the ‘Content-Type’ header.  And <a href="https://cwiki.apache.org/confluence/display/WW/S2-048">S2-048</a> worked by inserting OGNL expressions anywhere they might be used incorrectly with the ActionMessage class (most likely via an HTTP parameter).</p><p>With <a href="https://cwiki.apache.org/confluence/display/WW/S2-057">S2-057</a>, the payload is supplied via an action’s “namespace”. Semmel do a great job of explaining the exact conditions for this in their disclosure <a href="https://semmle.com/news/apache-struts-CVE-2018-11776">post</a>.</p><p>An example is to omit the "namespace" parameter from the  redirectAction result type.</p>
            <pre><code>&lt;package name="public" extends="struts-default"&gt;
    &lt;action name="login" class="..."&gt;
        &lt;!-- Redirect to another namespace --&gt;
        &lt;result type="redirectAction"&gt;
            &lt;param name="actionName"&gt;dashboard&lt;/param&gt;
            &lt;!-- namespace is omitted --&gt;
            &lt;!--&lt;param name="namespace"&gt;/secure&lt;/param&gt;--&gt;
        &lt;/result&gt;
    &lt;/action&gt;
&lt;/package&gt;</code></pre>
            <p>The documentation describes this parameter as optional. If you don't include an explicit "namespace" then the client can supply it in the URI.</p>
            <pre><code>vulnerablesite.com/struts2-blank/my-current-name-space/HelloWorld.action</code></pre>
            <p>If the client inserts an OGNL expression instead, it will be executed.</p>
            <pre><code>vulnerablesite.com/struts2-blank/${#_memberAccess["allowStaticMethodAccess"]=true,@java.lang.Runtime@getRuntime().exec('calc')}/HelloWorld.action</code></pre>
            
    <div>
      <h3>Cloudflare’s got your covered</h3>
      <a href="#cloudflares-got-your-covered">
        
      </a>
    </div>
    <p>Cloudflare has rules to protect against this particular vulnerability, and many other Struts vulnerabilities. These have been configured as Block by default, so no customer action is needed, assuming the Cloudflare Specials rule set is enabled in your WAF configuration.</p><p>For customers on our Pro, Business and Enterprise plans, you can do this by going to the “Firewall” tab:</p><p>Clicking “Web Application Firewall” and setting the toggle to “On”:</p><p>Then finally ensuring the “Cloudflare Specials” rule set is set to “On” as well:</p><p>Where possible, we signature OGNL expressions in general, because of how dangerous it is for a server to trust any user-supplied OGNL. This allows the WAF to protect you without detailed knowledge of how specific exploits might work.</p><p>Additionally, for this and other Struts vulnerabilities, we produce rules that target specific locations where payloads can be supplied in (e.g. URI, parameters, etc). By focusing on specific payload vectors these rules can be much stricter in the range of inputs allowed, without the risk of increased false positives.</p>
    <div>
      <h3>What we've seen in the last 24h</h3>
      <a href="#what-weve-seen-in-the-last-24h">
        
      </a>
    </div>
    <p>Since the disclosure, we've seen a fairly constant rate of attacks targeting S2-057 vulnerability:</p><p>About half of these are coming from known vulnerability scanners, however our research has shown that the vast majority of payloads are only probing, rather than attempting to execute malicious actions. The most common tactics for that are using the OGNL expression print extra strings in the server response, or append extra headers.</p><p>Aside from that, our Research team have also seen attempts to run various commands:</p><ul><li><p>Ipconfig.exe</p></li><li><p>dir</p></li><li><p>'cat /etc/passwd'</p></li><li><p>/sbin/ifconfig</p></li><li><p>net users</p></li><li><p>file /etc/passwd</p></li><li><p>Whoami</p></li><li><p>id</p></li><li><p>Ping and nslookup commands to contact external servers</p></li></ul><p>If you have any further questions about how our WAF works, or whether you have the right protections in place, please don’t hesitate to reach out to our Support teams.</p> ]]></content:encoded>
            <category><![CDATA[Attacks]]></category>
            <category><![CDATA[Vulnerabilities]]></category>
            <category><![CDATA[Reliability]]></category>
            <guid isPermaLink="false">62KfwHf41FynGZIUD4Fads</guid>
            <dc:creator>Richard Sommerville</dc:creator>
        </item>
        <item>
            <title><![CDATA[Additional Record Types Available with Cloudflare DNS]]></title>
            <link>https://blog.cloudflare.com/additional-record-types-available-with-cloudflare-dns/</link>
            <pubDate>Mon, 06 Aug 2018 16:45:17 GMT</pubDate>
            <description><![CDATA[ Cloudflare recently updated the authoritative DNS service to support nine new record types. Since these records are less commonly used than what we previously supported, we thought it would be a good idea to do a brief explanation of each record type and how it is used. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Photo by <a href="https://unsplash.com/@minkmingle?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit">Mink Mingle</a> / <a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit">Unsplash</a></p><p>Cloudflare recently updated the authoritative DNS service to support nine new record types. Since these records are less commonly used than what we previously supported, we thought it would be a good idea to do a brief explanation of each record type and how it is used.</p>
    <div>
      <h3>DNSKEY and DS</h3>
      <a href="#dnskey-and-ds">
        
      </a>
    </div>
    <p>DNSKEY and DS work together to allow you to enable DNSSEC on a child zone (subdomain) that you have delegated to another Nameserver. DS is useful if you are delegating DNS (through an NS record) for a child to a separate system and want to keep using DNSSEC for that child zone; without a DS entry in the parent, the child data will not be validated. We’ve blogged about the details of <a href="/introducing-universal-dnssec/">Cloudflare’s DNSSEC</a> <a href="/tag/dnssec/">implementation</a> and <a href="/bgp-leaks-and-crypto-currencies/">why it is important</a> in the past, and this new feature allows for more flexible adoption for customers who need to delegate subdomains.</p>
    <div>
      <h3>Certificate Related Record Types</h3>
      <a href="#certificate-related-record-types">
        
      </a>
    </div>
    <p>Today, there is no way to restrict which <a href="https://www.cloudflare.com/application-services/products/ssl/">TLS (SSL) certificates</a> are trusted to be served for a host. For example if an attacker were able to maliciously generate an SSL certificate for a host, they could use a on-path attacker attack to appear as the original site. With SSHFP, TLSA, SMIMEA, and CERT, a website owner can configure the exact certificate public key that is allowed to be used on the domain, stored inside the DNS and secured with DNSSEC, reducing the risk of these kinds of attacks working.</p><p><b>It is critically important that if you rely on these types of records that you enable and configure DNSSEC for your domain.</b></p>
    <div>
      <h4><a href="https://tools.ietf.org/html/rfc4255">SSHFP</a></h4>
      <a href="#">
        
      </a>
    </div>
    <p>This type of record is an answer to the question “When I’m connecting via SSH to this remote machine, it’s authenticating me, but how do I authenticate it?” If you’re the only person connecting to this machine, your <a href="https://www.cloudflare.com/learning/access-management/what-is-ssh/">SSH client</a> will compare the fingerprint of the public host key to the one it kept in the known_hosts file during the first connection. However across multiple machines or multiple users from an organization, you need to verify this information against a common source of trust. In essence, you need the equivalent of the authentication that a certificate authority provides by signing an HTTPS certificate, but for SSH. Although it’s possible to set certificate authorities for SSH and to have them sign public host keys, another way is to publish the fingerprint of the keys in the domain via the SSHFP record type.</p><p><b>Again, for these fingerprints to be trustworthy it is important to enable DNSSEC on your zone.</b></p><p>The SSHFP record type is similar to TLSA record. You are specifying the algorithm type, the signature type, and then the signature itself within the record for a given hostname.</p><p>If the domain and remote server have SSHFP set and you are running an SSH client (such as <a href="https://www.openbsd.org/openssh/txt/release-5.1">OpenSSH 5.1+</a>) that supports it, you can now verify the remote machine upon connection by adding the following parameters to your connection:</p><p><code>❯ ssh -o "VerifyHostKeyDNS=yes" -o "StrictHostKeyChecking=yes" [insertremoteserverhere]</code></p>
    <div>
      <h4>TLSA and SMIMEA</h4>
      <a href="#tlsa-and-smimea">
        
      </a>
    </div>
    <p>TLSA records were designed to specify which keys are allowed to be used for a given domain when connecting via TLS. They were introduced in the <a href="https://tools.ietf.org/html/rfc6698">DANE</a> specification and allow domain owners to announce which certificate can and should be used for specific purposes for the domain. While most major browsers do not support TLSA, it may still be valuable for non browser specific applications and services.</p><p>For example, I’ve set a TLSA record for the domain hasvickygoneonholiday.com for TCP traffic over port 443. There are a number of ways to generate the record, but the easiest is likely through <a href="https://www.huque.com/bin/gen_tlsa">Shumon Huque’s tool</a>.</p><p>For most of the examples in this post we will be using <a href="https://www.knot-dns.cz/docs/2.6/html/man_kdig.html">kdig</a> rather than the ubiquitous dig. Generally preinstalled dig versions can be old and may not handle newer record types well. If your queries do not quite match up, you should either upgrade your version of dig or install knot.</p>
            <pre><code>;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY; status: NOERROR; id: 2218
;; Flags: qr rd ra ad; QUERY: 1; ANSWER: 2; AUTHORITY: 0; ADDITIONAL: 1

;; QUESTION SECTION:
;; _443._tcp.hasvickygoneonholiday.com. 	IN	TLSA

;; ANSWER SECTION:
_443._tcp.hasvickygoneonholiday.com. 300	IN	TLSA	3 1 1 4E48ED671DFCDF6CBF55E52DBC8B9C9CC21121BD149BC24849D1398DA56FB242
_443._tcp.hasvickygoneonholiday.com. 300	IN	RRSIG	TLSA 13 4 300 20180803233834 20180801213834 35273 hasvickygoneonholiday.com. JvC9mZLfuAyEHZUZdq4n8kyRbF09vwgx4c1fas24Ag925LILr1armjHbr7ZTp8ycS/Go3y3lgyYCuBeW/vT/3w==

;; Received 232 B
;; Time 2018-08-02 15:38:34 PDT
;; From 192.168.1.1@53(UDP) in 28.5 ms</code></pre>
            <p>From the above request and response, we can see that a) the response for the zone is secured and signed with DNSSEC (Flag: <i><b>ad</b></i>) and that I should be verifying a certificate with the public key (3 <i><b>1</b></i> 1) SHA256 hash (3 1 <i><b>1</b></i>) of 4E48ED671DFCDF6CBF55E52DBC8B9C9CC21121BD149BC24849D1398DA56FB242. We can use openssl (v1.1.x or higher) to verify the results:</p>
            <pre><code>❯ openssl s_client  -connect hasvickygoneonholiday.com:443 -dane_tlsa_domain "hasvickygoneonholiday.com" -dane_tlsa_rrdata "
3 1 1 4e48ed671dfcdf6cbf55e52dbc8b9c9cc21121bd149bc24849d1398da56fb242"
CONNECTED(00000003)
depth=0 C = US, ST = CA, L = San Francisco, O = "CloudFlare, Inc.", CN = hasvickygoneonholiday.com
verify return:1
---
Certificate chain
 0 s:/C=US/ST=CA/L=San Francisco/O=CloudFlare, Inc./CN=hasvickygoneonholiday.com
   i:/C=US/ST=CA/L=San Francisco/O=CloudFlare, Inc./CN=CloudFlare Inc ECC CA-2
 1 s:/C=US/ST=CA/L=San Francisco/O=CloudFlare, Inc./CN=CloudFlare Inc ECC CA-2
   i:/C=IE/O=Baltimore/OU=CyberTrust/CN=Baltimore CyberTrust Root
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIE7jCCBJSgAwIBAgIQB9z9WxnovNf/lt2Lkrfq+DAKBggqhkjOPQQDAjBvMQsw
...
---
SSL handshake has read 2666 bytes and written 295 bytes
Verification: OK
Verified peername: hasvickygoneonholiday.com
DANE TLSA 3 1 1 ...149bc24849d1398da56fb242 matched EE certificate at depth 0</code></pre>
            <p><a href="https://tools.ietf.org/html/rfc8162">SMIMEA</a> records function similar to TLSA but are specific to email addresses. The domain for these records should be prefixed by “_smimecert.” and specific formatting is required to attach a SMIMEA record to an email address. The local-part (username) of the email address must be treated in a specific format and SHA-256 hashed as detailed in the RFC. From the RFC example: “ For example, to request an SMIMEA resource record for a user whose email address is "<a>hugh@example.com</a>", an SMIMEA query would be placed for the following QNAME: <code>c93f1e400f26708f98cb19d936620da35eec8f72e57f9eec01c1afd6._smimecert.example.com</code></p>
    <div>
      <h4><a href="https://tools.ietf.org/html/rfc4398">CERT</a></h4>
      <a href="#">
        
      </a>
    </div>
    <p>CERT records are used for generically storing certificates within DNS and are most commonly used by systems for email encryption. To create a CERT record, you must specify the certificate type, the key tag, the algorithm, and then the certificate, which is either the certificate itself, the CRL, a URL of the certificate, or fingerprint and a URL.</p>
    <div>
      <h3>Other Newly Supported Record Types</h3>
      <a href="#other-newly-supported-record-types">
        
      </a>
    </div>
    
    <div>
      <h4>PTR</h4>
      <a href="#ptr">
        
      </a>
    </div>
    <p>PTR (Pointer) records are pointers to canonical names. They are similar to CNAME in structure, meaning they only contain one FQDN (fully qualified domain name) but the RFC dictates that subsequent lookups are not done for PTR records, the value should just be returned back to the requestor. This is different to a CNAME where a recursive resolver would follow the target of the canonical name. The most common use of a PTR record is in reverse DNS, where you can look up which domains are meant to exist at a given IP address. These are useful for outbound mailservers as well as authoritative DNS servers.</p><p>It is only possible to delegate the authority for IP addresses that you own from your Regional Internet Registry (RIR). Creating reverse zones and PTR records for IPs that you can not (or do not) delegate does not serve any practical purpose.</p><p>For example, looking up the A record for marek.ns.cloudflare.com gives us the IP of 173.245.59.202.</p>
            <pre><code>❯ kdig a marek.ns.cloudflare.com +short
173.245.59.202</code></pre>
            <p>Now imagine we want to know if the owner of this IP ‘authorizes’ <code>marek.ns.cloudflare.com</code> to point to it. Reverse Zones are specifically crafted child zones within <code>in-addr.arpa.</code> (for IPv4) and <code>ip6.arpa.</code> (for IPv6) whom are delegated via the Regional Internet Registries to the owners of the IP address space. That is to say if you own a /24 from ARIN, ARIN will delegate the reverse zone space for your /24 to you to control. The IPv4 address is represented inverted as the subdomain in in-addr.arpa. Since Cloudflare owns the IP, we’ve delegated the reverse zone and created a PTR there.</p>
            <pre><code>❯ kdig -x 173.245.59.202
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY; status: NOERROR; id: 18658
;; Flags: qr rd ra; QUERY: 1; ANSWER: 1; AUTHORITY: 0; ADDITIONAL: 0

;; QUESTION SECTION:
;; 202.59.245.173.in-addr.arpa.		IN	PTR

;; ANSWER SECTION:
202.59.245.173.in-addr.arpa.	1222	IN	PTR	marek.ns.cloudflare.com.</code></pre>
            <p>For completeness, here is the +trace for the 202.59.245.173.in-addr.arpa zone. We can see that the /24 59.245.173.in-addr.arpa has been delegated to Cloudflare from ARIN:</p>
            <pre><code>❯ dig 202.59.245.173.in-addr.arpa +trace

; &lt;&lt;&gt;&gt; DiG 9.8.3-P1 &lt;&lt;&gt;&gt; 202.59.245.173.in-addr.arpa +trace
;; global options: +cmd
.			48419	IN	NS	a.root-servers.net.
.			48419	IN	NS	b.root-servers.net.
.			48419	IN	NS	c.root-servers.net.
.			48419	IN	NS	d.root-servers.net.
.			48419	IN	NS	e.root-servers.net.
.			48419	IN	NS	f.root-servers.net.
.			48419	IN	NS	g.root-servers.net.
.			48419	IN	NS	h.root-servers.net.
.			48419	IN	NS	i.root-servers.net.
.			48419	IN	NS	j.root-servers.net.
.			48419	IN	NS	k.root-servers.net.
.			48419	IN	NS	l.root-servers.net.
.			48419	IN	NS	m.root-servers.net.
;; Received 228 bytes from 2001:4860:4860::8888#53(2001:4860:4860::8888) in 25 ms

in-addr.arpa.		172800	IN	NS	e.in-addr-servers.arpa.
in-addr.arpa.		172800	IN	NS	d.in-addr-servers.arpa.
in-addr.arpa.		172800	IN	NS	b.in-addr-servers.arpa.
in-addr.arpa.		172800	IN	NS	f.in-addr-servers.arpa.
in-addr.arpa.		172800	IN	NS	c.in-addr-servers.arpa.
in-addr.arpa.		172800	IN	NS	a.in-addr-servers.arpa.
;; Received 421 bytes from 192.36.148.17#53(192.36.148.17) in 8 ms

173.in-addr.arpa.	86400	IN	NS	u.arin.net.
173.in-addr.arpa.	86400	IN	NS	arin.authdns.ripe.net.
173.in-addr.arpa.	86400	IN	NS	z.arin.net.
173.in-addr.arpa.	86400	IN	NS	r.arin.net.
173.in-addr.arpa.	86400	IN	NS	x.arin.net.
173.in-addr.arpa.	86400	IN	NS	y.arin.net.
;; Received 165 bytes from 199.180.182.53#53(199.180.182.53) in 300 ms

59.245.173.in-addr.arpa. 86400	IN	NS	ns1.cloudflare.com.
59.245.173.in-addr.arpa. 86400	IN	NS	ns2.cloudflare.com.
;; Received 95 bytes from 2001:500:13::63#53(2001:500:13::63) in 188 ms</code></pre>
            
    <div>
      <h4><a href="https://tools.ietf.org/html/rfc2915">NAPTR</a></h4>
      <a href="#">
        
      </a>
    </div>
    <p>Naming Authority Pointer Records are used in conjunction with SRV records, generally as a part of the SIP protocol. NAPTR records point to domains to specific services, if available for that domain. <a href="http://twitter.com/anders94">Anders Brownworth</a> has an excellent description in detail on his <a href="https://anders.com/cms/264/">blog</a>. The start of his example, with his permission:</p><blockquote><p>Let’s consider a call to <a>2125551212@example.com</a>. Given only this address though, we don't know what IP address, port or protocol to send this call to. We don't even know if example.com supports SIP or some other VoIP protocol like H.323 or IAX2. I'm implying that we're interested in placing a call to this URL but if no VoIP service is supported, we could just as easily fall back to emailing this user instead. To find out, we start with a NAPTR record lookup for the domain we were given:</p></blockquote>
            <pre><code>#host -t NAPTR example.com
example.com NAPTR 10 100 "S" "SIP+D2U" "" _sip._udp.example.com.
example.com NAPTR 20 100 "S" "SIP+D2T" "" _sip._tcp.example.com.
example.com NAPTR 30 100 "S" "E2U+email" "!^.*$!mailto:info@example.com!i" _sip._tcp.example.com.</code></pre>
            <blockquote><p>Here we find that example.com gives us three ways to contact example.com, the first of which is "SIP+D2U" which would imply SIP over UDP at _sip._udp.example.com.</p></blockquote>
    <div>
      <h4><a href="https://tools.ietf.org/html/rfc7553">URI</a></h4>
      <a href="#">
        
      </a>
    </div>
    <p>Uniform Resource Identifier records are commonly used as a compliment to NAPTR records and per the RFC, can be used to replace SRV records. As such, they contain a Weight and Priority field as well as Target, similar to SRV.</p><p>One use case is proposed by this <a href="https://tools.ietf.org/html/draft-mccallum-kitten-krb-service-discovery-03">draft RFC</a> is to replace SRV records with URI records for discovering Kerberos key distribution centers (KDC). It minimizes the number of requests over SRV records and allows the domain owner to specify preference for TCP or UDP.</p><p>In the below example, it specifies that we should use a KDC on TCP at the default port and UDP on port 89 should the primary connection fail.</p>
            <pre><code>❯ kdig URI _kerberos.hasvickygoneonholiday.com
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY; status: NOERROR; id: 8450
;; Flags: qr rd ra; QUERY: 1; ANSWER: 2; AUTHORITY: 0; ADDITIONAL: 0

;; QUESTION SECTION:
;; _kerberos.hasvickygoneonholiday.com. 	IN	URI

;; ANSWER SECTION:
_kerberos.hasvickygoneonholiday.com. 283	IN	URI	1 10 "krb5srv:m:tcp:kdc.hasbickygoneonholiday.com"
_kerberos.hasvickygoneonholiday.com. 283	IN	URI	1 20 "krb5srv:m:udp:kdc.hasbickygoneonholiday.com:89"</code></pre>
            
    <div>
      <h3>Summary</h3>
      <a href="#summary">
        
      </a>
    </div>
    <p>Cloudflare now supports CERT, DNSKEY, DS, NAPTR, PTR, SMIMEA, SSHFP, and TLSA in our authoritative DNS products. We would love to hear if you have any interesting example use cases for the new record types and what other record types we should support in the future.</p><p>Our DNS engineering teams in London and San Francisco are both hiring if you would like to contribute to the fastest authoritative and recursive DNS services in the world.</p><p><a href="https://boards.greenhouse.io/cloudflare/jobs/1213352?gh_jid=1213352">Software Engineer</a></p> ]]></content:encoded>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[Speed & Reliability]]></category>
            <category><![CDATA[DNS]]></category>
            <category><![CDATA[DNSSEC]]></category>
            <category><![CDATA[Product News]]></category>
            <guid isPermaLink="false">4hEsGfxkUT0Q2b2B53HPel</guid>
            <dc:creator>Sergi Isasi</dc:creator>
            <dc:creator>Etienne Labaume</dc:creator>
        </item>
    </channel>
</rss>