
<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>Thu, 09 Apr 2026 08:13:10 GMT</lastBuildDate>
        <item>
            <title><![CDATA[Finding the grain of sand in a heap of Salt]]></title>
            <link>https://blog.cloudflare.com/finding-the-grain-of-sand-in-a-heap-of-salt/</link>
            <pubDate>Thu, 13 Nov 2025 14:00:00 GMT</pubDate>
            <description><![CDATA[ We explore the fundamentals of Saltstack and how we use it at Cloudflare. We also explain how we built the infrastructure to reduce release delays due to Salt failures on the edge by over 5%.  ]]></description>
            <content:encoded><![CDATA[ <p>How do you find the root cause of a configuration management failure when you have a peak of hundreds of changes in 15 minutes on thousands of servers?</p><p>That was the challenge we faced as we built the infrastructure to reduce release delays due to failures of Salt, a configuration management tool. (We eventually reduced such failures on the edge by over 5%, as we’ll explain below.) We’ll explore the fundamentals of Salt, and how it is used at Cloudflare. We then describe the common failure modes and how they delay our ability to release valuable changes to serve our customers.</p><p>By first solving an architectural problem, we provided the foundation for self-service mechanisms to find the root cause of Salt failures on servers, datacenters and groups of datacenters. This system is able to correlate failures with git commits, external service failures and ad hoc releases. The result of this has been a reduction in the duration of software release delays, and an overall reduction in toilsome, repetitive triage for SRE.</p><p>To start, we will go into the basics of the Cloudflare network and how Salt operates within it. And then we’ll get to how we solved the challenge akin to finding a grain of sand in a heap of Salt.</p>
    <div>
      <h3>How Salt works</h3>
      <a href="#how-salt-works">
        
      </a>
    </div>
    <p>Configuration management (CM) ensures that a system corresponds to its configuration information, and maintains the integrity and traceability of that information over time. A good configuration management system ensures that a system does not “drift” – i.e. deviate from the desired state. Modern CM systems include detailed descriptions of infrastructure, version control for these descriptions, and other mechanisms to enforce the desired state across different environments. Without CM, administrators must manually configure systems, a process that is error-prone and difficult to reproduce.</p><p><a href="https://docs.saltproject.io/en/latest/topics/tutorials/walkthrough.html"><u>Salt</u></a> is an example of such a CM tool. Designed for high-speed remote execution and configuration management, it uses a simple, scalable model to manage large fleets. As a mature CM tool, it provides consistency, reproducibility, change control, auditability and collaboration across team and organisational boundaries.</p><p>Salt’s design revolves around a <b>master</b>/<b>minion</b> architecture, a message bus built on ZeroMQ, and a declarative state system. (At Cloudflare we generally avoid the terms "master" and "minion." But we will use them here because that's how Salt describes its architecture.) The <b>salt master</b> is a central controller that distributes jobs and configuration data. It listens for requests on the message bus and dispatches commands to targeted minions. It also stores state files, pillar data and cache files. The <b>salt minion </b>is a lightweight agent installed on each managed host/server. Each minion maintains a connection to the master via ZeroMQ and subscribes to published jobs. When a job matches the minion, it executes the requested function and returns results.</p><p>The diagram below shows a simplification of the Salt architecture described <a href="https://docs.saltproject.io/en/3006/topics/salt_system_architecture.html"><u>in the docs</u></a>, for the purpose of this blog post.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/19pmijzWlmIf3ACxW5M4hF/1c2ff0aab6afd76d1bc2286953ef509b/image5.png" />
          </figure><p>The <b>state system</b> provides declarative configuration management. States are often written in YAML and describe a resource (package, file, service, user, etc.) and the desired attributes. A common example is a package state, which ensures that a package is installed at a specified version.</p>
            <pre><code># /srv/salt/webserver/init.sls
include:
  - common

nginx:
  pkg.installed: []

/etc/nginx/nginx.conf:
  file.managed:
    - source: salt://webserver/files/nginx.conf
    - require:
      - pkg: nginx</code></pre>
            <p>States can call <b>execution modules</b>, which are Python functions that implement system actions. When applying states, Salt returns a structured result containing whether the state succeeded (<code>result: True/False</code>), a comment, changes made, and duration.</p>
    <div>
      <h3>Salt at Cloudflare</h3>
      <a href="#salt-at-cloudflare">
        
      </a>
    </div>
    <p>We use Salt to manage our ever-growing fleet of machines, and have previously written about our <a href="https://blog.cloudflare.com/tag/salt/"><u>extensive usage</u></a>. The master-minion architecture described above allows us to push configuration in the form of states to thousands of servers, which is essential for maintaining our network. We’ve designed our change propagation to involve blast radius protection. With these protections in place, a <a href="https://docs.saltproject.io/en/3006/ref/states/highstate.html"><u>highstate</u></a> failure becomes a signal, rather than a customer-impacting event.</p><p>This release design was intentional – we decided to “fail safe” instead of failing hard. By <a href="https://blog.cloudflare.com/safe-change-at-any-scale/"><u>further adding guardrails</u></a> to safely release new code before a feature reaches all users, we are able to propagate a change with confidence that failures will halt the Salt deployment pipeline by default. However, every halt blocks other configuration deployments and requires human intervention to determine the root cause. This can quickly become a toilsome process as the steps are repetitive and bring no enduring value.</p><p>Part of our deployment pipeline for Salt changes uses <a href="https://en.wikipedia.org/wiki/APT_(software)"><u>Apt</u></a>. Every X minutes a commit is merged into the master branch, per Y minutes those merges are bundled and deployed to APT servers. The key file to retrieving Salt Master configuration from that APT server is the APT source file:</p>
            <pre><code># /etc/apt/sources.list.d/saltcodebase.sources
# MANAGED BY SALT -- DO NOT MODIFY

Types: deb
URIs: mirror+file:/etc/apt/mirrorlists/saltcodebase.txt
Suites: stable canary
Components: cloudflare
Signed-By: /etc/apt/keyrings/cloudflare.gpg</code></pre>
            <p>This file directs a master to the correct suite for its specific environment. Using that suite, it retrieves the latest package containing the relevant Salt Debian package with the latest changes. It installs that package and begins deploying the included configuration. As it deploys the configuration on machines, the machines report their health using <a href="https://blog.cloudflare.com/how-cloudflare-runs-prometheus-at-scale/"><u>Prometheus</u></a>. If a version is healthy, it will be progressed into the next environment. Before it can be progressed, a version has to pass a certain soak threshold to allow a version to develop its errors, making more complex issues become apparent. That is the happy case.</p><p>The unhappy case brings a myriad of complications: As we do progressive deployments, if a version is broken, any subsequent version is also broken. And because broken versions are continuously overtaken by newer versions, we need to stop deployments altogether. In a broken version scenario, it is crucial to get a fix out as soon as possible. This touches upon the core question of this blog post: What if a broken Salt version is propagated across the environment, we are abandoning deployments, and we need to get a fix out as soon as possible?</p>
    <div>
      <h3>The pain: how Salt breaks and reports errors (and how it affects Cloudflare)</h3>
      <a href="#the-pain-how-salt-breaks-and-reports-errors-and-how-it-affects-cloudflare">
        
      </a>
    </div>
    <p>While Salt aims for idempotent and predictable configuration, failures can occur during the render, compile, or runtime stages. These failures are commonly due to misconfiguration. Errors in Jinja templates or invalid YAML can cause the render stage to fail. Examples include missing colons, incorrect indentation, or undefined variables. A syntax error is often raised with a stack trace pointing to the offending line.</p><p>Another frequent cause of failure is missing pillar or grain data. Since pillar data is compiled on the master, forgetting to update pillar top files or refreshing pillar can result in <i>KeyError</i> exceptions. As a system that maintains order using requisites, misconfigured requisites can lead to states executing out-of-order or being skipped. Failures can also happen when minions are unable to authenticate with the master, or cannot reach the master due to network or firewall issues.</p><p>Salt reports errors in several ways. By default, the <code>salt</code> and <code>salt-call</code> commands exit with a retcode <b>1 </b>when any state fails. Salt also sets internal retcodes for specific cases: 1 for compile errors, 2 when a state returns False, and 5 for pillar compilation errors. Test mode shows what changes would be made without actually executing them, but is useful for catching syntax or ordering issues. Debug logs can be toggled using the <code>-l debug</code> CLI option (<code>salt &lt;minion&gt; state.highstate -l debug</code>).</p><p>The state return also includes the details of the individual state failures - the durations, timestamps, functions and results. If we introduce a failure to the  <code>file.managed</code> state by referencing a file that doesn’t exist in the Salt fileserver, we see this failure:</p>
            <pre><code>web1:
----------
          ID: nginx
    Function: pkg.installed
      Result: True
     Comment: Package nginx is already installed
     Started: 15:32:41.157235
    Duration: 256.138 ms
     Changes:   

----------
          ID: /etc/nginx/nginx.conf
    Function: file.managed
      Result: False
     Comment: Source file salt://webserver/files/nginx.conf not found in saltenv 'base'
     Started: 15:32:41.415128
    Duration: 14.581 ms
     Changes:   

Summary for web1
------------
Succeeded: 1 (changed=0)
Failed:    1
------------
Total states run:     2
Total run time: 270.719 ms</code></pre>
            <p>The return can also be displayed in JSON:</p>
            <pre><code>{
  "web1": {
    "pkg_|-nginx_|-nginx_|-installed": {
      "comment": "Package nginx is already installed",
      "name": "nginx",
      "start_time": "15:32:41.157235",
      "result": true,
      "duration": 256.138,
      "changes": {}
    },
    "file_|-/etc/nginx/nginx.conf_|-/etc/nginx/nginx.conf_|-managed": {
      "comment": "Source file salt://webserver/files/nginx.conf not found in saltenv 'base'",
      "name": "/etc/nginx/nginx.conf",
      "start_time": "15:32:41.415128",
      "result": false,
      "duration": 14.581,
      "changes": {}
    }
  }
}</code></pre>
            <p>The flexibility of the output format means that humans can parse them in custom scripts. But more importantly, it can also be consumed by more complex, interconnected automation systems. We knew we could easily parse these outputs to attribute the cause of a Salt failure with an input – e.g. a change in source control, an external service failure, or a software release. But something was missing.</p>
    <div>
      <h3>The solutions</h3>
      <a href="#the-solutions">
        
      </a>
    </div>
    <p>Configuration errors are a common cause of failure in large-scale systems. Some of these could even lead to full system outages, which we prevent with our release architecture. When a new release or configuration breaks in production, our SRE team needs to find and fix the root cause to avoid release delays. As we’ve previously noted, this triage is tedious and increasingly difficult due to system complexity.</p><p>While some organisations use formal techniques such as automated root cause analysis, most triage is still frustratingly manual. After evaluating the scope of the problem, we decided to adopt an automated approach. This section describes the step-by-step approach to solving this broad, complex problem in production.</p>
    <div>
      <h3>Phase one: retrievable CM inputs</h3>
      <a href="#phase-one-retrievable-cm-inputs">
        
      </a>
    </div>
    <p>When a Salt highstate fails on a minion, SRE teams faced a tedious investigation process: manually SSHing into minions, searching through logs for error messages, tracking down job IDs (JIDs), and locating the job associated with the JID on one of multiple associated masters. This is all while racing against a 4-hour retention window on master logs. The fundamental problem was architectural: Job results live on Salt Masters, not on the minions where they're executed, forcing operators to guess which master processed their job (SSHing into each one) and limiting visibility for users without master access.</p><p>We built a solution that caches job results directly on minions, similar to the <a href="https://docs.saltproject.io/en/3006/ref/returners/all/index.html"><u>local_cache</u></a> returner that exists for masters. That enables local job retrieval and extended retention periods. This transformed a multistep, time-sensitive investigation into a single query — operators can retrieve job details, automatically extract error context, and trace failures back to specific file changes and commit authors, all from the minion itself. The custom returner filters and manages cache size intelligently, eliminating the “which master?” problem while also enabling automated error attribution, reducing time to resolution, and removing human toil from routine troubleshooting.</p><p>By decentralizing job history and making it queryable at the source, we moved significantly closer to a self-service debugging experience where failures are automatically contextualized and attributed, letting SRE teams focus on fixes rather than forensics.</p>
    <div>
      <h3>Phase two: Self-service using a Salt Blame Module</h3>
      <a href="#phase-two-self-service-using-a-salt-blame-module">
        
      </a>
    </div>
    <p>Once job information was available on the minion, we no longer needed to resolve which master triggered the job that failed. The next step was to write a Salt execution module that would allow an external service to query for job information, and more specifically failed job information, without needing to know Salt internals. This led us to write a module called <b><i>Salt Blame</i></b>. Cloudflare prides itself on its blameless culture, our software on the other hand…</p><p>The blame module is responsible for pulling together three things:</p><ul><li><p>Local job history information</p></li><li><p>CM inputs (latest commit present during the job)</p></li><li><p>Git repo commit history</p></li></ul><p>We chose to write an execution module for simplicity, decoupling external automation from the need to understand Salt internals, and potential usage by operators for further troubleshooting. Writing execution modules is already well established within operational teams and adheres to well-defined best practices such as unit tests, linting and extensive peer-review.</p><p>The module is understandably very simple. It iterates in reverse chronological order through the jobs in the local cache and looks for the first job failure chronologically, and then the successful job immediately prior to it. This is for no other reason than narrowing down the true first failure and giving us before and after state results. At this stage, we have several avenues to present context to the caller: To find possible commit culprits, we look through all commits between the last successful Job ID and the failure to determine if any of these changed files relevant to the failure. We also provided the list of failed states and their outputs as another avenue to spot the root cause. We’ve learned that this flexibility is important to cover the wide range of failure possibilities.</p><p>We also make a distinction between normal failed states, and compile errors. As <a href="https://docs.saltproject.io/en/3007/topics/return_codes/index.html"><u>described in the Salt docs</u></a>, each job returns different retcodes based on the outcome. </p><ul><li><p>Compile Error: 1 is set when any error is encountered in the state compiler.</p></li><li><p>Failed State: 2 is set when any state returns a <code>False</code> result.</p></li></ul><p>Most of our failures manifest as failed states as a result of a change in source control. An engineer building a new feature for our customers may unintentionally introduce a failure that was uncaught by our CI and Salt Master tests. In the first iteration of the module, listing all the failed states was sufficient to pinpoint the root cause of a highstate failure.</p><p>However, we noticed that we had a blind spot. Compile errors do not result in a failed state, since no state runs. Since these errors returned a different retcode from what we checked for, the module was completely blind to them. Most compile errors happen when a Salt service dependency fails during the state compile phase. They can also happen as a result of a change in source control, although that is rare.</p><p>With both state failures and compile errors accounted for, we drastically improved our ability to pinpoint issues. We released the module to SREs who immediately realised the benefits of faster Salt triage.</p>
            <pre><code># List all the recent failed states
minion~$ salt-call -l info blame.last_failed_states
local:
    |_
      ----------
      __id__:
          /etc/nginx/nginx.conf
      __run_num__:
          5221
      __sls__:
          foo
      changes:
          ----------
      comment:
          Source file salt://webserver/files/nginx.conf not found in saltenv 'base'
      duration:
          367.233
      finish_time_stamp:
          2025-10-22T10:00:17.289897+00:00
      fun:
          file.managed
      name:
          /etc/nginx/nginx.conf
      result:
          False
      start_time:
          10:00:16.922664
      start_time_stamp:
          2025-10-22T10:00:16.922664+00:00

# List all the commits that correlate with a failed state
minion~$ salt-call -l info blame.last_highstate_failure
local:
    ----------
    commits:
        |_
          ----------
          author_email:
              johndoe@cloudflare.com
          author_name:
              John Doe
          commit_datetime:
              2025-06-30T15:29:26.000+00:00
          commit_id:
              e4a91b2c9f7d3b6f84d12a9f0e62a58c3c7d9b5a
          path:
              /srv/salt/webserver/init.sls
    message:
        reviewed 5 change(s) over 12 commit(s) looking for 1 state failure(s)
    result:
        True

# List all the compile errors
minion~$ salt-call -l info blame.last_compile_errors
local:
    |_
      ----------
      error_types:
      job_timestamp:
          2025-10-24T21:55:54.595412+00:00
      message: A service failure has occured
      state: foo
      traceback:
          Full stack trace of the failure
      urls: http://url-matching-external-service-if-found</code></pre>
            
    <div>
      <h3>Phase three: automate, automate, automate!</h3>
      <a href="#phase-three-automate-automate-automate">
        
      </a>
    </div>
    <p>Faster triage is always a welcome development, and engineers were comfortable running local commands on minions to triage Salt failures. But in a busy shift, time is of the essence. When failures spanned across multiple datacenters or machines, it easily became cumbersome to run commands across all these minions. This solution also required context-switches between multiple nodes and datacenters. We needed a way to aggregate common failure types using a single command – single minions, pre-production datacenters and production datacenters.</p><p>We implemented several mechanisms to simplify triage and eliminate manual triggers. We aimed to get this tooling as close to the triage location as possible, which is often chat. With three distinct commands, engineers were now able to triage Salt failures right from chat threads.</p><p>With a hierarchical approach, we made individual triage possible for minions, data centers and groups of data centers. A hierarchy makes this architecture fully extensible, flexible and self-organising. An engineer is able to triage a failure on one minion, and at the same time the entire data center as needed.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/0lEOmpdw9err62tIWqn0Y/3905580de41daf9fc81928a740c2dd14/image2.png" />
          </figure><p>The ability to triage multiple data centers at the same time became immediately useful for tracking the root cause of failures in pre-production data centers. These failures delay the propagation of changes to other data centers, and hinder our ability to release changes for customer features, bug fixes or incident remediation. The addition of this triage option has cut down the time to debug and remediate Salt failures by over 5%, allowing us to consistently release important changes for our customers.</p><p>While 5% does not immediately look like a drastic improvement, the magic is in the cumulative effect. We won’t release actual figures of the amount of time releases are delayed for, but we can do a simple thought experiment. If the average amount of time spent is even just 60 minutes per day, a reduction by 5% saves us 90 minutes (one hour 30 minutes) per month. </p><p>Another indirect benefit lies in more efficient feedback loops. Since engineers spend less time fiddling with complex configurations, that energy is diverted towards preventing reoccurrence, further reducing the overall time by an immeasurable amount. Our future plans include measurement and data analytics to understand the outcomes of these direct and indirect feedback loops.</p><p>The image below shows an example of pre-production triage output. We are able to correlate failures with git commits, releases, and external service failures. During a busy shift, this information is invaluable for quickly fixing breakage. On average, each minion “blame” takes less than 30 seconds, while multiple data centers are able to return a result in a minute or less.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/70qnYIpPDFI1gl0u7FrT4o/51899c016dabc382fb3346ccaab254b5/Screenshot_2025-11-12_at_20.40.53.png" />
          </figure><p>The image below describes the hierarchical model. Each step in the hierarchy is executed in parallel, allowing us to achieve blazing fast results.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5HpNSQrNN4wZMjpOG9J30o/912164038586e57e1e09124f36998ff8/image6.png" />
          </figure><p>With these mechanisms available, we further cut down triage time by triggering the triage automation on known conditions, especially those with impact to the release pipeline. This directly improved the velocity of changes to the edge since it took less time to find a root cause and fix-forward or revert.</p>
    <div>
      <h3>Phase four: measure, measure, measure</h3>
      <a href="#phase-four-measure-measure-measure">
        
      </a>
    </div>
    <p>After we got blazing fast Salt triage, we needed a way to measure the root causes. While individual root causes are not immediately valuable, historical analysis was deemed important. We wanted to understand the common causes of failure, especially as they hinder our ability to deliver value to customers. This knowledge creates a feedback loop that can be used to keep the number of failures low.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5QeJ1C9CT3rlDqaqHsQjdA/02ac41494ef3594ced1fddc0f801fae7/image1.png" />
          </figure><p>Using Prometheus and Grafana, we track the top causes of failure: git commits, releases, external service failures and unattributed failed states. The list of failed states is particularly useful because we want to know repeat offenders and drive better adoption of stable releasing practices. We are also particularly interested in root causes — a spike in the number of failures due to git commits indicates a need to adopt better coding practices and linting, a spike in external service failures indicates a regression in an internal system to be investigated, and a spike in release-based failures indicates a need for better gating and release-shepherding.</p><p>We analyse these metrics on a monthly cycle, providing feedback mechanisms through internal tickets and escalations. While the immediate impact of these efforts is not yet visible as the efforts are nascent, we expect to improve the overall health of our Saltstack infrastructure and release process by reducing the amount of breakage we see.</p>
    <div>
      <h3>The broader picture</h3>
      <a href="#the-broader-picture">
        
      </a>
    </div>
    <p>Much of operational work is often seen as a “necessary evil”. Humans in ops are conditioned to intervene when failures happen and remediate them. This cycle of alert-response is necessary to keep the infrastructure running, but it often leads to toil. We have <a href="https://blog.cloudflare.com/improving-platform-resilience-at-cloudflare/"><u>discussed the effect of toil</u></a> in a previous blog post.</p><p>This work represents another step in the right direction – removing more toil for our on-call SREs, and freeing up valuable time to work on novel issues. We hope that this encourages other operations engineers to share the progress they are making towards reducing overall toil in their organizations. We also hope that this sort of work can be adopted within Saltstack itself, although the lack of homogeneity in production systems across several companies makes it unlikely.</p><p>In the future, we plan to improve the accuracy of detection and rely less on external correlation of inputs to determine the root cause of failed outcomes. We will investigate how to move more of this logic into our native Saltstack modules, further streamlining the process and avoiding regressions as external systems drift.</p><p>If this sort of work is exciting to you, we encourage you to take a look at our <a href="https://www.cloudflare.com/en-gb/careers/"><u>careers page</u></a>.</p> ]]></content:encoded>
            <category><![CDATA[Salt]]></category>
            <category><![CDATA[Engineering]]></category>
            <category><![CDATA[Configuration Management]]></category>
            <category><![CDATA[SRE]]></category>
            <guid isPermaLink="false">6NzBMptWpdowos2RocUWxl</guid>
            <dc:creator>Opeyemi Onikute</dc:creator>
            <dc:creator>Menno Bezema</dc:creator>
            <dc:creator>Nick Rhodes</dc:creator>
        </item>
        <item>
            <title><![CDATA[Deploying firmware at Cloudflare-scale: updating thousands of servers in more than 285 cities]]></title>
            <link>https://blog.cloudflare.com/deploying-firmware-at-cloudflare-scale-how-we-update-thousands-of-servers-in-more-than-285-cities/</link>
            <pubDate>Fri, 10 Mar 2023 14:00:00 GMT</pubDate>
            <description><![CDATA[ We have a huge number of servers of varying kinds, from varying vendors, spread over 285 cities worldwide. We need to be able to rapidly deploy various types of firmware updates to all of them, reliably, and automatically, without any kind of manual intervention. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>As a security company, it’s critical that we have good processes for dealing with security issues. We regularly release software to our servers - on a daily basis even - which includes new features, bug fixes, and as required, security patches. But just as critical is the software which is <i>embedded</i> into the server hardware, known as firmware. Primarily of interest is the BIOS and <a href="/bmc-vuln/">Baseboard Management Controller</a> (BMC), but many other components also have firmware such as Network Interface Cards (NICs).</p><p>As the world becomes more digital, software which needs updating is appearing in more and more devices. As well as my computer, over the last year, I have waited patiently while firmware has updated in my TV, vacuum cleaner, lawn mower and light bulbs. It can be a cumbersome process, including obtaining the firmware, deploying it to the device which needs updating, navigating menus and other commands to initiate the update, and then waiting several minutes for the update to complete.</p><p>Firmware updates can be annoying even if you only have a couple of devices. We have more than a few devices at Cloudflare. We have a huge number of servers of varying kinds, from varying vendors, spread over 285 cities worldwide. We need to be able to rapidly deploy various types of firmware updates to all of them, reliably, and automatically, without any kind of manual intervention.</p><p>In this blog post I will outline the methods that we use to automate firmware deployment to our entire fleet. We have been using this method for several years now, and have deployed firmware without interrupting our SRE team, entirely automatically.</p>
    <div>
      <h3>Background</h3>
      <a href="#background">
        
      </a>
    </div>
    <p>A key component of our ability to deploy firmware at scale is the iPXE, an open source boot loader. iPXE is the glue which operates between the server and operating system, and is responsible for loading the operating system after the server has completed the Power On Self Test (POST). It is very flexible and contains a scripting language. With iPXE, we can write boot scripts which query the firmware version, continue booting if the correct firmware version is deployed, or if not, boot into a flashing environment to flash the correct firmware.</p><p>We only deploy new firmware when our systems are out of production, so we need a method to coordinate deployment only on out of production systems. The simplest way to do this is when they are rebooting, because by definition they are out of production then. We reboot our entire fleet every month, and have the ability to schedule reboots more urgently if required to deal with a security issue. Regularly rebooting our fleets has many advantages. We can <a href="https://www.youtube.com/watch?v=8mlJu8hPpQQ">deploy the latest Linux kerne</a>l, base operating system, and ensure that we do not have any breaking changes in our operating system and configuration management environment that breaks on fresh boot.</p><p>Our entire fleet operates in <a href="https://en.wikipedia.org/wiki/UEFI">UEFI mode</a>. UEFI is a modern replacement for the BIOS and offers more features and more security, such as Secure Boot. A full description of all of these changes is outside the scope of this article, but essentially UEFI provides a minimal environment and shell capable of executing binaries. <a href="/anchoring-trust-a-hardware-secure-boot-story/">Secure Boot ensures</a> that the binaries are signed with keys embedded in the system, to prevent a bad actor from tampering with our software.</p>
    <div>
      <h3>How we update the BIOS</h3>
      <a href="#how-we-update-the-bios">
        
      </a>
    </div>
    <p>We are able to update the BIOS without booting any operating system, purely by taking advantage of features offered by iPXE and the UEFI shell. This requires a <a href="https://wiki.osdev.org/UEFI#UEFI_applications_in_detail">flashing binary written for the UEFI environment</a>.</p><p>Upon boot, iPXE is started. Through iPXE’s built-in variable <code>${smbios/0.5.0}</code>  it is possible to <a href="https://forum.ipxe.org/showthread.php?tid=7749">query the current BIOS version</a>, and compare it to the latest version, and trigger a flash only if there is a mis-match.  iPXE then downloads the files required for the firmware update to a ramdisk.</p><p>The following is an example of a very basic iPXE script which performs such an action:</p>
            <pre><code># Check whether the BIOS version is 2.03
iseq ${smbios/0.5.0} 2.03 || goto biosupdate
echo Nothing to do for {{ model }}
exit 0

:biosupdate
echo Trying to update BIOS/UEFI...
echo Current: ${smbios/0.5.0}
echo New: 2.03

imgfetch ${boot_prefix}/tools/x64/shell.efi || goto unexpected_error
imgfetch startup.nsh || goto unexpected_error

imgfetch AfuEfix64.efi || goto unexpected_error
imgfetch bios-2.03.bin || goto unexpected_error

imgexec shell.efi || goto unexpected_error</code></pre>
            <p>Meanwhile, startup.nsh contains the binary to run and command line arguments to effect the flash:</p><p><code>startup.nsh</code>:</p>
            <pre><code>%homefilesystem%\AfuEfix64.efi %homefilesystem%\bios-2.03.bin /P /B /K /N /X /RLC:E /REBOOT</code></pre>
            <p>After rebooting, the machine will boot using its new BIOS firmware, version 2.03. Since <code>${smbios/0.5.0}</code> now contains 2.03, the machine continues to boot and enter production.</p>
    <div>
      <h3>Other firmware updates such as BMC, network cards and more</h3>
      <a href="#other-firmware-updates-such-as-bmc-network-cards-and-more">
        
      </a>
    </div>
    <p>Unfortunately, the number of vendors that support firmware updates with UEFI flashing binaries is limited. There are a large number of other updates that we need to perform such as BMC and NIC.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1Bnbihh4sYojHTFzb0VX5k/d4e818e8959aaacdcff156a64b30bd89/image1-6.png" />
            
            </figure><p>Consequently, we need another way to flash these binaries. Thankfully, these vendors invariably support flashing from Linux. Consequently we can perform flashing from a minimal Linux environment. Since vendor firmware updates are typically closed source utilities and vendors are often highly secretive about firmware flashing, we can ensure that the flashing environment does not provide an attackable surface by ensuring that the network is not configured. If it’s not on the network, it can’t be attacked and exploited.</p><p>Not being on the network means that we need to inject files into the boot process when the machine boots. We can accomplish this with an <a href="https://docs.kernel.org/admin-guide/initrd.html">initial ramdisk</a> (<code>initrd</code>), and iPXE makes it easy to add additional <code>initrd</code> to the boot.</p><p>Creating an <code>initrd</code> is as simple as creating an archive of the files using cpio using the newc archive format.</p><p>Let’s imagine we are going to flash Broadcom NIC firmware. We’ll use the bnxtnvm firmware update utility, the firmware image <code>firmware.pkg</code>, and a shell script called <code>flash</code> to automate the task.</p><p>The files are laid out in the file system like this:</p>
            <pre><code>cd broadcom
find .
./opt/preflight
./opt/preflight/scripts
./opt/preflight/scripts/flash
./opt/broadcom
./opt/broadcom/firmware.pkg
./opt/broadcom/bnxtnvm</code></pre>
            <p>Now we compress all of these files into an image called <code>broadcom.img</code>.</p>
            <pre><code>find . | cpio --quiet -H newc -o | gzip -9 -n &gt; ../broadcom.img</code></pre>
            <p>This is the first step completed; we have the firmware packaged up into an <code>initrd</code>.</p><p>Since it’s challenging to read, say, the firmware version of the NIC, from the EFI shell, we store firmware versions as UEFI variables. These can be written from Linux via <a href="https://www.kernel.org/doc/html/next/filesystems/efivarfs.html"><code>efivars</code></a>, the UEFI variable file system, and then read by iPXE on boot.</p><p>An example of writing an EFI variable from Linux looks like this:</p>
            <pre><code>declare -r fw_path='/sys/firmware/efi/efivars/broadcom-fw-9ca25c23-368a-4c21-943f-7d91f2b76008'
declare -r efi_header='\x07\x00\x00\x00'
declare -r version='1.05'

/bin/mount -o remount,rw,nosuid,nodev,noexec,noatime none /sys/firmware/efi/efivars

# Files on efivarfs are immutable by default, so remove the immutable flag so that we can write to it: https://docs.kernel.org/filesystems/efivarfs.html
if [ -f "${fw_path}" ] ; then
    /usr/bin/chattr -i "${fw_path}"
fi

echo -n -e "${efi_header}${version}" &gt;| "$fw_path"</code></pre>
            <p>Then we can write an iPXE configuration file to load the flashing kernel, userland and flashing utilities.</p>
            <pre><code>set cf/guid 9ca25c23-368a-4c21-943f-7d91f2b76008

iseq ${efivar/broadcom-fw-${cf/guid}} 1.05 &amp;&amp; echo Not flashing broadcom firmware, version already at 1.05 || goto update
exit

:update
echo Starting broadcom firmware update
kernel ${boot_prefix}/vmlinuz initrd=baseimg.img initrd=linux-initramfs-modules.img initrd=broadcom.img
initrd ${boot_prefix}/baseimg.img
initrd ${boot_prefix}/linux-initramfs-modules.img
initrd ${boot_prefix}/firmware/broadcom.img</code></pre>
            <p>Flashing scripts are deposited into <code>/opt/preflight/scripts</code> and we use <code>systemd</code> to execute them with <a href="https://manpages.debian.org/stretch/debianutils/run-parts.8.en.html">run-parts</a> on boot:</p><p><code>/etc/systemd/system/preflight.service</code>:</p>
            <pre><code>[Unit]
Description=Pre-salt checks and simple configurations on boot
Before=salt-highstate.service
After=network.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/run-parts --verbose /opt/preflight/scripts

[Install]
WantedBy=multi-user.target
RequiredBy=salt-highstate.service</code></pre>
            <p>An example flashing script in <code>/opt/preflight/scripts</code> might look like:</p>
            <pre><code>#!/bin/bash

trap 'catch $? $LINENO' ERR
catch(){
    #error handling goes here
    echo "Error $1 occured on line $2"
}

declare -r fw_path='/sys/firmware/efi/efivars/broadcom-fw-9ca25c23-368a-4c21-943f-7d91f2b76008'
declare -r efi_header='\x07\x00\x00\x00'
declare -r version='1.05'

lspci | grep -q Broadcom
if [ $? -eq 0 ]; then
    echo "Broadcom firmware flashing starting"
    if [ ! -f "$fw_path" ] ; then
        chmod +x /opt/broadcom/bnxtnvm
        declare -r interface=$(/opt/broadcom/bnxtnvm listdev | grep "Device Interface Name" | awk -F ": " '{print $2}')
        /opt/broadcom/bnxtnvm -dev=${interface} -force -y install /opt/broadcom/BCM957414M4142C.pkg
        declare -r status=$?
        declare -r currentversion=$(/opt/broadcom/bnxtnvm -dev=${interface} device_info | grep "Package version on NVM" | awk -F ": " '{print $2}')
        declare -r expectedversion=$(echo $version | awk '{print $2}')
        if [ $status -eq 0 -a "$currentversion" = "$expectedversion" ]; then
            echo "Broadcom firmware $version flashed successfully"
            /bin/mount -o remount,rw,nosuid,nodev,noexec,noatime none /sys/firmware/efi/efivars
            echo -n -e "${efi_header}${version}" &gt;| "$fw_path"
            echo "Created $fw_path"
        else
            echo "Failed to flash Broadcom firmware $version"
            /opt/broadcom/bnxtnvm -dev=${interface} device_info
        fi
    else
        echo "Broadcom firmware up-to-date"
    fi
else
    echo "No Broadcom NIC installed"
    /bin/mount -o remount,rw,nosuid,nodev,noexec,noatime none /sys/firmware/efi/efivars
    if [ -f "${fw_path}" ] ; then
        /usr/bin/chattr -i "${fw_path}"
    fi
    echo -n -e "${efi_header}${version}" &gt;| "$fw_path"
    echo "Created $fw_path"
fi

if [ -f "${fw_path}" ]; then
    echo "rebooting in 60 seconds"
    sleep 60
    /sbin/reboot
fi</code></pre>
            
    <div>
      <h3>Conclusion</h3>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>Whether you manage just your laptop or desktop computer, or a fleet of servers, it’s important to keep the firmware updated to ensure that the availability, performance and security of the devices is maintained.</p><p>If you have a few devices and would benefit from automating the deployment process, we hope that we have inspired you to have a go by making use of some basic open source tools such as the iPXE boot loader and some scripting.</p><p>Final thanks to my colleague <a href="/author/ignat/">Ignat Korchagin</a> who did a large amount of the original work on the UEFI BIOS firmware flashing infrastructure.</p> ]]></content:encoded>
            <category><![CDATA[Hardware]]></category>
            <category><![CDATA[Security]]></category>
            <category><![CDATA[Salt]]></category>
            <guid isPermaLink="false">1jDz7Y0bfL3rEOW1hs3unN</guid>
            <dc:creator>Chris Howells</dc:creator>
        </item>
        <item>
            <title><![CDATA[Using Apache Kafka to process 1 trillion inter-service messages]]></title>
            <link>https://blog.cloudflare.com/using-apache-kafka-to-process-1-trillion-messages/</link>
            <pubDate>Tue, 19 Jul 2022 13:00:00 GMT</pubDate>
            <description><![CDATA[ We learnt a lot about Kafka on the way to 1 trillion messages, and built some interesting internal tools to ease adoption that will be explored in this blog post ]]></description>
            <content:encoded><![CDATA[ 
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3RvfaKNjkQcCDhobJWvu7o/e6fa0460c33b0250ceb61458d2d4bd8d/image3-8.png" />
            
            </figure><p>Cloudflare has been using Kafka in production since 2014. We have come a long way since then, and currently run 14 distinct Kafka clusters, across multiple data centers, with roughly 330 nodes. Between them, over a trillion messages have been processed over the last eight years.</p><p>Cloudflare uses Kafka to decouple microservices and communicate the creation, change or deletion of various resources via a common data format in a fault-tolerant manner. This decoupling is one of many factors that enables Cloudflare engineering teams to work on multiple features and products concurrently.</p><p>We learnt a lot about Kafka on the way to one trillion messages, and built some interesting internal tools to ease adoption that will be explored in this blog post. The focus in this blog post is on inter-application communication use cases alone and not logging (we have other Kafka clusters that power the dashboards where customers view statistics that handle more than one trillion messages <i>each day</i>). I am an engineer on the <a href="https://www.cloudflare.com/application-services/">Application Services</a> team and our team has a charter to provide tools/services to product teams, so they can focus on their core competency which is delivering value to our customers.</p><p>In this blog I’d like to recount some of our experiences in the hope that it helps other engineering teams who are on a similar journey of adopting Kafka widely.</p>
    <div>
      <h3>Tooling</h3>
      <a href="#tooling">
        
      </a>
    </div>
    <p>One of our Kafka clusters is creatively named Messagebus. It is the most general purpose cluster we run, and was created to:</p><ul><li><p>Prevent data silos;</p></li><li><p>Enable services to communicate more clearly with basically zero integration cost (more on how we achieved this below);</p></li><li><p>Encourage the use of a self-documenting communication format and therefore removing the problem of out of date documentation.</p></li></ul><p>To make it as easy to use as possible and to encourage adoption, the Application Services team created two internal projects. The first is unimaginatively named Messagebus-Client. Messagebus-Client is a Go library that wraps the fantastic <a href="https://github.com/Shopify/sarama">Shopify Sarama</a> library with an opinionated set of configuration options and the ability to manage the rotation of mTLS certificates.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1oHafIQiSG7GPT5Vy4NK2o/fccef1fe85ff5d635975d7397a5d6299/unnamed1-2.png" />
            
            </figure><p>The success of this project is also somewhat its downfall. By providing a ready-to-go Kafka client, we ensured teams got up and running quickly, but we also abstracted some core concepts of Kafka a little too much, meaning that small unassuming configuration changes could have a big impact.</p><p>One such example led to partition skew (a large portion of messages being directed towards a single partition, meaning we were not processing messages in real time; see the chart below). One drawback of Kafka is you can only have one consumer per partition, so when incidents do occur, you can’t trivially scale your way to faster throughput.</p><p>That also means before your service hits production it is wise to do some back of the napkin math to figure out what throughput might look like, otherwise you will need to add partitions later. We have since amended our library to make events like the below less likely.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1ZGNKq4vOi5vzkHe5FWqsV/f36dac854e7c8e67b5f66a75f16ddeda/image2-14.png" />
            
            </figure><p>The reception for the Messagebus-Client has been largely positive. We spent time as a team to understand what the predominant use cases were, and took the concept one step further to build out what we call the connector framework.</p>
    <div>
      <h3>Connectors</h3>
      <a href="#connectors">
        
      </a>
    </div>
    <p>The connector framework is based on Kafka-connectors and allows our engineers to easily spin up a service that can read from a system of record and push it somewhere else (such as Kafka, or even Cloudflare’s own <a href="/introducing-quicksilver-configuration-distribution-at-internet-scale/">Quicksilver</a>). To make this as easy as possible, we use Cookiecutter templating to allow engineers to enter a few parameters into a CLI and in return receive a ready to deploy service.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2zcySLWw14zCys58e2yJfn/5f0c05b47e424f5a9f3448fca01be0a1/unnamed2-3.png" />
            
            </figure><p>We provide the ability to configure data pipelines via environment variables. For simple use cases, we provide the functionality out of the box. However, extending the readers, writers and transformations is as simple as satisfying an interface and “registering” the new entry.</p><p>For example, adding the environment variables:</p>
            <pre><code>READER=kafka
TRANSFORMATIONS=topic_router:topic1,topic2|pf_edge
WRITER=quicksilver</code></pre>
            <p>will:</p><ul><li><p>Read messages from Kafka topic “topic1” and “topic2”;</p></li><li><p>Transform the message using a transformation function called “pf_edge” which maps the request from a Kafka protobuf to a Quicksilver request;</p></li><li><p>Write the result to Quicksilver.</p></li></ul><p>Connectors come readily baked with basic metrics and alerts, so teams know they can move to production quickly but with confidence.</p><p>Below is a diagram of how one team used our connector framework to read from the Messagebus cluster and write to various other systems. This is orchestrated by a system the Application Service team runs called Communication Preferences Service (CPS). Whenever a user opts in/out of marketing emails or changes their language preferences on cloudflare.com, they are calling CPS which ensures those settings are reflected in all the relevant systems.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/73VDgC81vyvClHrzGhC3ks/51f86d58fd8b9477c33a6d2808663d62/unnamed3-2.png" />
            
            </figure>
    <div>
      <h3>Strict Schemas</h3>
      <a href="#strict-schemas">
        
      </a>
    </div>
    <p>Alongside the Messagebus-Client library, we also provide a repo called Messagebus Schema. This is a schema registry for all message types that will be sent over our Messagebus cluster. For message format, we use protobuf and have been very happy with that decision. Previously, our team had used JSON for some of our kafka schemas, but we found it much harder to enforce forward and backwards compatibility, as well as message sizes being substantially larger than the protobuf equivalent. Protobuf provides strict message schemas (including type safety), the forward and backwards compatibility we desired, the ability to generate code in multiple languages as well as the files being very human-readable.</p><p>We encourage heavy commentary before approving a merge. Once merged, we use prototool to do breaking change detection, enforce some stylistic rules and to generate code for various languages (at time of writing it's just Go and Rust, but it is trivial to add more).</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4gukMjNyXSWw57NnycOs7U/7137d7d445fd0e0980406cce99b7cb80/image6-8.png" />
            
            </figure><p><i>An example Protobuf message in our schema</i></p><p>Furthermore, in Messagebus Schema we store a mapping of proto messages to a team, alongside that team’s chat room in our internal communication tool. This allows us to escalate issues to the correct team easily when necessary.</p><p>One important decision we made for the Messagebus cluster is to only allow one proto message per topic. This is configured in Messagebus Schema and enforced by the Messagebus-Client. This was a good decision to enable easy adoption, but it has led to numerous topics existing. When you consider that for each topic we create, we add numerous partitions and replicate them with a replication factor of at least three for resilience, there is a lot of potential to optimize compute for our lower throughput topics.</p>
    <div>
      <h3>Observability</h3>
      <a href="#observability">
        
      </a>
    </div>
    <p>Making it easy for teams to observe Kafka is essential for our decoupled engineering model to be successful. We therefore have automated metrics and alert creation wherever we can to ensure that all the engineering teams have a wealth of information available to them to respond to any issues that arise in a timely manner.</p><p>We use Salt to manage our infrastructure configuration and follow a Gitops style model, where our repo holds the source of truth for the state of our infrastructure. To add a new Kafka topic, our engineers make a pull request into this repo and add a couple of lines of YAML. Upon merge, the topic and an alert for high lag (where lag is defined as the difference in time between the last committed offset being read and the last produced offset being produced) will be created. Other alerts can (and should) be created, but this is left to the discretion of application teams. The reason we automatically generate alerts for high lag is that this simple alert is a great proxy for catching a high amount of issues including:</p><ul><li><p>Your consumer isn’t running.</p></li><li><p>Your consumer cannot keep up with the amount of throughput or there is an anomalous amount of messages being produced to your topic at this time.</p></li><li><p>Your consumer is misbehaving and not acknowledging messages.</p></li></ul><p>For metrics, we use Prometheus and display them with Grafana. For each new topic created, we automatically provide a view into production rate, consumption rate and partition skew by producer/consumer. If an engineering team is called out, within the alert message is a link to this Grafana view.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2IVbiHGj7DRPdVUXorpOEQ/1be04566221051b8ec499ae265f083fb/image7-cropped.png" />
            
            </figure><p>In our Messagebus-Client, we expose some metrics automatically and users get the ability to extend them further. The metrics we expose by default are:</p><p>For producers:</p><ul><li><p>Messages successfully delivered.</p></li><li><p>Message failed to deliver.</p></li></ul><p>For consumer:</p><ul><li><p>Messages successfully consumed.</p></li><li><p>Message consumption errors.</p></li></ul><p>Some teams use these for alerting on a significant change in throughput, others use them to alert if no messages are produced/consumed in a given time frame.</p>
    <div>
      <h3>A Practical Example</h3>
      <a href="#a-practical-example">
        
      </a>
    </div>
    <p>As well as providing the Messagebus framework, the Application Services team looks for common concerns within Engineering and looks to solve them in a scalable, extensible way which means other engineering teams can utilize the system and not have to build their own (thus meaning we are not building lots of disparate systems that are only slightly different).</p><p>One example is the Alert Notification System (ANS). ANS is the backend service for the “Notifications” tab in the Cloudflare dashboard. You may have noticed over the past 12 months that new alert and policy types have been made available to customers very regularly. This is because we have made it very easy for other teams to do this. The approach is:</p><ul><li><p>Create a new entry into ANS’s configuration YAML (We use CUE lang to validate the configuration as part of our continuous integration process);</p></li><li><p>Import our Messagebus-Client into your code base;</p></li><li><p>Emit a message to our alert topic when an event of interest takes place.</p></li></ul><p>That’s it! The producer team now has a means for customers to configure granular alerting policies for their new alert that includes being able to dispatch them via Slack, Google Chat or a custom webhook, PagerDuty or email (by both API and dashboard). Retrying and dead letter messages are managed for them, and a whole host of metrics are made available, all by making some very small changes.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4csJmS7UJAwNtrWvV0WKwx/73d4fd1ff6528c14d3ec42b9237f00a4/unnamed4.png" />
            
            </figure>
    <div>
      <h3>What’s Next?</h3>
      <a href="#whats-next">
        
      </a>
    </div>
    <p>Usage of Kafka (and our Messagebus tools) is only going to increase at Cloudflare as we continue to grow, and as a team we are committed to making the tooling around Messagebus easy to use, customizable where necessary and (perhaps most importantly) easy to observe. We regularly take feedback from other engineers to help improve the Messagebus-Client (we are on the fifth version now) and are currently experimenting with abstracting the intricacies of Kafka away completely and allowing teams to use gRPC to stream messages to Kafka. Blog post on the success/failure of this to follow!</p><p>If you're interested in building scalable services and solving interesting technical problems, we are hiring engineers on our team in <a href="https://boards.greenhouse.io/cloudflare/jobs/3252504?gh_jid=3252504"><i>Austin</i></a><i>, and </i><a href="https://boards.greenhouse.io/cloudflare/jobs/3252504?gh_jid=3252504"><i>Remote US</i></a><i>.</i></p> ]]></content:encoded>
            <category><![CDATA[Kafka]]></category>
            <category><![CDATA[Salt]]></category>
            <guid isPermaLink="false">227GWCIbrOPz01S0w39hHZ</guid>
            <dc:creator>Matt Boyle</dc:creator>
        </item>
        <item>
            <title><![CDATA[Future-proofing SaltStack]]></title>
            <link>https://blog.cloudflare.com/future-proofing-saltstack/</link>
            <pubDate>Thu, 31 Mar 2022 12:59:45 GMT</pubDate>
            <description><![CDATA[ This blogpost chronicles the recent CVEs investigation, our findings, and how we are helping secure Salt now and in the Quantum future ]]></description>
            <content:encoded><![CDATA[ <p></p><p>At Cloudflare, we are <a href="/post-quantumify-cloudflare/">preparing the Internet and our infrastructure</a> for the arrival of quantum computers. A sufficiently large and stable quantum computer <a href="/quantum-solace-and-spectre/">will easily break</a> commonly deployed cryptography such as RSA. Luckily there is a solution: we can swap out the vulnerable algorithms with so-called <i>post-quantum</i> algorithms that are believed to be secure even against quantum computers. For a particular system, this means that we first need to figure out which cryptography is used, for what purpose, and under which (performance) constraints. Most systems use the <a href="https://www.cloudflare.com/learning/ssl/transport-layer-security-tls/">TLS</a> protocol in a standard way, and there a post-quantum upgrade is routine. However, some systems such as <a href="https://saltproject.io/">SaltStack</a>, the focus of this blog post, are more interesting. This blog post chronicles our path of making SaltStack quantum-secure, so welcome to this adventure: this secret extra post-quantum blog post!</p><p>SaltStack, or simply <i>Salt</i>, is an open-source infrastructure management tool used by many organizations. At Cloudflare, <a href="/tag/salt/">we rely on Salt</a> for provisioning and automation, and it has <a href="/manage-cloudflare-records-with-salt/">allowed us to grow our infrastructure quickly</a>.</p><p>Salt uses a bespoke cryptographic protocol to secure its communication. Thus, the first step to a post-quantum Salt was to examine what the protocol was actually doing. In the process we discovered a number of security vulnerabilities (<a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=2022-22934">CVE-2022-22934</a>, <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=2022-22935">CVE-2022-22935</a>, <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=2022-22936">CVE-2022-22936</a>). This blogpost chronicles the investigation, our findings, and how we are helping secure Salt now and in the Quantum future.</p>
    <div>
      <h2>Cryptography in Salt</h2>
      <a href="#cryptography-in-salt">
        
      </a>
    </div>
    <p>Let’s start with a high-level overview of Salt.</p><p>The main agents in a Salt system are servers and clients (referred to as <i>masters</i> and <i>minions</i> in the Salt documentation). A server is the central control point for a number of clients, which can be in the tens of thousands: it can issue a command to the entire fleet, provision client machines with different characteristics, collect reports on jobs running on each machine, and much more. Depending on the architecture, there can be multiple servers managing the same fleet of clients. This is what makes Salt great, as it helps the management of complex infrastructure.</p><p>By default, the communication between a server and a client happens over <a href="https://zeromq.org/">ZeroMQ</a> on top of TCP though there is an experimental option to switch to a custom transport directly on <a href="https://en.wikipedia.org/wiki/Transmission_Control_Protocol">TCP</a>. The cryptographic protocol is largely the same for both transports. The experimental TCP transport has an option to enable TLS which does not replace the custom protocol but wraps it in server-authenticated TLS. More about that later on.</p><p>The custom protocol relies on a setup phase in which each server and each client has its own long-term RSA-2048 keypair. On the surface similar to TLS, Salt defines a handshake, or key exchange protocol, that generates a shared secret, and a record protocol which uses this secret with symmetric encryption (the symmetric channel).</p>
    <div>
      <h3>Key exchange protocol</h3>
      <a href="#key-exchange-protocol">
        
      </a>
    </div>
    <p>In its basic form, the key exchange (or handshake) protocol is an RSA key exchange in which the server chooses the secret and encrypts it to the client’s public key. The exact form of the protocol then depends on whether either party already knows the other party’s long-term public key, since certificates (like in TLS) are not used. By default, clients trust the server’s public key on first use, and servers only trust the client’s public key after it has been accepted by an out-of-band mechanism. The shared secret is shared among the entire fleet of clients_,_ so it is not specific to a particular server and client pair. This allows the server to encrypt a broadcast message only once. We will come back to this performance trade-off later on.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/OOEK47GfL4jKc8uua4lRX/843b1e90771e36612635a04c47b49509/image4-27.png" />
            
            </figure><p>Salt key exchange (as of version 3004) under default settings, showing the first connection between the given server and client.</p>
    <div>
      <h3>Symmetric channel</h3>
      <a href="#symmetric-channel">
        
      </a>
    </div>
    <p>The shared secret is used as the key for encryption. Most of the messages between a server and a client are secured in an Encrypt-then-MAC fashion, with AES-192 in CBC mode with SHA-256 for HMAC. For certain more sensitive messages, variations on this protocol are used to add more security. For example, commands are signed using the server’s long-term secret key, and “<a href="https://docs.saltproject.io/en/3004/topics/tutorials/pillar.html">pillar data</a>” (deemed more sensitive) is encrypted only to a particular client using a freshly generated secret key.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/xYB4BWt379cUihxp8hnjs/7f1c7c74be3981f69986df75491d1683/image3-43.png" />
            
            </figure><p>Symmetric channel in Salt (as of version 3004).</p>
    <div>
      <h2>Security vulnerabilities</h2>
      <a href="#security-vulnerabilities">
        
      </a>
    </div>
    <p>We found that the protocol variation used for pillar messages contains a flaw. As shown in the diagram below, a <a href="/monsters-in-the-middleboxes/">monster-in-the-middle attacker</a> (MitM) that sits between a server and a client can substitute arbitrary “pillar data” to the client. It needs to know the client’s public key, but that is easy to find since clients broadcast it as part of their key exchange request. The initial key exchange can be observed, or one could be triggered on-demand using a specially crafted message. This MitM was possible because neither the newly generated key nor the actual payload were authenticated as coming from the server. This matters because “pillar data” can include anything from specifying packages to be installed to credentials and cryptographic keys. Thus, it is possible that this flaw could allow an attacker to gain access to the vulnerable client machine.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/Pho9IvH1FEmLmEywHZ2iM/9fcea35fd78622ed159a06e7c2026609/image1-107.png" />
            
            </figure><p>Illustration of the monster-in-the-middle attack, <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=2022-22934">CVE-2022-22934</a>.</p><p>We reported the issue to Salt November 5, 2021, which assigned <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=2022-22934">CVE-2022-22934</a> to it. Earlier this week, on March 28, 2022, Salt <a href="https://saltproject.io/security_announcements/salt-security-advisory-release/">released a patch</a> that adds a signature of the server on the pillar message to prevent the attack.</p><p>There were several other smaller issues we found. Messages could be <a href="https://en.wikipedia.org/wiki/Replay_attack">replayed</a> to the same or a different client. This could allow a file intended for one client, to be served to a different one, perhaps aiding lateral movement. This is <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=2022-22936">CVE-2022-22936</a> and has been patched by adding the name of the addressed client, a nonce and a signature to messages.</p><p>Finally, there were some messages which could be manipulated to cause the client to crash.  This is <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=2022-22935">CVE-2022-22935</a> and was patched similarly by adding the addressee, nonce and signature.</p><p>If you are running Salt, please update as soon as possible to either 3002.8, 3003.4 or 3004.1.</p>
    <div>
      <h2>Moving forward</h2>
      <a href="#moving-forward">
        
      </a>
    </div>
    <p>These patches add signatures to almost every single message. The decision to have a single shared secret was a performance trade-off: only a single encryption is required to broadcast a message. As signatures are computationally much more expensive than symmetric encryption, this trade-off didn’t work out that well. It’s better to switch to a separate shared key per client, so that we don’t need to add a signature on every separate message. In effect, we are creating a single long-lived mutually-authenticated channel per client. But then we are getting very close to what <a href="https://www.cloudflare.com/learning/access-management/what-is-mutual-tls/">mutually authenticated TLS</a> (mTLS) can provide. What would that look like? Hold that thought for a moment: we will return to it below.</p><p>We got sidetracked from our original question: what does this all mean for making Salt post-quantum secure? One thing to take away about post-quantum cryptography today is that signatures <a href="/sizing-up-post-quantum-signatures/">are much larger</a>: Dilithium2, for instance, weighs in at 2.4 kB compared to 256 bytes for an RSA-2048 signature. So ironically, patching these vulnerabilities has made our job more difficult as there are many more signatures. Thus, also for our post-quantum goal, mTLS seems very attractive. Not the least because there are post-quantum TLS stacks ready to go.</p><p>Finally, as the security properties of  mTLS are well understood, it will be much easier to add new messages and functionality to Salt’s protocol. With the current complex protocol, any change is much harder to judge with confidence.</p>
    <div>
      <h3>An mTLS-based transport</h3>
      <a href="#an-mtls-based-transport">
        
      </a>
    </div>
    <p>So what would such an mTLS-based protocol for Salt look like? Clients would pin the server certificate and the server would pin the client certificates. Thus, we wouldn’t have any traditional public key infrastructure (PKI). This matches up nicely with how Salt deals with keys currently. This allows clients to establish long-lived connections with their server and be sure that all data exchanged between them is confidential, mutually authenticated and has forward secrecy. This mitigates replays, swapping of messages, reflection attacks or subtle denial of service pathways for free.</p><p>We tested this idea by implementing a third transport using WebSocket over mTLS (WSS). As mentioned before, Salt already offers an option to use TLS with the TCP transport, but it doesn’t authenticate clients and creates a new TCP connection for every client request which leads to a multitude of unnecessary TLS handshakes. Internally, Salt has been architected to work with new connections for each request, so our proof of concept required some laborious retooling.</p><p>Our findings show promise that there would be no significant losses and potentially some improvements when it comes to performance at scale. In our preliminary experiments with a single server handling a thousand clients, there was no difference in several metrics compared to the default ZeroMQ transport. Resource-intensive operations such as the fetching of pillar and state data resulted, in our experiment, in lower CPU usage in the mTLS transport. Enabling long-lived connections reduced the amount of data transmitted between the clients and the server, in some cases, significantly so.</p><p>We have shared our preliminary results with Salt, and we are working together to add an mTLS-based transport upstream. Stay tuned!</p>
    <div>
      <h2>Conclusion</h2>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>We had a look at how to make Salt post-quantum secure. While doing so, we found and helped fix several issues. We see a clear path forward to a future post-quantum Salt based on mTLS. Salt is but one system: we will continue our work, checking system-by-system, collaborating with vendors to bring post-quantum into the present.</p><p>With thanks to Bas and Sofía for their help on the project.</p> ]]></content:encoded>
            <category><![CDATA[Research]]></category>
            <category><![CDATA[Post-Quantum]]></category>
            <category><![CDATA[Cryptography]]></category>
            <category><![CDATA[Security]]></category>
            <category><![CDATA[Salt]]></category>
            <guid isPermaLink="false">3GLfe9jBqeJ4TF1vpYmFzd</guid>
            <dc:creator>Lenka Mareková</dc:creator>
        </item>
        <item>
            <title><![CDATA[Research Directions in Password Security]]></title>
            <link>https://blog.cloudflare.com/research-directions-in-password-security/</link>
            <pubDate>Thu, 14 Oct 2021 12:59:14 GMT</pubDate>
            <description><![CDATA[ We've been studying password problems, including malicious logins using compromised credentials. Here's what we learned and here's where we think we can go from here with safer password systems. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>As Internet users, we all deal with passwords every day. With so many different services, each with their own login systems, we have to somehow keep track of the credentials we use with each of these services. This situation leads some users to delegate credential storage to password managers like LastPass or a browser-based password manager, but this is far from universal. Instead, many people still rely on old-fashioned human memory, which has its limitations — leading to reused passwords and to security problems. This blog post discusses how Cloudflare Research is exploring how to minimize password exposure and thwart password attacks.</p>
    <div>
      <h2>The Problem of Password Reuse</h2>
      <a href="#the-problem-of-password-reuse">
        
      </a>
    </div>
    <p>Because it’s too difficult to remember many distinct passwords, people often reuse them across different online services. When breached password datasets are leaked online, attackers can take advantage of these to conduct “credential stuffing attacks”. In a credential stuffing attack, an attacker tests breached credentials against multiple online login systems in an attempt to hijack user accounts. These attacks are highly effective because users tend to reuse the same credentials across different websites, and they have quickly become one of the most prevalent types of online guessing attacks. Automated attacks can be run at a large scale, testing out exposed passwords across multiple systems, under the assumption that some of these passwords will unlock accounts somewhere else (if they have been reused). When a data breach is detected, users of that service will likely receive a security notification and will reset that account password. However, if this password was reused elsewhere, they may easily forget that it needs to be changed for those accounts as well.</p><p>How can we protect against credential stuffing attacks? There are a number of methods that have been deployed — with varying degrees of success. Password managers address the problem of remembering a strong, unique password for every account, but many users have yet to adopt them. Multi-factor authentication is another potential solution — that is, using another form of authentication in addition to the username/password pair. This can work well, but has limits: for example, such solutions may rely on specialized hardware that not all clients have. Consumer systems are often reluctant to mandate multi-factor authentication, given concerns that people may find it too complicated to use; companies do not want to deploy something that risks impeding the growth of their user base.</p><p>Since there is no perfect solution, security researchers continue to try to find improvements. Two different approaches we will discuss in this blog post are hardening password systems using cryptographically secure keys, and detecting the reuse of compromised credentials, so they don’t leave an account open to guessing attacks.</p>
    <div>
      <h2>Improved Authentication with PAKEs</h2>
      <a href="#improved-authentication-with-pakes">
        
      </a>
    </div>
    <p>Investigating how to securely authenticate a user just using what they can remember has been an important area in secure communication. To this end, the subarea of cryptography known as Password Authenticated Key Exchange (PAKE) came about. PAKEs deal with protocols for establishing cryptographically secure keys where the only source of authentication is a human memorizable (low-entropy, attacker-guessable) password — that is, the “what you know” side of authentication.</p><p>Before diving into the details, we’ll provide a high-level overview of the basic problem. Although passwords are typically protected in transit by being sent over HTTPS, servers handle them in <i>plaintext</i> to verify them once they arrive. Handling plaintext passwords increases security risk — for instance, they might get inadvertently logged and exposed. Ideally, the user’s password never gets sent to the server in the first place. This is where PAKEs come in — a means of verifying that the user and server share a password, ideally without revealing information about the password that could help attackers to discover or crack it.</p>
    <div>
      <h3>A few words on PAKEs</h3>
      <a href="#a-few-words-on-pakes">
        
      </a>
    </div>
    <p>PAKE protocols let two parties turn a password into a shared key. Each party only gets one guess at the password the other holds. If a user tries to log in to the wrong server with a PAKE, that server will not be able to turn around and impersonate the user. As such, PAKEs guarantee that communication with one of the parties is the only way for an attacker to test their (single) password guess. This may seem like an unneeded level of complexity when we could use already available tools like a key distribution mechanism along with <a href="/opaque-oblivious-passwords/">password-over-TLS</a>, but this puts a lot of trust in the service. You may trust a service with learning your password on that service, but what about if you accidentally use a password for a different service when trying to log in? Note the particular risks of a reused password: it is no longer just a secret shared between a user and a <i>single</i> service, but is now a secret shared between a user and <i>multiple</i> services. This therefore increases the password’s privacy sensitivity — a service should not know users’ account login information for <i>other</i> services.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/953CGN6o81Ak25ZlQLpdL/3b467111621985bded03b137ad464c1c/ifYbW6e-iYo9uU3KtBcbMzgURxbxi5Q-29EBuZT46b9RypGo3zco16W3sx9UuACOVKTpKe6ZiJq3QUoZQM3v9_G22YDk6cQJeXIVOlRbjP2C0ssQrMVG7qhDM7XM.png" />
            
            </figure><p>A comparison of shared secrets between passwords over TLS versus PAKEs.With passwords over TLS, a service might learn passwords used on another service. This problem does not arise with PAKEs.</p><p>PAKE protocols are built with the assumption that the server isn’t always working in the best interest of the client and, even more, cannot use any kind of public-key infrastructure during login (although it doesn’t hurt to have both!). This precludes the user from sending their plaintext password (or any information that could be used to derive it —  in a computational sense) to the server during login.</p><p>PAKE protocols have expanded into new territory since the <a href="https://scholar.google.com/scholar?cluster=2364773997049033938&amp;hl=en&amp;as_sdt=0,31">seminal EKE paper of Bellovin and Merritt</a>, where the client and server both remembered a plaintext version of the password. As mentioned above, when the server stores the plaintext password, the client risks having the password logged or leaked. To address this, new protocols were developed, referred to as augmented, verifier-based, or <b>asymmetric PAKE</b>s (aPAKEs), where the server stored a modified version (similar to a hash) of the password instead of the plaintext password. This mirrors the way many of us were <a href="/keeping-passwords-safe-by-staying-up-to-date/">taught to store passwords</a> in a database, specifically as a hash of the password with accompanying salt and pepper. However, in these cases, attackers can still use traditional methods of attack such as targeted rainbow tables. To avoid these kinds of attacks, a new kind of PAKE was born, the <b>strong asymmetric PAKE</b> (saPAKE).</p><p><a href="https://scholar.google.com/scholar?cluster=5047618283495879801&amp;hl=en&amp;as_sdt=0,31">OPAQUE was the first saPAKE</a> and it guarantees defense against precomputation by hiding the password dictionary itself! It does this by replacing the noninteractive hash function with an interactive protocol referred to as an Oblivious Pseudorandom Function (OPRF) where one party inputs their “salt”, another inputs their “password”, and only the password-providing party learns the output of the function. The fact that the password-providing party learns nothing (computationally) about the salt prevents offline precomputation by disallowing an attacker from evaluating the function in their head.</p><p>Another way to think about the three PAKE paradigms has to do with how each of them treats the password dictionary:</p><p>PAKE type</p><p>Password Dictionary</p><p>Threat Model</p><p>PAKE</p><p>The password dictionary is public and common to every user.</p><p>Without any guessing, the attacker learns the user’s password upon compromise of the server.</p><p>aPAKE</p><p>Each user gets their own password dictionary; a description of the dictionary (e.g., the “salt”) is leaked to the client when they attempt to log in.</p><p>The attacker must perform an independent precomputation for each client they want to attack.</p><p>saPAKE (e.g., OPAQUE)</p><p>Each user gets their own password dictionary; the server only provides an online interface (the OPRF) to the dictionary.</p><p>The adversary must wait until after they compromise the server to run an offline attack on the user’s password<sup>1</sup>.</p><p>OPAQUE also goes one step further and allows the user to perform the password transformation on their own device so that the server doesn’t see the plaintext password during registration either. Cloudflare Research has been involved with OPAQUE for a while now — for instance, you can read about our previous <a href="/opaque-oblivious-passwords/">implementation work and demo</a> if you want to learn more.</p><p>But OPAQUE is not a panacea: in the event of server compromise, the attacker can learn the salt that the server uses to evaluate the OPRF and can still run the same offline attack that was available in the aPAKE world, although this is now considerably more time-consuming and can be made increasingly difficult through the use of memory-hard hash functions like scrypt. This means that despite our best efforts, when a server is breached, the attacker can eventually come out with a list of plaintext passwords. Indeed, this attack is always inevitable as the attacker can always run the (sa)PAKE protocol in their head acting as both parties to test each password. With this being the case, we still need to take steps to defend against automated password attacks such as credential stuffing attacks and have ways of mitigating them.</p>
    <div>
      <h2>Are You Overexposed?</h2>
      <a href="#are-you-overexposed">
        
      </a>
    </div>
    <p>To help detect and respond to credential stuffing, Cloudflare recently <a href="/account-takeover-protection/">rolled out the Exposed Credential Checks feature</a> on the <a href="https://www.cloudflare.com/learning/ddos/glossary/web-application-firewall-waf/">Web Application Firewall (WAF)</a>, which can alert the origin if a user’s login credentials have appeared in a recent breach. Historically, compromised credential checking services have allowed users to be proactive against credential stuffing attacks when their username and password appear together in a breach. However, they do not account for <a href="https://scholar.google.com/scholar?cluster=1197873264049178787&amp;hl=en&amp;as_sdt=0,31">recently proposed credential tweaking attacks</a>, in which an attacker tries <i>variants</i> of a breached password, under the assumption that users often use slight modifications of the same password for different accounts, such as “sunshineFB”, “sunshineIG”, and so on. Therefore, compromised credential check services should incorporate methods of checking for credential tweaks.</p><p>Under the hood, Cloudflare’s Exposed Credential Checks feature relies on an underlying protocol deemed <a href="https://scholar.google.com/scholar?cluster=13673195091406912846&amp;hl=en&amp;as_sdt=0,31">Might I Get Pwned (MIGP)</a>. MIGP uses the bucketization method proposed in <a href="https://scholar.google.com/scholar?cluster=11401588548541554564&amp;hl=en&amp;as_sdt=0,31">Li et al.</a> to avoid sending the plaintext username or password to the server while handling a large breach dataset. After receiving a user’s credentials, MIGP hashes the username and sends a portion of that hash as a “bucket identifier” to the server. The client and server can then perform a private membership test protocol to verify whether the user’s username/password pair appeared in that bucket, without ever having to send plaintext credentials to the server.</p><p>Unlike previous compromised credential check services, MIGP also enables credential tweaking checks by augmenting the original breach dataset with a set of password “variants”. For each leaked password, it generates a list of password variants, which are labeled as such to differentiate them from the original leaked password and added to the original dataset. For more information, you can check out the Cloudflare Research <a href="/privacy-preserving-compromised-credential-checking">blog post</a> detailing our open-source implementation and deployment of the MIGP protocol.  </p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6s0cOYGpG1oabqonc0mF9O/11882b44b6803b77a7f7235c0e4efb01/image2-24.png" />
            
            </figure>
    <div>
      <h2>Measuring Credential Compromises</h2>
      <a href="#measuring-credential-compromises">
        
      </a>
    </div>
    <p>The question remains, just how important are these exposed credential checks for detecting and preventing credential stuffing attacks in practice? To answer this question, the Research Team has initiated a study investigating login requests to our own Cloudflare dashboard. For this study, we are collecting the data logged by Cloudflare’s Exposed Credential Check feature (described above), designed to be privacy-preserving: this check does not reveal a password, but provides a “yes/no” response on whether the submitted credentials appear in our breach dataset. Along with this signal, we are looking at other fields that may be indicative of malicious behavior such as <a href="/mitigating-bot-attacks-against-cloudflare/">bot score</a> and IP reputation. As this project develops, we plan to cluster the data to find patterns of different types of credential stuffing attacks that we can generalize to form attack fingerprints. We can then feed these fingerprints into the alert logs for the Cloudflare Detection &amp; Response team to see if they provide useful information for the security analysts.</p><p>Additionally, we hope to investigate potential post-compromise behavior as it relates to these compromise check fields. After an attacker successfully hijacks an account, they may take a number of actions such as changing the password, revoking all valid access tokens, or setting up a malicious script. By analyzing compromised credential checks along with these signals, we may be able to better differentiate benign from malicious behavior.</p>
    <div>
      <h3>Future directions: OPAQUE and MIGP combined</h3>
      <a href="#future-directions-opaque-and-migp-combined">
        
      </a>
    </div>
    <p>This post has discussed how we’re approaching the problem of preventing credential stuffing attacks from two different angles. Through the deployment and analysis of compromised credential checks, we aim to prevent server compromise by detecting and preventing credential stuffing attacks before they happen. In addition, in the case that a server does get compromised, the wider use of OPAQUE would help address the problem of leaking passwords to an attacker by avoiding the reception and storage of plaintext passwords on the server as well as preventing precomputation attacks.</p><p>However, there are still remaining research challenges to address. Notably, the current method for interfacing with MIGP still requires the server to either pass along a plaintext version of the client’s password, or trust the client to honestly communicate with the MIGP service on behalf of the server. If we want to leverage the security guarantees of OPAQUE (or generally an saPAKE) with the analytics and alert system provided by MIGP in a privacy-preserving way, we need additional mechanisms.</p><p>At first glance, the privacy-preserving goals of both protocols seem to be perfect matches for each other. Both OPAQUE and MIGP are built upon the idea of replacing the traditional salted password hashes with an OPRF as a way of keeping the client’s plaintext passwords from ever leaving their device. However, both the interfaces for these protocols rely on user-provided inputs which aren’t cryptographically tied to each other. This allows an attacker to provide a false password to MIGP while providing their actual password to the OPAQUE server. Further, the security analysis of both protocols assume that their idealized building blocks are separated in an important way. This isn’t to say that the two protocols are incompatible, and indeed, much of these protocols may be salvaged.</p><p>The next stages for password privacy will be an integration of these two protocols such that a server can be made aware of credential stuffing attacks and the patterns of compromised account usage that can protect a server against the compromise of other servers while providing the same privacy guarantees OPAQUE does. Our goal is to allow you to protect yourself from <i>other</i> compromised servers while protecting your clients from compromise of <i>your</i> server. Stay tuned for updates!</p><p>We’re always keen to collaborate with others to build more secure systems, and would love to hear from those interested in password research. You can reach us with questions, comments, and research ideas at <a>ask-research@cloudflare.com</a>. For those interested in joining our team, please visit our <a href="https://www.cloudflare.com/careers/jobs/?department=Technology%20Research&amp;location=default">Careers Page</a>.</p><p>...</p><p><sup>1</sup>There are other ways of constructing saPAKE protocols. The curious reader can see <a href="https://scholar.google.com/scholar?cluster=7458935618932751816&amp;hl=en&amp;as_sdt=0,31">this CRYPTO 2019 paper</a> for details.</p> ]]></content:encoded>
            <category><![CDATA[Research]]></category>
            <category><![CDATA[Security]]></category>
            <category><![CDATA[Product News]]></category>
            <category><![CDATA[Salt]]></category>
            <category><![CDATA[Passwords]]></category>
            <guid isPermaLink="false">5KZNCnkEzTgAysfN3nPrLX</guid>
            <dc:creator>Ian McQuoid</dc:creator>
            <dc:creator>Marina Sanusi</dc:creator>
            <dc:creator>Tara Whalen</dc:creator>
        </item>
        <item>
            <title><![CDATA[OPAQUE: The Best Passwords Never Leave your Device]]></title>
            <link>https://blog.cloudflare.com/opaque-oblivious-passwords/</link>
            <pubDate>Tue, 08 Dec 2020 12:00:00 GMT</pubDate>
            <description><![CDATA[ Imagine passwords for online services that never leave your device, encrypted or otherwise. OPAQUE is a new cryptographic protocol that makes this idea possible, giving you and only you full control of your password. ]]></description>
            <content:encoded><![CDATA[ 
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/ooidY51NqRXSzRAvVf2Kc/d952f9c1e38f135a535cbd1641b03d0f/Opaque-Header-1.png" />
            
            </figure><p><i>Update: On January 19, 2022, we added </i><a href="https://opaque-full.research.cloudflare.com/"><i>a new demo for the OPAQUE protocol</i></a><i>.</i></p><p>Passwords are a problem. They are a problem for reasons that are familiar to most readers. For us at Cloudflare, the problem lies much deeper and broader. Most readers will immediately acknowledge that passwords are hard to remember and manage, especially as password requirements grow increasingly complex. Luckily there are great software packages and browser add-ons to help manage passwords. Unfortunately, the greater underlying problem is beyond the reaches of software to solve.</p><p>The fundamental password problem is simple to explain, but hard to solve: A password that leaves your possession is guaranteed to sacrifice security, no matter its complexity or how hard it may be to guess. Passwords are insecure by their very existence.</p><p>You might say, “but passwords are always stored in encrypted format!” That would be great. More accurately, they are likely stored as a salted hash, as explained below. Even worse is that there is no way to verify the way that passwords are stored, and so we can assume that on some servers passwords are stored in cleartext. The truth is that even responsibly stored passwords can be leaked and broken, albeit (and thankfully) with enormous effort. An increasingly pressing problem stems from the nature of passwords themselves: any direct use of a password, today, means that the password must be handled in the clear.</p><p>You say, “but my password is transmitted securely over HTTPS!” This is true.</p><p>You say, “but I know the server stores my password in hashed form, secure so no one can access it!” Well, this puts a lot of faith in the server. Even so, let’s just say that yes, this may be true, too.</p><p>There remains, however, an important caveat — a gap in the end-to-end use of passwords. Consider that once a server receives a password, between being securely transmitted and securely stored, the password has to be read and processed. Yes, as cleartext!</p><p>And it gets worse — because so many are used to thinking in software, it’s easy to forget about the vulnerability of hardware. This means that even if the software is somehow trusted, the password must at some point reside in memory. The password must at some point be transmitted over a shared bus to the CPU. These provide vectors of attack to on-lookers in many forms. Of course, these attack vectors are far less likely than those presented by transmission and permanent storage, but they are no less severe (recent CPU vulnerabilities such as Spectre and Meltdown should serve as a stark reminder.)</p><p>The only way to fix this problem is to get rid of passwords altogether. There is hope! Research and private sector communities are working hard to do just that. New standards are emerging and growing mature. Unfortunately, passwords are so ubiquitous that it will take a long time to agree on and supplant passwords with new standards and technology.</p><p>At Cloudflare, we’ve been asking if there is something that can be done now, imminently. Today’s deep-dive into OPAQUE is one possible answer. OPAQUE is one among many examples of systems that enable a password to be useful without it ever leaving your possession. No one likes passwords, but as long they’re in use, at least we can ensure they are never given away.</p><p>I’ll be the first to admit that password-based authentication is annoying. Passwords are hard to remember, tedious to type, and notoriously insecure. Initiatives to reduce or replace passwords are promising. For example, <a href="/cloudflare-now-supports-security-keys-with-web-authentication-webauthn/">WebAuthn</a> is a standard for web authentication based primarily on public key cryptography using hardware <a href="https://github.com/github/SoftU2F">(or software)</a> tokens. Even so, passwords are frustratingly persistent as an authentication mechanism. Whether their persistence is due to their ease of implementation, familiarity to users, or simple ubiquity on the web and elsewhere, we’d like to make password-based authentication as secure as possible while they persist.</p><p>My internship at Cloudflare focused on OPAQUE, a cryptographic protocol that solves one of the most glaring security issues with password-based authentication on the web: though passwords are typically protected in transit by HTTPS, <b>servers</b> <b>handle them in plaintext</b> to check their correctness. Handling plaintext passwords is dangerous, as accidentally logging or caching them could lead to a catastrophic breach. The goal of the project, rather than to advocate for adoption of any particular protocol, is to show that OPAQUE is a viable option among many for authentication. Because the web case is most familiar to me, and likely many readers, I will use the web as my main example.</p>
    <div>
      <h3>Web Authentication 101: Password-over-TLS</h3>
      <a href="#web-authentication-101-password-over-tls">
        
      </a>
    </div>
    <p>When you type in a password on the web, what happens? The website must check that the password you typed is the same as the one you originally registered with the site. But how does this check work?</p><p>Usually, your username and password are sent to a server. The server then checks if the registered password associated with your username matches the password you provided. Of course, to prevent an attacker eavesdropping on your Internet traffic from stealing your password, your connection to the server should be encrypted via HTTPS (HTTP-over-TLS).</p><p>Despite use of HTTPS, there still remains a glaring problem in this flow: the server must store a representation of your password somewhere. Servers are hard to secure, and breaches are all too common. Leaking this representation can cause catastrophic security problems. (For records of the latest breaches, check out <a href="https://haveibeenpwned.com/">https://haveibeenpwned.com/</a>).</p><p>To make these leaks less devastating, servers often apply a <i>hash function</i> to user passwords. A hash function maps each password to a unique, random-looking value. It’s easy to apply the hash to a password, but almost impossible to reverse the function and retrieve the password. (That said, anyone can guess a password, apply the hash function, and check if the result is the same.)</p><p>With password hashing, plaintext passwords are no longer stored on servers.  An attacker who steals a password database no longer has direct access to passwords. Instead, the attacker must apply the hash to many possible passwords and compare the results with the leaked hashes.</p><p>Unfortunately, if a server hashes only the passwords, attackers can download precomputed <i>rainbow tables</i> containing hashes of trillions of possible passwords and almost instantly retrieve the plaintext passwords. (See <a href="https://project-rainbowcrack.com/table.htm">https://project-rainbowcrack.com/table.htm</a> for a list of some rainbow tables).</p><p>With this in mind, a good defense-in-depth strategy is to use <i>salted</i> hashing, where the server hashes your password appended to a random, per-user value called a <i>salt</i>. The server also saves the salt alongside the username, so the user never sees or needs to submit it. When the user submits a password, the server re-computes this hash function using the salt. An attacker who steals password data, i.e., the password representations and salt values, must then guess common passwords one by one and apply the (salted) hash function to each guessed password. Existing rainbow tables won’t help because they don’t take the salts into account, so the attacker needs to make a new rainbow table for each user!</p><p>This (hopefully) slows down the attack enough for the service to inform users of a breach, so they can change their passwords. In addition, the salted hashes should be <i>hardened</i> by applying a hash many times to further slow attacks. (See <a href="/keeping-passwords-safe-by-staying-up-to-date/">https://blog.cloudflare.com/keeping-passwords-safe-by-staying-up-to-date/</a> for a more detailed discussion).</p><p>These two mitigation strategies — encrypting the password in transit and storing salted, hardened hashes — are the current best practices.</p><p>A large security hole remains open. <i>Password-over-TLS</i> (as we will call it) requires users to <b>send plaintext passwords to servers during login</b>, because servers must see these passwords to match against registered passwords on file. Even a well-meaning server could accidentally cache or log your password attempt(s), or become corrupted in the course of checking passwords. (For example, Facebook detected in 2019 that it had <a href="https://about.fb.com/news/2019/03/keeping-passwords-secure/">accidentally been storing hundreds of millions of plaintext user passwords</a>). Ideally, servers should never see a plaintext password at all.</p><p>But that’s quite a conundrum: how can you check a password if you never see the password? Enter OPAQUE: a Password-Authenticated Key Exchange (PAKE) protocol that simultaneously proves knowledge of a password and derives a secret key. Before describing OPAQUE in detail, we’ll first summarize PAKE functionalities in general.</p>
    <div>
      <h3>Password Proofs with Password-Authenticated Key Exchange</h3>
      <a href="#password-proofs-with-password-authenticated-key-exchange">
        
      </a>
    </div>
    <p>Password-Authenticated Key Exchange (PAKE) was proposed by Bellovin and Merrit[1] in 1992, with an initial motivation of allowing password-authentication without the possibility of dictionary attacks based on data transmitted over an insecure channel.</p><p>Essentially, a plain, or <i>symmetric</i>, PAKE is a cryptographic protocol that allows two parties who share only a password to establish a strong shared secret key. The goals of PAKE are:</p><ol><li><p>The secret keys will match if the passwords match, and appear random otherwise.</p></li><li><p>Participants do not need to trust third parties (in particular, no Public Key Infrastructure),</p></li><li><p>The resulting secret key is not learned by anyone not participating in the protocol - including those who know the password.</p></li><li><p>The protocol does not reveal either parties’ password to each other (unless the passwords match), or to eavesdroppers.</p></li></ol><p>In sum, the only way to successfully attack the protocol is to guess the password correctly while participating in the protocol. (Luckily, such attacks can be mostly thwarted by rate-limiting, i.e, blocking a user from logging in after a certain number of incorrect password attempts).</p><p>Given these requirements, password-over-TLS is clearly <i>not</i> a PAKE, because:</p><ul><li><p>It relies on WebPKI, which places trust in third-parties called Certificate Authorities (see <a href="/introducing-certificate-transparency-and-nimbus/">https://blog.cloudflare.com/introducing-certificate-transparency-and-nimbus/</a> for an in-depth explanation of WebPKI and some of its shortcomings).</p></li><li><p>The user’s password is revealed to the server.</p></li><li><p>Password-over-TLS provides the user no assurance that the server knows their password or a derivative of it — a server could accept any input from the user with no checks whatsoever.</p></li></ul><p>That said, plain PAKE is still worse than Password-over-TLS, simply because it requires the server to <i>store</i> plaintext passwords. We need a PAKE that lets the server store salted hashes if we want to beat the current practice.</p><p>An improvement over plain PAKE is what’s called an <i>asymmetric</i> PAKE (aPAKE), because only the client knows the password, and the server knows a <i>hashed</i> password. An aPAKE has the four properties of PAKE, plus one more:</p><ol><li><p>An attacker who steals password data stored on the server must perform a dictionary attack to retrieve the password.</p></li></ol><p>The issue with most existing aPAKE protocols, however, is that they do not allow for a <i>salted</i> hash (or if they do, they require that salt to be transmitted to the user, which means the attacker has access to the salt beforehand and can begin computing a rainbow table for the user before stealing any data). We’d like, therefore, to upgrade the security property as follows:</p><p>5*) An attacker who steals password data stored on the server must perform a <i>per-user</i> dictionary attack to retrieve the password <i>after the data is compromised</i>.</p><p>OPAQUE is the first aPAKE protocol with a formal security proof that has this property: it allows for a completely secret salt.</p>
    <div>
      <h3>OPAQUE - Servers safeguard secrets without knowing them!</h3>
      <a href="#opaque-servers-safeguard-secrets-without-knowing-them">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/39WP72kgESNW6mjf08g5UM/db539617b444e7683825d02b9d704b14/opaque-wordmark.png" />
            
            </figure><p><a href="https://eprint.iacr.org/2018/163.pdf">OPAQUE</a> is what’s referred to as a <i>strong aPAKE</i>, which simply means that it resists these pre-computation attacks by using a secretly salted hash on the server. OPAQUE was proposed and formally analyzed by Stanislaw Jarecki, Hugo Krawcyzk and Jiayu Xu in 2018 (full disclosure: Stanislaw Jarecki is my academic advisor). The name OPAQUE is a combination of the names of two cryptographic protocols: OPRF and PAKE. We already know PAKE, but what is an OPRF? OPRF stands for Oblivious Pseudo-Random Function, which is a protocol by which two parties compute a function <i>F(key, x)</i> that is deterministic but outputs random-looking values. One party inputs the value <i>x</i>, and another party inputs the key - the party who inputs <i>x</i> learns the result <i>F(key, x)</i> but not the key, and the party providing the key learns nothing.  (You can dive into the math of OPRFs here: <a href="/privacy-pass-the-math/">https://blog.cloudflare.com/privacy-pass-the-math/</a>).</p><p>The core of OPAQUE is a method to store user secrets for safekeeping on a server, without giving the server access to those secrets. Instead of storing a traditional salted password hash, the server stores a secret envelope for you that is “locked” by two pieces of information: your password known only by you, and a random secret key (like a salt) known only by the server. To log in, the client initiates a cryptographic exchange that reveals the envelope key to the client, but, importantly, not to the server.</p><p>The server then sends the envelope to the user, who now can retrieve the encrypted keys. (The keys included in the envelope are a private-public key pair for the user, and a public key for the server.) These keys, once unlocked, will be the inputs to an Authenticated Key Exchange (AKE) protocol, which allows the user and server to establish a secret key which can be used to encrypt their future communication.</p><p>OPAQUE consists of two phases, being credential registration and login via key exchange.</p>
    <div>
      <h3>OPAQUE: Registration Phase</h3>
      <a href="#opaque-registration-phase">
        
      </a>
    </div>
    <p>Before registration, the user first signs up for a service and picks a username and password. Registration begins with the OPRF flow we just described: Alice (the user) and Bob (the server) do an OPRF exchange. The result is that Alice has a random key <b><i>rwd</i></b>, derived from the OPRF output <i>F(key, pwd), where key</i> is a server-owned OPRF key specific to Alice and <i>pwd</i> is Alice’s password.</p><p>Within his OPRF message, Bob sends the public key for his OPAQUE identity. Alice then generates a new private/public key pair, which will be her persistent OPAQUE identity for Bob’s service, and encrypts <i>her</i> private key along with <i>Bob’s</i> public key with the <b>rwd</b> (we will call the result an <i>encrypted envelope</i>). She sends this encrypted envelope along with her public key (unencrypted) to Bob, who stores the data she provided, along with Alice’s specific OPRF keysecret, in a database indexed by her username.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5FwREcK0qMw6EVKrxDjUyg/399a52baf731039c16d03644a57cb5f2/OPAQUE-diagram-1_3x.png" />
            
            </figure>
    <div>
      <h3>OPAQUE: Login Phase</h3>
      <a href="#opaque-login-phase">
        
      </a>
    </div>
    <p>The login phase is very similar. It starts the same way as registration — with an OPRF flow. However, on the server side, instead of generating a new OPRF key, Bob instead looks up the one he created during Alice’s registration. He does this by looking up Alice’s username (which she provides in the first message), and retrieving his record of her. This record contains her public key, her encrypted envelope, and Bob’s OPRF key for Alice.</p><p>He also sends over the encrypted envelope which Alice can decrypt with the output of the OPRF flow. (If decryption fails, she aborts the protocol — this likely indicates that she typed her password incorrectly, or Bob isn’t who he says he is). If decryption succeeds, she now has her own secret key and Bob’s public key. She inputs these into an AKE protocol with Bob, who, in turn, inputs his private key and her public key, which gives them both a fresh shared secret key.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/75WquAD9w7Z3AJ8RcBdtiF/03e77ccaad51380d96fcc8e1c395d1b8/OPAQUE-diagram-2_3x.png" />
            
            </figure>
    <div>
      <h3>Integrating OPAQUE with an AKE</h3>
      <a href="#integrating-opaque-with-an-ake">
        
      </a>
    </div>
    <p>An important question to ask here is: what AKE is suitable for OPAQUE? The <a href="https://tools.ietf.org/html/draft-irtf-cfrg-opaque-01">emerging CFRG specification</a> outlines several options, including 3DH and SIGMA-I. However, on the web, we already have an AKE at our disposal: TLS!</p><p>Recall that TLS is an AKE because it provides unilateral (and mutual) authentication with shared secret derivation. The core of TLS is a Diffie-Hellman key exchange, which by itself is <i>unauthenticated</i>, meaning that the parties running it have no way to verify who they are running it with. (This is a problem because when you log into your bank, or any other website that stores your private data, you want to be sure that they are who they say they are). Authentication primarily uses certificates, which are issued by trusted entities through a system called <a href="/how-to-build-your-own-public-key-infrastructure/">Public Key Infrastructure (PKI)</a>. Each certificate is associated with a secret key. To prove its identity, the server presents its certificate to the client, and signs the TLS handshake with its secret key.</p><p>Modifying this ubiquitous certificate-based authentication on the web is perhaps not the best place to start. Instead, an improvement would be to authenticate the TLS shared secret, <i>using</i> OPAQUE, after the TLS handshake completes. In other words, once a server is authenticated with its typical WebPKI certificate, clients could subsequently authenticate to the server. This authentication could take place “post handshake” in the TLS connection using OPAQUE.</p><p><a href="https://datatracker.ietf.org/doc/draft-ietf-tls-exported-authenticator/">Exported Authenticators</a> are one mechanism for “post-handshake” authentication in TLS. They allow a server or client to provide proof of an identity without setting up a new TLS connection. Recall that in the standard web case, the server establishes their identity with a certificate (proving, for example, that they are “cloudflare.com”). But if the same server also holds alternate identities, they must run TLS again to prove who they are.</p><p>The basic Exported Authenticator flow works resembles a classical challenge-response protocol, and works as follows. (We’ll consider the server authentication case only, as the client case is symmetric).</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3eYv5LQOx1cD9iTFxqfkAC/3231d07f2a1b4a140b345454dc2ca2e0/OPAQUE-diagram-3_3x.png" />
            
            </figure><p>At any point after a TLS connection is established, Alice (the client) sends an <i>authenticator request</i> to indicate that she would like Bob (the server) to prove an additional identity. This request includes a context (an unpredictable string — think of this as a challenge), and extensions which include information about what identity the client wants to be provided. For example, the client could include the SNI extension to ask the server for a certificate associated with a certain domain name other than the one initially used in the TLS connection.</p><p>On receipt of the client message, if the server has a valid certificate corresponding to the request, it sends back an <i>exported authenticator</i> which proves that it has the secret key for the certificate. (This message has the same format as an Auth message from the client in TLS 1.3 handshake - it contains a Certificate, a CertificateVerify and a Finished message). If the server cannot or does not wish to authenticate with the requested certificate, it replies with an empty authenticator which contains only a well formed Finished message.</p><p>The client then checks that the Exported Authenticator it receives is well-formed, and then verifies that the certificate presented is valid, and if so, accepts the new identity.</p><p>In sum, Exported Authenticators provide authentication in a higher layer (such as the application layer) safely by leveraging the well-vetted cryptography and message formats of TLS. Furthermore, it is tied to the TLS session so that authentication messages can't be copied and pasted from one TLS connection into another. In other words, Exported Authenticators provide exactly the right hooks needed to add OPAQUE-based authentication into TLS.</p>
    <div>
      <h3>OPAQUE with Exported Authenticators (OPAQUE-EA)</h3>
      <a href="#opaque-with-exported-authenticators-opaque-ea">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/13SUbsSrju6qTw13hFBhoh/8a41eefa575f8661b6c0b821d4516b72/OPAQUE-diagram-2_3x-1.png" />
            
            </figure><p><a href="https://datatracker.ietf.org/doc/html/draft-sullivan-tls-opaque-00">OPAQUE-EA</a> allows OPAQUE to run at any point after a TLS connection has already been set up. Recall that Bob (the server) will store his OPAQUE identity, in this case a signing key and verification key, and Alice will store her identity — encrypted — on Bob’s server. (The registration flow where Alice stores her encrypted keys is the same as in regular OPAQUE, except she stores a signing key, so we will skip straight to the login flow). Alice and Bob run two request-authenticate EA flows, one for each party, and OPAQUE protocol messages ride along in the extensions section of the EAs. Let’s look in detail how this works.</p><p>First, Alice generates her OPRF message based on her password. She creates an Authenticator Request asking for Bob’s OPAQUE identity, and includes (in the extensions field) her username and her OPRF message, and sends this to Bob over their established TLS connection.</p><p>Bob receives the message and looks up Alice’s username in his database. He retrieves her OPAQUE record containing her verification key and encrypted envelope, and his OPRF key. He uses the OPRF key on the OPRF message, and creates an Exported Authenticator proving ownership of his OPAQUE signing key, with an extension containing his OPRF message and the encrypted envelope. Additionally, he sends a new Authenticator Request asking Alice to prove ownership of her OPAQUE signing key.</p><p>Alice parses the message and completes the OPRF evaluation using Bob’s message to get output <i>rwd</i>, and uses <i>rwd</i> to decrypt the envelope. This reveals her signing key and Bob’s public key. She uses Bob’s public key to validate his Authenticator Response proof, and, if it checks out, she creates and sends an Exported Authenticator proving that she holds the newly decrypted signing key. Bob checks the validity of her Exported Authenticator, and if it checks out, he accepts her login.</p>
    <div>
      <h3>My project: OPAQUE-EA over HTTPS</h3>
      <a href="#my-project-opaque-ea-over-https">
        
      </a>
    </div>
    <p>Everything described above is supported by lots and lots of theory that has yet to find its way into practice. My project was to turn the theory into reality. I started with written descriptions of <a href="https://tools.ietf.org/html/draft-ietf-tls-exported-authenticator-13">Exported Authenticators</a>, <a href="https://tools.ietf.org/html/draft-irtf-cfrg-opaque-01">OPAQUE</a>, and a preliminary draft of <a href="https://tools.ietf.org/html/draft-sullivan-tls-opaque-00">OPAQUE-in-TLS</a>. My goal was to get from those to a working prototype.</p><p>My demo shows the feasibility of implementing OPAQUE-EA on the web, completely removing plaintext passwords from the wire, even encrypted. This provides a possible alternative to the current password-over-TLS flow with better security properties, but no visible change to the user.</p><p>A few of the implementation details are worth knowing. In computer science, abstraction is a powerful tool. It means that we can often rely on existing tools and APIs to avoid duplication of effort. In my project I relied heavily on <a href="https://github.com/bifurcation/mint">mint</a>, an open-source implementation of TLS 1.3 in Go that is great for prototyping. I also used <a href="https://github.com/cloudflare/circl/tree/master/oprf">CIRCL’s OPRF API</a>. I built libraries for Exported Authenticators, the core of OPAQUE, and OPAQUE-EA (which ties together the two).</p><p>I made the web demo by wrapping the OPAQUE-EA functionality in a simple HTTP server and client that pass messages to each other over HTTPS. Since a browser can’t run Go, I compiled from Go to WebAssembly (WASM) to get the Go functionality in the browser, and wrote a simple script in JavaScript to call the WASM functions needed.</p><p>Since current browsers do not give access to the underlying TLS connection on the client side, I had to implement a work-around to allow the client to access the exporter keys, namely, that the server simply computes the keys and sends them to the client over HTTPS. This workaround reduces the security of the resulting demo — it means that trust is placed in the server to provide the right keys. Even so, the user’s password is still safe, even if a malicious server provided bad keys— they just don’t have assurance that they actually previously registered with that server. However, in the future, browsers could include a mechanism to support exported keys and allow OPAQUE-EA to run with its full security properties.</p><p>You can explore my implementation <a href="https://github.com/cloudflare/opaque-ea">on Github</a>, and even follow the instructions to spin up your own OPAQUE-EA test server and client. I’d like to stress, however, that the implementation is meant as a proof-of-concept only, and must not be used for production systems without significant further review.</p>
    <div>
      <h3>OPAQUE-EA Limitations</h3>
      <a href="#opaque-ea-limitations">
        
      </a>
    </div>
    <p>Despite its great properties, there will definitely be some hurdles in bringing OPAQUE-EA from a proof-of-concept to a fully fledged authentication mechanism.</p><p><b>Browser support for TLS exporter keys.</b> As mentioned briefly before, to run OPAQUE-EA in a browser, you need to access secrets from the TLS connection called <i>exporter keys</i>. There is no way to do this in the current most popular browsers, so support for this functionality will need to be added.</p><p><b>Overhauling password databases.</b> To adopt OPAQUE-EA, servers need not only to update their password-checking logic, but also completely overhaul their password databases. Because OPAQUE relies on special password representations that can only be generated interactively, existing salted hashed passwords cannot be automatically updated to OPAQUE records. Servers will likely need to run a special OPAQUE registration flow on a user-by-user basis. Because OPAQUE relies on buy-in from both the client and the server, servers may need to support the old method for a while before all clients catch up.</p><p><b>Reliance on emerging standards.</b> OPAQUE-EA relies on OPRFs, which is in the process of standardization, and Exported Authenticators, a proposed standard. This means that support for these dependencies is not yet available in most existing cryptographic libraries, so early adopters may need to implement these tools themselves.</p>
    <div>
      <h3>Summary</h3>
      <a href="#summary">
        
      </a>
    </div>
    <p>As long as people still use passwords, we’d like to make the process as secure as possible. Current methods rely on the risky practice of handling plaintext passwords on the server side while checking their correctness. PAKEs, and (specifically aPAKEs) allow secure password login without ever letting the server see the passwords.</p><p>OPAQUE is also being explored within other companies. According to Kevin Lewi, a research scientist from the Novi Research team at Facebook, they are “excited by the strong cryptographic guarantees provided by OPAQUE and are actively exploring OPAQUE as a method for further safeguarding credential-protected fields that are stored server-side.”</p><p>OPAQUE is one of the best aPAKEs out there, and can be fully integrated into TLS. You can check out the core OPAQUE implementation <a href="https://github.com/cloudflare/opaque-core">here</a> and the demo TLS integration <a href="https://github.com/cloudflare/opaque-ea">here</a>. A running version of the demo is also available <a href="https://opaque.research.cloudflare.com/">here</a>. A Typescript client implementation of OPAQUE is coming soon. If you're interested in implementing the protocol, or encounter any bugs with the current implementation, please drop us a line at <a>ask-research@cloudflare.com</a>! Consider also subscribing to the <a href="https://irtf.org/cfrg">IRTF CFRG mailing list</a> to track discussion about the OPAQUE specification and its standardization.</p><p>[1] Bellovin, S. M., and Merritt, M. “Encrypted key exchange: Password-based protocols secure against dictionary attacks.” In Proc. IEEE Computer Society Symposium on Research in Security and Privacy (Oakland, May 1992), pp. 72–84.</p> ]]></content:encoded>
            <category><![CDATA[Privacy Week]]></category>
            <category><![CDATA[Research]]></category>
            <category><![CDATA[Passwords]]></category>
            <category><![CDATA[Protocols]]></category>
            <category><![CDATA[Security]]></category>
            <category><![CDATA[Salt]]></category>
            <guid isPermaLink="false">7daEt3ab6jwAnizdsMzbfl</guid>
            <dc:creator>Tatiana Bradley</dc:creator>
        </item>
        <item>
            <title><![CDATA[Moving Quicksilver into production]]></title>
            <link>https://blog.cloudflare.com/moving-quicksilver-into-production/</link>
            <pubDate>Wed, 25 Nov 2020 15:11:22 GMT</pubDate>
            <description><![CDATA[ We previously explained how and why we built Quicksilver. This second blog post is about the long journey to production which culminates with Kyoto Tycoon removal from Cloudflare infrastructure and points to the first signs of obsolescence. ]]></description>
            <content:encoded><![CDATA[ <p>One of the great arts of software engineering is making updates and improvements to working systems without taking them offline. For some systems this can be rather easy, spin up a new web server or load balancer, redirect traffic and you’re done. For other systems, such as the core distributed data store which keeps millions of websites online, it’s a bit more of a challenge.</p><p>Quicksilver is the data store responsible for storing and distributing the billions of KV pairs used to configure the millions of sites and Internet services which use Cloudflare. <a href="/introducing-quicksilver-configuration-distribution-at-internet-scale/">In a previous post</a>, we discussed why it was built and what it was replacing. Building it, however, was only a small part of the challenge. We needed to deploy it to production into a network which was designed to be fault tolerant and in which downtime was unacceptable.</p><p>We needed a way to deploy our new service seamlessly, and to roll back that deploy should something go wrong. Ultimately many, many, things did go wrong, and every bit of failure tolerance put into the system proved to be worth its weight in gold because none of this was visible to customers.</p>
    <div>
      <h2>The Bridge</h2>
      <a href="#the-bridge">
        
      </a>
    </div>
    <p>Our goal in deploying Quicksilver was to run it in parallel with our then existing KV distribution tool, Kyoto Tycoon. Once we had evaluated its performance and scalability, we would gradually phase out reads and writes to Kyoto Tycoon, until only Quicksilver was handling production traffic. To make this possible we decided to build a bridge - QSKTBridge.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6pUDqhqWX3ZCG0ihI9972P/a6b75ed8cf5e34d9c44c1d6229faf98e/image3-16.png" />
            
            </figure><p><i>Image Credit: </i><a href="https://en.wikipedia.org/wiki/Bodie_Creek_Suspension_Bridge"><i>https://en.wikipedia.org/wiki/Bodie_Creek_Suspension_Bridge</i></a></p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4AeGYvTKsKEaF4n4llh3KY/56f665316d1a91f6f1635a9fc0e13b96/image1-18.png" />
            
            </figure><p>Our bridge replicated from Kyoto Tycoon, sending write and delete commands to our Quicksilver root node. This bridge service was deployed on Kubernetes within our infrastructure, consumed the Kyoto Tycoon update feed, and wrote the batched changes every 500ms.</p><p>In the event of node failure or misconfiguration it was possible for multiple bridge nodes to be live simultaneously. To prevent duplicate entries we included a timestamp with each change. When writing into Quicksilver we used the Compare And Swap command to ensure that only one batch with a given timestamp would ever be written.</p>
    <div>
      <h3>First Baby Steps In To Production</h3>
      <a href="#first-baby-steps-in-to-production">
        
      </a>
    </div>
    <p>Gradually we began to point reads over a loopback interface from the Kyoto Tycoon port to the Quicksilver port. Fortunately we implemented the memcached and the KT HTTP protocol to make it transparent to the many client instances that connect to Kyoto Tycoon and Quicksilver.</p><p>We began with DOG, DOG is a virtual data center which serves traffic for Cloudflare employees only. It’s called DOG because we use it for dog-fooding. Testing releases on the dog-fooding data center helps prevent serious issues from ever reaching the rest of the world. Our DOG testing went suspiciously well, so we began to move forward with more of our data centers around the world. Little did we know this rollout would take more than a year!</p>
    <div>
      <h3>Replication Saturation</h3>
      <a href="#replication-saturation">
        
      </a>
    </div>
    <p>To make life easier for SREs provisioning a new data center, we implemented a bootstrap mechanism that pulls an entire database from a remote server. This was an easy win because our datastore library - <a href="https://symas.com/lmdb/">LMDB</a> - provides the ability to copy an entire LMDB environment to a file descriptor. Quicksilver simply wrapped this code and sent a specific version of the DB to a network socket using its file descriptor.</p><p>When bootstrapping our Quicksilver DBs to more servers, Kyoto Tycoon was still serving production traffic in parallel. As we mentioned in the first blogpost, Kyoto Tycoon has an exclusive write lock that is sensitive to I/O. We were used to the problems this can cause such as write bursts slowing down reads. This time around we found the separate bootstrap process caused issues. It filled the page cache quickly, causing I/O saturation, which impacted all production services reading from Kyoto Tycoon.</p><p>There was no easy fix to that, to bootstrap Quicksilver DBs in a datacenter we'd have to wait until it was moved offline for maintenance, which pushed the schedule beyond our initial estimates. Once we had a data center deployment we could finally see metrics of Quicksilver running in the wild. It was important to validate that the performance was healthy before moving on to the next data center. This required coordination with the engineering teams that consume from Quicksilver.</p>
    <div>
      <h3>The FL (front line) test candidate</h3>
      <a href="#the-fl-front-line-test-candidate">
        
      </a>
    </div>
    <p>Many requests reaching Cloudflare’s edge are forwarded to a component called FL, which acts as the "brain". It uses multiple configuration values to decide what to do with the request. It might apply the <a href="https://www.cloudflare.com/learning/ddos/glossary/web-application-firewall-waf/">WAF</a>, pass the request to Workers and so on. FL requires a lot of QS access, so it was the perfect candidate to help validate Quicksilver performance in a real environment.</p><p>Here are some screenshots showing FL metrics. The vertical red line marks the switchover point, on the left of the line is Kyoto Tycoon, on the right is Quicksilver. The drop immediately before the line is due to the upgrade procedure itself. We saw an immediate and significant improvement in error rates and response time by migrating to Quicksilver.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3VmLmi8X5cQlWQ722gNbTq/124a47513364913e9fae8b6db4d9c42e/image6-6.png" />
            
            </figure><p>The middle graph shows the error count. Green dot errors are non-critical errors: the first request to Kyoto Tycoon/Quicksilver failed so FL will try again. The red dot errors are the critical ones, they mean the second request also failed. In that case FL will return an error code to an end user. Both counts decreased substantially.</p><p>The bottom graph shows the read latency average from Kyoto Tycoon/Quicksilver. The average drops a lot and is usually around 500 microseconds and no longer reaches 1ms which it used to do quite often with Kyoto Tycoon.</p><p>Some readers may notice a few things. First of all, it was said earlier that the consumers were reading through the loopback interface. How come we experience errors there? How come we need 500us to read from Quicksilver?</p><p>At that time Cloudflare had some old SSDs and these could sometimes take <i>hundreds of milliseconds</i> to respond and this was affecting the response time from Quicksilver hence triggering read timeout from FL.</p><p>That was also obviously increasing the average response time above.</p><p>From there, some readers would ask why using averages and not percentiles? This screenshot dates back to 2017 and at that time the tool used for gathering FL metrics did not offer percentiles, only min, max and average.</p><p>Also, back then, all consumers were reading through TCP over loopback. Later on we switched to Unix socket.</p><p>Finally, we enabled memcached and KT HTTP malformed request detection. It appears that some consumers were sending us bogus requests and not monitoring the value returned properly, so they could not detect any error. We are now alerting on all bogus requests as this should never happen.</p>
    <div>
      <h3>Spotting the wood for the trees</h3>
      <a href="#spotting-the-wood-for-the-trees">
        
      </a>
    </div>
    <p>Removing Kyoto Tycoon on the edge took around a year. We'd done a lot of work already but rolling Quicksilver out to production services meant the project was just getting started. Thanks to the new metrics we put in place, we learned a lot about how things actually happen in the wild. And this let us come up with some ideas for improvement.</p><p>Our biggest surprise was that most of our replication delays were caused by saturated I/O and not network issues. This is something we could not easily see with Kyoto Tycoon. A server experiencing I/O contention could take seconds to write a batch to disk. It slowly became out of sync and then failed to propagate updates fast enough to its own clients, causing them to fall out of sync. The workaround was quite simple, if the latest received transaction log is over 30 seconds old, Quicksilver would disconnect and try the next server in the list of sources.</p><p>This was again an issue caused by aging SSDs. When a disk reaches that state it is very likely to be queued for a hardware replacement.</p><p>We quickly had to address another weakness in our codebase. A Quicksilver instance which was not currently replicating from a remote server would stop its own replication server, forcing clients to disconnect and reconnect somewhere else. The problem is this behavior has a cascading effect, if an intermediate server disconnects from its server to move somewhere else, it will disconnect all its clients, etc. The problem was compounded by an exponential backoff approach. In some parts of the world our replication topology has six layers, triggering the backoff many times caused significant and unnecessary replication lag. Ultimately the feature was fully removed.</p>
    <div>
      <h3>Reads, writes, and sad SSDs</h3>
      <a href="#reads-writes-and-sad-ssds">
        
      </a>
    </div>
    <p>We discovered that we had been underestimating the frequency of I/O errors and their effect on performance. LMDB maps the database file into memory and when the kernel experiences an I/O error while accessing the SSD, it will terminate Quicksilver with a SIGBUS. We could see these in kernel logs. I/O errors are a sign of unhealthy disks and cause us to see spikes in Quicksilver's read and write latency metrics. They can also cause spikes in the system load average, which affects all running services. When I/O errors occur, a check usually finds such disks are close to their maximum allowed write cycles, and further writes will cause a permanent failure.</p><p>Something we didn't anticipate was LMDB's interaction with our filesystem, causing high write amplification that increased I/O load and accelerated the wear and tear of our SSDs. For example, when Quicksilver wrote 1 megabyte, 30 megabytes were flushed to disk. This amplification is due to LMDB copy-on-write, writing a 2 byte key-value (KV) pair ends up copying the whole page. That was the price to pay for crashproof storage. We've seen amplification factors between 1.5X and 80X. All of this happens before any internal amplification that might happen in an SSD.</p><p>We also spotted that some producers kept writing the same KV pair over and over. Although we saw low rates of 50 writes per second, considering the amplification problem above, repetition increased pressure on SSDs. To fix this we just drop identical KV writes on the root node.</p>
    <div>
      <h3>Where does a server replicate from?</h3>
      <a href="#where-does-a-server-replicate-from">
        
      </a>
    </div>
    <p>Each small data center replicates from multiple bigger sites and these replicate from our two core data centers. To decide which data centers to use, we talk to the Network team, get an answer and hardcode the topology in Salt, the same place we configure all our infrastructure.</p><p>Each replication node is identified using IP addresses in our Salt configuration. This is quite a rigid way of doing things, wouldn't DNS be easier? The interesting thing is that Quicksilver is a source of DNS for customers and Cloudflare infrastructure. We do not want Quicksilver to become dependent on itself, that could lead to problems.</p><p>While this somewhat rigid way of configuring topology works fine, as Cloudflare continues to scale there is room for improvement. Configuring Salt can be tricky and changes need to be thoroughly tested to avoid breaking things. It would be nicer for us to have a way to build the topology more dynamically, allowing us to more easily respond to any changes in network details and provision new data centers. That is something we are working on.</p>
    <div>
      <h3>Removing Kyoto Tycoon from the Edge</h3>
      <a href="#removing-kyoto-tycoon-from-the-edge">
        
      </a>
    </div>
    <p>Migrating services away from Kyoto Tycoon requires identifying them. There were some obvious candidates like FL and DNS which play a big part in day-to-day Cloudflare activity and do a lot of reads. But the tricky part to completely removing Kyoto Tycoon is in finding <b>all</b> the services that use it.</p><p>We informed engineering teams of our migration work but that was not enough. Some consumers get less attention because they were done during a research activity, or they run as part of a team's side project. We added some logging code into Kyoto Tycoon so we could see who exactly was connecting and reached out directly to them. That's a good way to catch the consumers that are permanently connected or connect often. However, some consumers only connect rarely and briefly, for example at startup time to load some configuration. So this takes time.</p><p>We also spotted some special cases that used exotic setups like using stunnel to read from the memcached interface remotely. That might have been a "quick-win" back in the day but its technical debt that has to be paid off; we now strictly enforce the methods that consumers use to access Quicksilver.</p><p>The migration activity was steady and methodical and it took a few months. We deployed Quicksilver per group of data centers and instance by instance, removing Kyoto Tycoon only when we deemed it ready. We needed to support two sets of configuration and alerting in parallel. That's not ideal but it gave us confidence and ensured that customers were not disrupted. The only thing they might have noticed is the performance improvement!</p>
    <div>
      <h3>Quicksilver, Core side, welcome to the mouth of technical debt madness</h3>
      <a href="#quicksilver-core-side-welcome-to-the-mouth-of-technical-debt-madness">
        
      </a>
    </div>
    <p>Once the edge migration was complete, it was time to take care of the core data centers. We just dealt with 200+ data centers so doing two should be easy right? Well no, the edge side of Quicksilver uses the reading interface, the core side is the writing interface so it is a totally different kind of job. Removing Kyoto Tycoon from the core was harder than the edge.</p><p>Many Kyoto Tycoon components were all running on a <b><i>single</i></b> physical server - the Kyoto Tycoon root node. This single point of failure had become a growing risk over the years. It had been responsible for incidents, for example it once completely disappeared due to faulty hardware. In that emergency we had to start all services on a backup server. The move to Quicksilver was a great opportunity to remove the Kyoto Tycoon root node server. This was a daunting task and almost all the engineering teams across the company got involved.</p><p><i>Note: Cloudflare’s migration from Marathon to Kubernetes was happening in parallel to this task so each time we refer to Kubernetes it is likely that the job was started on Marathon before being migrated later on.</i></p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1D3wqBGrywDAwzET2SJSpA/35969bba003824ef7828842b97ce44fa/Quicksilver-blog-_2x--1-.png" />
            
            </figure><p>The diagram above shows how all components below interact with each other.</p>
    <div>
      <h3>From KTrest to QSrest</h3>
      <a href="#from-ktrest-to-qsrest">
        
      </a>
    </div>
    <p>KTrest is a stateless service providing a REST interface for writing and deleting KV pairs from Kyoto Tycoon. Its only purpose is to enforce access control (ACL) so engineering teams do not experience accidental keyspace overlap. Of course, sometimes keyspaces are shared on purpose but it is not the norm.</p><p>The Quicksilver team took ownership of KTrest and migrated it from the root server to Kubernetes. We asked all teams to move their KTrest producers to Kubernetes as well. This went smoothly and did not require code changes in the services.</p><p>Our goal was to move people to Quicksilver, so we built QSrest, a KTrest compatible service for Quicksilver. Remember the problem about disk load? The QSKTBridge was in charge of batching: aggregating 500ms of updates before flushing to Quicksilver, to help our SSDs cope with our sync frequency. If we moved people to QSrest, it needed to support batching too. So it does. We used QSrest as an opportunity to implement write quotas. Once a quota is reached, all further writes from the same producer would be slowed down until the quota goes back to normal.</p><p>We found that not all teams actually used KTrest. Many teams were still writing directly to Kyoto Tycoon. One reason for this is that they were sending large range read requests in order to read thousands of keys in one shot - a feature that KTrest did not provide. People might ask why we would allow reads on a write interface. This is an unfortunate historical artefact and we wanted to put things right. Large range requests would hurt Quicksilver (we learned this from our experience with the bootstrap mechanism) so we added a cluster of servers which would serve these range requests: the Quicksilver consumer nodes. We asked the teams to switch their writes to KTrest and their reads to Quicksilver consumers.</p><p>Once the migration of the producers out of the root node was complete, we asked teams to start switching from KTrest to QSrest. Once the move was started, moving back would be really hard: our Kyoto Tycoon and Quicksilver DB were now inconsistent. We had to move over 50 producers, owned by teams in different time zones. So we did it one after another while carefully babysitting our servers to spot any early warning which could end up in an incident.</p><p>Once we were all done, we then started to look at Kyoto Tycoon transaction logs: is there something still writing to it? We found an obsolete heartbeat mechanism which was shut down.</p><p>Finally, Kyoto Tycoon root processes were turned off to never be turned on again.</p><p><i>Removing Kyoto Tycoon from all over Cloudflare ended up taking four years.</i></p>
    <div>
      <h2>No hardware single point of failure</h2>
      <a href="#no-hardware-single-point-of-failure">
        
      </a>
    </div>
    <p>We have made great progress, Kyoto Tycoon is no longer among us, we smoothly moved all Cloudflare services to Quicksilver, our new KV store. And things now look more like this.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2TAvdFTskE3MjXy8GF8GUP/c5959a7d5ae9ea84a195db68fd673491/Quicksilver-blog-2_2x.png" />
            
            </figure><p>The job is still far from done though. The Quicksilver root server was still a single point of failure, so we decided to build Quicksilver Raft - a <a href="https://en.wikipedia.org/wiki/Raft_(computer_science)">Raft</a>-enabled root cluster using the etcd Raft package. It was harder than I originally thought. Adding Raft into Quicksilver required proper synchronization between the Raft snapshot and the current Quicksilver DB. Sometimes there are situations where Quicksilver needs to fall back to asynchronous replication to catch up before doing proper Raft synchronous writes. Getting all of this to work required deep changes in our code base, which also proved to be hard to build proper unit and integration tests. But removing single points of failure is worth it.</p>
    <div>
      <h2>Introducing QSQSBridge</h2>
      <a href="#introducing-qsqsbridge">
        
      </a>
    </div>
    <p>We like to test our components in an environment very close to production before releasing it. How do we test the core side/writer interface of Quicksilver then? Well the days of Kyoto Tycoon, we used to have a second Quicksilver root node feeding from Kyoto Tycoon through the KTQSbridge. In turn, some very small data centers were being fed from that root node. When Kyoto Tycoon was removed we lost that capability, limiting our testing. So we built QSQSbridge, which replicates from a Quicksilver instance and writes to a Quicksilver root node.</p>
    <div>
      <h2>Removing the Quicksilver legacy top-main</h2>
      <a href="#removing-the-quicksilver-legacy-top-main">
        
      </a>
    </div>
    <p>With Quicksilver Raft and QSQSbridge in place, we tested three small data centers replicating from the test Raft cluster over the course of weeks. We then wanted to promote the high availability (HA) cluster and make the whole world replicate from it. In the same way we did for Kyoto Tycoon removal, we wanted to be able to roll back at any time if things go wrong.</p><p>Ultimately we reworked the QSQSbridge so that it builds compatible transaction logs with the feeding root node. That way, we started to move groups of data centers underneath the Raft cluster and we could, at any time, move them back to the legacy lop-main.</p><p>We started with this:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5D04BFHgTQ5PLvyJy8zsTo/292e21bd14efd716055e4065f558e86b/Quicksilver-blog-3_2x--1-.png" />
            
            </figure><p>We moved our 10 QSrest instances one after another from the legacy root node to write against the HA cluster. We did this slowly without any significant issue and we were finally able to turn off the legacy top-main.This is what we ended up with:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1qOBQIBnPZVqpOuQ9co2zK/e5c9f669c0ce7f2c11959a6f68ec4cd2/Quicksilver-blog-4_2x.png" />
            
            </figure><p>And that was it, <i>Quicksilver was running in the wild without a hardware single point of failure.</i></p>
    <div>
      <h2>First signs of obsolescence</h2>
      <a href="#first-signs-of-obsolescence">
        
      </a>
    </div>
    <p>The Quicksilver bootstrap mechanism we built to make SRE life better worked by pulling a full copy of a database but it had pains. When bootstrapping begins, a long lived read transaction is opened on the server, it must keep the DB version requested intact while also applying new log entries. This causes two problems. First, if the read is interrupted by something like a network glitch the read transaction is closed and the version of the DB is not available anymore. The entire process has to start from scratch. Secondly, it causes fragmentation in the source DB, which requires somebody to go and compact it.</p><p>For the first six months, the databases were fairly small and everything worked fine. However, as our databases continued to grow, these two problems came to fruition. Longer transfers are at risk of network glitches and the problem compounds, especially for more remote data centers. Longer transfers mean more fragmentation and more time compacting it. Bootstrapping was becoming a pain.</p><p>One day an SRE reported that manually bootstrapping instances one after another was much faster than bootstrapping all together in parallel. We investigated and saw that when all Quicksilver instances were bootstrapping at the same time the kernel and SSD were overwhelmed swapping pages. There was page cache contention caused by the ratio of the combined size of the DBs vs. available physical memory.</p><p>The workaround was to serialize bootstrapping across instances. We did this by implementing a lock between Quicksilver processes, a client grabs the lock to bootstrap and gives it back once done, ready for the next client. The lock moves around in round robin fashion forever.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/525KVnuK1hF4S7YuihIwP4/a1d0607e4410d87240b9b356192bc248/Quicksilver-blog-5_2x.png" />
            
            </figure><p>Unfortunately, we hit another page cache thrashing issue. We know that LMDB mostly does random I/O but we turned on readahead to load as much DB as possible into memory. But again as our DBs grew, the readahead started evicting useful pages. So we improved the performance by… disabling it.</p><p>Our biggest issue by far though is more fundamental: disk space and wear and tear! Each and every server in Cloudflare stores the same data. So a piece of data one megabyte in size consumes at least 10 gigabytes globally. To accommodate continued growth you can add more disks, replace dying disks, and use bigger disks. That's not a very sustainable solution. It became clear that the Quicksilver design we came up with five years ago was becoming obsolete and needed a rethink. We approach that problem both in the short term and long term.</p>
    <div>
      <h2>The long and short of it</h2>
      <a href="#the-long-and-short-of-it">
        
      </a>
    </div>
    <p>In the long term we are now working on a sharded version of Quicksilver. This will avoid storing all data on all machines but guarantee the entire dataset is in each data center.</p><p>In the shorter term we have addressed our storage size problems with a few approaches.</p><p>Many engineering teams did not even know how many bytes of Quicksilver they used. Some might have had an impression that storage is free. We built a service named “QSusage” which uses the QSrest ACL to match KV with their owner and computes the total disk space used per producer, including Quicksilver metadata. This service allows teams to better understand their usage and pace of growth.</p><p>We also built a service name "QSanalytics" to help answer the question “How do I know which of my KV pairs are never used?”. It gathers all keys being accessed all over Cloudflare, aggregates these and pushes these into a ClickHouse cluster and we store these information over a 30 days rolling window. There's no sampling here, we keep track of all read access. We can easily report back to engineering teams responsible for unused keys, they can consider if these can be deleted or must be kept.</p><p>Some of our issues are caused by the storage engine LMDB. So we started to look around and got quickly interested in RocksDB. It provides built in compression, online defragmentation and other features like prefix deduplication.</p><p>We ran some tests using representative Quicksilver data and they seemed to show that RocksDB could store the same data in 40% of the space compared to LMDB. Read latency was a little bit higher in some cases but nothing too serious. CPU usage was also higher, using around 150% of CPU time compared to LMDBs 70%. Write amplification appeared to be much lower, giving some relief to our SSD and the opportunity to ingest more data.</p><p>We decided to switch to RocksDB to help sustain our growing product and customer bases. In a follow-up blog we'll do a deeper dive into performance comparisons and explain how we managed to switch the entire business without impacting customers at all.</p>
    <div>
      <h2>Conclusion</h2>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>Migrating from Kyoto Tycoon to Quicksilver was no mean feat. It required company-wide collaboration, time and patience to smoothly roll out a new system without impacting customers. We've removed single points of failure and improved the performance of database access, which helps to deliver a better experience.</p><p>In the process of moving to Quicksilver we learned a lot. Issues that were unknown at design time were surfaced by running software and services at scale. Furthermore, as the customer and product base grows and their requirements change, we've got new insight into what our KV store needs to do in the future. Quicksilver gives us a solid technical platform to do this.</p> ]]></content:encoded>
            <category><![CDATA[Product News]]></category>
            <category><![CDATA[Salt]]></category>
            <guid isPermaLink="false">2fYMrDzxCQdRGlWLH3WxlU</guid>
            <dc:creator>Geoffrey Plouviez</dc:creator>
        </item>
        <item>
            <title><![CDATA[How Cloudflare uses Cloudflare Spectrum: A look into an intern’s project at Cloudflare]]></title>
            <link>https://blog.cloudflare.com/how-cloudflare-uses-cloudflare-spectrum-a-look-into-an-interns-project-at-cloudflare/</link>
            <pubDate>Fri, 21 Aug 2020 11:00:00 GMT</pubDate>
            <description><![CDATA[ As part of my onboarding as an intern on the Spectrum (a layer 4 reverse proxy) team, I learned that many internal services dogfood Spectrum, as they are exposed to the Internet and benefit from layer 4 DDoS protection. ]]></description>
            <content:encoded><![CDATA[ 
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3Z5QW1BQ7OCth8QdTIQddz/6db79a8f7df3cad36ac62c12ca2b65ba/Dogfooding-Spectrum_2x-1.png" />
            
            </figure><p>Cloudflare extensively uses its own products internally in a process known as <a href="https://en.wikipedia.org/wiki/Eating_your_own_dog_food">dogfooding</a>. As part of my onboarding as an intern on the Spectrum (a layer 4 reverse proxy) team, I learned that many internal services dogfood Spectrum, as they are exposed to the Internet and benefit from layer 4 DDoS protection. One of my first tasks was to update the configuration for an internal service that was using Spectrum. The configuration was managed in Salt (<a href="/manage-cloudflare-records-with-salt/">used for configuration management at Cloudflare</a>), which was not particularly user-friendly, and required an engineer on the Spectrum team to handle updating it manually.</p><p>This process took about a week. That should instantly raise some questions, as a typical Spectrum customer can create a new Spectrum app in under a minute through Cloudflare Dashboard. So why couldn’t I?</p><p>This question formed the basis of my intern project for the summer.</p>
    <div>
      <h3>The Process</h3>
      <a href="#the-process">
        
      </a>
    </div>
    <p>Cloudflare uses various IP ranges for its products. Some customers also authorize Cloudflare to announce their IP prefixes on their behalf (this is known as <a href="https://developers.cloudflare.com/spectrum/getting-started/byoip/">BYOIP</a>). Collectively, we can refer to these IPs as <i>managed</i> addresses. To prevent Bad Stuff (defined later) from happening, we prohibit managed addresses from being used as Spectrum origins. To accomplish this, <a href="https://www.cloudflare.com/products/cloudflare-spectrum/">Spectrum</a> had its own table of denied networks that included the managed addresses. For the average customer, this approach works great – they have no legitimate reason to use a managed address as an origin.</p><p>Unfortunately, the services dogfooding Spectrum all use Cloudflare IPs, preventing those teams with a legitimate use-case from creating a Spectrum app through the configuration service (i.e. Cloudflare Dashboard). To bypass this check, these <i>internal customers</i> needed to define a custom Spectrum configuration, which needed to be manually deployed to the edge via a pull request to our Salt repo, resulting in a time consuming process.</p><p>If an internal customer wanted to change their configuration, the same time consuming process must be used. While this allowed internal customers to use Spectrum, it was tedious and error prone.</p>
    <div>
      <h3>Bad Stuff</h3>
      <a href="#bad-stuff">
        
      </a>
    </div>
    <p><i>Bad Stuff</i> is quite vague and deserves a better definition. It may seem arbitrary that we deny Cloudflare managed addresses. To motivate this, consider two Spectrum apps, A and B, where the origin of app A is the Cloudflare edge IP of app B, and the origin of app B is the edge IP of app A. Essentially, app A will proxy incoming connections to app B, and app B will proxy incoming connections to app A, creating a cycle.</p><p>This could potentially crash the daemon or degrade performance. In practice, this configuration is useless and would only be created by a malicious user, as the proxied connection never reaches an origin, so it is never allowed.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1RAT655ZFI4uFjH14ymleJ/93d5e29de5b132b635bbea52560b006d/Spectrum-loop_2x.png" />
            
            </figure><p>In fact, the more general case of setting another Spectrum app as an origin (even when the configuration does not result in a cycle) is (almost<sup><a href="#footnote">1</a></sup>) never needed, so it also needs to be avoided.</p><p>As well, since we are providing a reverse proxy to customer origins, we do not need to allow connections to IP ranges that cannot be used on the public Internet, as specified in this <a href="https://tools.ietf.org/html/rfc6890">RFC</a>.</p>
    <div>
      <h3>The Problem</h3>
      <a href="#the-problem">
        
      </a>
    </div>
    <p>To improve usability and allow internal Spectrum customers to create apps using the Dashboard instead of the static configuration workflow, we needed a way to give particular customers permission to use Cloudflare managed addresses in their Spectrum configuration. Solving this problem was my main project for the internship.</p><p>A good starting point ended up being the Addressing API. The Addressing API is Cloudflare’s solution to IP management, an internal database and suite of tools to keep track of IP prefixes, with the goal of providing a unified source of truth for how IP addresses are being used across the organization. This makes it possible to provide a cross-product platform for products and features such as <a href="https://developers.cloudflare.com/spectrum/getting-started/byoip/">BYOIP</a>, <a href="/tag/bgp/">BGP On Demand</a>, and <a href="https://www.cloudflare.com/magic-transit/">Magic Transit</a>.</p><p>The Addressing API keeps track of all Cloudflare managed IP prefixes, along with who owns the prefix. As well, the owner of a prefix can give permission for someone else to use the prefix. We call this a <i>delegation</i>.</p><p>A user’s permission to use an IP address managed by the Addressing API is determined as followed:</p><ol><li><p>Is the user the owner of the prefix containing the IP address?a) Yes, the user has permission to use the IPb) No, go to step 2</p></li><li><p>Has the user been delegated a prefix containing the IP address?a) Yes, the user has permission to use the IP.b) No, the user does not have permission to use the IP.</p></li></ol>
    <div>
      <h3>The Solution</h3>
      <a href="#the-solution">
        
      </a>
    </div>
    <p>With the information present in the Addressing API, the solution starts to become clear. For a given customer and IP, we use the following algorithm:</p><ol><li><p>Is the IP managed by Cloudflare (or contained in the previous <a href="https://tools.ietf.org/html/rfc6890">RFC</a>)?a) Yes, go to step 2b) No, allow as origin</p></li><li><p>Does the customer have permission to use the IP address?a) Yes, allow as originb) No, deny as origin</p></li></ol><p>As long as the internal customer has been given permission to use the Cloudflare IP (through a delegation in the Addressing API), this approach would allow them to use it as an origin.</p><p>However, we run into a corner case here – since BYOIP customers also have permission to use their own ranges, they would be able to set their own IP as an origin, potentially causing a cycle. To mitigate this, we need to check if the IP is a Spectrum edge IP. Fortunately, the Addressing API also contains this information, so all we have to do is check if the given origin IP is already in use as a Spectrum edge IP, and if so, deny it. Since all of the denied networks checks occur in the Addressing API, we were able to remove Spectrum's own deny network database, reducing the engineering workload to maintain it along the way.</p><p>Let's go through a concrete example. Consider an internal customer who wants to use 104.16.8.54/32 as an origin for their Spectrum app. This address is managed by Cloudflare, and suppose the customer has permission to use it, and the address is not already in use as an edge IP. This means the customer is able to specify this IP as an origin, since it meets all of our criteria.</p><p>For example, a request to the Addressing API could look like this:</p>
            <pre><code>curl --silent 'https://addr-api.internal/edge_services/spectrum/validate_origin_ip_acl?cidr=104.16.8.54/32' -H "Authorization: Bearer $JWT" | jq .
{
  "success": true,
  "errors": [],
  "result": {
    "allowed_origins": {
      "104.16.8.54/32": {
        "allowed": true,
        "is_managed": true,
        "is_delegated": true,
        "is_reserved": false,
        "has_binding": false
      }
    }
  },
  "messages": []
}</code></pre>
            <p>Now we have completely moved the responsibility of validating the use of origin IP addresses from Spectrum’s configuration service to the Addressing API.</p>
    <div>
      <h3>Performance</h3>
      <a href="#performance">
        
      </a>
    </div>
    <p>This approach required making another HTTP request on the critical path of every create app request in the Spectrum configuration service. Some basic performance testing showed (as expected) increased response times for the API call (about 100ms). This led to discussion among the Spectrum team about the performance impact of different HTTP requests throughout the critical path. To investigate, we decided to use OpenTracing.</p><p><a href="https://opentracing.io/">OpenTracing</a> is a standard for providing distributed tracing of microservices. When an HTTP request is received, special headers are added to it to allow it to be traced across the different services. Within a given trace, we can see how long a SQL query took, the time a function took to complete, the amount of time a request spent at a given service, and more.</p><p>We have been deploying a tracing system for our services to provide more visibility into a complex system.</p><p>After instrumenting the Spectrum config service with OpenTracing, we were able to determine that the Addressing API accounted for a very small amount of time in the overall request, and allowed us to identify potentially problematic request times to other services.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4hdvsPKhjS41OxLNPDltxj/27ccf978efbe73a81d47960aa6dcf981/image1-14.png" />
            
            </figure>
    <div>
      <h3>Lessons Learned</h3>
      <a href="#lessons-learned">
        
      </a>
    </div>
    <p>Reading documentation is important! Having a good understanding of how the Addressing API and the config service worked allowed me to create and integrate an endpoint that made sense for my use-case.</p><p>Writing documentation is just as important. For the final part of my project, I had to onboard <a href="/project-crossbow-lessons-from-refactoring-a-large-scale-internal-tool/">Crossbow</a> – an internal Cloudflare tool used for diagnostics – to Spectrum, using the new features I had implemented. I had written an onboarding guide, but some stuff was unclear during the onboarding process, so I made sure to gather feedback from the Crossbow team to improve the guide.</p><p>Finally, I learned not to underestimate the amount of complexity required to implement relatively simple validation logic. In fact, the implementation required understanding the entire system. This includes how multiple microservices work together to validate the configuration and understanding how the data is moved from the Core to the Edge, and then processed there. I found increasing my understanding of this system to be just as important and rewarding as completing the project.</p><p><a href="http://staging.blog.mrk.cfdata.org/introducing-regional-services/">Regional Services</a> actually makes use of proxying a Spectrum connection to another colocation, and then proxying to the origin, but the configuration plane is not involved in this setup.</p> ]]></content:encoded>
            <category><![CDATA[Spectrum]]></category>
            <category><![CDATA[Product News]]></category>
            <category><![CDATA[Internship Experience]]></category>
            <category><![CDATA[Salt]]></category>
            <guid isPermaLink="false">2I8392q8zDjUlkCyIJ2vAk</guid>
            <dc:creator>Ryan Jacobs</dc:creator>
        </item>
        <item>
            <title><![CDATA[Cloudflare Bot Management: machine learning and more]]></title>
            <link>https://blog.cloudflare.com/cloudflare-bot-management-machine-learning-and-more/</link>
            <pubDate>Wed, 06 May 2020 11:00:00 GMT</pubDate>
            <description><![CDATA[ This is the ongoing story of Bot Management at Cloudflare and also an introduction to a series of blog posts about the detection mechanisms powering it ]]></description>
            <content:encoded><![CDATA[ <p></p>
    <div>
      <h3>Introduction</h3>
      <a href="#introduction">
        
      </a>
    </div>
    <p>Building <a href="https://www.cloudflare.com/application-services/products/bot-management/">Cloudflare Bot Management platform</a> is an exhilarating experience. It blends Distributed Systems, Web Development, Machine Learning, Security and Research (and every discipline in between) while fighting ever-adaptive and motivated adversaries at the same time.</p><p>This is the ongoing story of Bot Management at Cloudflare and also an introduction to a series of blog posts about the detection mechanisms powering it. I’ll start with several definitions from the Bot Management world, then introduce the product and technical requirements, leading to an overview of the platform we’ve built. Finally, I’ll share details about the detection mechanisms powering our platform.</p><p>Let’s start with Bot Management’s nomenclature.</p>
    <div>
      <h3>Some Definitions</h3>
      <a href="#some-definitions">
        
      </a>
    </div>
    <p><a href="https://www.cloudflare.com/learning/bots/what-is-a-bot/"><b>Bot</b></a> - an autonomous program on a network that can interact with computer systems or users, imitating or replacing a human user's behavior, performing repetitive tasks much faster than human users could.</p><p><b>Good bots</b> - bots which are useful to businesses they interact with, e.g. <a href="https://www.cloudflare.com/learning/bots/what-is-a-web-crawler/">search engine bots</a> like Googlebot, Bingbot or bots that operate on social media platforms like Facebook Bot.</p><p><b>Bad bots</b> - bots which are designed to perform malicious actions, ultimately hurting businesses, e.g. <a href="https://www.cloudflare.com/learning/bots/what-is-credential-stuffing/">credential stuffing</a> bots, <a href="https://www.cloudflare.com/learning/bots/what-is-data-scraping/">third-party scraping</a> bots, <a href="https://www.cloudflare.com/learning/bots/what-is-a-spambot/">spam</a> bots and sneakerbots.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5nwyutK4DVA1cjsfMY8ore/fd2ebf6ec92ec7795ea423f4e7d61713/image12.png" />
            
            </figure><p><a href="https://www.cloudflare.com/learning/bots/what-is-bot-management/"><b>Bot Management</b></a> - blocking undesired or malicious Internet bot traffic while still allowing useful bots to access web properties by detecting bot activity, discerning between desirable and undesirable bot behavior, and identifying the sources of the undesirable activity.</p><p><a href="https://www.cloudflare.com/learning/ddos/glossary/web-application-firewall-waf/"><b>WAF</b></a> - a security system that monitors and controls network traffic based on a set of security rules.</p>
    <div>
      <h3>Gathering requirements</h3>
      <a href="#gathering-requirements">
        
      </a>
    </div>
    <p>Cloudflare has been stopping malicious bots from accessing websites or misusing <a href="https://www.cloudflare.com/learning/security/api/what-is-an-api/">APIs</a> from the very <a href="/cloudflare-uses-intelligent-caching-to-avoid/">beginning</a>, at the same time <a href="/cleaning-up-bad-bots/">helping the climate</a> by offsetting the carbon costs from the bots. Over time it became clear that we needed a dedicated platform which would unite different bot fighting techniques and streamline the customer experience. In designing this new platform, we tried to fulfill the following key requirements.</p><ul><li><p><b>Complete, not complex</b> - customers can turn on/off Bot Management with a single click of a button, to protect their websites, mobile applications, or <a href="https://www.cloudflare.com/application-services/solutions/api-security/">APIs</a>.</p></li><li><p><b>Trustworthy</b> - customers want to know whether they can trust the website visitor is who they say they are and provide a certainty indicator for that trust level.</p></li><li><p><b>Flexible</b> - customers should be able to define what subset of the traffic Bot Management mitigations should be applied to, e.g. only login URLs, pricing pages or sitewide.</p></li><li><p><b>Accurate</b> - Bot Management detections should have a very small error, e.g. none or very few human visitors ever should be mistakenly identified as bots.</p></li><li><p><b>Recoverable</b> - in case a wrong prediction was made, human visitors still should be able to access websites as well as good bots being let through.</p></li></ul><p>Moreover, the goal for new Bot Management product was to make it work well on the following use cases:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5z0o8rXLkecZWUhx1UDRHF/78e1e55cc47dac3d8bb58ac274870387/image8.png" />
            
            </figure>
    <div>
      <h3>Technical requirements</h3>
      <a href="#technical-requirements">
        
      </a>
    </div>
    <p>Additionally, to the product requirements above, we engineers had a list of must-haves for the new Bot Management platform. The most critical were:</p><ul><li><p><b>Scalability</b> - the platform should be able to calculate a score on every request, even at over 10 million requests per second.</p></li><li><p><b>Low latency</b> - detections must be performed extremely quickly, not slowing down request processing by more than 100 microseconds, and not requiring additional hardware.</p></li><li><p><b>Configurability</b> - it should be possible to configure what detections are applied on what traffic, including on per domain/data center/server level.</p></li><li><p><b>Modifiability</b> - the platform should be easily extensible with more detection mechanisms, different mitigation actions, richer analytics and logs.</p></li><li><p><b>Security</b> - no sensitive information from one customer should be used to build models that protect another customer.</p></li><li><p><b>Explainability &amp; debuggability</b> - we should be able to explain and tune predictions in an intuitive way.</p></li></ul><p>Equipped with these requirements, back in 2018, our small team of engineers got to work to design and build the next generation of Cloudflare Bot Management.</p>
    <div>
      <h3>Meet the Score</h3>
      <a href="#meet-the-score">
        
      </a>
    </div>
    <blockquote><p><i>“Simplicity is the ultimate sophistication.”- Leonardo Da Vinci</i></p></blockquote><p>Cloudflare operates on a vast scale. At the time of this writing, this means covering 26M+ Internet properties, processing on average 11M requests per second (with peaks over 14M), and examining more than 250 request attributes from different protocol levels. The key question is how to harness the power of such “gargantuan” data to <a href="https://www.cloudflare.com/products/zero-trust/threat-defense/">protect all of our customers from modern day cyberthreats</a> in a simple, reliable and explainable way?</p><p>Bot management is hard. Some bots are much harder to detect and require looking at multiple dimensions of request attributes over a long time, and sometimes a single request attribute could give them away. More signals may help, but are they generalizable?</p><p>When we classify traffic, should customers decide what to do with it or are there decisions we can make on behalf of the customer? What concept could possibly address all these uncertainty problems and also help us to deliver on the requirements from above?</p><p>As you might’ve guessed from the section title, we came up with the concept of Trusted Score or simply <b>The Score</b> <i>-</i> one thing to rule them all - indicating the likelihood between 0 and 100 whether a request originated from a human (high score) vs. an automated program (low score).</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3caFJFhAGnz4989GtGg5s4/c03d3fd90168d7d35f79dcc547912db7/image5-1.jpg" />
            
            </figure><p><a href="https://www.flickr.com/photos/purple-lover/13583362554">"One Ring to rule them all"</a> by idreamlikecrazy, used under <a href="https://creativecommons.org/licenses/by/2.0/">CC BY</a> / Desaturated from original</p><p>Okay, let’s imagine that we are able to assign such a score on every incoming HTTP/HTTPS request, what are we or the customer supposed to do with it? Maybe it’s enough to provide such a score in the logs. Customers could then analyze them on their end, find the most frequent IPs with the lowest scores, and then use the <a href="https://www.cloudflare.com/application-services/products/waf/">Cloudflare Firewall</a> to block those IPs. Although useful, such a process would be manual, prone to error and most importantly cannot be done in real time to protect the customer's Internet property.</p><p>Fortunately, around the same time we started worked on this system , our colleagues from the Firewall team had <a href="/announcing-firewall-rules/">just announced Firewall Rules</a>. This new capability provided customers the ability to control requests in a flexible and intuitive way, inspired by the widely known Wireshark®  language. Firewall rules supported a variety of request fields, and we thought - why not have the score be one of these fields? Customers could then write granular rules to block very specific attack types. That’s how the <code>cf.bot_management.score</code> field was born.</p><p>Having a score in the heart of Cloudflare Bot Management addressed multiple product and technical requirements with one strike - it’s simple, flexible, configurable, and it provides customers with telemetry about bots on a per request basis. Customers can adjust the score threshold in firewall rules, depending on their sensitivity to false positives/negatives. Additionally, this intuitive score allows us to extend our detection capabilities under the hood without customers needing to adjust any configuration.</p><p>So how can we produce this score and how hard is it? Let’s explore it in the following section.</p>
    <div>
      <h3>Architecture overview</h3>
      <a href="#architecture-overview">
        
      </a>
    </div>
    <p>What is powering the Bot Management score? The short answer is a set of <a href="https://www.cloudflare.com/learning/serverless/glossary/serverless-microservice/">microservices</a>. Building this platform we tried to re-use as many pipelines, databases and components as we could, however many services had to be built from scratch. Let’s have a look at overall architecture (this overly simplified version contains Bot Management related services):</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5OSC0Ty0XKfbmw651kO9bQ/ebfbf8204161f3db6622291ddb7e4721/image13.png" />
            
            </figure>
    <div>
      <h3>Core Bot Management services</h3>
      <a href="#core-bot-management-services">
        
      </a>
    </div>
    <p>In a nutshell our systems process data received from the edge data centers, produce and store data required for bot detection mechanisms using the following technologies:</p><ul><li><p><b>Databases &amp; data stores</b> - <a href="/squeezing-the-firehose/">Kafka</a>, <a href="/http-analytics-for-6m-requests-per-second-using-clickhouse/">ClickHouse</a>, Postgres, Redis, Ceph.</p></li><li><p><b>Programming languages</b> - Go, Rust, Python, Java, Bash.</p></li><li><p><b>Configuration &amp; schema management</b> - Salt, <a href="/introducing-quicksilver-configuration-distribution-at-internet-scale/">Quicksilver</a>, <a href="https://capnproto.org/">Cap’n Proto</a>.</p></li><li><p><b>Containerization</b> - Docker, Kubernetes, Helm, Mesos/Marathon.</p></li></ul><p>Each of these services is built with resilience, performance, <a href="https://www.cloudflare.com/learning/performance/what-is-observability/">observability</a> and security in mind.</p>
    <div>
      <h3>Edge Bot Management module</h3>
      <a href="#edge-bot-management-module">
        
      </a>
    </div>
    <p>All bot detection mechanisms are applied on every request in real-time during the request processing stage in the Bot Management module running on every machine at Cloudflare’s edge locations. When a request comes in we extract and transform the required request attributes and feed them to our detection mechanisms. The Bot Management module produces the following output:</p><p><b>Firewall fields</b> - <a href="https://support.cloudflare.com/hc/en-us/articles/360027519452-Understanding-Cloudflare-Bot-Management">Bot Management fields</a>- <b>cf.bot_management.score</b> - an integer indicating the likelihood between 0 and 100 whether a request originated from an automated program (low score) to a human (high score).- <b>cf.bot_management.verified_bot</b> - a boolean indicating whether such request comes from a Cloudflare allowlisted bot.- <b>cf.bot_management.static_resource</b> - a boolean indicating whether request matches file extensions for many types of static resources.</p><p><b>Cookies</b> - most notably it produces <a href="https://community.cloudflare.com/t/cf-bm-cookie/56696"><b>cf_bm</b></a>, which helps manage incoming traffic that matches criteria associated with bots.</p><p><b>JS challenges</b> - for some of our detections and customers we inject into invisible JavaScript challenges, providing us with more signals for bot detection.</p><p><b>Detection logs</b> - we log through our data pipelines to ClickHouse details about each applied detection, used features and flags, some of which are used for analytics and customer logs, while others are used to debug and improve our models.</p><p>Once the Bot Management module has produced the required fields, the Firewall takes over the actual bot mitigation.</p>
    <div>
      <h3>Firewall integration</h3>
      <a href="#firewall-integration">
        
      </a>
    </div>
    <p>The Cloudflare Firewall's intuitive dashboard enables users to build powerful rules through easy clicks and also provides Terraform integration. Every request to the firewall is inspected against the rule engine. Suspicious requests can be blocked, challenged or logged as per the needs of the user while legitimate requests are routed to the destination, based on the score produced by the Bot Management module and the configured threshold.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5oSiddu0b8BknoqrAQfCYV/3c6c1e456a6d5dedae0e7e50ac7cf346/image6.png" />
            
            </figure><p>Firewall rules provide the following bot mitigation <a href="https://developers.cloudflare.com/firewall/cf-firewall-rules/actions/">actions</a>:</p><ul><li><p><b>Log</b> - records matching requests in the Cloudflare Logs provided to customers.</p></li><li><p><b>Bypass</b> - allows customers to dynamically disable Cloudflare security features for a request.</p></li><li><p><b>Allow</b> - matching requests are exempt from challenge and block actions triggered by other Firewall Rules content.</p></li><li><p><b>Challenge (Captcha)</b> - useful for ensuring that the visitor accessing the site is human, and not automated.</p></li><li><p><b>JS Challenge</b> - useful for ensuring that bots and spam cannot access the requested resource; browsers, however, are free to satisfy the challenge automatically.</p></li><li><p><b>Block</b> - matching requests are denied access to the site.</p></li></ul><p>Our <a href="/updates-to-firewall-analytics/">Firewall Analytics</a> tool, powered by ClickHouse and <a href="/introducing-the-graphql-analytics-api-exactly-the-data-you-need-all-in-one-place/">GraphQL API</a>, enables customers to quickly identify and investigate security threats using an intuitive interface. In addition to analytics, we provide detailed logs on all bots-related activity using either the <a href="https://developers.cloudflare.com/logs/logpull-api/">Logpull API</a> and/or <a href="/cloudflare-logpush-the-easy-way-to-get-your-logs-to-your-cloud-storage/">LogPush</a>, which provides the easy way to get your logs to your cloud storage.</p>
    <div>
      <h3>Cloudflare Workers integration</h3>
      <a href="#cloudflare-workers-integration">
        
      </a>
    </div>
    <p>In case a customer wants more flexibility on what to do with the requests based on the score, e.g. they might want to inject new, or change existing, HTML page content, or serve incorrect data to the bots, or stall certain requests, <a href="https://www.cloudflare.com/developer-platform/workers/">Cloudflare Workers</a> provide an option to do that. For example, using this small code-snippet, we can pass the score back to the origin server for more advanced real-time analysis or mitigation:</p>
            <pre><code>addEventListener('fetch', event =&gt; {
  event.respondWith(handleRequest(event.request))
})
 
async function handleRequest(request) {
  request = new Request(request);
 
  request.headers.set("Cf-Bot-Score", request.cf.bot_management.score)
 
  return fetch(request);
}</code></pre>
            <p>Now let’s have a look into how a single score is produced using multiple detection mechanisms.</p>
    <div>
      <h3>Detection mechanisms</h3>
      <a href="#detection-mechanisms">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3avrETqHNSco30pzXKi2Bi/d83a61d9a294c2f96ed8ae3101fc8839/image10.png" />
            
            </figure><p>The Cloudflare Bot Management platform currently uses five complementary detection mechanisms, producing their own scores, which we combine to form the single score going to the Firewall. Most of the detection mechanisms are applied on every request, while some are enabled on a per-customer basis to better fit their needs.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6kznWqiXGLzyUvqGbNgrco/3d3d777f8b268bcda1b319c841a518e9/image14.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2SlwP5FY8XUmzYUGbIne0n/f589b67119defdc46d4b80762f81d3f4/image4-1.png" />
            
            </figure><p>Having a score on every request for every customer has the following benefits:</p><ul><li><p><b>Ease of onboarding</b> - even before we enable Bot Management in active mode, we’re able to tell how well it’s going to work for the specific customer, including providing historical trends about bot activity.</p></li><li><p><b>Feedback loop</b> - availability of the score on every request along with all features has tremendous value for continuous improvement of our detection mechanisms.</p></li><li><p><b>Ensures scaling</b> - if we can compute for score every request and customer, it means that every Internet property behind Cloudflare is a potential Bot Management customer.</p></li><li><p><b>Global bot insights</b> - Cloudflare is sitting in front of more than 26M+ Internet properties, which allows us to understand and react to the tectonic shifts happening in security and threat intelligence over time.</p></li></ul><p>Overall globally, more than third of the Internet traffic visible to Cloudflare is coming from bad bots, while Bot Management customers have the ratio of bad bots even higher at ~43%!</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/18xm3tKE1ir3wbIDSb1oet/8c7675efd856354dd50648b001662839/image7.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/79Mscr2mfcUGezTFmVG5nM/0bb09659f0707e84b8f8a15b52ba7af4/image9.png" />
            
            </figure><p>Let’s dive into specific detection mechanisms in chronological order of their integration with Cloudflare Bot Management.</p>
    <div>
      <h3>Machine learning</h3>
      <a href="#machine-learning">
        
      </a>
    </div>
    <p>The majority of decisions about the score are made using our machine learning models. These were also the first detection mechanisms to produce a score and to on-board customers back in 2018. The successful application of <a href="https://www.cloudflare.com/learning/ai/what-is-machine-learning/">machine learning</a> requires data high in <a href="/stop-the-bots-practical-lessons-in-machine-learning/">Quantity, Diversity, and Quality</a>, and thanks to both free and paid customers, Cloudflare has all three, enabling continuous learning and improvement of our models for all of our customers.</p><p>At the core of the machine learning detection mechanism is CatBoost  - a high-performance open source library for gradient boosting on decision trees. The choice of CatBoost was driven by the library’s outstanding capabilities:</p><ul><li><p><b>Categorical features support</b> - allowing us to train on even very high cardinality features.</p></li><li><p><b>Superior accuracy</b> - allowing us to reduce overfitting by using a novel gradient-boosting scheme.</p></li><li><p><b>Inference speed</b> - in our case it takes less than 50 microseconds to apply any of our models, making sure request processing stays extremely fast.</p></li><li><p><b>C and Rust API</b> - most of our business logic on the edge is written using Lua, more specifically LuaJIT, so having a compatible FFI interface to be able to apply models is fantastic.</p></li></ul><p>There are multiple CatBoost models run on Cloudflare’s Edge in the <a href="https://christophergs.com/machine%20learning/2019/03/30/deploying-machine-learning-applications-in-shadow-mode/#what">shadow mode</a> on <i>every request on every machine</i>. One of the models is run in active mode, which influences the final score going to Firewall. All ML detection results and features are logged and recorded in ClickHouse for further analysis, model improvement, analytics and customer facing logs. We feed both categorical and numerical features into our models, extracted from request attributes and inter-request features built using those attributes, calculated and delivered by the <i>Gagarin</i> inter-requests features platform.</p><p>We’re able to deploy new ML models in a matter of seconds using an extremely reliable and performant <a href="/introducing-quicksilver-configuration-distribution-at-internet-scale/">Quicksilver</a> configuration database. The same mechanism can be used to configure which version of an ML model should be run in active mode for a specific customer.</p><p>A deep dive into our machine learning detection mechanism deserves a blog post of its own and it will cover how do we train and validate our models on trillions of requests using GPUs, how model feature delivery and extraction works, and how we explain and debug model predictions both internally and externally.</p>
    <div>
      <h3>Heuristics engine</h3>
      <a href="#heuristics-engine">
        
      </a>
    </div>
    <p>Not all problems in the world are the best solved with machine learning. We can tweak the ML models in various ways, but in certain cases they will likely underperform basic heuristics. Often the problems machine learning is trying to solve are not entirely new. When building the Bot Management solution it became apparent that sometimes a single attribute of the request could give a bot away. This means that we can create a bunch of simple rules capturing bots in a straightforward way, while also ensuring lowest false positives.</p><p>The heuristics engine was the second detection mechanism integrated into the Cloudflare Bot Management platform in 2019 and it’s also applied on every request. We have multiple heuristic types and hundreds of specific rules based on certain attributes of the request, some of which are very hard to spoof. When any of the requests matches any of the heuristics - we assign the lowest possible score of 1.</p><p>The engine has the following properties:</p><ul><li><p><b>Speed</b> - if ML model inference takes less than 50 microseconds per model, hundreds of heuristics can be applied just under 20 microseconds!</p></li><li><p><b>Deployability</b> - the heuristics engine allows us to add new heuristic in a matter of seconds using <a href="/introducing-quicksilver-configuration-distribution-at-internet-scale/">Quicksilver</a>, and it will be applied on every request.</p></li><li><p><b>Vast coverage</b> - using a set of simple heuristics allows us to classify ~15% of global traffic and ~30% of Bot Management customers’ traffic as bots. Not too bad for a few if conditions, right?</p></li><li><p><b>Lowest false positives</b> - because we’re very sure and conservative on the heuristics we add, this detection mechanism has the lowest FP rate among all detection mechanisms.</p></li><li><p><b>Labels</b> <b>for ML</b> - because of the high certainty we use requests classified with heuristics to train our ML models, which then can generalize behavior learnt from from heuristics and improve detections accuracy.</p></li></ul><p>So heuristics gave us <a href="https://developers.google.com/machine-learning/guides/rules-of-ml#rule_7_turn_heuristics_into_features_or_handle_them_externally">a lift when tweaked with machine learning</a> and they contained a lot of the intuition about the bots, which helped to advance the Cloudflare Bot Management platform and allowed us to onboard more customers.</p>
    <div>
      <h3>Behavioral analysis</h3>
      <a href="#behavioral-analysis">
        
      </a>
    </div>
    <p>Machine learning and heuristics detections provide tremendous value, but both of them require human input on the labels, or basically a teacher to distinguish between right and wrong. While our supervised ML models can generalize well enough even on novel threats similar to what we taught them on, we decided to go further. What if there was an approach which doesn’t require a teacher, but rather can learn to distinguish bad behavior from the normal behavior?</p><p>Enter the behavioral analysis detection mechanism, initially developed in 2018 and integrated with the Bot Management platform in 2019. This is an unsupervised machine learning approach, which has the following properties:</p><ul><li><p><b>Fitting specific customer needs</b> - it’s automatically enabled for all Bot Management customers, calculating and analyzing normal visitor behavior over an extended period of time.</p></li><li><p><b>Detects bots never seen before</b> - as it doesn’t use known bot labels, it can detect bots and anomalies from the normal behavior on specific customer’s website.</p></li><li><p><b>Harder to evade</b> - anomalous behavior is often a direct result of the bot’s specific goal.</p></li></ul><p>Please stay tuned for a more detailed blog about behavioral analysis models and the platform powering this incredible detection mechanism, protecting many of our customers from unseen attacks.</p>
    <div>
      <h3>Verified bots</h3>
      <a href="#verified-bots">
        
      </a>
    </div>
    <p>So far we’ve discussed how to detect bad bots and humans. What about good bots, some of which are extremely useful for the customer website? Is there a need for a dedicated detection mechanism or is there something we could use from previously described detection mechanisms? While the majority of good bot requests (e.g. Googlebot, Bingbot, LinkedInbot) already have low score produced by other detection mechanisms, we also need a way to avoid accidental blocks of useful bots. That’s how the Firewall field <i>cf.bot_management.verified_bot</i> came into existence in 2019, allowing customers to decide for themselves whether they want to let all of the good bots through or restrict access to certain parts of the website.</p><p>The actual platform calculating Verified Bot flag deserves a detailed blog on its own, but in the nutshell it has the following properties:</p><ul><li><p><b>Validator based approach</b> - we support multiple validation mechanisms, each of them allowing us to reliably confirm good bot identity by clustering a set of IPs.</p></li><li><p><b>Reverse DNS validator</b> - performs a reverse DNS check to determine whether or not a bots IP address matches its alleged hostname.</p></li><li><p><b>ASN Block validator</b> - similar to rDNS check, but performed on ASN block.</p></li><li><p><b>Downloader validator</b> - collects good bot IPs from either text files or HTML pages hosted on bot owner sites.</p></li><li><p><b>Machine learning validator</b> - uses an unsupervised learning algorithm, clustering good bot IPs which are not possible to validate through other means.</p></li><li><p><b>Bots Directory</b> - a database with UI that stores and manages bots that pass through the Cloudflare network.</p></li></ul>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7ENyHN774m5EVfRIQpQzXO/d5d8127a3235fc8f26eb44b2de2a3919/image2-1.png" />
            
            </figure><p>Bots directory UI sample‌‌</p><p>Using multiple validation methods listed above, the Verified Bots detection mechanism identifies hundreds of unique good bot identities, belonging to different companies and categories.</p>
    <div>
      <h3>JS fingerprinting</h3>
      <a href="#js-fingerprinting">
        
      </a>
    </div>
    <p>When it comes to Bot Management detection quality it’s all about the signal quality and quantity. All previously described detections use request attributes sent over the network and analyzed on the server side using different techniques. Are there more signals available, which can be extracted from the client to improve our detections?</p><p>As a matter of fact there are plenty, as every browser has unique implementation quirks. Every web browser graphics output such as canvas depends on multiple layers such as hardware (GPU) and software (drivers, operating system rendering). This highly unique output allows precise differentiation between different browser/device types. Moreover, this is achievable without sacrificing website visitor privacy as it’s not a supercookie, and it cannot be used to track and identify individual users, but only to confirm that request’s user agent matches other telemetry gathered through browser canvas API.</p><p>This detection mechanism is implemented as a challenge-response system with challenge injected into the webpage on Cloudflare’s edge. The challenge is then rendered in the background using provided graphic instructions and the result sent back to Cloudflare for validation and further action such as  producing the score. There is a lot going on behind the scenes to make sure we get reliable results without sacrificing users’ privacy while being tamper resistant to replay attacks. The system is currently in private beta and being evaluated for its effectiveness and we already see very promising results. Stay tuned for this new detection mechanism becoming widely available and the blog on how we’ve built it.</p><p>This concludes an overview of the five detection mechanisms we’ve built so far. It’s time to sum it all up!</p>
    <div>
      <h3>Summary</h3>
      <a href="#summary">
        
      </a>
    </div>
    <p>Cloudflare has the unique ability to collect data from trillions of requests flowing through its network every week. With this data, Cloudflare is able to identify likely bot activity with Machine Learning, Heuristics, Behavioral Analysis, and other detection mechanisms. Cloudflare Bot Management integrates seamlessly with other Cloudflare products, such as WAF  and Workers.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7thZNko18uGAk7PKwxuG8s/1baf723065de6b686c81d139fbaa0163/image1-1.png" />
            
            </figure><p>All this could not be possible without hard work across multiple teams! First of all thanks to everybody on the Bots Team for their tremendous efforts to make this platform come to life. Other Cloudflare teams, most notably: Firewall, Data, Solutions Engineering, Performance, SRE, helped us a lot to design, build and support this incredible platform.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3ox1rh9KPNDIy5h37liIEO/eadc3dc802b748ccc9279bc01b89b508/image11-1.jpg" />
            
            </figure><p>Bots team during Austin team summit 2019 hunting bots with axes :)</p><p>Lastly, there are more blogs from the Bots series coming soon, diving into internals of our detection mechanisms, so stay tuned for more exciting stories about Cloudflare Bot Management!</p> ]]></content:encoded>
            <category><![CDATA[Deep Dive]]></category>
            <category><![CDATA[Bot Management]]></category>
            <category><![CDATA[Bots]]></category>
            <category><![CDATA[Security]]></category>
            <category><![CDATA[Firewall]]></category>
            <category><![CDATA[Product News]]></category>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Salt]]></category>
            <category><![CDATA[Machine Learning]]></category>
            <guid isPermaLink="false">5yHu3o1Z2Z1reLsRB0q026</guid>
            <dc:creator>Alex Bocharov</dc:creator>
        </item>
        <item>
            <title><![CDATA[Diving into Technical SEO using Cloudflare Workers]]></title>
            <link>https://blog.cloudflare.com/diving-into-technical-seo-cloudflare-workers/</link>
            <pubDate>Thu, 07 Mar 2019 16:05:41 GMT</pubDate>
            <description><![CDATA[ With this post we illustrate the potential applications of Cloudflare Workers in relation to search engine optimization, which is more commonly referred to as ‘SEO’ using our research and testing over the past year making Sloth. ]]></description>
            <content:encoded><![CDATA[ <p><i>This is a guest post by Igor Krestov and Dan Taylor. Igor is a lead software developer at SALT.agency, and Dan a lead technical SEO consultant, and has also been credited with </i><a href="https://searchengineland.com/service-workers-and-seo-seo-for-developers-311292"><i>coining the term “edge SEO”</i></a><i>. </i><a href="https://salt.agency/"><i>SALT.agency</i></a><i> is a technical SEO agency with offices in London, Leeds, and Boston, offering bespoke consultancy to brands around the world. You can reach them both via </i><a href="https://twitter.com/salt_agency"><i>Twitter</i></a><i>.</i></p><p>With this post we illustrate the potential applications of <a href="https://www.cloudflare.com/products/cloudflare-workers/">Cloudflare Workers</a> in relation to search engine optimization, which is more commonly referred to as ‘SEO’ using our research and testing over the past year making Sloth.</p><p>This post is aimed at readers who are both proficient in writing performant JavaScript, as well as complete newcomers, and less technical stakeholders, who haven’t really written many lines of code before.</p>
    <div>
      <h2>Endless practical applications to overcome obstacles</h2>
      <a href="#endless-practical-applications-to-overcome-obstacles">
        
      </a>
    </div>
    <p>Working with various clients and projects over the years we’ve continuously encountered the same problems and obstacles in getting their websites to a point of “technical SEO excellence”. A lot of these problems come from platform restriction at an enterprise level, legacy tech stacks, incorrect builds, and years of patching together various services and infrastructures.</p><p>As a team of technical SEO consultants, we can often be left frustrated by these barriers, that often lead to essential fixes and implementations either being not possible or delayed for months (if not years) at a time – and in this time, the business is often losing traffic and revenue.</p><p>Workers offers us a hail Mary solution to a lot of common frustrations in getting technical SEO implemented, and we believe in the long run can become an integral part of overcoming legacy issues, reducing DevOps costs, speeding up lead times, all in addition to utilising a globally distributed serverless platform with blazing fast cold start times.</p>
    <div>
      <h2>Creating accessibility at scale</h2>
      <a href="#creating-accessibility-at-scale">
        
      </a>
    </div>
    <p>When we first started out, we needed to implement simple redirects, which should be easy to create on the majority of platforms but wasn’t supported in this instance.</p><p>When the second barrier arose, we needed to inject Hreflang tags, cross-linking an old multi-lingual website on a bespoke platform build to an outdated spec. This required experiments to find an efficient way of implementing the tags without increasing latency or adding new code to the server – in a manner befitting of search engine crawling.</p><p>At this point we had a number of other applications for Workers, with arising need for non-developers to be able to modify and deploy new Worker code. This has since become an idea of Worker code generation, via Web UI or command line.</p><p>Having established a number of different use cases for Workers, we identified 3 processing phases:</p><ul><li><p>Incoming request modification – changing origin request URL or adding authorization headers.</p></li><li><p>Outgoing response modification - adding security headers, Hreflang header injection, logging.</p></li><li><p>Response body modification – injecting/changing content e.g. canonicals, robots and JSON-LD</p></li></ul><p>We wanted to generate lean Worker code, which would enable us to keep each functionality contained and independent of another, and went with an idea of filter chains, which can be used to compose fairly complex request processing.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5XNqSuHWNflu8gXityDn7E/71deac0da1e6aa40f55fb22e387e3ffd/request-filter-chain.png" />
            
            </figure><p>A request chain depicting the path of a request as it is transformed while moving from client to origin server and back again.</p><p>A key accessibility issue we identified from a non-technical perspective was the goal trying of making this serverless technology accessible to all in SEO, because with understanding comes buy-in from stakeholders. In order to do this, we had to make Workers:</p><ul><li><p>Accessible to users who don’t understand how to write JavaScript / Performant JavaScript</p></li><li><p>Process of implementation can complement existing deployment processes</p></li><li><p>Process of implementation is secure (internally and externally)</p></li><li><p>Process of implementation is compliant with data and privacy policies</p></li><li><p>Implementations must be able to be verified through existing processes and practices (BAU)</p></li></ul><p>Before we dive into actual filters, here are partial TypeScript interfaces to illustrate filter APIs:</p>
            <pre><code>interface FilterExecutor&lt;Type, Context, ReturnType extends Type | void&gt; {
    apply(filterChain: { next: (c: Context, obj: Type) =&gt; ReturnType | Promise&lt;ReturnType&gt; }&gt;, context: Context, obj: Type): ReturnType | Promise&lt;ReturnType&gt;;
}
interface RequestFilterContext {
    // Request URL
    url: URL;
    // Short-circuit request filters 
    respondWith(response: Response | Promise&lt;Response&gt;): void;
    // Short-circuit all filters
    respondWithAndStop(response: Response | Promise&lt;Response&gt;): void;
    // Add additonal response filter
    appendResponseFilter(filter: ResponseFilter): void;
    // Add body filter
    appendBodyFilter(filter: BodyFilter): void;
}
interface RequestFilter extends FilterExecutor&lt;Request, RequestFilterContext, Request&gt; { };
interface ResponseFilterContext {
    readonly startMs: number;
    readonly endMs: number;
    readonly url: URL;
    waitUntil(promise: Promise&lt;any&gt;): void;
    respondWith(response: Response | Promise&lt;Response&gt;): void;
    respondWithAndStop(response: Response | Promise&lt;Response&gt;): void;
    appendBodyFilter(filter: BodyFilter): void;
}
interface ResponseFilter extends FilterExecutor&lt;Response, ResponseFilterContext, Response&gt; { };
interface BodyFilterContext {
    waitUntil(promise: Promise&lt;any&gt;): void;
}
interface ChunkChain {
    public next: ChunkChain | null;
    public chunk: Uint8Array;
}
interface BodyFilter extends MutableFilterExecutor&lt;ChunkChain | null, BodyFilterContext, ChunkChain | null&gt; { };</code></pre>
            <p>Request filter — Simple Redirects</p><hr /><p>Firstly, we would like to point out that this is very niche use case, if your platform supports redirects natively, you should absolutely do it through your platform, but there are a number of limited, legacy or bespoke platforms, where redirects are not supported or are limited, or are charged for (per line) by your <a href="https://www.cloudflare.com/developer-platform/solutions/hosting/">hosting</a> or platform. For example, Github Pages only support redirects via HTML refresh meta tag.</p><p>The most basic redirect filter, would look like this:</p>
            <pre><code>class RedirectRequestFilter {
    constructor(redirects) {
        this.redirects = redirects;
    }

    apply(filterChain, context, request) {
        const redirect = this.redirects[context.url.href];
        if (redirect)
            context.respondWith(new Response('', {
                status: 301,
                headers: { 'Location': redirect }
            }));
        else
            return filterChain.next(context, request);
    }
}

const { requestFilterHandle } = self.slothRequire('./worker.js');
requestFilterHandle.append(new RedirectRequestFilter({
    "https://sloth.cloud/old-homepage": "https://sloth.cloud/"
}));</code></pre>
            <p>You can see it live in Cloudflare’s playground <a href="https://cloudflareworkers.com/#f59a71db84c026a5d2bee72170113f26:https://sloth.cloud/old-homepage">here</a>.</p><p>The one implemented in Sloth supports basic path matching, hostname matching and query string matching, as well as wildcards.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7bOFFqK57Xr5IsGHGsxCyd/683f3bb5a86104abf6112949e4ddcb6d/sloth-redirect-manager.png" />
            
            </figure><p>The Sloth dashboard for visually creating and modifying redirects. </p><p>It is all well and good when you do not have a lot of redirects to manage, but what do you do when size of redirects starts to take up significant memory available to Worker? This is where we faced another scaling issue, in taking a small handful of possible redirects, to the tens of thousands.</p>
    <div>
      <h2>Managing Redirects with Workers KV and Cuckoo Filters</h2>
      <a href="#managing-redirects-with-workers-kv-and-cuckoo-filters">
        
      </a>
    </div>
    <p>Well, here is one way you can solve it by using <a href="https://developers.cloudflare.com/workers/kv/">Workers KV</a> - a key-value data store.</p><p>Instead of hard coding redirects inside Worker code, we will store them inside Workers KV. Naive approach would be to check redirect for each URL. But Workers KV, maximum performance is not reached until a key is being read on the order of once-per-second in any given data center.</p><p>Alternative could be using a probabilistic data structure, like <a href="https://en.wikipedia.org/wiki/Cuckoo_hashing">Cuckoo Filters</a>, stored in KV, possibly split between a couple of keys as KV is limited to 64KB. Such filter flow would be:</p><ol><li><p>Retrieve frequently read filter key.</p></li><li><p>Check whether full url (or only pathname) is in the filter.</p></li><li><p>Get redirect from Worker KV using URL as a key.</p></li></ol><p>In our tests, we managed to pack 20 thousand redirects into Cuckoo Filter taking up 128KB, split between 2 keys, verified against 100 thousand active URLs with a false-positive rate of 0.5-1%.</p>
    <div>
      <h2>Body filter - Hreflang Injection</h2>
      <a href="#body-filter-hreflang-injection">
        
      </a>
    </div>
    <p>Hreflang meta tags need to be placed inside HTML  element, so before actually injecting them, we need to find either start or end of the head HTML tag, which in itself is a streaming search problem.</p><p>The caveat here is that naive method decoding UTF-8 into JavaScript string, performing search, re-encoding back into UTF-8 is fairly slow. Instead, we attempted pure JavaScript search on bytes strings (<i>Uint8Array</i>), which straight away showed promising results.</p><p>For our use case, we picked the <a href="https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore%E2%80%93Horspool_algorithm">Boyer-Moore-Horspool</a> algorithm as a base of our streaming search, as it is simple, has great average case performance and only requires a pre-processing search pattern, with manual prefix/suffix matching at chunk boundaries.</p><p>Here is comparison of methods we have tested on Node v10.15.0:</p>
            <pre><code>| Chunk Size | Method                               | Ops/s               |
|------------|--------------------------------------|---------------------|
|            |                                      |                     |
| 1024 bytes | Boyer-Moore-Horspool over byte array | 163,086 ops/sec     |
| 1024 bytes | **precomputed BMH over byte array**  | **424,948 ops/sec** |
| 1024 bytes | decode utf8 into strings &amp; indexOf() | 91,685 ops/sec      |
|            |                                      |                     |
| 2048 bytes | Boyer-Moore-Horspool over byte array | 119,634 ops/sec     |
| 2048 bytes | **precomputed BMH over byte array**  | **232,192 ops/sec** |
| 2048 bytes | decode utf8 into strings &amp; indexOf() | 52,787 ops/sec      |
|            |                                      |                     |
| 4096 bytes | Boyer-Moore-Horspool over byte array | 78,729 ops/sec      |
| 4096 bytes | **precomputed BMH over byte array**  | **117,010 ops/sec** |
| 4096 bytes | decode utf8 into strings &amp; indexOf() | 25,835 ops/sec      |</code></pre>
            
    <div>
      <h2>Can we do better?</h2>
      <a href="#can-we-do-better">
        
      </a>
    </div>
    <p>Having achieved decent performance improvement with pure JavaScript search over naive method, we wanted to see whether we can do better. As Workers support <a href="https://developers.cloudflare.com/workers/api/resource-bindings/webassembly-modules/">WASM</a>, we used rust to build a simple WASM module, which exposed standard rust string search.</p>
            <pre><code>| Chunk Size | Method                              | Ops/s               |
|------------|-------------------------------------|---------------------|
|            |                                     |                     |
| 1024 bytes | Rust WASM                           | 348,197 ops/sec     |
| 1024 bytes | **precomputed BMH over byte array** | **424,948 ops/sec** |
|            |                                     |                     |
| 2048 bytes | Rust WASM                           | 225,904 ops/sec     |
| 2048 bytes | **precomputed BMH over byte array** | **232,192 ops/sec** |
|            |                                     |                     |
| 4096 bytes | **Rust WASM**                       | **129,144 ops/sec** |
| 4096 bytes | precomputed BMH over byte array     | 117,010 ops/sec     |</code></pre>
            <p>As rust version did not use precomputed search pattern, it should be significantly faster, if we precomputed and cached search patterns.</p><p>In our case, we were searching for a single pattern and stopping once it was found, where pure JavaScript version was fast enough, but if you need multi-pattern, advanced search, WASM is the way to go.</p><p>We could not record statistically significant change in latency, between basic worker and one with a body filter deployed to production, due to unstable network latency, with a mean response latency of 150ms and 10% 90th percentile standard deviation.</p>
    <div>
      <h2>What’s next?</h2>
      <a href="#whats-next">
        
      </a>
    </div>
    <p>We believe that Workers and serverless applications can open up new opportunities to overcome a lot of issues faced by the SEO community when working with legacy tech stacks, platform limitations, and heavily congested development queues.</p><p>We are also investigating whether Workers can allow us to make a more efficient Tag Manager, which bundles and pushes only matching Tags with their code, to minimize number of external requests caused by trackers and thus reduce load on user browser.</p><p>You can experiment with Cloudflare Workers yourself through <a href="https://sloth.cloud/">Sloth</a>, even if you don’t know how to write JavaScript.</p> ]]></content:encoded>
            <category><![CDATA[SEO]]></category>
            <category><![CDATA[Serverless]]></category>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Cloudflare Workers KV]]></category>
            <category><![CDATA[Salt]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <category><![CDATA[Developers]]></category>
            <guid isPermaLink="false">4hfeeckurXOimDtbX2H6cO</guid>
            <dc:creator>Guest Author</dc:creator>
        </item>
        <item>
            <title><![CDATA[Leave your VPN and cURL secure APIs with Cloudflare Access]]></title>
            <link>https://blog.cloudflare.com/leave-your-vpn-and-curl-secure-apis-with-cloudflare-access/</link>
            <pubDate>Fri, 05 Oct 2018 18:30:07 GMT</pubDate>
            <description><![CDATA[ We built Access to solve a problem here at Cloudflare: our VPN. Our team members hated the slowness and inconvenience of VPN but, that wasn’t the issue we needed to solve. The security risks posed by a VPN required a better solution. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>We built Access to solve a problem here at Cloudflare: our VPN. Our team members hated the slowness and inconvenience of VPN but, that wasn’t the issue we needed to solve. The security risks posed by a VPN required a better solution.</p><p>VPNs punch holes in the <a href="https://www.cloudflare.com/learning/access-management/what-is-the-network-perimeter/">network perimeter</a>. Once inside, individuals can access everything. This can include  critically sensitive content like private keys, cryptographic salts, and log files. Cloudflare is a security company; this situation was unacceptable. We need a better method that gives every application control over precisely who is allowed to  reach it.</p><p>Access meets that need. We started by moving our browser-based applications behind Access. Team members could connect to applications faster, from anywhere, while we improved the security of the entire organization. However, we weren’t yet ready to turn off our VPN as some tasks are better done through a command line. We cannot #EndTheVPN without replacing all of its use cases. Reaching a server from the command line required us to fall back to our VPN.</p><p>Today, we’re releasing a beta command line tool to help your team, and ours. Before we started using this feature at Cloudflare, curling a server required me to stop, find my VPN client and credentials, login, and run my curl command. With Cloudflare’s command line tool, <code>cloudflared</code>, and Access, I can run <code>$ cloudflared access curl https://example.com/api</code> and Cloudflare authenticates my request to the server. I save time and the security team at Cloudflare can control who reaches that endpoint (and monitor the logs).</p>
    <div>
      <h3>Protect your API with Cloudflare Access</h3>
      <a href="#protect-your-api-with-cloudflare-access">
        
      </a>
    </div>
    <p>To protect an <a href="https://www.cloudflare.com/learning/security/api/what-is-an-api/">API</a> with Access, you’ll follow the same <a href="https://developers.cloudflare.com/access/setting-up-access/securing-applications/">steps</a> that you use to protect a browser-based application. Start by adding the hostname where your API is deployed to your Cloudflare account.</p><p>Just like web applications behind Access, you can create granular policies for different paths of your HTTP API. Cloudflare Access will evaluate every request to the API for permission based on settings you configure. Placing your API behind Access means requests from any operation, CLI or other, will continue to be gated by Cloudflare. You can continue to use your API keys, if needed, as a second layer of security.</p>
    <div>
      <h3>Reach a protected API</h3>
      <a href="#reach-a-protected-api">
        
      </a>
    </div>
    <p>Cloudflare Access protects your application by checking for a valid JSON Web Token (JWT), whether the request comes through a browser or from the command line. We <a href="https://developers.cloudflare.com/access/setting-up-access/validate-jwt-tokens/">issue and sign</a> that JWT when you successfully login with your identity provider. That token contains claims about your identity and session. The Cloudflare network looks at the claims in that token to determine if the request should proceed to the target application.</p><p>When you use a browser with Access, we redirect you to your identity provider, you login, and we store that token in a cookie. Authenticating from the command line requires a different flow, but relies on the same principles. When you need to reach an application behind Access from your command line, the Cloudflare CLI tool, <code>cloudflared</code>, launches a browser window so that you can login with your identity provider. Once you login, Access will generate a JWT for your session, scoped to your user identity.</p><p>Rather than placing that JWT in a cookie, Cloudflare transfers the token in a cryptographically secure handoff to your machine. The client stores the token for you so that you don’t need to re-authenticate each time. The token is valid for the session duration as configured in Access.</p><p>When you make requests from your command line, Access will look for an HTTP header, <code>cf-access-token</code>, instead of a cookie. We’ll evaluate the token in that header and on every request.  <b>If you use cURL, we can help you move even faster.</b> <code>cloudflared</code> includes a subcommand that wraps cURL and injects the JWT into the header for you.</p>
    <div>
      <h3>Why use cloudflared to reach your application?</h3>
      <a href="#why-use-cloudflared-to-reach-your-application">
        
      </a>
    </div>
    <p>With <code>cloudflared</code> and its cURL wrapper, you can perform any cURL operation against an API protected by Cloudflare Access.</p><ul><li><p><b>Control endpoint access for specific users</b>Cloudflare Access can be configured to protect specific endpoints. For example, you can create a rule that only a small group within your team can reach a particular URL path. You can apply that granular protection to sensitive endpoints so that you control who can reach those, while making other parts of the tool available to the full team.</p></li><li><p><b>Download sensitive data</b>Placing applications with sensitive data behind Access lets you control who can reach that information. If a particular file is stored at a known location, you can save time by downloading it to your machine from the command line instead of walking through the UI flow.</p></li></ul>
    <div>
      <h3>What's next?</h3>
      <a href="#whats-next">
        
      </a>
    </div>
    <p>CLI authentication is available today to all Access customers through the <code>cloudflared</code> tool. Just add the API hostname to your Cloudflare account and enable Access to start building policies that control who can reach that API. If you do not have an Access subscription yet, you can read more about the plans <a href="https://www.cloudflare.com/products/cloudflare-access/">here</a> and sign up.</p><p>Once you’re ready to continue ditching your VPN, follow this <a href="https://developers.cloudflare.com/access/cli/connecting-from-cli/">link</a> to install <code>cloudflared</code> today. The tool is in beta and does not yet support automated scripting or service-to-service connections. Full instructions and known limitations can be found <a href="https://developers.cloudflare.com/access/cli/connecting-from-cli/">here</a>. If you are interested in providing feedback, you can post your comments in this <a href="https://community.cloudflare.com/t/cloudflare-access-cli-auth-beta/37564">thread</a>.</p> ]]></content:encoded>
            <category><![CDATA[Cloudflare Access]]></category>
            <category><![CDATA[VPN]]></category>
            <category><![CDATA[Security]]></category>
            <category><![CDATA[Product News]]></category>
            <category><![CDATA[Salt]]></category>
            <category><![CDATA[Passwords]]></category>
            <category><![CDATA[SASE]]></category>
            <guid isPermaLink="false">6jHWUuoTWxxosKdUqelM0K</guid>
            <dc:creator>Sam Rhea</dc:creator>
        </item>
        <item>
            <title><![CDATA[Validating Leaked Passwords with k-Anonymity]]></title>
            <link>https://blog.cloudflare.com/validating-leaked-passwords-with-k-anonymity/</link>
            <pubDate>Wed, 21 Feb 2018 19:00:44 GMT</pubDate>
            <description><![CDATA[ Today, v2 of Pwned Passwords was released as part of the Have I Been Pwned service offered by Troy Hunt. Containing over half a billion real world leaked passwords, this database provides a vital tool for correcting the course of how the industry combats modern threats against password security. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Today, <a href="https://www.troyhunt.com/ive-just-launched-pwned-passwords-version-2/">v2 of <i>Pwned Passwords</i> was released</a> as part of the <i>Have I Been Pwned</i> service offered by Troy Hunt. Containing over half a billion real world leaked passwords, this database provides a vital tool for correcting the course of how the industry combats modern threats against password security.</p><p>I have written about how we need to rethink password security and <i>Pwned Passwords v2</i> in the following post: <a href="/how-developers-got-password-security-so-wrong/"><i>How Developers Got Password Security So Wrong</i></a>. Instead, in this post I want to discuss one of the technical contributions Cloudflare has made towards protecting user information when using this tool.</p><p>Cloudflare continues to support <i>Pwned Passwords</i> by providing <a href="https://www.cloudflare.com/learning/cdn/what-is-a-cdn/">CDN</a> and security functionality such that the data can easily be made available for download in raw form to organisations to protect their customers. Further, as part of the second iteration of this project, I have also worked with Troy on designing and implementing <a href="https://www.cloudflare.com/learning/security/api/what-is-api-endpoint/">API endpoints</a> that support anonymised <i>range queries</i> to function as an additional layer of security for those consuming the API, that is visible to the client.</p><p>This contribution allows for <i>Pwned Passwords</i> clients to use <i>range queries</i> to search for breached passwords, without having to disclose a complete unsalted password hash to the service.</p>
    <div>
      <h3>Getting Password Security Right</h3>
      <a href="#getting-password-security-right">
        
      </a>
    </div>
    <p>Over time, the industry has realised that complex password composition rules (such as requiring a minimum number of special characters) have done little to improve user behaviour in making stronger passwords; they have done little to prevent users from putting personal information in passwords, avoiding common passwords or prevent the use of previously breached passwords<a href="#fn1">[1]</a>. <a href="https://www.cloudflare.com/learning/bots/what-is-credential-stuffing/">Credential Stuffing</a> has become a real threat recently; usernames and passwords are obtained from compromised websites and then injected into other websites until you find user accounts that are compromised.</p><p>This fundamentally works because users reuse passwords across different websites; when one set of credentials is breached on one site, this can be reused on other websites. Here are some examples of how credentials can be breached from insecure websites:</p><ul><li><p>Websites which don't use <a href="https://www.cloudflare.com/learning/bots/what-is-rate-limiting/">rate limiting</a> or challenge login requests can have a user's log-in credentials breached using brute force attacks of common passwords for a given user,</p></li><li><p>database dumps from hacked websites can be taken offline and the password hashes can be cracked; modern GPUs make this very efficient for dictionary passwords (even with algorithms like Argon2, PBKDF2 and BCrypt),</p></li><li><p>many websites continue not to use any form of password hashing, once breached they can be captured in raw form,</p></li><li><p>Proxy Attacks or hijacking a web server can allow for capturing passwords before they're hashed.</p></li></ul><p>This becomes a problem with password reuse; having obtained real life username/password combinations, they can be injected into other websites (such as payment gateways, social networks, etc) until access is obtained to more accounts (often of a higher value than the original compromised site).</p><p>Under <a href="https://pages.nist.gov/800-63-3/sp800-63b.html">recent NIST guidance</a>, it is a requirement, when storing or updating passwords, to ensure they do not contain values which are commonly used, expected or compromised<a href="#fn2">[2]</a>. Research has found that 88.41% of users who received a <i>fear appeal</i> later set unique passwords, whilst only 4.45% of users who did not receive a fear appeal would set a unique password<a href="#fn3">[3]</a>.</p><p>Unfortunately, there are a lot of leaked passwords out there; the downloadable raw data from <i>Pwned Passwords</i> currently contains over 30 GB in password hashes.</p>
    <div>
      <h3>Anonymising Password Hashes</h3>
      <a href="#anonymising-password-hashes">
        
      </a>
    </div>
    <p>The key problem in checking passwords against the old <i>Pwned Passwords</i> API (and all similar services) lies in how passwords are checked; with users being effectively required to submit unsalted hashes of passwords to identify if the password is breached. The hashes must be unsalted, as salting them makes them computationally difficult to search quickly.</p><p>Currently there are two choices that are available for validating whether a password is or is not leaked:</p><ul><li><p>Submit the password (in an unsalted hash) to a third-party service, where the hash can potentially be stored for later cracking or analysis. For example, if you make an API call for a leaked password to a third-party API service using a WordPress plugin, the IP of the request can be used to identify the WordPress installation and then breach it when the password is cracked (such as from a later disclosure); or,</p></li><li><p>download the entire list of password hashes, uncompress the dataset and then run a search to see if your password hash is listed.</p></li></ul><p>Needless to say, this conflict can seem like being placed between a <a href="https://www.cloudflare.com/learning/security/how-to-improve-wordpress-security/">security-conscious rock</a> and an insecure hard place.</p>
    <div>
      <h3>The Middle Way</h3>
      <a href="#the-middle-way">
        
      </a>
    </div>
    
    <div>
      <h4>The Private Set Intersection (PSI) Problem</h4>
      <a href="#the-private-set-intersection-psi-problem">
        
      </a>
    </div>
    <p>Academic computer scientists have considered the problem of how two (or more) parties can validate the intersection of data (from two or more unequal sets of data either side already has) without either sharing information about what they have. Whilst this work is exciting, unfortunately these techniques are new and haven't been subject to long-term review by the cryptography community and cryptographic primitives have not been implemented in any major libraries. Additionally (but critically), PSI implementations have substantially higher overhead than our <i>k</i>-Anonymity approach (particularly for communication<a href="#fn4">[4]</a>). Even the current academic state-of-the-art is not with acceptable performance bounds for an API service, with the communication overhead being equivalent to downloading the entire set of data.</p>
    <div>
      <h4>k-Anonymity</h4>
      <a href="#k-anonymity">
        
      </a>
    </div>
    <p>Instead, our approach adds an additional layer of security by utilising a mathematical property known as <i>k</i>-Anonymity and applying it to password hashes in the form of <i>range queries</i>. As such, the <i>Pwned Passwords</i> API service never gains enough information about a non-breached password hash to be able to breach it later.</p><p><i>k</i>-Anonymity is used in multiple fields to release anonymised but workable datasets; for example, so that hospitals can release patient information for medical research whilst withholding information that discloses personal information. Formally, a data set can be said to hold the property of <i>k</i>-Anonymity, if for every record in a released table, there are <code>k − 1</code> other records identical to it.</p><p>By using this property, we are able to seperate hashes into anonymised "buckets". A client is able to anonymise the user-supplied hash and then download all leaked hashes in the same anonymised "bucket" as that hash, then do an offline check to see if the user-supplied hash is in that breached bucket.</p><p>In more concrete terms:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6FkAe2DhLMl2u6Dd4ZXx0P/fc76ccce5fe7570981625977f7d85ace/hash-bucket.png" />
            
            </figure><p>In essence, we turn the table on password derivation functions; instead of seeking to salt hashes to the point at which they are unique (against identical inputs), we instead introduce ambiguity into what the client is requesting.</p><p>Given hashes are essentially fixed-length hexadecimal values, we are able to simply truncate them, instead of having to resort to a decision tree structure to filter down the data. This does mean buckets are of unequal sizes but allows clients to query in a single API request.</p><p>This approach can be implemented in a trivial way. Suppose a user enters the password <code>test</code> into a login form and the service they’re logging into is programmed to validate whether their password is in a database of leaked password hashes. Firstly the client will generate a hash (in our example using SHA-1) of <code>a94a8fe5ccb19ba61c4c0873d391e987982fbbd3</code>. The client will then truncate the hash to a predetermined number of characters (for example, 5) resulting in a Hash Prefix of <code>a94a8</code>. This Hash Prefix is then used to query the remote database for all hashes starting with that prefix (for example, by making a HTTP request to <code>example.com/a94a8.txt</code>). The entire hash list is then downloaded and each downloaded hash is then compared to see if any match the locally generated hash. If so, the password is known to have been leaked.</p><p>As this can easily be implemented over HTTP, client side caching can easily be used for performance purposes; the API is simple enough for developers to implement with little pain.</p><p>Below is a simple Bash implementation of how the <i>Pwned Passwords</i> API can be queried using <i>range queries</i> (<a href="https://gist.github.com/IcyApril/56c3fdacb3a640f37c245e5813b98b99">Gist</a>):</p>
            <pre><code>#!/bin/bash

echo -n Password:
read -s password
echo
hash="$(echo -n $password | openssl sha1)"
upperCase="$(echo $hash | tr '[a-z]' '[A-Z]')"
prefix="${upperCase:0:5}"
response=$(curl -s https://api.pwnedpasswords.com/range/$prefix)
while read -r line; do
  lineOriginal="$prefix$line"
  if [ "${lineOriginal:0:40}" == "$upperCase" ]; then
    echo "Password breached."
    exit 1
  fi
done &lt;&lt;&lt; "$response"

echo "Password not found in breached database."
exit 0</code></pre>
            
    <div>
      <h3>Implementation</h3>
      <a href="#implementation">
        
      </a>
    </div>
    <p>Hashes (even in unsalted form) have two useful properties that are useful in anonymising data.</p><p>Firstly, the Avalanche Effect means that a small change in a hash results in a very different output; this means that you can't infer the contents of one hash from another hash. This is true even in truncated form.</p><p>For example; the Hash Prefix <code>21BD1</code> contains 475 seemingly unrelated passwords, including:</p>
            <pre><code>lauragpe
alexguo029
BDnd9102
melobie
quvekyny</code></pre>
            <p>Further, hashes are fairly uniformally distributed. If we were to count the original 320 million leaked passwords (in Troy's dataset) by the first hexadecimal charectar of the hash, the difference between the hashes associated to the largest and the smallest Hash Prefix is ≈ 1%. The chart below shows hash count by their first hexadecimal digit:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7IqJBkvelNZ0QVFoDEfrKY/96682f7d36961752b3f2c14bc6235f20/hashes_by_hash_prefix.png" />
            
            </figure><p>Algorithm 1 provides us a simple check to discover how much we should truncate hashes by to ensure every "bucket" has more than one hash in it. This requires every hash to be sorted by hexadecimal value. This algorithm, including an initial merge sort, runs in roughly <code>O(n log n + n)</code> time (worst-case):</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/rdI6HJEupI0hSGAsDvr4m/74045dd1a84842e41127e4a9d9213480/Screen-Shot-2018-02-18-at-23.37.15.png" />
            
            </figure><p>After identifying the Maximum Hash Prefix length, it is fairly easy to seperate the hashes into seperate buckets, as described in Algorithm 3:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3peODDMG8GqOHrkA48VOPt/168f1da40b0b41342d571791c3789541/Screen-Shot-2018-02-18-at-23.02.02.png" />
            
            </figure><p>This implementation was originally evaluated on a dataset of over 320 million breached passwords and we find the Maximum Prefix Length that all hashes can be truncated to, whilst maintaining the property k-anonymity, is 5 characters. When hashes are grouped together by a Hash Prefix of 5 characters, we find the median number of hashes associated with a Hash Prefix is 305. With the range of response sizes for a query varying from 8.6KB to 16.8KB (a median of 12.2KB), the dataset is usable in many practical scenarios and is certainly a good response size for an API client.</p><p>On the new <i>Pwned Password</i> dataset (with over half a billion) passwords and whilst keeping the Hash Prefix length 5; the average number of hashes returned is 478 - with the smallest being 381 (<code>E0812</code> and <code>E613D</code>) and the largest Hash Prefix being 584 (<code>00000</code> and <code>4A4E8</code>).</p><p>Splitting the hashes into buckets by a Hash Prefix of 5 would mean a maximum of 16^5 = 1,048,576 buckets would be utilised (for SHA-1), assuming that every possible Hash Prefix would contain at least one hash. In the datasets we found this to be the case and the amount of distinct Hash Prefix values was equal to the highest possible quantity of buckets. Whilst for secure hashing algorithms it is computationally inefficient to invert the hash function, it is worth noting that as the length of a SHA-1 hash is a total of 40 hexadecimal characters long and 5 characters is utilised by the Hash Prefix, the total number of possible hashes associated with a Hash Prefix is 16^{35} ≈ 1.39E42.</p>
    <div>
      <h3>Important Caveats</h3>
      <a href="#important-caveats">
        
      </a>
    </div>
    <p>It is important to note that where a user's password is already breached, an API call for a specific range of breached passwords can reduce the search candidates used in a <a href="https://www.cloudflare.com/learning/bots/brute-force-attack/">brute-force attack</a>. Whilst users with existing breached passwords are already vulnerable to brute-force attacks, searching for a specific range can help reduce the amount of search candidates - although the API service would have no way of determining if the client was or was not searching for a password that was breached. Using a deterministic algorithm to run queries for other Hash Prefixes can help reduce this risk.</p><p>One reason this is important is that this implementation does not currently guarantee <i>l</i>-diversity, meaning a bucket may contain a hash which is of substantially higher use than others. In the future we hope to use percentile-based usage information from the original breached data to better guarantee this property.</p><p>For general users, <i>Pwned Passwords</i> is usually exposed via web interface, it uses a JavaScript client to run this process; if the origin web server was hijacked to change the JavaScript being returned, this computation could be removed (and the password could be sent to the hijacked origin server). Whilst JavaScript requests are somewhat transparent to the client (in the case of a developer), this may not be depended on and for technical users, non-web client based requests are preferable.</p><p>The original use-case for this service was to be deployed privately in a Cloudflare data centre where our services can use it to enhance user security, and use <i>range queries</i> to complement the existing transport security used. Depending on your risks, it's safer to deploy this service yourself (in your own data centre) and use the <i>k</i>-anonymity approach to validate passwords where services do not themselves have the resources to store an entire database of leaked password hashes.</p><p>I would strongly recommend against storing the <i>range queries</i> used by users of your service, but if you do for whatever reason, store them as aggregate analytics such that they cannot be linked back to any given user's password.</p>
    <div>
      <h3>Final Thoughts</h3>
      <a href="#final-thoughts">
        
      </a>
    </div>
    <p>Going forward, as we test this technology more, Cloudflare is looking into how we can use a private deployment of this service to better offer security functionality, both for log-in requests to our dashboard and for customers who want to prevent against credential stuffing on their own websites using our edge network. We also seek to consider how we can incorporate recent work on the Private Set Interesection Problem alongside considering <i>l</i>-diversity for additional security guarantees. As always; we'll keep you updated right here, on our blog.</p><hr /><ol><li><p>Campbell, J., Ma, W. and Kleeman, D., 2011. Impact of restrictive composition policy on user password choices. Behaviour &amp; Information Technology, 30(3), pp.379-388. <a href="#fnref1">↩︎</a></p></li><li><p>Grassi, P. A., Fenton, J. L., Newton, E. M., Perlner, R. A., Regenscheid, A. R., Burr, W. E., Richer, J. P., Lefkovitz, N. B., Danker, J. M., Choong, Y.-Y., Greene, K. K., and Theofanos, M. F. (2017). NIST Special Publication 800-63B Digital Identity Guidelines, chapter Authentication and Lifecycle Management. National Institute of Standards and Technology, U.S. Department of Commerce. <a href="#fnref2">↩︎</a></p></li><li><p>Jenkins, Jeffrey L., Mark Grimes, Jeffrey Gainer Proudfoot, and Paul Benjamin Lowry. "Improving password cybersecurity through inexpensive and minimally invasive means: Detecting and deterring password reuse through keystroke-dynamics monitoring and just-in-time fear appeals." Information Technology for Development 20, no. 2 (2014): 196-213. <a href="#fnref3">↩︎</a></p></li><li><p>De Cristofaro, E., Gasti, P. and Tsudik, G., 2012, December. Fast and private computation of cardinality of set intersection and union. In International Conference on Cryptology and Network Security (pp. 218-231). Springer, Berlin, Heidelberg. <a href="#fnref4">↩︎</a></p></li></ol> ]]></content:encoded>
            <category><![CDATA[Passwords]]></category>
            <category><![CDATA[Best Practices]]></category>
            <category><![CDATA[Security]]></category>
            <category><![CDATA[Salt]]></category>
            <guid isPermaLink="false">4k6ry6xuTMJwpexgEzV2hB</guid>
            <dc:creator>Junade Ali</dc:creator>
        </item>
        <item>
            <title><![CDATA[How Developers got Password Security so Wrong]]></title>
            <link>https://blog.cloudflare.com/how-developers-got-password-security-so-wrong/</link>
            <pubDate>Wed, 21 Feb 2018 19:00:11 GMT</pubDate>
            <description><![CDATA[ Both in our real lives, and online, there are times where we need to authenticate ourselves - where we need to confirm we are who we say we are. This can be done using three things. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Both in our real lives, and online, there are times where we need to authenticate ourselves - where we need to confirm we are who we say we are. This can be done using three things:</p><ul><li><p>Something you <i>know</i></p></li><li><p>Something you <i>have</i></p></li><li><p>Something you <i>are</i></p></li></ul><p>Passwords are an example of something you <i>know</i>; they were introduced in 1961 for computer authentication for a time-share computer in MIT. Shortly afterwards, a PhD researcher breached this system (by being able to simply download a list of unencrypted passwords) and used the time allocated to others on the computer.</p><p>As time has gone on; developers have continued to store passwords insecurely, and users have continued to set them weakly. Despite this, no viable alternative has been created for password security. To date, no system has been created that retains all the benefits that passwords offer as researchers have rarely considered real world constraints<a href="#fn1">[1]</a>. For example; when using fingerprints for authentication, engineers often forget that there is a sizable percentage of the population that do not have usable fingerprints or hardware upgrade costs.</p>
    <div>
      <h3>Cracking Passwords</h3>
      <a href="#cracking-passwords">
        
      </a>
    </div>
    <p>In the 1970s, people started thinking about how to better store passwords and cryptographic hashing started to emerge.</p><p>Cryptographic hashes work like trapdoors; whilst it's easy to hash a password, it's far harder to turn that "hash" back into the original output (or computationally difficult for an ideal hashing algorithm). They are used in a lot of things from speeding up searching from files, to the One Time Password generators in banks.</p><p>Passwords should ideally use specialised hashing functions like Argon2, BCrypt or PBKDF2, they are modified to prevent Rainbow Table attacks.</p><p>If you were to hash the password, <code>p4$$w0rd</code> using the SHA-1 hashing algorithm, the output would be <code>6c067b3288c1b5c791afa04e12fb013ed2e84d10</code>. This output is the same every time the algorithm is run. As a result, attackers are able to create Rainbow Tables which contain the hashes of common passwords and then this information is used to break password hashes (where the password and hash is listed in a Rainbow Table).</p><p>Algorithms like BCrypt essentially salt passwords before they hash them using a random string. This random string is stored alongside the password hash and is used to help make the password harder to crack by making the output unique. The hashing process is repeated many times (defined by a difficulty variable), each time adding the random salt onto the output of the hash and rerunning the hash computation.</p><p>For example; the BCrypt hash <code>$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy</code> starts with <code>$2a$10$</code> which indicates the algorithm used is BCrypt and contains a random salt of <code>N9qo8uLOickgx2ZMRZoMye</code> and a resulting hash of <code>IjZAgcfl7p92ldGxad68LJZdL17lhWy</code>. Storing the salt allows the password hash to be regenerated identically when the input is known.</p><p>Unfortunately; salting is no longer enough, passwords can be cracked quicker and quicker using modern GPUs (specialised at doing the same task over and over). When a site suffers a security breach, users passwords can be taken offline in database dumps in order to be cracked offline.</p><p>Additionally; websites that fail to rate limit login requests or use captchas, can be challenged by Brute Force attacks. For a given user, an attacker will repeatedly try different (but common) passwords until they gain access to a given users account.</p><p>Sometimes sites will lock users out after a handful of failed login attempts, attacks can instead be targeted to move on quickly to a new account after the most common set of a passwords has been attempted. Lists like the following (in some cases with many, many more passwords) can be attempted to breach an account:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5uMRyoSntS2dkOn7C9Zc6v/c882908f5dfc1b8b5c257e8583f4b27a/common-weak-passwords.png" />
            
            </figure><p>The industry has tried to combat this problem by requiring password composition rules; requiring users comply to complex rules before setting passwords (requiring a minimum amount of numbers or punctuation symbols). Research has shown that this work hasn't helped combat the problem of password reuse, weak passwords or users putting personal information in passwords.</p>
    <div>
      <h4>Credential Stuffing</h4>
      <a href="#credential-stuffing">
        
      </a>
    </div>
    <p>Whilst it may seem that this is only a bad sign for websites that store passwords weakly, Credential Stuffing makes this problem even worse.</p><p>It is common for users to reuse passwords from site to site, meaning a username and password from a compromised website can be used to breach far more important information - like online banking gateways or government logins. When a password is reused - it takes just one website being breached, to gain access to others that a users has credentials for.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6l6Zm2PWsT6cXcXHpPevKX/87148160a2ed6d72bfd6288e156ecd28/this-is-not-fine-009-a7b6e6.png" />
            
            </figure><p> <a href="https://thenib.com/this-is-not-fine">This Is Not Fine - The Nib</a></p>
    <div>
      <h3>Fixing Passwords</h3>
      <a href="#fixing-passwords">
        
      </a>
    </div>
    <p>There are fundamentally three things that need to be done to fix this problem:</p><ul><li><p>Good UX to improve User Decisions</p></li><li><p>Improve Developer Education</p></li><li><p>Eliminating reuse of breached passwords</p></li></ul>
    <div>
      <h4>How Can I Secure Myself (or my Users)?</h4>
      <a href="#how-can-i-secure-myself-or-my-users">
        
      </a>
    </div>
    <p>Before discussing the things we're doing, I wanted to briefly discuss what you can do to help protect yourself now. For most users, there are three steps you can immediately take to help yourself.</p><p>Use a Password Manager (like 1Password or LastPass) to set random, unique passwords for every site. Additionally, look to enable Two-Factor Authentication where possible; this uses something you <i>have</i>, in addition to the password you <i>know</i>, to validate you. This will mean, alongside your password, you have to enter a short-lived password from a device like your phone before being able to login to any site.</p><p>Two-Factor Authentication is supported on many of the worlds most popular social media, banking and shopping sites. You can find out how to enable it on popular websites at <a href="https://www.turnon2fa.com/tutorials/">turnon2fa.com</a>. If you are a developer, you should take efforts to ensure you support Two Factor Authentication.</p><p>Set a secure memorable password for your password manager; and yes, turn on Two-Factor Authentication for it (and keep your backup codes safe). You can find additional security tips (including tips on how to create a secure main password) in my blog post: <a href="/cyber-security-advice-for-your-parents/">Simple Cyber Security Tips</a>.</p><p>Developers should look to abolish bad practice composition rules (and simplify them as much as possible). Password expiration policies do more harm than good, so seek to do away with them. For further information refer to the blog post by the UK's National Cyber Security Centre: <a href="https://www.ncsc.gov.uk/articles/problems-forcing-regular-password-expiry">The problems with forcing regular password expiry</a>.</p><p>Finally; Troy Hunt has an excellent blog post on passwords for users and developers alike: <a href="https://www.troyhunt.com/passwords-evolved-authentication-guidance-for-the-modern-era/">Passwords Evolved: Authentication Guidance for the Modern Era</a></p>
    <div>
      <h4>Improving Developer Education</h4>
      <a href="#improving-developer-education">
        
      </a>
    </div>
    <p>Developers should seek to build a culture of security in the organisations where they work; try and talk about security, talk about the benefits of challenging malicious login requests and talk about password hashing in simple terms.</p><p>If you're working on an open-source project that handles authentication; expose easy password hashing APIs - for example the <code>password_hash</code>, <code>password_​needs_​rehash</code> &amp; <code>password_verify</code> functions in modern PHP versions.</p>
    <div>
      <h4>Eliminating Password Reuse</h4>
      <a href="#eliminating-password-reuse">
        
      </a>
    </div>
    <p>We know that complex password composition rules are largely ineffective, and recent guidance has followed suit. A better alternative to composition rules is to block users from signing up with passwords which are known to have been breached. Under <a href="https://pages.nist.gov/800-63-3/sp800-63b.html">recent NIST guidance</a>, it is a requirement, when storing or updating passwords, to ensure they do not contain values which are commonly used, expected or compromised<a href="#fn2">[2]</a>.</p><p>This is easier said than done, the recent version of Troy Hunt's <i>Pwned Passwords</i> database contains over half a billion passwords (over 30 GB uncompressed). Whilst developers can use API services to check if a password is reused, this requires either sending the raw password, or the password in an unsalted hash. This can be especially problematic when multiple services handle authentication in a business, and each has to store a large quantity of passwords.</p><p>This is a problem I've started looking into recently; as part of our contribution to Troy Hunt's <i>Pwned Passwords</i> database, I have designed a <i>range search</i> API that allows developers to check if a password is reused without needing to share the password (even in hashed form) - instead only needing to send a short segment of the cryptographic hash used. You can find more information on this contribution in the post: <a href="/validating-leaked-passwords-with-k-anonymity/">Validating Leaked Passwords with k-Anonymity</a>.</p><p>Version 2 of <i>Pwned Passwords</i> is now available - you can find more information on how it works on Troy Hunt's blog post "<a href="https://www.troyhunt.com/ive-just-launched-pwned-passwords-version-2/">I've Just Launched Pwned Passwords, Version 2</a>".</p><hr /><ol><li><p>Bonneau, J., Herley, C., Van Oorschot, P.C. and Stajano, F., 2012, May. The quest to replace passwords: A framework for comparative evaluation of web authentication schemes. In Security and Privacy (SP), 2012 IEEE Symposium on (pp. 553-567). IEEE. <a href="#fnref1">↩︎</a></p></li><li><p>Grassi, P. A., Fenton, J. L., Newton, E. M., Perlner, R. A., Regenscheid, A. R., Burr, W. E., Richer, J. P., Lefkovitz, N. B., Danker, J. M., Choong, Y.-Y., Greene, K. K., and Theofanos, M. F. (2017). NIST Special Publication 800-63B Digital Identity Guidelines, chapter Authentication and Lifecycle Management. National Institute of Standards and Technology, U.S. Department of Commerce. <a href="#fnref2">↩︎</a></p></li></ol> ]]></content:encoded>
            <category><![CDATA[Passwords]]></category>
            <category><![CDATA[Best Practices]]></category>
            <category><![CDATA[Security]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Salt]]></category>
            <guid isPermaLink="false">6lsrdeZvgI7O6CidQWI49j</guid>
            <dc:creator>Junade Ali</dc:creator>
        </item>
        <item>
            <title><![CDATA[NANOG - the art of running a network and discussing common operational issues]]></title>
            <link>https://blog.cloudflare.com/nanog-the-art-of-running-a-network-and-discussing-common-operational-issues/</link>
            <pubDate>Thu, 02 Feb 2017 12:15:26 GMT</pubDate>
            <description><![CDATA[ The North American Network Operators Group (NANOG) is the loci of modern Internet innovation and the day-to-day cumulative network-operational knowledge of thousands and thousands of network engineers. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>The <a href="https://nanog.org/">North American Network Operators Group</a> (NANOG) is the loci of modern Internet innovation and the day-to-day cumulative network-operational knowledge of thousands and thousands of network engineers. NANOG itself is a non-profit membership organization; but you don’t need to be a member in order to attend the conference or <a href="https://nanog.org/list/join">join</a> the mailing list. That said, if you can become a member, then you’re helping a good cause.</p><p>The next NANOG conference starts in a few days (February 6-8 2017) in <a href="https://www.nanog.org/meetings/nanog69/agenda">Washington, DC</a>. Nearly 900 network professionals are converging on the city to discuss a variety of network-related issues, both big and small; but all related to running and improving the global Internet. For this upcoming meeting, Cloudflare has three network professionals in attendance. Two from the San Francisco office and one from the London office.</p><p>With the conference starting next week, it seemed a great opportunity to introduce readers of the blog as to why a NANOG conference is so worth attending.</p>
    <div>
      <h2>Tutorials</h2>
      <a href="#tutorials">
        
      </a>
    </div>
    <p>While it seems obvious how to do some network tasks (you unpack the spiffy new wireless router from its box, you set up its security and plug it in); alas the global Internet is somewhat more complex. Even seasoned professionals could do with a recap on how <a href="https://youtu.be/WL0ZTcfSvB4">traceroute</a> actually works, or how <a href="https://youtu.be/9ksfOUyvNi8">DNSSEC</a> operates, or this years subtle BGP complexities, or be enlightened about <a href="https://youtu.be/_KFpXuHqHQg">Optical Networking</a>. All this can assist you with deployments within your networks or datacenter.</p>
    <div>
      <h2>Peering</h2>
      <a href="#peering">
        
      </a>
    </div>
    <p>If there’s one thing that keeps the Internet (a network-of-networks) operating, it’s peering. Peering is the act of bringing together two or more networks to allow traffic (bits, bytes, packets, email messages, web pages, audio and video streams) to flow efficiently and cleanly between source and destination. The Internet is nothing more than a collection of individual networks. NANOG provides one of many forums for diverse network operators to meet face-to-face and negotiate and enable those interconnections.</p><p>While NANOG isn’t the only event that draws networks together to discuss interconnection, it’s one of the early forums to support these peering discussions.</p>
    <div>
      <h2>Security and Reputation</h2>
      <a href="#security-and-reputation">
        
      </a>
    </div>
    <p>In this day-and-age we are brutally aware that security is the number-one issue when using the Internet. This is something to think about when you choose your email password, lock screen password on your laptop, tablet or smartphone. Hint: you should always have a lock screen!</p><p>At NANOG the security discussion is focused on a much deeper part of the global Internet, in the very hardware and software practices, that operate and support the underlying networks we all use on a daily basis. An Internet backbone (rarely seen) is a network that moves traffic from one side of the globe to the other (or from one side of a city to the other). At NANOG we discuss how that underlying infrastructure can operate efficiently, securely, and be continually strengthened. The growth of the Internet over the last handful of decades has pushed the envelope when it comes to hardware deployments and network-complexity. Sometimes it only takes one compromised box to ruin your day. Discussions at conferences like NANOG are vital to the sharing of knowledge and collective improvement of everyone's networks.</p><p>Above the hardware layer (from a network stack point of view) is the Domain Name System (DNS). DNS has always been a major subject of discussion within the NANOG community. It’s very much up to the operational community to make sure that when you type a website name into web browser or type in someone’s email address into your email program that there’s a highly efficient process to convert from names to numbers (numbers, or IP address, are the address book and routing method of the Internet). DNS has had its fair share of focus in the security arena and it comes down to network operators (and their system administrator colleagues) to protect DNS infrastructure.</p>
    <div>
      <h2>Network Operations; best practices and stories of disasters</h2>
      <a href="#network-operations-best-practices-and-stories-of-disasters">
        
      </a>
    </div>
    <p>Nearly everyone knows that bad news sells. It’s a fact. To be honest, the same is the case in the network operator community. However, within NANOG, those stories of disasters are nearly always told from a learning and improvement point of view. There’s simply no need to repeat a failure, no-one enjoys it a second time around. Notable stories have included subjects like <a href="https://youtu.be/XNubCYBprjE">route-leaks</a>, <a href="https://youtu.be/_95pC8khh8Y?list=PLO8DR5ZGla8iHYAM_AL7ZcO8F2F4AcosD">BGP protocol hiccups</a>, <a href="https://www.nanog.org/meetings/nanog17/presentations/vixie.pdf">peering points</a>, and plenty more.</p><p>We simply can’t rule out failures within portions of the network; hence NANOG has spent plenty of time discussing redundancy. The internet operates using routing protocols that explicitly allow for redundancy in the paths that traffic travels. Should a failure occur (a hardware failure, or a fiber cut), the theory is that the traffic will be routed around that failure. This is a recurring topic for NANOG meetings. <a href="https://youtu.be/GMi3pP21nHc">Subsea cables</a> (and their occasional cuts) always make for good talks.</p>
    <div>
      <h2>Network Automation</h2>
      <a href="#network-automation">
        
      </a>
    </div>
    <p>While we learned twenty or more years ago how to type into Internet routers on the command line, those days are quickly becoming history. We simply can’t scale if network operational engineers have to type the same commands into hundreds (or thousands?) of boxes around the globe. We need automation. This is where NANOG has been a leader in this space. Cloudflare has been active in this arena and Mircea Ulinic presented our experience for <a href="https://youtu.be/gV2918bH5_c?list=PLO8DR5ZGla8hcpeEDSBNPE5OrZf70iXZg">Network Automation with Salt and NAPALM</a> at the previous NANOG meeting. Mircea (and Jérôme Fleury) will be giving a follow-up in-depth tutorial on the subject at next week’s meeting.</p>
    <div>
      <h2>Many more subjects covered</h2>
      <a href="#many-more-subjects-covered">
        
      </a>
    </div>
    <p>The first NANOG conference was held June 1994 in Ann Arbor, Michigan and the conference has grown significantly since then. While it’s fun to follow the <a href="https://www.nanog.org/history">history</a>, it’s maybe more important to realize that NANOG has covered a multitude of subjects since that start. Go scan the archives at <a href="https://www.nanog.org/">nanog.org</a> and/or watch some of the online <a href="https://www.youtube.com/user/TeamNANOG/playlists">videos</a>.</p>
    <div>
      <h2>The socials (downtime between technical talks)</h2>
      <a href="#the-socials-downtime-between-technical-talks">
        
      </a>
    </div>
    <p>Let’s not forget the advantages of spending time with other operators within a relaxed setting. After all, sometimes the big conversations happen when spending time over a beer discussing common issues. NANOG has long understood this and it’s clear that the Tuesday evening Beer ’n Gear social is set up specifically to let network geeks both grab a drink (soft drinks included) and poke around with the latest and greatest network hardware on show. The social is as much about blinking lights on shiny network boxes as it is about tracking down that network buddy.</p><p>Oh; there’s a fair number of vendor giveaways (so far there’s 15 hardware and software vendors signed up for next week’s event). After all, who doesn’t need a new t-shirt?</p><p>But there’s more to the downtime and casual hallway conversations. For myself (the author of this blog), I know that sometimes the most important work is done within the hallways during breaks in the meeting vs. standing in front of the microphone presenting at the podium. The industry has long recognized this and the NANOG organizers were one of the early pioneers in providing full-time coffee and snacks that cover the full conference agenda times. Why? Because sometimes you have to step out of the regular presentations to meet and discuss with someone from another network. NANOG knows its audience!</p>
    <div>
      <h2>Besides NANOG, there’s IETF, ICANN, ARIN, and many more</h2>
      <a href="#besides-nanog-theres-ietf-icann-arin-and-many-more">
        
      </a>
    </div>
    <p>NANOG isn’t the only forum to discuss network operational issues, however it’s arguably the largest. It started off as a “North American” entity; however, in the same way that the Internet doesn’t have country barriers, NANOG meetings (which take place in the US, Canada and at least once in the Caribbean) have fostered an online community that has grown into a global resource. The mailing list (well worth reviewing) is a bastion of networking discussions.</p><p>In a different realm, the <a href="https://www.ietf.org/about/">Internet Engineering Task Force</a> (IETF) focuses on protocol standards. Its existence is why diverse entities can communicate. Operators participate in IETF meetings; however, it’s a meeting focused outside of the core operational mindset.</p><p>Central to the Internet’s existence is ICANN. Meeting three times a year at locations around the globe, it focused on the governance arena and in domain names and related items. Within the meetings there’s an excellent <a href="https://www.icann.org/resources/pages/tech-day-archive-2015-10-15-en">Tech Day</a>.</p><p>In the numbers arena <a href="https://arin.net/">ARIN</a> is an example of a regional routing registry (an RIR) that runs members meeting. An RIR deals with allocating resources like IP addresses and AS numbers. ARIN focuses on the North American area and sometimes holds its meetings alongside NANOG meetings.</p><p>ARIN’s counterparts in other parts of the world also hold meetings. Sometimes they simply focus on resource policy and sometimes they also focus on network operational issues. For example RIPE (in Europe, Central Asia and the Middle East) runs a five-day meeting that covers operational and policy issues. APNIC (Asia Pacific), AFRINIC (Africa), LACNIC (Latin America &amp; Caribbean) all do similar variations. There isn’t one absolute method and that's a good thing. It’s worth pointing out that APNIC holds it’s members meetings once a year in conjunction with <a href="https://2017.apricot.net/">APRICOT</a> which is the primary operations meeting in the Asia Pacific region.</p><p>While NANOG is somewhat focused on North America, there are also the regional NOGs. These regional NOGs are vital to help the education of network operators globally. Japan has JANOG, Southern Africa has SAFNOG, MENOG in the Middle East, AUSNOG &amp; NZNOG in Australia &amp; New Zealand, DENOG in Germany, PHNOG in the Philippines, and just to be different, the UK has UKNOF (“Forum” vs. “Group”). It would be hard to list them all; but each is a worthwhile forum for operational discussions.</p><p>Peering specific meetings also exist. <a href="https://www.peeringforum.com/">Global Peering Forum</a>, <a href="https://www.peering-forum.eu/">European Peering Forum</a>, and <a href="http://www.lacnog.org/wg-peeringforum/">Peering Forum de LACNOG</a> for example. Those focus on bilateral meetings within a group of network operators or administrators and specifically focus on interconnect agreements.</p><p>In the commercial realms there’s plenty of other meetings that are attended by networks like Cloudflare. <a href="https://council.ptc.org/">PTC</a> and <a href="https://www.internationaltelecomsweek.com/">International Telecoms Week</a> (ITW) are global telecom meetings specifically designed to host one-to-one (bilateral) meetings. They are very commercial in nature and less operational in focus.</p>
    <div>
      <h2>NANOG isn’t the only forum Cloudflare attends</h2>
      <a href="#nanog-isnt-the-only-forum-cloudflare-attends">
        
      </a>
    </div>
    <p>As you would guess, you will find our network team at RIR meetings, sometimes at IETF meetings, sometimes at ICANN meetings, often at various regional NOG meetings (like SANOG in South East Asia, NoNOG in Norway, RONOG in Romania, AUSNOG/NZNOG in Australia/New Zealand and many other NOGs). We get around; however, we also run a global network and we need to interact with many many networks around the globe. These meetings provide an ideal opportunity for one-to-one discussions.</p><p>If you've heard something you like from Cloudflare at one of these operational-focused conferences, then check out our <a href="https://www.cloudflare.com/join-our-team/">jobs listings</a> (in various North American cities, London, Singapore, and beyond!)</p> ]]></content:encoded>
            <category><![CDATA[BGP]]></category>
            <category><![CDATA[Peering]]></category>
            <category><![CDATA[Events]]></category>
            <category><![CDATA[Salt]]></category>
            <category><![CDATA[Best Practices]]></category>
            <guid isPermaLink="false">510pAYiPNeGP55tWvRXwko</guid>
            <dc:creator>Martin J Levy</dc:creator>
        </item>
        <item>
            <title><![CDATA[Manage Cloudflare records with Salt]]></title>
            <link>https://blog.cloudflare.com/manage-cloudflare-records-with-salt/</link>
            <pubDate>Wed, 14 Dec 2016 14:25:52 GMT</pubDate>
            <description><![CDATA[ We use Salt to manage our ever growing global fleet of machines. Salt is great for managing configurations and being the source of truth. We use it for remote command execution and for network automation tasks. ]]></description>
            <content:encoded><![CDATA[ <p>We use <a href="https://github.com/saltstack/salt">Salt</a> to manage our ever growing global fleet of machines. Salt is great for managing configurations and being the source of truth. We use it for remote command execution and for <a href="/the-internet-is-hostile-building-a-more-resilient-network/">network automation tasks</a>. It allows us to grow our infrastructure quickly with minimal human intervention.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5HTPX88whBMGq7gOYzrjhw/1c30f21eeaae6e03d229aa8e548313dc/grains.jpg" />
            
            </figure><p><a href="https://creativecommons.org/licenses/by/2.0/">CC-BY 2.0</a> <a href="https://secure.flickr.com/photos/pagedooley/2769134850/">image</a> by <a href="https://secure.flickr.com/photos/pagedooley/">Kevin Dooley</a></p><p>We got to thinking. Are DNS records not just a piece of the configuration? We concluded that they are and decided to manage our own records from Salt too.</p><p>We are strong believers in <a href="https://en.wikipedia.org/wiki/Eating_your_own_dog_food">eating our own dog food</a>, so we make our employees use the next version of our service before rolling it to everyone else. That way if there's a problem visiting one of the 5 million websites that use Cloudflare it'll get spotted quickly internally. This is also why we keep our own DNS records on Cloudflare itself.</p><p>Cloudflare has an <a href="https://api.cloudflare.com/">API</a> that allows you to manage your zones programmatically without ever logging into the dashboard. Until recently, we were using handcrafted scripts to manage our own DNS records via our API. These scripts were in exotic languages like PHP for historical reasons and had interesting behavior that not everybody enjoyed. While we were dogfooding our own APIs, these scripts were pushing the source of truth for DNS out of Salt.</p><p>When we decided to move some zones to Salt, we had a few key motivations:</p><ol><li><p>Single source of truth</p></li><li><p>Peer-reviewed, audited and versioned changes</p></li><li><p>Making things that our customers would want to use</p></li></ol><p>Points 1 and 2 were achieved by having DNS records in a Salt repo. The Salt configuration is itself in git, so we get peer reviews and audit trail for free. We think that we made progress on point 3 also.</p><p>After extensive internal testing and finding a few bugs in our API (that's what we wanted!), we are happy to announce the public availability of <a href="https://github.com/cloudflare/salt-cloudflare">Cloudflare Salt module</a>.</p><p>If you are familiar with Salt, it should be easy to see how to configure your records via Salt. All you need is the following:</p><p>Create the state <code>cloudflare</code> to deploy your zones:</p>
            <pre><code>example.com:
  cloudflare.manage_zone_records:
    - zone: {{ pillar["cloudflare_zones"]["example.com"]|yaml }}</code></pre>
            <p>Add a pillar to configure your zone:</p>
            <pre><code>cloudflare_zones:
  example.com:
    auth_email: ivan@example.com
    auth_key: auth key goes here
    zone_id: 0101deadbeefdeadbeefdeadbeefdead
    records:
      - name: blog.example.com
        content: 93.184.216.34
        proxied: true</code></pre>
            <p>Here we configure zone <code>example.com</code> to only have one record <code>blog.example.com</code> pointing to <code>93.184.216.34</code> behind Cloudflare.</p><p>You can test your changes before you deploy:</p>
            <pre><code>salt-call state.apply cloudflare test=true</code></pre>
            <p>And then deploy if you are happy with the dry run:</p>
            <pre><code>salt-call state.apply cloudflare</code></pre>
            <p>After the initial setup, all you need is to change the <code>records</code> array in pillar and re-deploy the state. See the <a href="https://github.com/cloudflare/salt-cloudflare">README</a> for more details.</p><p>DNS records are only one part of configuration you may want to change for your Cloudflare domain. We have plans to "saltify" other settings like WAF, caching, page rules and others too.</p><p><a href="https://www.cloudflare.com/join-our-team/">Come work with us</a> if you want to help!</p> ]]></content:encoded>
            <category><![CDATA[GitHub]]></category>
            <category><![CDATA[API]]></category>
            <category><![CDATA[DNS]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[Salt]]></category>
            <guid isPermaLink="false">7cpWAbZAOswJhWNOR3oex8</guid>
            <dc:creator>Ivan Babrou</dc:creator>
        </item>
        <item>
            <title><![CDATA[The Internet is Hostile: Building a More Resilient Network]]></title>
            <link>https://blog.cloudflare.com/the-internet-is-hostile-building-a-more-resilient-network/</link>
            <pubDate>Tue, 08 Nov 2016 18:56:49 GMT</pubDate>
            <description><![CDATA[ The strength of the Internet is its ability to interconnect all sorts of networks — big data centers, e-commerce websites at small hosting companies, Internet Service Providers (ISP), and Content Delivery Networks (CDN) — just to name a few.  ]]></description>
            <content:encoded><![CDATA[ <p>In a recent <a href="/a-post-mortem-on-this-mornings-incident/">post</a> we discussed how we have been adding resilience to our network.</p><p>The strength of the Internet is its ability to interconnect all sorts of networks — big data centers, <a href="https://www.cloudflare.com/ecommerce/">e-commerce websites</a> at small hosting companies, Internet Service Providers (ISP), and <a href="https://www.cloudflare.com/learning/cdn/what-is-a-cdn/">Content Delivery Networks (CDN)</a> — just to name a few. These networks are either interconnected with each other directly using a dedicated physical fiber cable, through a common interconnection platform called an Internet Exchange (IXP), or they can even talk to each other by simply being on the Internet connected through intermediaries called transit providers.</p><p>The Internet is like the network of roads across a country and navigating roads means answering questions like “How do I get from Atlanta to Boise?” The Internet equivalent of that question is asking how to reach one network from another. For example, as you are reading this on the Cloudflare blog, your web browser is connected to your ISP and packets from your computer found their way across the Internet to Cloudflare’s blog server.</p><p>Figuring out the route between networks is accomplished through a protocol designed 25 years ago (on <a href="http://www.computerhistory.org/atchm/the-two-napkin-protocol/">two napkins</a>) called <a href="https://en.wikipedia.org/wiki/Border_Gateway_Protocol">BGP</a>.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4hf3aJRfh6KcsuPEJfYTSe/27f3c58f9490b6f6d135dafc287ee486/BGP.jpg" />
            
            </figure><p>BGP allows interconnections between networks to change dynamically. It provides an administrative protocol to exchange routes between networks, and allows for withdrawals in the case that a path is no longer viable (when some route no longer works).</p><p>The Internet has become such a complex set of tangled fibers, neighboring routers, and millions of servers that you can be certain there is a server failing or a optical fibre being damaged at any moment. Whether it’s in a datacenter, a trench next to a railroad, or <a href="https://en.wikipedia.org/wiki/2008_submarine_cable_disruption">at the bottom of the ocean</a>. The reality is that the Internet is in a constant state of flux as connections break and are fixed; it’s incredible strength is that it operates in the face of the real world where conditions constantly change.</p><p>While BGP is the cornerstone of Internet routing, it does not provide first class mechanisms to automatically deal with these events, nor does it provide tools to manage quality of service in general.</p><p>Although BGP is able to handle the coming and going of networks with grace, it wasn’t designed to deal with Internet brownouts. One common problem is that a connection enters a state where it hasn’t failed, but isn’t working correctly either. This usually presents itself as packet loss: packets enter a connection and never arrive at their destination. The only solution to these brownouts is active, continuous monitoring of the health of the Internet.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2HIfOhD0jflahkGrgaVNZA/3165e9cdb056961f56364bc86568a508/916142_ddc2fd0140_o.gif" />
            
            </figure><p><a href="https://creativecommons.org/licenses/by/2.0/">CC BY 2.0</a> <a href="https://www.flickr.com/photos/jurvetson/916142/in/photolist-5Gky-6yWE3-e2fQKB-eWnwZ-6wHvD2-dgZcgm-6KosGR-e3Hopo-px8hdd-7ZC1ZE-6Kpc5g-mwSyiS-mwSmbA-9cEASh-jXe2g-mDdk7X-far2ZD-ajTJc1-jVhjV4-fsq7m3-p7tksy-6Dfpax-7mbpjF-8m3K8i-ryoZoC-7wCB5-687rPk-njcKr4-7wzXXn-4EnS8a-2kafd3-tcCu6-tcCti-6V5RaY-pGCHzT-4yzuYg-9uwrFi-d9CeFw-7BfKzq-7Bc244-7Bc15c-7BfQRh-6JRaSd-7Bc1zp-7BfRgJ-k17mn-6JM5pM-q4R4Kw-aBAv3F-7BfNCY">image</a> by <a href="https://www.flickr.com/photos/jurvetson/">Steve Jurvetson</a></p><p>Again, the metaphor of a system of roads is useful. A printed map may tell you the route from one city to another, but it won't tell you where there's a traffic jam. However, modern GPS applications such as Waze can tell you which roads are congested and which are clear. Similarly, Internet monitoring shows which parts of the Internet are blocked or losing packets and which are working well.</p><p>At Cloudflare we decided to deploy our own mechanisms to react to unpredictable events causing these brownouts. While most events do not fall under our jurisdiction — they are “external” to the Cloudflare network — we have to operate a reliable service by minimizing the impact of external events.</p><p>This is a journey of continual improvement, and it can be deconstructed into a few simple components:</p><ul><li><p>Building an exhaustive and consistent view of the quality of the Internet</p></li><li><p>Building a detection and alerting mechanism on top of this view</p></li><li><p>Building the automatic mitigation mechanisms to ensure the best reaction time</p></li></ul>
    <div>
      <h3>Monitoring the Internet</h3>
      <a href="#monitoring-the-internet">
        
      </a>
    </div>
    <p>Having deployed our network in <a href="/amsterdam-to-zhuzhou-cloudflare-global-network/">a hundred locations</a> worldwide, we are in a unique position to monitor the quality of the Internet from a wide variety of locations. To do this, we are leveraging the probing capabilities of our network hardware and have added some extra tools that we’ve built.</p><p>By collecting data from thousands of automatically deployed probes, we have a real-time view of the Internet’s infrastructure: packet loss in any of our transit provider’s backbones, packet loss on Internet Exchanges, or packet loss between continents. It is salutary to watch this real-time view over time and realize how often parts of the Internet fail and how resilient the overall network is.</p><p>Our monitoring data is stored in real-time in our metrics pipeline powered by a mix of open-source software: <a href="http://zeromq.org">ZeroMQ</a>, <a href="https://prometheus.io">Prometheus</a> and <a href="http://opentsdb.net/">OpenTSDB</a>. The data can then be queried and filtered on a single dashboard to give us a clear view of the state of a specific transit provider, or one specific PoP.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/451Jz0B6feZP4SHDMdUm0q/85f6ccc1e0ca94684c2abc4bef3c30d1/loss_1.gif" />
            
            </figure><p>Above we can see a time-lapse of a transit provider having some packet loss issues.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3g8KEnve4KdnOmZqvTWLrD/0666a47829dce22097cbdf4aa68bfdf5/Screenshot-2016-10-30-16.34.45.png" />
            
            </figure><p>Here we see a transit provider having some trouble on the US West Coast on October 28, 2016.</p>
    <div>
      <h3>Building a Detection Mechanism</h3>
      <a href="#building-a-detection-mechanism">
        
      </a>
    </div>
    <p>We didn’t want to stop here. Having a real-time map of Internet quality puts us in a great position to detect problems and create alerts as they unfold. We have defined a set of triggers that we know are indicative of a network issue, which allow us to quickly analyze and repair problems.</p><p>For example, 3% packet loss from Latin America to Asia is expected under normal Internet conditions and not something that would trigger an alert. However, 3% packet loss between two countries in Europe usually indicates a bigger and potentially more impactful problem, and thus will immediately trigger alerts for our Systems Reliability Engineering and Network Engineering teams to look into the issue.</p><p>Sitting between eyeball networks and content networks, it is easy for us to correlate this packet loss with various other metrics in our system, such as difficulty connecting to customer origin servers (which manifest as Cloudflare error 522) or a sudden decrease of traffic from a local ISP.</p>
    <div>
      <h3>Automatic Mitigation</h3>
      <a href="#automatic-mitigation">
        
      </a>
    </div>
    <p>Receiving valuable and actionable alerts is great, however we were still facing the hard to compress time-to-reaction factor. Thankfully in our early years, we’ve learned a lot from DDoS attacks. We’ve learned how to detect and auto-mitigate most attacks with our <a href="/introducing-the-bpf-tools/">efficient automated DDoS mitigation pipeline</a>. So naturally we wondered if we could apply what we’ve learned from DDoS mitigation to these generic internet events? After all, they do exhibit the same characteristics: they’re unpredictable, they’re external to our network, and they can impact our service.</p><p>The next step was to correlate these alerts with automated actions. The actions should reflect what an on-call network engineer would have done given the same information. This includes running some important checks: is the packet loss really external to our network? Is the packet loss correlated to an actual impact? Do we currently have enough capacity to reroute the traffic? When all the stars align, we know we have a case to perform some action.</p><p>All that said, automating actions on network devices turns out to be more complicated than one would imagine. Without going into too much detail, we struggled to find a common language to talk to our equipment with because we’re a multi-vendor network. We decided to contribute to the brilliant open-source project <a href="https://github.com/napalm-automation/napalm">Napalm</a>, coupled it with the automation framework <a href="https://saltstack.com/">Salt</a>, and <a href="http://nanog.org/meetings/abstract?id=2951">and improved it to bring us the features we needed</a>.</p><p>We wanted to be able to perform actions such as configuring probes, retrieving their data, and managing complex BGP neighbor configuration regardless of the network device a given PoP was using. With all these features put together into an automated system, we can see the impact of actions it has taken:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7BUEy4XCIg71TuqUQvJqo1/3b49d0cee7acff31949542ad2e3f3665/Screenshot-2016-10-31-11.04.44.png" />
            
            </figure><p>Here you can see one of our transit provider having a sudden problem in Hong-Kong. Our system automatically detects the fault and takes the necessary action, which is to disable this link for our routing.</p><p>Our system keeps improving every day, but it is already running at a high pace and making immediate adjustments across our network to <a href="https://www.cloudflare.com/solutions/ecommerce/optimization/">optimize performance</a> every single day.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6d2bX0eRLMj91oM9LrN2Ny/21f516b784e01bcdb7326cf3037e3962/Screenshot-2016-10-31-14.31.19-2.png" />
            
            </figure><p>Here we can see actions taken during 90 days of our mitigation bot.</p><p>The impact of this is that we’ve managed to make the Internet perform better for our customers and reduce the number of errors that they'd see if they weren't using Cloudflare. One way to measure this is how often we're unable to reach a customer's origin. Sometimes origins are completely offline. However, we are increasingly at a point where if an origin is reachable we'll find a path to reach it. You can see the effects of our improvements over the last year in the graph below.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1Xhgv1pZz3h5ql0xp26nv9/d6493cdf3157ec25d3fcf3708cd6c561/522_year-1.png" />
            
            </figure>
    <div>
      <h3>The Future</h3>
      <a href="#the-future">
        
      </a>
    </div>
    <p>While we keep improving this resiliency pipeline every day, we are looking forward to deploying some new technologies to streamline it further: <a href="http://movingpackets.net/2016/01/11/99-problems-and-configuration-and-telemetry-aint-two/">Telemetry</a> will permit a more real-time collection of our data by moving from a pull model to a push model, and new automation languages like <a href="http://www.openconfig.net/">OpenConfig</a> will unify and simplify our communication with network devices. We look forward to deploying these improvements as soon as they are mature enough for us to release.</p><p>At Cloudflare our mission is to help build a better internet. The internet though, by its nature and size, is in constant flux — breaking down, being added to, and being repaired at almost any given moment — meaning services are often interrupted and traffic is slowed without warning. By enhancing the reliability and resiliency of this complex network of networks we think we are one step closer to fulfilling our mission and building a better internet.</p> ]]></content:encoded>
            <category><![CDATA[DDoS]]></category>
            <category><![CDATA[Mitigation]]></category>
            <category><![CDATA[Attacks]]></category>
            <category><![CDATA[Salt]]></category>
            <category><![CDATA[Network]]></category>
            <guid isPermaLink="false">1YLXNdbFOfJePGpwFKQuXa</guid>
            <dc:creator>Jérôme Fleury</dc:creator>
        </item>
        <item>
            <title><![CDATA[Economical With The Truth: Making DNSSEC Answers Cheap]]></title>
            <link>https://blog.cloudflare.com/black-lies/</link>
            <pubDate>Fri, 24 Jun 2016 16:31:10 GMT</pubDate>
            <description><![CDATA[ We launched DNSSEC late last year and are already signing 56.9 billion DNS record sets per day. At this scale, we care a great deal about compute cost. ]]></description>
            <content:encoded><![CDATA[ <p>We launched DNSSEC late last year and are already signing 56.9 billion DNS record sets per day. At this scale, we care a great deal about compute cost. One of the ways we save CPU cycles is our unique implementation of negative answers in DNSSEC.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/39pYW2SBON2GibSMDXYXr9/1f9e5f863b435eaa642f67b810acbfbf/217591669_c31a16e301_o.jpg" />
            
            </figure><p><a href="https://creativecommons.org/licenses/by-sa/2.0/">CC BY-SA 2.0</a> <a href="https://www.flickr.com/photos/88478656@N00/217591669">image</a> by <a href="https://www.flickr.com/photos/chris-short/">Chris Short</a></p><p>I will briefly explain a few concepts you need to know about <a href="https://www.cloudflare.com/learning/dns/dnssec/ecdsa-and-dnssec/">DNSSEC</a> and negative answers, and then we will dive into how CloudFlare saves on compute when asked for names that don’t exist.</p>
    <div>
      <h3>What You Need To Know: DNSSEC Edition</h3>
      <a href="#what-you-need-to-know-dnssec-edition">
        
      </a>
    </div>
    <p>Here’s a quick summary of DNSSEC:</p><p>This is an unsigned DNS answer (unsigned == no DNSSEC):</p>
            <pre><code>cloudflare.com.		299	IN	A	198.41.214.162
cloudflare.com.		299	IN	A	198.41.215.162</code></pre>
            <p>This is an answer with DNSSEC:</p>
            <pre><code>cloudflare.com.		299	IN	A	198.41.214.162
cloudflare.com.		299	IN	A	198.41.215.162
cloudflare.com.		299	IN	RRSIG	A 13 2 300 20160311145051 20160309125051 35273     cloudflare.com. RqRna0qkih8cuki++YbFOkJi0DGeNpCMYDzlBuG88LWqx+Aaq8x3kQZX TzMTpFRs6K0na9NCUg412bOD4LH3EQ==</code></pre>
            <p>Answers with DNSSEC contain a signature for every record type that is returned. (In this example, only A records are returned so there is only one signature.) The signatures allow DNS resolvers to validate the records returned and prevent on-path attackers from intercepting and changing the answers.</p>
    <div>
      <h3>What You Need To Know: Negative Answer Edition</h3>
      <a href="#what-you-need-to-know-negative-answer-edition">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/EDDHJnSfGNBWos6pw07VT/cbc431245dbf7cb97dc788ea6a909fcb/250521158_0c5de0ef97_z.jpg" />
            
            </figure><p>There are two types of negative answers. The first is <code>NXDOMAIN</code>, which means that the name asked for does not exist. An example of this is a query asking for <code>missing.cloudflare.com</code>. <code>missing.cloudflare.com</code> doesn’t exist at all.</p><p>The second type is <code>NODATA</code>, which means that the name does exist, just not in the requested type. An example of this would be asking for the <code>MX</code> record of <code>blog.cloudflare.com</code>. There are <code>A</code> records for <code>blog.cloudflare.com</code> but no <code>MX</code> records so the appropriate response is <code>NODATA</code>.</p>
    <div>
      <h3>What Goes Into An <code>NXDOMAIN</code> With DNSSEC</h3>
      <a href="#what-goes-into-an-nxdomain-with-dnssec">
        
      </a>
    </div>
    <p>To see what gets returned in a negative <code>NXDOMAIN</code> answer, let’s look at the response for a query for <code>bogus.ietf.org</code>.</p><p>The first record that has to be returned in a negative answer with DNSSEC is an SOA, just like in an unsigned negative answer. The SOA contains some metadata about the zone and lets the recursor know how long to cache the negative answer for.</p>
            <pre><code>ietf.org.	1179	IN	SOA	ns0.amsl.com. glen.amsl.com. 1200000325 1800 1800 604800 1800</code></pre>
            <p>Because the domain is signed with DNSSEC, the signature for the <code>SOA</code> is also returned:</p>
            <pre><code>ietf.org.	1179	IN	RRSIG	SOA 5 2 1800 20170308083354 20160308073501 40452 ietf.org. S0gIjTnQGA6TyIBjCeBXL4ip8aEQEgg2y+kCQ3sLtFa3oNy9vj9kj4aP 8EVu4oIexr8X/i9L8Oj5ec4HOrQoYsMGObRUG0FGT0MEbxepi+wWrfed vD/3mq8KZg/pj6TQAKebeSQGkmb8y9eP0PdWdUi6EatH9ZY/tsoiKyqg U4vtq9sWZ/4mH3xfhK9RBI4M7XIXsPX+biZoik6aOt4zSWR5WDq27pXI 0l+BLzZb72C7McT4PlBiF+U86OngBlGxVBnILyW2aUisi2LY6KeO5AmK WNT0xHWe5+JtPD5PgmSm46YZ8jMP5mH4hSYr76jqwvlCtXvq8XgYQU/P QyuCpQ==</code></pre>
            <p>The next part of the negative answer in DNSSEC is a record type called <code>NSEC</code>. The <code>NSEC</code> record returns the previous and next name in the zone, which proves to the recursor that the queried name cannot possibly exist, because nothing exists between the two names listed in the NSEC record.</p>
            <pre><code>www.apps.ietf.org.	1062	IN	NSEC	cloudflare-verify.ietf.org. A RRSIG NSEC</code></pre>
            <p>This <code>NSEC</code> record above tells you that <code>bogus.ietf.org</code> does not exist because no names exist canonically between <code>www.apps.ietf.org</code> and <code>cloudflare-verify.ietf.org</code>. Of course, this record also has a signature contained in the answer:</p>
            <pre><code>www.apps.ietf.org.	1062	IN	RRSIG	NSEC 5 4 1800 20170308083322 20160308073501 40452 ietf.org. NxmjhCkTtoiolJUow/OreeBRxTtf2AnIPM/r2p7oS/hNeOdFI9tpgGQY g0lTOYjcNNoIoDB/r56Kd+5wtuaKT+xsYiZ4K413I+cmrNQ+6oLT+Mz6 Kfzvo/TcrJD99PVAYIN1MwzO42od/vi/juGkuKJVcCzrBKNHCZqu7clu mU3DEqbQQT2O8dYIUjLlfom1iYtZZrfuhB6FCYFTRd3h8OLfMhXtt8f5 8Q/XvjakiLqov1blZAK229I2qgUYEhd77n2pXV6SJuOKcSjZiQsGJeaM wIotSKa8EttJELkpNAUkN9uXfhU+WjouS1qzgyWwbf2hdgsBntKP9his 9MfJNA==</code></pre>
            <p>A second NSEC record is also returned to prove that there is no wildcard that would have covered <code>bogus.ietf.org</code>:</p>
            <pre><code>ietf.org.	1062	IN	NSEC	ietf1._domainkey.ietf.org. A NS SOA MX TXT AAAA RRSIG NSEC DNSKEY SPF</code></pre>
            <p>This record above tells you that a wildcard (<code>*. ietf.org</code>) would have existed between those two names. Because there is no wildcard record at <code>*.ietf.org</code>, as proven by this NSEC record, the DNS resolver knows that really nothing should have been returned for <code>bogus.ietf.org</code>. This <code>NSEC</code> record also has a signature:</p>
            <pre><code>ietf.org.	1062	IN	RRSIG	NSEC 5 2 1800 20170308083303 20160308073501 40452 ietf.org. homg5NrZIKo0tR+aEp0MVYYjT7J/KGTKP46bJ8eeetbq4KqNvLKJ5Yig ve4RSWFYrSARAmbi3GIFW00P/dFCzDNVlMWYRbcFUt5NfYRJxg25jy95 yHNmInwDUnttmzKuBezdVVvRLJY3qSM7S3VfI/b7n6++ODUFcsL88uNB V6bRO6FOksgE1/jUrtz6/lEKmodWWI2goFPGgmgihqLR8ldv0Dv7k9vy Ao1uunP6kDQEj+omkICFHaT/DBSSYq59DVeMAAcfDq2ssbr4p8hUoXiB tNlJWEubMnHi7YmLSgby+m8b97+8b6qPe8W478gAiggsNjc2gQSKOOXH EejOSA==</code></pre>
            <p>All in all, the negative answer for <code>bogus.ietf.org</code> contains an <code>SOA + SOA RRSIG + (2) NSEC + (2) NSEC RRSIG</code>. It is 6 records in total, returning an answer that is 1095 bytes (this is a large DNS answer).</p>
    <div>
      <h3>Zone Walking</h3>
      <a href="#zone-walking">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/IvO8IS03cvULjAZJGiGNh/493fdb6facdde177c88222bd3226f535/4950628049_030625b5e1_z.jpg" />
            
            </figure><p>What you may have noticed is that because the negative answer returns the previous and next name, you can keep asking for next names and essentially “walk” the zone until you learn every single name contained in it.</p><p>For example, if you ask for the <code>NSEC</code> on <code>ietf.org</code>, you will get back the first name in the zone, <code>ietf1._domainkey.ietf.org</code>:</p>
            <pre><code>ietf.org.		1799	IN	NSEC 	ietf1._domainkey.ietf.org.  A NS SOA MX TXT AAAA RRSIG NSEC DNSKEY SPF</code></pre>
            <p>Then if you ask for the <code>NSEC</code> on <code>ietf1._domainkey.ietf.org</code> you will get the next name in the zone:</p>
            <pre><code>ietf1._domainkey.ietf.org. 1799	IN	NSEC 	apps.ietf.org. TXT RRSIG NSEC</code></pre>
            <p>And you can keep going until you get every name in the zone:</p>
            <pre><code>apps.ietf.org.		1799	IN	NSEC 	mail.apps.ietf.org. MX RRSIG NSEC</code></pre>
            <p>The root zone uses <code>NSEC</code> as well, so you can walk the root to see every TLD:</p><p>The root NSEC:</p>
            <pre><code>.			21599	IN	NSEC 	aaa. NS SOA RRSIG NSEC DNSKEY</code></pre>
            <p><code>.aaa NSEC</code>:</p>
            <pre><code>aaa.			21599	IN	NSEC 	aarp. NS DS RRSIG NSEC</code></pre>
            <p><code>.aarp NSEC</code>:</p>
            <pre><code>aarp.			21599	IN	NSEC	 abb. NS DS RRSIG NSEC</code></pre>
            <p>Zone walking was actually considered a feature of the original design:</p><blockquote><p>The complete <code>NXT</code> chains specified in this document enable a resolver to obtain, by successive queries chaining through <code>NXT</code>s, all of the names in a zone. - <a href="https://www.ietf.org/rfc/rfc2535.txt">RFC2535</a></p></blockquote><p>(<a href="https://www.ietf.org/rfc/rfc2535.txt"><code>NXT</code></a> is the original DNS record type that <code>NSEC</code> was based off of)</p><p>However, as you can imagine, this is a terrible idea for some zones. If you could walk the <code>.gov</code> zone, you could learn every US government agency and government agency portal. If you owned a real estate company where every realtor got their own subdomain, a competitor could walk through your zone and find out who all of your realtors are.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3r4Sa7oIA4l8dHp0Vfb8ZE/600b78872744b8a3af69169d1c3b2dfc/3694621030_76a7e356e8_z.jpg" />
            
            </figure><p><a href="https://creativecommons.org/licenses/by/2.0/">CC BY 2.0</a> <a href="https://www.flickr.com/photos/kiui/3694621030/in/photolist-6CtU7A-asJTAM-7CPbHo-8EwW4-3eVmjc-hJRKMq-6yqn7i-fHud6f-vkbXQ-dYdajL-Tvem-hhyi-yCJFx-faZG48-4NqD5n-4AznYu-agJiCs-7rHcZi-uctPy-86shBZ-5i6jk8-2FM8ku-4r6pDg-nKT4AD-89gnn7-4raAGu-5GZFu6-ediZYA-4ALrZC-47jTd2-dDUiSp-2UDPN5-dDU83M-89d89Z-dDUhX6-52rBrz-hkLCcd-dDTPvR-9yZg4K-67tzSW-8YUTHK-4YeciD-pdczj5-otQve1-72reNd-dDUoZV-F5Pg-4qFHBC-6yuv4A-54xhoz">image</a> by <a href="https://www.flickr.com/photos/kiui/">KIUI</a></p><p>So the DNS community rallied together and found a solution. They would continue to return previous and next names, but they would hash the outputs. This was defined in an upgrade to <code>NSEC</code> called <a href="https://tools.ietf.org/html/rfc5155"><code>NSEC3</code></a>.</p>
            <pre><code>6rmo7l6664ki2heho7jtih1lea9k6los.icann.org. 3599 IN NSEC3 1 0 5 2C21FAE313005174 6S2J9F2OI56GPVEIH3KBKJGGCL21SKKL A RRSIG</code></pre>
            <p><code>NSEC3</code> was a “close but no cigar” solution to the problem. While it’s true that it made zone walking harder, it did not make it impossible. Zone walking with <code>NSEC3</code> is still possible with a dictionary attack. An attacker can use a list of the most common hostnames, hash them with the hashing algorithm used in the <code>NSEC3</code> record (which is listed in the record itself) and see if there are any matches. Even if the domain owner uses a salt on the hash, the length of the salt is included in the <code>NSEC3</code> record, so there are a finite number of salts to guess.</p><blockquote><p>The Salt Length field defines the length of the salt in octets, ranging in value from 0 to 255.”</p></blockquote><ul><li><p><a href="https://tools.ietf.org/html/rfc5155">RFC5155</a></p></li></ul>
    <div>
      <h3><code>NODATA</code> Responses</h3>
      <a href="#nodata-responses">
        
      </a>
    </div>
    <p>If you recall from above, <code>NODATA</code> is the response from a server when it is asked for a name that exists, but not in the requested type (like an <code>MX</code> record for <code>blog.cloudflare.com</code>). <code>NODATA</code> is similar in output to <code>NXDOMAIN</code>. It still requires <code>SOA</code>, but it only takes one <code>NSEC</code> record to prove the next name, and to specify which types do exist on the queried name.</p><p>For example, if you look for a <code>TXT</code> record on <code>apps.ietf.org</code>, the <code>NSEC</code> record will tell you that while there is no <code>TXT</code> record on <code>apps.ietf.org</code>, there are <code>MX</code>, <code>RRSIG</code> and <code>NSEC</code> records.</p>
            <pre><code>apps.ietf.org.		1799	IN	NSEC 	mail.apps.ietf.org. MX RRSIG NSEC</code></pre>
            
    <div>
      <h3>Problems With Negative Answers</h3>
      <a href="#problems-with-negative-answers">
        
      </a>
    </div>
    <p>There are two problems with negative answers:</p><p>The first is that the authoritative server needs to return the previous and next name. As you’ll see, this is computationally expensive for CloudFlare, and as you’ve already seen, it can leak information about a zone.</p><p>The second is that negative answers require two <code>NSEC</code> records and their two subsequent signatures (or three <code>NSEC3</code> records and three <code>NSEC3</code> signatures) to authenticate the nonexistence of one name. This means that answers are bigger than they need to be.</p>
    <div>
      <h3>The Trouble with Previous and Next Names</h3>
      <a href="#the-trouble-with-previous-and-next-names">
        
      </a>
    </div>
    <p>CloudFlare has a custom in house DNS server built in Go called <a href="/what-weve-been-doing-with-go/">RRDNS</a>. What's unique about RRDNS is that unlike standard DNS servers, it does not have the concept of a zone file. Instead, it has a <a href="/kyoto-tycoon-secure-replication/">key value store</a> that holds all of the DNS records of all of the domains. When it gets a query for a record, it can just pick out the record that it needs.</p><p>Another unique aspect of CloudFlare's DNS is that a lot of our business logic is handled in the DNS. We often dynamically generate DNS answers on the fly, so we don't always know what we will respond with before we are asked.</p><p>Traditional negative answers require the authoritative server to return the previous and next name of a missing name. Because CloudFlare does not have the full view of the zone file, we'd have to ask the database to do a sorted search just to figure out the previous and next names. Beyond that, because we generate answers on the fly, we don’t have a reliable way to know what might be the previous and next name, unless we were to precompute every possible option ahead of time.</p><p>One proposed solution to the previous and next name, and secrecy problems is <a href="https://www.ietf.org/rfc/rfc4470.txt">RFC4470</a>, dubbed 'White Lies'. This RFC proposes that DNS operators make up a previous and next name by randomly generating names that are canonically slightly before and after the requested name.</p><p>White lies is a great solution to block zone walking (and it helps us prevent unnecessary database lookups), but it still requires 2 <code>NSEC</code> records (one for previous and next name and another for the wildcard) to say one thing, so the answer is still bigger than it needs to be.</p>
    <div>
      <h3>When CloudFlare Lies</h3>
      <a href="#when-cloudflare-lies">
        
      </a>
    </div>
    <p>We decided to take lying in negative answers to its fullest extent. Instead of white lies, we do black lies.</p><p>For an <code>NXDOMAIN</code>, we always return <code>\000</code>.(the missing name) as the next name, and because we return an <code>NSEC</code> directly on the missing name, we do not have to return an additional <code>NSEC</code> for the wildcard. This way we only have to return <code>SOA</code>, <code>SOA RRSIG</code>, <code>NSEC</code> and <code>NSEC RRSIG</code>, and we do not need to search the database or precompute dynamic answers.</p><p>Our negative answers are usually around 300 bytes. For comparison, negative answers for <code>ietf.org</code> which uses <code>NSEC</code> and <code>icann.org</code>, which uses <code>NSEC3</code> are both slightly over 1000 bytes, three times the size. The reason this matters so much is that the maximum size of an unsigned UDP packet is typically 512 octets. DNSSEC requires support for at least 1220 octets long messages over UDP, but above that limit, the client may need to upgrade to DNS over TCP. A good practice is to keep enough headroom in order to keep response sizes below fragmentation threshold during zone signing key rollover periods.</p><p><code>NSEC</code>: 1096 bytes</p>
            <pre><code>ietf.org.		1799	IN	SOA	ns0.amsl.com. glen.amsl.com. 1200000317 1800 1800 604800 1800
ietf.org.		1799	IN	RRSIG	SOA 5 2 1800 20170213210533 20160214200831 40452 ietf.org. P8XoJx+SK5nUZAV/IqiJrsoKtP1c+GXmp3FvEOUZPFn1VwW33242LVrJ GMI5HHjMEX07EzOXZyLnQeEvlf2QLxRIQm1wAnE6W4SUp7TgKUZ7NJHP dgLr2gqKYim4CI7ikYj3vK7NgcaSE5jqIZUm7oFxxYO9/YPz4Mx7COw6 XBOMYS2v8VY3DICeJdZsHJnVKlgl8L7/yqrL8qhkSW1yDo3YtB9cZEjB OVk8uRDxK7aHkEnMRz0LODOJ10AngJpg9LrkZ1CO444RhZGgTbwzN9Vq rDyH47Cn3h8ofEOJtYCJvuX5CCzaZDInBsjq9wNAiNBgIQatPkNriR77 hCEHhQ==
ietf.org.		1799	IN	NSEC	ietf1._domainkey.ietf.org. A NS SOA MX TXT AAAA RRSIG NSEC DNSKEY SPF
ietf.org.		1799	IN	RRSIG	NSEC 5 2 1800 20170213210816 20160214200831 40452 ietf.org. B9z/JJs30tkn0DyxVz0zaRlm4HkeNY1TqYmr9rx8rH7kC32PWZ1Fooy6 16qmB33/cvD2wtOCKMnNQPdTG2qUs/RuVxqRPZaQojIVZsy/GYONmlap BptzgOJLP7/HOxgYFgMt5q/91JHfp6Mn0sd218/H86Aa98RCXwUOzZnW bdttjsmbAqONuPQURaGz8ZgGztFmQt5dNeNRaq5Uqdzw738vQjYwppfU 9GSLkT7RCh3kgbNcSaXeuWfFnxG1R2SdlRoDICos+RqdDM+23BHGYkYc /NEBLtjYGxPqYCMe/7lOtWQjtQOkqylAr1r7pSI2NOA9mexa7yTuXH+x o/rzRA==
www.apps.ietf.org.	1799	IN	NSEC	cloudflare-verify.ietf.org. A RRSIG NSEC
www.apps.ietf.org.	1799	IN	RRSIG	NSEC 5 4 1800 20170213210614 20160214200831 40452 ietf.org. U+hEHcTps2IC8VKS61rU3MDZq+U0KG4/oJjIHVYbrWufQ7NdMdnY6hCL OmQtsvuZVRQjWHmowRhMj83JMUagxoZuWTg6GuLPin3c7PkRimfBx7jI wjqORwcuvpBh92A/s/2HXBma3PtDZl2UDLy4z7wdO62rbxGU/LX1jTqY FoJJLJfJ/C+ngVMIE/QVneXSJkAjHV96FSEnreF81V62x9azv3AHo4tl qnoYvRDtK+cR072A5smtWMKDfcIr2fI11TAGIyhR55yAiollPDEz5koj BfMstC/JXVURJMM+1vCPjxvwYzTZN8iICf1AupyyR8BNWxgic5yh1ljH 1AuAVQ==</code></pre>
            <p>Black Lies: 357 bytes</p>
            <pre><code>cloudflare.com.		1799	IN	SOA	ns3.cloudflare.com. dns.cloudflare.com. 2020742566 10000 2400 604800 3600
blog.cloudflare.com.	3599	IN	NSEC	\000.blog.cloudflare.com. RRSIG NSEC
cloudflare.com.		1799	IN	RRSIG	SOA 13 2 86400 20160220230013 20160218210013 35273 cloudflare.com. kgjtJDuuNC/yX8yWQpol4ZUUr8s8yAXZi26KWBI6S3HDtry2t6LnP1ou QK10Ut7DXO/XhyZddRBVj3pIpWYdBQ==
blog.cloudflare.com.	3599	IN	RRSIG	NSEC 13 3 3600 20160220230013 20160218210013 35273 cloudflare.com. 8BKAAS8EXNJbm8DxEI1OOBba8KaiimIuB47mPlteiZf3sVLGN1edsrXE +q+pHaSHEfYG5mHfCBJrbi6b3EoXOw==</code></pre>
            
    <div>
      <h3>DNS Shotgun</h3>
      <a href="#dns-shotgun">
        
      </a>
    </div>
    <p>Our take on <code>NODATA</code> responses is also unique. Traditionally, <code>NODATA</code> responses contain one <code>NSEC</code> record to tell the resolver which types exist on the requested name. This is highly inefficient. To do this, we’d have to search the database for all the types that do exist, just to answer that the requested type does not exist. Remember that’s not even always possible because we have dynamic answers that are generated on the fly.</p><p>What we realized was that <code>NSEC</code> is a denial of existence. What matters in <code>NSEC</code> are the missing types, not the present ones. So what we do is we set all the types. We say, this name does exist, just not on the one type you asked for.</p><p>For example, if you asked for an <code>TXT</code> record of <code>blog.cloudflare.com</code> we would say, all the types exist, just not <code>TXT</code>.</p>
            <pre><code>blog.cloudflare.com.	3599	IN	NSEC	\000.blog.cloudflare.com. A WKS HINFO MX AAAA LOC SRV CERT SSHFP IPSECKEY RRSIG NSEC TLSA HIP OPENPGPKEY SPF</code></pre>
            <p>And then if you queried for a <code>MX</code> on <code>blog.cloudflare.com</code>, we would return saying we have every record type, even <code>TXT</code>, but just not <code>MX</code>.</p>
            <pre><code>blog.cloudflare.com.	3599	IN	NSEC	\000.blog.cloudflare.com. A WKS HINFO TXT AAAA LOC SRV CERT SSHFP IPSECKEY RRSIG NSEC TLSA HIP OPENPGPKEY SPF</code></pre>
            <p>This saves us a database lookup and from leaking any zone information in negative answers. We call this the DNS Shotgun.</p>
    <div>
      <h3>How Are Black Lies and DNS Shotgun Standards Compliant</h3>
      <a href="#how-are-black-lies-and-dns-shotgun-standards-compliant">
        
      </a>
    </div>
    <p>We put a lot of care to ensure CloudFlare’s negative answers are standards compliant. We’re even pushing for them to become an Internet Standard by <a href="https://tools.ietf.org/html/draft-valsorda-dnsop-black-lies">publishing an Internet Draft</a> earlier this year.</p><p><a href="https://www.ietf.org/rfc/rfc4470.txt">RFC4470</a>, White Lies, allows us to randomly generate next names in <code>NSEC</code>. Not setting the second <code>NSEC</code> for the wildcard subdomain is also allowed, so long as there exists an <code>NSEC</code> record on the actual queried name. And lastly, our lie of setting every record type in <code>NSEC</code> records for <code>NODATA</code>, is okay too –– after all, domains are constantly changing, it’s feasible that the zone file changed in between the time the <code>NSEC</code> record indicated to you there was no <code>MX</code> record on <code>blog.cloudflare.com</code> and when you queried successfully for <code>MX</code> on <code>blog.cloudflare.com</code>.</p>
    <div>
      <h3>Conclusion</h3>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>We’re proud of our negative answers. They help us keep packet size small, and CPU consumption low enough for us to provide <a href="https://www.cloudflare.com/dnssec/">DNSSEC for free</a> for any domain. Let us know what you think, we’re looking forward to hearing from you.</p> ]]></content:encoded>
            <category><![CDATA[DNS]]></category>
            <category><![CDATA[DNSSEC]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[RRDNS]]></category>
            <category><![CDATA[Salt]]></category>
            <category><![CDATA[Speed & Reliability]]></category>
            <guid isPermaLink="false">2gk2SvhQNI2AbzoJivm97n</guid>
            <dc:creator>Dani Grant</dc:creator>
        </item>
        <item>
            <title><![CDATA[DNSSEC: Complexities and Considerations]]></title>
            <link>https://blog.cloudflare.com/dnssec-complexities-and-considerations/</link>
            <pubDate>Wed, 05 Nov 2014 14:25:04 GMT</pubDate>
            <description><![CDATA[ DNSSEC is an extension to DNS: it provides a system of trust for DNS records. In this post we examine some of the complications of DNSSEC, and what CloudFlare plans to do to reduce any negative impact they might have.  ]]></description>
            <content:encoded><![CDATA[ <p><i>This blog post is a follow-up to our previous </i><a href="/dnssec-an-introduction/"><i>introduction to DNSSEC</i></a><i>. Read that first if you are not familiar with DNSSEC.</i></p><p>DNSSEC is an extension to DNS: it provides a system of trust for DNS records. It’s a major change to one of the core components of the Internet. In this post we examine some of the complications of DNSSEC, and what CloudFlare plans to do to reduce any negative impact they might have. The main issues are zone content exposure, key management, and the impact on DNS reflection/amplification attacks.</p>
    <div>
      <h3>Zone content exposure</h3>
      <a href="#zone-content-exposure">
        
      </a>
    </div>
    <p>DNS is split into smaller pieces called zones. A zone typically starts at a <a href="https://www.cloudflare.com/learning/dns/glossary/what-is-a-domain-name/">domain name</a>, and contains all records pertaining to the subdomains. Each zone is managed by a single manager. For example, cloudflare.com is a zone containing all DNS records for cloudflare.com and its subdomains (e.g. <a href="http://www.cloudflare.com">www.cloudflare.com</a>, api.cloudflare.com).</p><p>There is no directory service for subdomains in DNS so if you want to know if api.cloudflare.com exists, you have to ask a DNS server and that DNS server will end up asking cloudflare.com whether api.cloudflare.com exists. This is not true with DNSSEC. In some cases, enabling DNSSEC may expose otherwise obscured zone content. Not everyone cares about the secrecy of subdomains, and zone content may already be easily guessable because most sites have a ‘www’ subdomain; however, subdomains are sometimes used as login portals or other services that the site owner wants to keep private. A site owner may not want to reveal that “secretbackdoor.example.com” exists in order to protect that site from attackers.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/70515kXx5jQKNOoSIaHgTW/a545b4f7c5b4d48d1b5bf7ad8fbc02a0/x-ray_specs.jpg" />
            
            </figure><p>The reason DNSSEC can expose subdomains has to do with how zones are signed. Historically, DNSSEC is used to sign static zones. A static zone is a complete set of records for a given domain. The DNSSEC signature records are created using the Key Signing Key (KSK) and Zone Signing Key (ZSK) in a central location and sent to the authoritative server to be published. This set of records allows an authoritative server to answer any question it is asked, including questions about subdomains that don’t exist.</p><p>Unlike standard DNS, where the server returns an unsigned NXDOMAIN (Non-Existent Domain) response when a subdomain does not exist, DNSSEC guarantees that every answer is signed. This is done with a special record that serves as a proof of non-existence called the NextSECure (NSEC) record. An NSEC record can be used to say: “there are no subdomains between subdomains X and subdomain Y.” By filling the gap between every domain in the zone, NSEC provides a way to answer any query with a static record. The NSEC record also lists what Resource Record types exist at each name.</p><p>For statically signed zones, there are, by definition, a fixed number of records. Since each NSEC record points to the next, this results in a finite ‘ring’ of NSEC records that covers all the subdomains. Anyone can ‘walk’ a zone by following one NSEC record to the next until they know all subdomains. This method can be used to reveal all of the names in that zone---possibly exposing internal information.</p><p>Suppose there is a DNSSEC-enabled zone called example.com, with subdomains public.example.com and secret.example.com. Adding NSEC records will reveal the existence of all subdomains.</p><p>Asking for the NSEC record of example.com gives the following:</p>
            <pre><code>example.com.		NSEC	public.example.com.     A NS SOA TXT AAAA RRSIG NSEC DNSKEY</code></pre>
            <p>Asking for public.example.com gives the following NSEC record:</p>
            <pre><code>public.example.com.    	NSEC	secret.example.com.  A TXT AAAA RRSIG NSEC</code></pre>
            <p>Asking for secret.example.com gives the following NSEC record:</p>
            <pre><code>secret.example.com.    	NSEC	example.com.         A TXT AAAA RRSIG NSEC</code></pre>
            <p>The first one is for the zone top/apex, and says that the name “example.com” exists and the next name is “public.example.com”. The public.example.com record says that the next name is “secret.example.com” revealing the existence of a private subdomain. The “secret.example.com” says the next record is “example.com” completing the chain of subdomains. Therefore, with a few queries anybody can know the complete set of records in the zone.</p><p>Technically, DNS records are not supposed to be secret, but in practice they are sometimes considered so. Subdomains have been used to keep things (such as a corporate login page) private for a while, and suddenly revealing the contents of the zone file may be unexpected and unappreciated.</p><p>Before DNSSEC the only way to discover the contents of names in a zone was to either query for them, or attempt to perform a transfer of the zone from one of the authoritative servers. Zone Transfers (AXFR) are frequently blocked. NSEC’s alternatative, NSEC3, was introduced to fight zone enumeration concerns, but even NSEC3 can be used to reveal the existence of subdomains.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5G9hHvkwGCjvyGbRWTQmsd/aec1d348a3977ac627c08e39fb4c8e0d/dnssec_nsec_stat.png" />
            
            </figure><p><a href="http://securityblog.switch.ch/2013/02/19/dnssec-deployment-in-ch/"><i>Most domains under .ch use NSEC3</i></a></p><p>The NSEC3 record is like an NSEC record, but, rather than a signed gap of domain names for which there are no answers to the question, NSEC3 provides a signed gap of hashes of domain names. This was intended to prevent zone enumeration. Thus, the NSEC3 chain for a zone containing “example.com” and “<a href="http://www.example.com”">www.example.com”</a> could be (each NSEC3 record is on 3 lines for clarity):</p>
            <pre><code>231SPNAMH63428R68U7BV359PFPJI2FC.example.com. NSEC3 1 0 3 ABCDEF
            NKDO8UKT2STOL6EJRD1EKVD1BQ2688DM
            A NS SOA TXT AAAA RRSIG DNSKEY NSEC3PARAM</code></pre>
            
            <pre><code>NKDO8UKT2STOL6EJRD1EKVD1BQ2688DM.example.com. NSEC3 1 0 3 ABCDEF
            231SPNAMH63428R68U7BV359PFPJI2FC
            A TXT AAAA RRSIG</code></pre>
            <p>Where <code>231SPNAMH63428R68U7BV359PFPJI2FC</code> is the salted hash of <code>example.com</code> and <code>NKDO8UKT2STOL6EJRD1EKVD1BQ2688DM</code> is the salted hash of <code>www.example.com</code>. This is reminiscent of the way <a href="/keeping-passwords-safe-by-staying-up-to-date/">password databases work</a>.</p><p>The first line of the NSEC3 record contains the “name” of the zone after it has been hashed, the number of hash rounds and salt used in the hashing are the two last parameters on the first line “3 ABCDEF”. The “1 0” stands for digest algorithm (1 means SHA-1) and if the zone uses Opt-out (0 means no). The second line is the “next hashed name in the zone”, the third line lists the types at the name. You can see the “next name” at the first NSEC3 record matches the name on the second NSEC3 record and the “next name” on that one completes the chain.</p><p>For NSEC enumeration, you can create the full list of domains by starting to guess at possible names in the domain. If the zone has around 100 domain names, it will take around 100 requests to enumerate the entire zone. With NSEC3, when you request a record that does not exist, a signed NSEC3 record is returned with the next zone present ordered alphabetically by hash. Checking if the next query name candidate fits in one of the known gaps allows anyone to discover the full chain in around 100 queries. There are many tools that can do this computation for you, including <a href="http://nmap.org/nsedoc/scripts/dns-nsec3-enum.html">a plug-in to nmap</a>.</p><p>With the hashes that correspond to all the valid names in the zone, a dictionary attack can be used to figure out the real names. Short names are easily guessed, and by using a dictionary, longer names can be revealed as existing without having to flood the authoritative nameservers with guesses. Tools like <a href="http://hashcat.net/oclhashcat/">HashCat</a> make this easy to do in software, and the popularity of bitcoin has dramatically lowered the price of hashing-specific hardware. There is a burgeoning cottage industry of devices built to compute cryptographic hashes. The Tesla Password cracker (below) is just one example of these off-the shelf devices.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6gsig6X5hT2Ke0PzKMBVgv/24f738923ef83e3a307e05c41370961d/Tesla-cracker.jpg" />
            
            </figure><p><i>The Tesla Password Cracker</i></p><p>Because hashing is cheap, zone privacy is only slightly improved when using NSEC3 as designed; the amount of protection a name gets is proportional to its unguessability.</p><p>In short, NSEC is like revealing plaintext passwords, and NSEC3 is like revealing a Unix-style passwords file. Neither technique is very secure. With NSEC3 a subdomain is only as private as it is hard to guess.</p><p>This vulnerability can be mitigated by a techniques introduced in RFCs 4470 and 4471 (<a href="https://tools.ietf.org/html/rfc4470">https://tools.ietf.org/html/rfc4470</a> and <a href="https://tools.ietf.org/html/rfc4471">https://tools.ietf.org/html/rfc4471</a>) called “DNSSEC white lies”; this was implemented by Dan Kaminsky for demonstration purposes. When a request comes in for a domain that is not present, instead of providing an NSEC3 record of the next real domain, an NSEC3 record of the next hash alphabetically is presented. This does not break the NSEC3 guarantee that there are no domains whose hash fits lexicographically between the NSEC3 response and the question.</p><p>You can only implement NSEC3 or NSEC “white lies” if signatures can be computed in real-time in response to questions. Traditionally, static zone records for DNS resolution are created offline, and all the records with signatures stored in a zone file. This file is then read by a live DNS server allowing it to answer questions about the zone. Having a DNS server with the minimum amount of logic inside allows the operator to conserve CPU resources and maximize the number of queries that can be answered. In order to do DNSSEC white lies, the servers must have keys available to perform generation of signatures on the fly. This is a major change in the traditional operating practices of DNS servers because the DNS authoritative server itself needs to do the cryptographic operations in response to the incoming query. This demand for live signing imposes several other security problems in distributed environments.</p>
    <div>
      <h3>Key management</h3>
      <a href="#key-management">
        
      </a>
    </div>
    <p>DNSSEC was designed to operate in various modes, each providing different security, performance and convenience tradeoffs. Live signing solves the zone content exposure problem in exchange for less secure key management.</p><p>The most common DNSSEC mode is offline signing of static zones. This allows the signing system to be highly protected from external threats by keeping the private keys on a machine that is not connected to the network. This operating model works well when the DNS information does not change often.</p><p>Another common operating mode is centralized online signing. If you sign data in restricted access, dedicated DNS signing systems, it allows DNS data to change and get published quickly. Some operators run DNS signing on their main DNS servers. Just like offline signing of static zones, this mode follows the central signing model, i.e., a single (or replicated) central signer does all the signing and data gets propagated from it to the actual authoritative DNS servers.</p><p>A more radical mode is to allow the actual authoritative DNS servers to sign data on the fly when needed, this allows a number of new features including geographically dependant information signed where the answer is generated. The downside is that now the keying material is on many different machines that have direct access to the Internet. Doing live signing at the edge introduces new problems such as key distribution and places extra computing requirements on the nodes.</p><p>Recently, a bug known as <a href="/answering-the-critical-question-can-you-get-private-ssl-keys-using-heartbleed/">Heartbleed</a> was found that opened a major security hole in server applications. It was caused by a coding error in OpenSSL that created a remote memory disclosure vulnerability. This bug allowed remote attackers to extract cryptographic keys from Internet-facing servers. Remote memory exposure bug are just one of the many threats to private key security when the key is being used in an active process such as DNSSEC live signing. The more a machine is exposed to the Internet, the more vectors of attack there are. Offline signing machines have a much smaller window of exposure to such threats.</p><p>One way to keep keys secure is to use a hardware-backed solution such as a Hardware Security Module (HSM). The major drawback for this is cost – HSMs are very expensive (and slow). This is one of the stickiest points for running DNS servers that are spread out geographically in order to be close to their customers. Running an HSM in every server location can not only be expensive, but there can also be <a href="http://www.kslaw.com/imageserver/KSPublic/library/publication/2011articles/11-11WorldECRCloutierCohen.pdf">legal complications</a> too.</p><p>Another solution to protect keys from remote disclosure is to offload cryptographic operations into trusted component of the system. This is where having a <a href="/cloudflare-fastest-free-dns-among-fastest-dns/">custom DNS server</a> that can offload cryptography can come in handy.</p><p>Key management for DNSSEC is similar to key management for TLS and has similar challenges. Earlier this year, we introduced <a href="/keyless-ssl-the-nitty-gritty-technical-details/">Keyless SSL</a> to help improve key security for TLS. We are looking at extending Keyless SSL to provide the advantages of remote key servers for DNSSEC live-signing.</p>
    <div>
      <h3>Reflection/amplification threat</h3>
      <a href="#reflection-amplification-threat">
        
      </a>
    </div>
    <p>Operators running an authoritative DNS server are often nervous their server will be used as a conduit for malicious distributed denial of service (DDoS) attacks. This stems from the fact that DNS uses UDP, a stateless protocol.</p><p>In TCP, each connection begins with a three-way handshake. This ensures that the IP address of both parties is known and correct before starting a connection. In UDP, there is no such handshake: messages are just sent directly to an IP with an unverified ‘from’ IP address. If an attacker can craft a UDP packet that says ‘hi, from IP X’ to a server, the server will typically respond by sending a UDP packet to X. Choosing X as a victim’s IP address instead of the sender’s is called UDP ‘spoofing’. By spoofing a victim, an attacker can cause a server that responds to UDP requests to flood the victim with ‘reflected’ traffic. This applies as much to authoritative servers as to open recursive resolvers.</p><p>DNSSEC also works over UDP, and the answers to DNS queries can be very long, containing multiple DNSKEY and RRSIG records. This is an attractive target for attackers since it allows them to ‘amplify’ their reflection attacks. If a small volume of spoofed UDP DNSSEC requests is sent to nameservers, the victim will receive a large volume of reflected traffic. Sometimes this is enough to overwhelm the victim’s server, and cause a denial of service.</p><p>Asking for a <a href="https://www.cloudflare.com/learning/dns/top-level-domain/">TLD</a> that does not exist from a root server returns an answer that is around 100 bytes, the signed answer for the same question is about 650 bytes or an amplification factor of 6.5. The root is signed using a 1,024 bit RSA key and uses NSEC for negative answers. Asking for a domain that does not exist in a TLD using NSEC3 signed with 1,024 bit key will yield an amplification factor of around 10. There are other queries that can yield even higher amplification factors, the most effective being the “ANY” query.</p><p>Like many services, DNS can also work over TCP. There is a ‘truncation’ flag that can be sent back to a resolver to indicate that TCP is required. This would fix the issue of DNS reflection at the cost of slower DNS requests. This solution is not practical at the moment since 16% of resolvers don’t respect the TCP truncation flag, and <a href="http://www.circleid.com/posts/20130820_a_question_of_dns_protocols/">4% don’t try a second server</a>.</p><p>Another option to reduce the size of responses is to use <a href="/ecdsa-the-digital-signature-algorithm-of-a-better-internet/">Elliptic Curve Digital Signature Algorithm (ECDSA)</a> keys instead of traditional RSA keys. ECDSA keys are much smaller than RSA keys of equivalent strength, and they produce smaller signatures making DNSSEC responses much smaller, reducing the amplification factor. Unfortunately, many recursive resolvers (including <a href="https://lists.dns-oarc.net/pipermail/dns-operations/2014-January/011257.html">Google Public DNS</a>) do not support this key type yet, and many <a href="https://www.cloudflare.com/learning/dns/glossary/what-is-a-domain-name-registrar/">registrars</a> have not added the option to their DNS management portals.</p><p>Support for TCP and ECDSA is still lagging behind general DNSSEC support, so traditional anti-abuse methods can be used instead. This includes <a href="https://kb.isc.org/article/AA-01000/0/A-Quick-Introduction-to-Response-Rate-Limiting.html">Resource Rate Limiting (RRL)</a> and other heuristics.</p><p>To protect against reflection attacks, CloudFlare is working on a multi-pronged approach. First, by using attack identification heuristics and anti-abuse techniques that we are currently using in our DNS server, and second by reducing the amplification factor of DNSSEC responses. Ways to reduces the maximum amplification factor includes only replying to “ANY” requests over TCP, using smaller ECDSA keys when possible, and reducing the frequency of key rollovers.</p>
    <div>
      <h3>Conclusions</h3>
      <a href="#conclusions">
        
      </a>
    </div>
    <p>CloudFlare is aware of the complexity introduced by DNSSEC with respect to zone privacy, key management, and reflection/amplification risk. With smart engineering decisions, and operational controls in place, the dangers of DNSSEC can be prevented.</p> ]]></content:encoded>
            <category><![CDATA[DNSSEC]]></category>
            <category><![CDATA[Speed & Reliability]]></category>
            <category><![CDATA[DNS]]></category>
            <category><![CDATA[Programming]]></category>
            <category><![CDATA[Salt]]></category>
            <guid isPermaLink="false">4JIaBxM74zVImDCAEApK96</guid>
            <dc:creator>Nick Sullivan</dc:creator>
        </item>
        <item>
            <title><![CDATA[Red October: CloudFlare’s Open Source Implementation of the Two-Man Rule]]></title>
            <link>https://blog.cloudflare.com/red-october-cloudflares-open-source-implementation-of-the-two-man-rule/</link>
            <pubDate>Thu, 21 Nov 2013 09:00:00 GMT</pubDate>
            <description><![CDATA[ At CloudFlare, we are always looking for better ways to secure the data we’re entrusted with. This means hardening our system against outside threats such as hackers, but it also means protecting against insider threats.  ]]></description>
            <content:encoded><![CDATA[ <p></p><p>At CloudFlare, we are always looking for better ways to secure the data we’re entrusted with. This means hardening our system against outside threats such as hackers, but it also means protecting against insider threats. According to a <a href="http://www.verizonenterprise.com/DBIR/2013/">recent Verizon report</a>, insider threats account for around 14% of data breaches in 2013. While we perform background checks and carefully screen team members, we also implement technical barriers to protect the data with which we are entrusted.</p><p>One good information security practice is known as the “two-man rule.” It comes from military history, where a nuclear missile couldn’t be launched unless two people agreed and turned their launch keys simultaneously. This requirement was introduced in order to prevent one individual from accidentally (or intentionally) starting World War III.</p><p>To prevent the risk of rogue employees misusing sensitive data we built a service in Go to enforce the two-person rule. We call the service Red October after the famous scene from “The Hunt for Red October.” In line with <a href="/a-note-about-kerckhoffs-principle">our philosophy on security software</a>, we are open sourcing the technology so you can use it in your own organization (<a href="https://github.com/cloudflare/redoctober">here’s a link</a> to the public Github repo). If you are interested in the nitty-gritty details, read on.</p>
    <div>
      <h3>What it is</h3>
      <a href="#what-it-is">
        
      </a>
    </div>
    <p>Red October is a cryptographically-secure implementation of the two-person rule to protect sensitive data. From a technical perspective, Red October is a software-based encryption and decryption server. The server can be used to encrypt a payload in such a way that no one individual can decrypt it. The encryption of the payload is cryptographically tied to the credentials of the authorized users.</p><p>Authorized persons can delegate their credentials to the server for a period of time. The server can decrypt any previously-encrypted payloads as long as the appropriate number of people have delegated their credentials to the server.</p><p>This architecture allows Red October to act as a convenient decryption service. Other systems, including CloudFlare’s build system, can use it for decryption and users can delegate their credentials to the server via a simple web interface. All communication with Red October is encrypted with TLS, ensuring that passwords are not sent in the clear.</p>
    <div>
      <h3>How to use it</h3>
      <a href="#how-to-use-it">
        
      </a>
    </div>
    <p>Setting up a Red October server is simple; all it requires is a locally-readable path and an SSL key pair. After that, all control is handled remotely through a set of JSON-based APIs.</p><p>Red October is backed by a database of accounts stored on disk in a portable password vault. The server never stores the account password there, only a <a href="/keeping-passwords-safe-by-staying-up-to-date">salted hash of the password</a> for each account. For each user, the server creates an RSA key pair and encrypts the private key with a key derived from the password and a randomly generated salt using a secure derivation function.</p><p>Any administrator can encrypt any piece of data with the encrypt API. This request takes a list of users and the minimum number of users needed to decrypt it. The server returns a somewhat larger piece of data that contains an encrypted version of this data. The encrypted data can then be stored elsewhere.</p><p>This data can later be decrypted with the decrypt API, but only if enough people have delegated their credentials to the server. The delegation API lets a user grant permission to a server to use their credentials for a limited amount of time and a limited number of uses.</p>
    <div>
      <h3>Cryptographic Design</h3>
      <a href="#cryptographic-design">
        
      </a>
    </div>
    <p>Red October was designed from cryptographic first principles, combining trusted and understood algorithms in known ways. CloudFlare is also opening the source of the server to allow others to analyze its design.</p><p>Red October is based on combinatorial techniques and trusted cryptographic primitives. We investigated using complicated secret primitives like <a href="http://en.wikipedia.org/wiki/Shamir's_Secret_Sharing">Shamir's sharing scheme</a>, but we found that a simpler combinatorial approach based on primitives from Go's standard library was preferable to implementing a mathematical algorithm from scratch. Red October uses <a href="http://en.wikipedia.org/wiki/Advanced_Encryption_Standard">128-bit AES</a>, <a href="http://en.wikipedia.org/wiki/RSA_(algorithm)">2048-bit RSA</a> and <a href="http://en.wikipedia.org/wiki/Scrypt">scrypt</a> as its cryptographic primitives.</p>
    <div>
      <h4>Creating an account</h4>
      <a href="#creating-an-account">
        
      </a>
    </div>
    <p>Each user is assigned a unique, randomly-generated RSA key pair when creating an account on a Red October server. The private key is encrypted with a password key derived from the user’s password and salt using scrypt. The public key is stored unencrypted in the vault with the encrypted private key.</p>
    <div>
      <h4>Encrypting data</h4>
      <a href="#encrypting-data">
        
      </a>
    </div>
    <p>When asked to encrypt a piece of data, the server generates a random 128-bit AES key. This key is used to encrypt the data. For each user that is allowed to decrypt the data, a user-specific key encryption key is chosen. For each unique pair of users, the data key is doubly encrypted, once with the key encryption key of each user. The key encryption keys are then encrypted with the public RSA key associated with their account. The encrypted data, the set of doubly-encrypted data keys, and the RSA-encrypted key encryption keys are all bundled together and returned. The encrypted data is never stored on the server.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/38JLECxsa5YaGcwkkJnhEn/3054808bc0b25afda9d7c3be1fdc8f6b/cryptography1.png" />
            
            </figure><p>Delegating credentials to the server</p><p>When a user delegates their key to the server, they submit their username and password over TLS using the delegate JSON API. For each account, the password is verified against the salted hash. If the password is correct, a password key is derived from the password and used to decrypt the user’s RSA private key. This key is now “Live” for the length of time and number of decryptions chosen by the user.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/Jefh1rq4DwCnifHejHJNe/c10f4e6420354b9c16f3f8f12ff15ae8/cryptography3.png" />
            
            </figure><p>Decrypting data</p><p>To decrypt a file, the server validates that the requesting user is an administrator and has the correct password. If two users of the list of valid users have delegated their keys, then decryption can occur. First the RSA private key is used to decrypt the key encryption key for these two users, then the key encryption keys are used to decrypt the doubly encrypted data key, which is then used to decrypt the data.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6nvlGuGFWguhaebYbrsY9n/1432bb6989d6b48631c7271d95bd12a6/cryptography2.png" />
            
            </figure><p>Some other key points:</p><ol><li><p>Cryptographic security. The Red October server does not have the ability to decrypt user keys without their password. This prevents someone with access to the vault from decrypting data.</p></li><li><p>Password flexibility. Passwords can be changed without changing the encryption of a given file. Key encryption keys ensure that password changes are decoupled from data encryption keys.</p></li></ol>
    <div>
      <h3>Looking ahead</h3>
      <a href="#looking-ahead">
        
      </a>
    </div>
    <p>The version of Red October we are releasing to GitHub is in beta. It is licensed under the <a href="http://opensource.org/licenses/BSD-3-Clause">3-clause BSD license</a>. We plan to continue to release our improvements to the open source community. Here is the project on GitHub: <a href="https://github.com/cloudflare/redoctober">Red October</a>.</p><p>Writing the server in Go allowed us to design the different components of this server in a modular way. Our hope is this modularity will make it easy for anyone to build in support for different authentication methods that are not based on passwords (for example, TLS client certificates, time-based one-time-passwords) and new core cryptographic primitives (for example, elliptic curve cryptography).</p><p>CloudFlare is always looking to improve the state of security on the Internet. It is important to us to share our advances with the world and <a href="/open-source-two-way-street">contribute back to the community</a>. See the <a href="http://cloudflare.github.io/">CloudFlare GitHub page</a> for the list of our open source projects and initiatives.</p> ]]></content:encoded>
            <category><![CDATA[Open Source]]></category>
            <category><![CDATA[Encryption]]></category>
            <category><![CDATA[RSA]]></category>
            <category><![CDATA[GitHub]]></category>
            <category><![CDATA[TLS]]></category>
            <category><![CDATA[Security]]></category>
            <category><![CDATA[Cryptography]]></category>
            <category><![CDATA[Salt]]></category>
            <guid isPermaLink="false">6tG7fMY0ykeCo1uPglwZFn</guid>
            <dc:creator>Nick Sullivan</dc:creator>
        </item>
        <item>
            <title><![CDATA[A note about Kerckhoff's Principle]]></title>
            <link>https://blog.cloudflare.com/a-note-about-kerckhoffs-principle/</link>
            <pubDate>Tue, 19 Jun 2012 15:56:00 GMT</pubDate>
            <description><![CDATA[ The other day I wrote a long post describing in detail how we used to and how we now store customer passwords. Some people were surprised that we were open about this. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Image credit: <a href="http://www.flickr.com/photos/psicologiaclinica/">psicologiaclinica</a></p><p>The other day I wrote a long post describing in detail <a href="/keeping-passwords-safe-by-staying-up-to-date">how we used to and how we now store customer passwords</a>. Some people were surprised that we were open about this, and others wanted to understand exactly what part of a security system needs to be kept secret.</p><p>The simple answer is: a security system is only secure if its details can be safely shared with the world. This is known as <a href="http://en.wikipedia.org/wiki/Kerckhoffs's_principle">Kerckhoff's Principle</a>.</p><p>The principle is sometimes stated as "a cryptosystem should be secure even if everything about the system, except the key, is public knowledge" or using Claude Shannon's simpler version: "the enemy knows the system".</p><p>The idea is that if any part of a cryptosystem (except the individual secret key) has to be kept secret then the cryptosystem is not secure. That's because if the simple act of disclosing some detail of the system were to make it suddenly insecure then you've got a problem on your hands.</p><p>You've somehow got to keep that detail secret and for that you'll need a cryptosystem! Given that the whole point of the cryptosystem was to keep secrets, it's useless if it needs some other system to keep itself secret.</p><p>So, the gold standard for any secret keeping system is that all its details should be able to be made public without compromising the security of the system. The security relies on the system itself, not the secrecy of the system. (And as a corollary if anyone tells you've they've got some supersecret encryption system they can't tell you about then it's likely rubbish).</p><p>A great example of this is the breaking of the <a href="http://en.wikipedia.org/wiki/Enigma_machine">Nazi German Enigma cipher</a> during the Second World War. By stealing machines, receiving information from other secret services, and reading the manuals, the Allies knew everything there was to know about how the Enigma machine worked.</p><p>Engima's security relied not on its secrecy, but on its complexity (and on keeping the daily key a secret). Engima was broken by attacking the mathematics behind its encryption and building special machines to exploit mathematical flaws in the encryption.</p><p>That's just as true today. The security of HTTPS, SSL and ciphers like AES or RSA rely on the complexity of the algorithm, not on keeping them secret. In fact, they are all published, detailed standards. The only secret is the key that's chosen when you connect to a secure web site (that's done automatically and randomly by your browser and the server) or when you encrypt a document using a program like GPG.</p><p>Another example is home security. Imagine if you bought a lock that stated that it must be hidden from view so that no one knew what type of lock you had installed. That wouldn't provide much reassurance that the lock was any good. The security of the lock should depend on its mechanism and you keeping the key safe not on you keeping the lock a secret!</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2a7e3lQQwJd4EQe1cvSE3A/87c92e843914277edca262a9758859bf/7190315846_1a651daaf7.jpeg.scaled500.jpg" />
            
            </figure><p>Image credit: <a href="http://www.flickr.com/photos/paulorear/">paul.orear</a></p><p>When storing passwords securely we rely on the complexity of the bcrypt algorithm. Everything about our storage mechanism is assumed to be something that can be made public. So it's safe to say that we choose a random salt, and that we use bcrypt. The salt is not a key, and it does not need to be kept secret.</p><p>But even more we assume that in the horrible case that our password database were accessed it will still be secure even though the hashed passwords and salts would be available to a hacker. The security of the system relies on the security of bcrypt and nothing else.</p><p>Of course, as a practical matter we don't leave the database lying around for anyone to access. It's kept behind firewalls and securely stored. But when thinking about security it's important to think about the worst case situation, a full disclosure of the secured information, and rely on the algorithm's strength and nothing else.</p> ]]></content:encoded>
            <category><![CDATA[Tech Talks]]></category>
            <category><![CDATA[Deep Dive]]></category>
            <category><![CDATA[Salt]]></category>
            <guid isPermaLink="false">5jPpUkNtZivIfb5kAu7ja1</guid>
            <dc:creator>John Graham-Cumming</dc:creator>
        </item>
    </channel>
</rss>