
<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>Sat, 04 Apr 2026 10:18:54 GMT</lastBuildDate>
        <item>
            <title><![CDATA[Improving your monitoring setup by integrating Cloudflare’s analytics data into Prometheus and Grafana]]></title>
            <link>https://blog.cloudflare.com/improving-your-monitoring-setup-by-integrating-cloudflares-analytics-data-into-prometheus-and-grafana/</link>
            <pubDate>Thu, 20 May 2021 13:00:15 GMT</pubDate>
            <description><![CDATA[ Here at Labyrinth Labs, we put great emphasis on monitoring. Having a working monitoring setup is a critical part of the work we do for our clients.
Improving your monitoring setup by integrating Cloudflare’s analytics data into Prometheus and Grafana ]]></description>
            <content:encoded><![CDATA[ <p><i>The following is a guest post by Martin Hauskrecht, DevOps Engineer at Labyrinth Labs.</i></p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1No9XvnguRN5bpcRgbSZBe/5e776b72c64573b51921171da88be6c1/image1-7.png" />
            
            </figure><p>Here at Labyrinth Labs, we put great emphasis on monitoring. Having a working monitoring setup is a critical part of the work we do for our clients.</p><p>Cloudflare's Analytics dashboard provides a lot of useful information for debugging and analytics purposes for our customer Pixel Federation. However, it doesn’t automatically integrate with existing monitoring tools such as Grafana and Prometheus, which our DevOps engineers use every day to monitor our infrastructure.</p><p>Cloudflare provides a Logs API, but the amount of logs we’d need to analyze is so vast, it would be simply inefficient and too pricey to do so. Luckily, Cloudflare already does the hard work of aggregating our thousands of events per second and exposes them in an <a href="https://developers.cloudflare.com/analytics/graphql-api/">easy-to-use API</a>.</p><p>Having Cloudflare’s data from our zones integrated with other systems’ metrics would give us a better understanding of our systems and the ability to correlate metrics and create more useful alerts, making our Day-2 operations (e.g. debugging incidents or analyzing the usage of our systems) more efficient.</p><p>Since our monitoring stack is primarily based on Prometheus and Grafana, we decided to implement our own Prometheus exporter that pulls data from Cloudflare’s GraphQL Analytics API.</p>
    <div>
      <h3>Design</h3>
      <a href="#design">
        
      </a>
    </div>
    <p>Based on current cloud trends and our intention to use the exporter in Kubernetes, writing the code in Go was the obvious choice. Cloudflare provides an <a href="https://github.com/cloudflare/cloudflare-go">API SDK for Golang</a>, so the common API tasks were made easy to start with.</p><p>We take advantage of Cloudflare’s GraphQL API to obtain analytics data about each of our zones and transform them into Prometheus metrics that are then exposed on a metrics endpoint.</p><p>We are able to obtain data about the total number and rate of requests, bandwidth, cache utilization, threats, SSL usage, and HTTP response codes. In addition, we are also able to monitor what type of content is being transmitted and what countries and locations the requests originate from.</p><p>All of this information is provided through the <i>http1mGroups</i> node in Cloudflare’s GraphQL API. If you want to see what Datasets are available, you can find a brief description at <a href="https://developers.cloudflare.com/analytics/graphql-api/features/data-sets">https://developers.cloudflare.com/analytics/graphql-api/features/data-sets</a>.</p><p>On top of all of these, we can also obtain data for Cloudflare’s data centers. Our graphs can easily show the distribution of traffic among them, further helping in our evaluations. The data is obtained from the <code><i>httpRequestsAdaptiveGroups</i></code> node in GraphQL.</p><p>After running the queries against the GraphQL API, we simply format the results to follow the Prometheus metrics format and expose them on the /metrics endpoint. To make things faster, we use Goroutines and make the requests in parallel.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1d6eIT9Tv7F4p5iLP4bYQR/1fc81995d3304539456ace57170af022/image4-9.png" />
            
            </figure>
    <div>
      <h3>Deployment</h3>
      <a href="#deployment">
        
      </a>
    </div>
    <p>Our primary intention was to use the exporter in Kubernetes. Therefore, it comes with a <a href="https://hub.docker.com/repository/docker/lablabs/cloudflare_exporter">Docker image</a> and <a href="https://github.com/lablabs/cloudflare-exporter/tree/master/charts/cloudflare-exporter">Helm chart</a> to make deployments easier. You might need to adjust the Service annotations to match your Prometheus configuration.</p><p>The exporter itself exposes the gathered metrics on the /metrics endpoint. Therefore setting the Prometheus annotations either on the pod or a Kubernetes service will do the job.</p>
            <pre><code>apiVersion: v1
kind: Service
metadata:
  annotations:
    prometheus.io/path: /metrics
    prometheus.io/scrape: "true"</code></pre>
            <p>We plan on adding a Prometheus ServiceMonitor to the Helm chart to make scraping the exporter even easier for those who use the Prometheus operator in Kubernetes.</p><p>The configuration is quite easy, you just provide your API email and key. Optionally you can limit the scraping to selected zones only. Refer to our docs in the <a href="https://github.com/lablabs/cloudflare-exporter">GitHub repo</a> or see the example below.</p>
            <pre><code> env:
   - name: CF_API_EMAIL
     value: &lt;YOUR_API_EMAIL&gt;
   - name: CF_API_KEY
     value: &lt;YOUR_API_KEY&gt;

  # Optionally, you can filter zones by adding IDs following the example below.
  # - name: ZONE_XYZ
  #   value: &lt;zone_id&gt;</code></pre>
            <p>To deploy the exporter with Helm you simply need to run:</p>
            <pre><code>helm repo add lablabs-cloudflare-exporter https://lablabs.github.io/cloudflare-exporter
helm repo update

helm install cloudflare-exporter lablabs-cloudflare-exporter/cloudflare-exporter \
--set env[0].CF_API_EMAIL=&lt;API_EMAIL&gt; \
--set env[1].CF_API_KEY=&lt;API_KEY&gt;</code></pre>
            <p>We also provide a <a href="https://github.com/lablabs/cloudflare-exporter/blob/master/examples/helmfile/cloudflare-exporter.yaml">Helmfile</a> in our repo to make deployments easier, you just need to add your credentials to make it work.</p>
    <div>
      <h3>Visualizing the data</h3>
      <a href="#visualizing-the-data">
        
      </a>
    </div>
    <p>I’ve already explained how the exporter works and how you can get it running. As I mentioned before, we use Grafana to visualize our metrics from Prometheus. We’ve created a <a href="https://grafana.com/grafana/dashboards/13133">dashboard</a> that takes the data from Prometheus and puts it into use.</p><p>The dashboard is divided into several rows, which group individual panels for easier navigation. It allows you to target individual zones for metrics visualization.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4zGurfsIFldJAl7JWn1Ugm/f7e1173d0d3ccadb91de95d49902b6fc/image2-5.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2Wui3JqzgAU1GAU5J7XXj3/b5fa5aab63702997b97d7be3cc5ed7f0/image3-6.png" />
            
            </figure><p>To make things even more beneficial for the operations team, you can use the gathered metrics to create alerts. These can be created either in Grafana directly or using Prometheus alert rules.</p><p>Furthermore, if you integrate <a href="https://github.com/thanos-io/thanos">Thanos</a> or <a href="https://grafana.com/oss/cortex/">Cortex</a> into your monitoring setup, you can store these metrics indefinitely.</p>
    <div>
      <h3>Future work</h3>
      <a href="#future-work">
        
      </a>
    </div>
    <p>We’d like to integrate even more analytics data into our exporters, eventually reaching every metric that Cloudflare’s GraphQL can provide. We plan on creating new metrics for firewall analytics, DoS analytics, and Network analytics soon.</p><p>Feel free to create a GitHub issue if you have any questions, problems, or suggestions. Any pull request is greatly appreciated.</p>
    <div>
      <h3>About us</h3>
      <a href="#about-us">
        
      </a>
    </div>
    <p><a href="https://lablabs.io/">Labyrinth Labs</a> helps companies build, run, deploy and scale software and infrastructure by embracing the right technologies and principles.</p> ]]></content:encoded>
            <category><![CDATA[Analytics]]></category>
            <category><![CDATA[Customers]]></category>
            <category><![CDATA[Prometheus]]></category>
            <category><![CDATA[Grafana]]></category>
            <category><![CDATA[Monitoring]]></category>
            <guid isPermaLink="false">4IQoisV5GHmCHWVLWy6LNK</guid>
            <dc:creator>Martin Hauskrecht</dc:creator>
        </item>
        <item>
            <title><![CDATA[Want to see your DNS analytics? We have a Grafana plugin for that]]></title>
            <link>https://blog.cloudflare.com/grafana-plugin/</link>
            <pubDate>Tue, 14 Feb 2017 18:04:08 GMT</pubDate>
            <description><![CDATA[ Curious where your DNS traffic is coming from, how much DNS traffic is on your domain, and what records people are querying for that don’t exist? We now have a Grafana plugin for you.

 ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Curious where your DNS traffic is coming from, how much DNS traffic is on your domain, and what records people are querying for that don’t exist? We now have a Grafana plugin for you.</p><p>Grafana is an open source data visualization tool that you can use to integrate data from many sources into one cohesive dashboard, and <a href="http://docs.grafana.org/alerting/rules/">even use it to set up alerts</a>. We’re big Grafana fans here - we use Grafana internally for our ops metrics dashboards.</p><p>In the Cloudflare Grafana plugin, you can see the response code breakdown of your DNS traffic. During a random prefix flood, a common type of DNS DDoS attack where an attacker queries random subdomains to bypass DNS caches and overwhelm the origin nameservers, you will see the number of NXDOMAIN responses increase dramatically. It is also common during normal traffic to have a small amount of negative answers due to typos or clients searching for missing records.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2lx4BwSBiV5nQUNAbNolzl/4297d330f64822e001a478a9555d7f78/rcode.png" />
            
            </figure><p>You can also see the breakdown of queries by data center and by query type to understand where your traffic is coming from and what your domains are being queried for. This is very useful to identify localized issues, and to see how your traffic is spread globally.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5pOm5hXg0QRuSySo23lL3v/c917f8cd3db5f557eebfa75b3c4274c1/colo-qtype.png" />
            
            </figure><p>You can filter by specific data centers, record types, query types, response codes, and query name, so you can filter down to see analytics for just the MX records that are returning errors in one of the data centers, or understand whether the negative answers are generated because of a DNS attack, or misconfigured records.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3h1OmevfS9qBnIfHnTil6L/18f4fd1b286addec94829765eb60c9ab/Screen-Shot-2017-02-13-at-10.59.45-AM.png" />
            
            </figure><p>Once you have the Cloudflare Grafana Plugin installed, you can also make your own charts using the Cloudflare data set in Grafana, and integrate them into your existing dashboards.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/738PJEVjnkrzf5qnIUSL0S/7cca7ada36e01cb425efeb85a710e979/Screen-Shot-2017-02-13-at-11.08.11-AM.png" />
            
            </figure><p><a href="https://www.cloudflare.com/virtual-dns/">Virtual DNS customers</a> can also take advantage of the Grafana plugin. There is a custom Grafana dashboard that comes installed with the plugin to show traffic distribution and <a href="https://www.cloudflare.com/learning/cdn/glossary/round-trip-time-rtt/">RTT</a> from different Virtual DNS origins, as well as the top queries that uncached or are returning SERVFAIL.</p><p>The Grafana plugin is just one step to install once you have Grafana up and running:</p>
            <pre><code>grafana-cli plugins install cloudflare-app</code></pre>
            <p>Once you sign in using your user email and API key, the plugin will automatically discover domains and Virtual DNS clusters you have access to.</p><p>The Grafana plugin is built on our new <a href="https://developers.cloudflare.com/api/#dns-analytics-properties">DNS analytics API</a>. If you want to explore your DNS traffic but Grafana isn’t your tool of choice, our DNS analytics API is very easy to get started with. Here’s a curl to get you started:</p>
            <pre><code>curl -s -H 'X-Auth-Key:####' -H 'X-Auth-Email:####' 'https://api.cloudflare.com/client/v4/zones/####/dns_analytics/report?metrics=queryCount’</code></pre>
            <p>To make all of this work, Cloudflare DNS is answering and logging millions of queries each second. Having high resolution data at this scale enables us to quickly pinpoint and resolve problems, and we’re excited to share this with you. More on this in a follow up deep dive blog post on improvements in our new data pipeline.</p><p>Instructions for how to get started with Grafana are <a href="https://support.cloudflare.com/hc/en-us/articles/115002722267">here</a> and DNS analytics API documentation is <a href="https://api.cloudflare.com/#dns-analytics-properties">here</a>. Enjoy!</p><p><i>This blog post was edited on 9/20/18 to update installation instructions.</i></p> ]]></content:encoded>
            <category><![CDATA[Analytics]]></category>
            <category><![CDATA[DNS]]></category>
            <category><![CDATA[Grafana]]></category>
            <category><![CDATA[DDoS]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[Security]]></category>
            <guid isPermaLink="false">2mtV4vGRyX5uleTcj97Xrq</guid>
            <dc:creator>Marek Vavruša</dc:creator>
        </item>
        <item>
            <title><![CDATA[The Porcupine Attack: investigating millions of junk requests]]></title>
            <link>https://blog.cloudflare.com/the-porcupine-attack-investigating-millions-of-junk-requests/</link>
            <pubDate>Mon, 09 Jan 2017 14:08:58 GMT</pubDate>
            <description><![CDATA[ We extensively monitor our network and use multiple systems that give us visibility including external monitoring and internal alerts when things go wrong. ]]></description>
            <content:encoded><![CDATA[ <p>We extensively monitor our network and use multiple systems that give us visibility including external monitoring and internal alerts when things go wrong. One of the most useful systems is <a href="http://grafana.org/">Grafana</a> that allows us to quickly create arbitrary dashboards. And a heavy user of Grafana we are: at last count we had 645 different Grafana dashboards configured in our system!</p>
            <pre><code>grafana=&gt; select count(1) from dashboard;
 count
-------
   645
(1 row)</code></pre>
            <p>This post is not about our Grafana systems though. It's about something we noticed a few days ago, while looking at one of those dashboards. We noticed this:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5J5NcPnvP0aNMRm7SdcuAI/68d1f8a5edf4f600666ca51aba6c4a7b/hedgehog.png" />
            
            </figure><p>This chart shows the number of HTTP requests per second handled by our systems globally. You can clearly see multiple spikes, and this chart most definitely should not look like a porcupine! The spikes were large in scale - <i>500k to 1M HTTP requests per second</i>. Something very strange was going on.</p>
    <div>
      <h3>Tracing the spikes<a href="#fn1">[1]</a></h3>
      <a href="#tracing-the-spikes">
        
      </a>
    </div>
    <p>Our intuition indicated an attack - but our attack mitigation systems didn't confirm it. We'd seen no major HTTP attacks at those times.</p><p>It would be <i>bad</i> if we were under such heavy HTTP attack and our mitigation systems didn't notice it. Without more ideas, we went back to one of our favorite debugging tools - <code>tcpdump</code>.</p><p>The spikes happened every 80 minutes and lasted about 10 minutes. We waited, and tried to catch the offending traffic. Here is what the HTTP traffic looked like on the wire:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/acRydqIF0JozrKjwO470H/d86d7e850604998cf33db9d1a66d4561/hwire.png" />
            
            </figure><p>The client had sent some binary junk to our HTTP server on port 80; they weren't even sending a fake GET or POST line!</p><p>Our server politely responded with HTTP 400 error. This explains why it wasn't caught by our attack mitigation systems. Invalid HTTP requests don't trigger our HTTP DDoS mitigations - it makes no sense to mitigate traffic which is never accepted by NGINX in the first place!</p>
    <div>
      <h3>The payload</h3>
      <a href="#the-payload">
        
      </a>
    </div>
    <p>At first glance the payload sent to HTTP servers seems random. A colleague of mine, <a href="https://twitter.com/chrisbranch">Chris Branch</a>, investigated and proved me wrong. The payload has patterns.</p><p>Let me show what's happening. Here are the first 24 bytes of the mentioned payload:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6xuqzBVwsArs569h0oJmAa/f44b29516fae40a6226870f8fb9f2853/hp1.png" />
            
            </figure><p>If you look closely, the pattern will start to emerge. Let's add some colors and draw it in not eight, but seven bytes per row:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/l8hPvQM54L9hQnRbRZ3S1/f70c83ac3c81f7488129eefc06cab033/hp2-1.png" />
            
            </figure><p>This checkerboard-like pattern, is exhibited in most of the requests with payload sizes below 512 bytes.</p><p>Another <a href="https://twitter.com/jgrahamc">engineer</a> pointed out there appear to actually be two separate sequences generated in the same fashion. Starting with the <code>a6</code> and the <code>cb</code> take alternating bytes</p>
            <pre><code>a6 ef 39 82 cb 15 5e a7 f0 3a 83 cc 16 5f
cb 15 5e a7 f0 3a 83 cc 16 5f a8 f1 3b</code></pre>
            <p>Aligning that differently shows that the second sequence is essentially the same as the first:</p>
            <pre><code>a6 ef 39 82 cb 15 5e a7 f0 3a 83 cc 16 5f
            cb 15 5e a7 f0 3a 83 cc 16 5f a8 f1 3b</code></pre>
            <p>Thinking of that as one sequence gets</p>
            <pre><code>a6 ef 39 82 cb 15 5e a7 f0 3a 83 cc 16 5f a8 f1 3b</code></pre>
            <p>Which is generated by starting at <code>ef</code> and adding the following repeating sequence.</p>
            <pre><code>4a 49 49 4a 49 49 49</code></pre>
            <p>The 'random' binary junk is actually generated by some simple code.</p><p>The length distribution of the requests is also interesting. Here's the histogram showing the popularity of particular lengths of payloads.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7CqXp7Q2ihFt6gWng6lJqP/2269db7f9437f2a681bad630554e290f/hlengths.png" />
            
            </figure><p>About 80% of the junk requests we received had length of up to 511 bytes, uniformly distributed.</p><p>The remaining 20% had length uniformly distributed between 512 and 2047 bytes, with a few interesting spikes. For some reason lengths of 979, 1383 and 1428 bytes stand out. The rest of the distribution looks uniform.</p>
    <div>
      <h3>The scale</h3>
      <a href="#the-scale">
        
      </a>
    </div>
    <p>The spikes were large. It takes a lot of firepower to generate a spike in our global HTTP statistics! On the first day the spikes reached about 600k junk requests per second. On second day the score went up to 1M rps. In total we recorded 37 spikes.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/dRBYTfiRAb6aYn3yGhlKQ/61cc57d15679a62d4cb3b3f1bb714f00/hattacks.png" />
            
            </figure>
    <div>
      <h3>Geography</h3>
      <a href="#geography">
        
      </a>
    </div>
    <p>Unlike L3 attacks, L7 attacks require TCP/IP connections to be fully established. That means the source IP addresses are not spoofed and can be used to investigate the geographic distribution of attacking hosts.</p><p>The spikes were generated by IP addresses from all around the world. We recorded IP numbers from 4,912 distinct Autonomous Systems. Here are top ASN numbers by number of unique attacking IP addresses:</p>
            <pre><code>Percent of unique IP addresses seen:
21.51% AS36947  # AS de Algerie Telecom, Algeria
 5.34% AS18881  # Telefonica Brasil S.A, Brasil
 3.60% AS7738   # Telemar Norte Leste S.A., Brasil
 3.48% AS27699  # Telefonica Brasil S.A, Brasil
 3.37% AS28573  # CLARO S.A., Brasil
 3.20% AS8167   # Brasil Telecom S/A, Brasil
 2.44% AS2609   # Tunisia BackBone, Tunisia
 2.22% AS6849   # PJSC "Ukrtelecom", Ukraine
 1.77% AS3320   # Deutsche Telekom AG, Germany
 1.73% AS12322  # Free SAS, France
 1.73% AS8452   # TE-AS, Egypt
 1.35% AS12880  # Information Technology Company, Iran
 1.30% AS37705  # TOPNET, Tunisia
 1.26% AS53006  # Algar Telecom S/A, Brasil
 1.22% AS36903  # ASN du reseaux MPLs de Maroc Telecom, Morocco
 ... 4897 AS numbers below 1% of IP addresses.</code></pre>
            <p>You get the picture - the traffic was sourced all over the place, with bias towards South America and North Africa. Here is the country distribution of attacking IPs:</p>
            <pre><code>Percent of unique IP addresses seen:
31.76% BR
21.76% DZ
 7.49% UA
 5.73% TN
 4.89% IR
 3.96% FR
 3.76% DE
 2.09% EG
 1.78% SK
 1.36% MA
 1.15% GB
 1.05% ES
 ... 109 countries below 1% of IP addresses</code></pre>
            <p>The traffic was truly global and launched with IPs from 121 countries. This kind of globally distributed attack is where <a href="/how-cloudflares-architecture-allows-us-to-scale-to-stop-the-largest-attacks/">Cloudflare's Anycast</a> network shines. During these spikes the load was nicely distributed across dozens of datacenters. <a href="/parabens-brasil-cloudflares-27th-data-center-now-live/">Our datacenter in São Paulo</a> absorbed the most traffic, roughly 4 times more traffic than the second in line - Paris. This chart shows how the traffic was distributed across many datacenters:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2qrKg7vQPH8xcmC2rMOVcn/f637b781e9fc738eddbdd164a10af826/hcolos.png" />
            
            </figure>
    <div>
      <h3>Unique IPs</h3>
      <a href="#unique-ips">
        
      </a>
    </div>
    <p>During each of the spikes our systems recorded 200k unique source IP addresses sending us junk requests.</p><p>Normally we would conclude that whoever generated the attack controlled roughly 200k bots, and that's it. But these spikes were different. It seems the bots rotated IPs aggressively. Here is an example: during these 16 spikes we recorded a total count of a whopping 1.2M unique IP addresses attacking us.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6EtSV8z8pfbXnnebomGU0i/d8619334d05cd0637953111b5e650079/hmillion.png" />
            
            </figure><p>This can be explained by bots churning through IP addresses. We believe that out of the estimated 200k bots, between 50k and 100k bots changed their IP addresses during the 80 minutes between attacks. This resulted in 1.2M unique IP addresses during the 16 spikes happening over 24 hours.</p>
    <div>
      <h3>A botnet?</h3>
      <a href="#a-botnet">
        
      </a>
    </div>
    <p>These spikes were unusual for a number of reasons.</p><ul><li><p>They were generated by a large number of IP addresses. We estimate 200k concurrent bots.</p></li><li><p>The bots were rotating IP addresses aggressively.</p></li><li><p>The bots were from around the world with an emphasis on South America and North Africa.</p></li><li><p>The traffic generated was enormous, reaching 1M junk connections per second.</p></li><li><p>The spikes happened exactly every 80 minutes and lasted for 10 minutes.</p></li><li><p>The payload of the traffic was junk, not a usual HTTP request attack.</p></li><li><p>The payload had uniformly distributed payload sizes.</p></li></ul><p>It's hard to draw conclusions, but we can imagine two possible scenarios. It is possible these spikes were an attack intended to break our HTTP servers.</p><p>A second possibility is that these spikes were legitimate connection attempts by some weird, obfuscated protocol. For some reason the clients were connecting to port 80/TCP and retried precisely every 80 minutes.</p><p>We are continuing our investigation. In the meantime we are looking for clues. Please do let us know if you have encountered this kind of TCP/IP payload. We are puzzled by these large spikes.</p><p>If you'd like to work on this type of problem <a href="https://www.cloudflare.com/join-our-team/">we're hiring</a> in London, San Francisco, Austin, Champaign and Singapore.</p><p><i>Update</i> A <a href="https://twitter.com/GGreg/status/818462582998704128">Twitter user</a> pointed out that the sequence <code>a6 ef 39 82 cb 15 5e a7 f0 3a 83 cc 16 5f a8 f1 3b</code> appears in this set of <a href="https://github.com/gvanas/KeccakCodePackage/blob/master/TestVectors/KetjeJr.txt">test vectors</a> so we contacted the <a href="http://gva.noekeon.org/">author</a> who was kind enough to reply and point us to the <a href="https://github.com/gvanas/KeccakCodePackage/blob/master/Tests/testKetje.c#L46">code</a> that generated those vectors.</p>
            <pre><code>static void generateSimpleRawMaterial(unsigned char* data, unsigned int length, unsigned char seed1, unsigned int seed2)
{
    unsigned int i;

    for( i=0; i&lt;length; i++) {
        unsigned int iRolled = i*seed1;
        unsigned char byte = (iRolled+length+seed2)%0xFF;
        data[i] = byte;
    }
}</code></pre>
            <p>Since we identified above that the difference between two bytes seemed to be 0x49 or 0x4a it's worth looking at the difference between bytes in this algorithm. Simplifying, bytes are generated from:</p>
            <pre><code>((i * seed1) + length + seed2)%0xFF</code></pre>
            <p>Ignoring the <code>% 0xff</code> for the moment that's <code>(i * seed1) + length + seed</code>. Taking the difference between two adjacent bytes (for <code>i</code> and <code>i+1</code>) gives a difference of just <code>seed1</code>.</p><p>Thus in our case it's likely that <code>seed1</code> is 0x49. It's fairly easy to end up with the following code to generate the sequence:</p>
            <pre><code>seed = 0x49
byte = 0xa6

do
   byte = (seed + byte) % 0xff
done</code></pre>
            <p>One big mystery remaining is 'what's the 0x75 at the start of the junk data?'.</p><hr /><ol><li><p>Yes, we're aware that porcupines have spines/quills not spikes. <a href="#fnref1">↩︎</a></p></li></ol> ]]></content:encoded>
            <category><![CDATA[Attacks]]></category>
            <category><![CDATA[Grafana]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[Security]]></category>
            <guid isPermaLink="false">2W4ED6tvTfgStUaMEus73C</guid>
            <dc:creator>Marek Majkowski</dc:creator>
        </item>
    </channel>
</rss>