
<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 08:31:51 GMT</lastBuildDate>
        <item>
            <title><![CDATA[How and why the leap second affected Cloudflare DNS]]></title>
            <link>https://blog.cloudflare.com/how-and-why-the-leap-second-affected-cloudflare-dns/</link>
            <pubDate>Sun, 01 Jan 2017 22:40:26 GMT</pubDate>
            <description><![CDATA[ At midnight UTC on New Year’s Day, deep inside Cloudflare’s custom RRDNS software, a number went negative when it should always have been, at worst, zero. A little later this negative value caused RRDNS to panic.  ]]></description>
            <content:encoded><![CDATA[ <p>At midnight UTC on New Year’s Day, deep inside Cloudflare’s custom <a href="/tag/rrdns/">RRDNS</a> software, a number went negative when it should always have been, at worst, zero. A little later this negative value caused RRDNS to panic. This panic was caught using the recover feature of the Go language. The net effect was that some DNS resolutions to some Cloudflare managed web properties failed.</p><p>The problem only affected customers who use CNAME DNS records with Cloudflare, and only affected a small number of machines across Cloudflare's 102 data centers. At peak approximately 0.2% of DNS queries to Cloudflare were affected and less than 1% of all HTTP requests to Cloudflare encountered an error.</p><p>This problem was quickly identified. The most affected machines were patched in 90 minutes and the fix was rolled out worldwide by 0645 UTC. We are sorry that our customers were affected, but we thought it was worth writing up the root cause for others to understand.</p>
    <div>
      <h3>A little bit about Cloudflare DNS</h3>
      <a href="#a-little-bit-about-cloudflare-dns">
        
      </a>
    </div>
    <p>Cloudflare customers use our <a href="https://www.cloudflare.com/dns/">DNS service</a> to serve the authoritative answers for DNS queries for their domains. They need to tell us the IP address of their origin web servers so we can contact the servers to handle non-cached requests. They do this in two ways: either they enter the IP addresses associated with the names (e.g. the IP address of example.com is 192.0.2.123 and is entered as an A record) or they enter a CNAME (e.g. example.com is origin-server.example-hosting.biz).</p><p>This image shows a test site with an A record for <code>theburritobot.com</code> and a CNAME for <code>www.theburritobot.com</code> pointing directly to Heroku.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6849XKj9F4rFAMEnAT53RX/4a550069ff1b976af330dafffc087783/cloudflare_dns_control_panel.png.scaled500.png" />
            
            </figure><p>When a customer uses the CNAME option, Cloudflare has occasionally to do a lookup, using DNS, for the actual IP address of the origin server. It does this automatically using standard recursive DNS. It was this CNAME lookup code that contained the bug that caused the outage.</p><p>Internally, Cloudflare operates DNS resolvers to lookup DNS records from the Internet and RRDNS talks to these resolvers to get IP addresses when doing CNAME lookups. RRDNS keeps track of how well the internal resolvers are performing and does a weighted selection of possible resolvers (we operate multiple per data center for redundancy) and chooses the most performant. Some of these resolutions ended up recording in a data structure a negative value during the leap second.</p><p>The weighted selection code, at a later point, was being fed the negative number which caused it to panic. The negative number got there through a combination of the leap second and smoothing.</p>
    <div>
      <h3>A falsehood programmers believe about time</h3>
      <a href="#a-falsehood-programmers-believe-about-time">
        
      </a>
    </div>
    <p>The root cause of the bug that affected our DNS service was the belief that <i>time cannot go backwards</i>. In our case, some code assumed that the <i>difference</i> between two times would always be, at worst, zero.</p><p>RRDNS is written in Go and uses Go’s <a href="https://golang.org/pkg/time/#Now">time.Now()</a> function to get the time. Unfortunately, this function does not guarantee monotonicity. Go currently doesn’t offer a monotonic time source (see issue <a href="https://github.com/golang/go/issues/12914">12914</a> for discussion).</p><p>In measuring the performance of the upstream DNS resolvers used for CNAME lookups RRDNS contains the following code:</p>
            <pre><code>// Update upstream sRTT on UDP queries, penalize it if it fails
if !start.IsZero() {
	rtt := time.Now().Sub(start)
	if success &amp;&amp; rcode != dns.RcodeServerFailure {
		s.updateRTT(rtt)
	} else {
		// The penalty should be a multiple of actual timeout
		// as we don't know when the good message was supposed to arrive,
		// but it should not put server to backoff instantly
		s.updateRTT(TimeoutPenalty * s.timeout)
	}
}</code></pre>
            <p>In the code above <code>rtt</code> could be negative if time.Now() was earlier than <code>start</code> (which was set by a call to <code>time.Now()</code> earlier).</p><p>That code works well if time moves forward. Unfortunately, we’ve tuned our resolvers to be very fast which means that it’s normal for them to answer in a few milliseconds. If, right when a resolution is happening, time goes back a second the perceived resolution time will be <i>negative</i>.</p><p>RRDNS doesn’t just keep a single measurement for each resolver, it takes many measurements and smoothes them. So, the single measurement wouldn’t cause RRDNS to think the resolver was working in negative time, but after a few measurements the smoothed value would eventually become negative.</p><p>When RRDNS selects an upstream to resolve a CNAME it uses a weighted selection algorithm. The code takes the upstream time values and feeds them to Go’s <a href="https://golang.org/pkg/math/rand/#Int63n">rand.Int63n()</a> function. <code>rand.Int63n</code> promptly panics if its argument is negative. That's where the RRDNS panics were coming from.</p><p>(Aside: there are many other <a href="http://infiniteundo.com/post/25326999628/falsehoods-programmers-believe-about-time">falsehoods programmers believe about time</a>)</p>
    <div>
      <h3>The one character fix</h3>
      <a href="#the-one-character-fix">
        
      </a>
    </div>
    <p>One precaution when using a non-monotonic clock source is to always check whether the difference between two timestamps is negative. Should this happen, it’s not possible to accurately determine the time difference until the clock stops rewinding.</p><p>In this patch we allowed RRDNS to forget about current upstream performance, and let it normalize again if time skipped backwards. This prevents leaking of negative numbers to the server selection code, which would result in throwing errors before attempting to contact the upstream server.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2j85WZisqjCJVcyemxck8s/5fdacf08b5b00ac2f764671e133b49ed/Screen-Shot-2017-01-01-at-12.22.33.png" />
            
            </figure><p>The fix we applied prevents the recording of negative values in server selection. Restarting all the RRDNS servers then fixed any recurrence of the problem.</p>
    <div>
      <h3>Timeline</h3>
      <a href="#timeline">
        
      </a>
    </div>
    <p>The following is the complete timeline of the events around the leap second bug.</p><p>2017-01-01 00:00 UTC Impact starts2017-01-01 00:10 UTC Escalated to engineers2017-01-01 00:34 UTC Issue confirmed2017-01-01 00:55 UTC Mitigation deployed to one canary node and confirmed2017-01-01 01:03 UTC Mitigation deployed to canary data center and confirmed2017-01-01 01:23 UTC Fix deployed in most impacted data center2017-01-01 01:45 UTC Fix being deployed to major data centers2017-01-01 01:48 UTC Fix being deployed everywhere2017-01-01 02:50 UTC Fix rolled out to most of the affected data centers2017-01-01 06:45 UTC Impact ends</p><p>This chart shows error rates for each Cloudflare data center (some data centers were more affected than others) and the rapid drop in errors as the fix was deployed. We deployed the fix prioritizing those locations with the most errors first.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6jwqwG3byUaTj1jux5soqZ/d7a15c7b78547a96f1c7af8b30853f69/Screen-Shot-2017-01-01-at-13.59.43-1.png" />
            
            </figure>
    <div>
      <h3>Conclusion</h3>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>We are sorry that our customers were affected by this bug and are inspecting all our code to ensure that there are no other leap second sensitive uses of time intervals.</p> ]]></content:encoded>
            <category><![CDATA[DNS]]></category>
            <category><![CDATA[Post Mortem]]></category>
            <category><![CDATA[RRDNS]]></category>
            <category><![CDATA[Bugs]]></category>
            <category><![CDATA[Reliability]]></category>
            <guid isPermaLink="false">2JqGGC2jqza5Af6kS3C3EA</guid>
            <dc:creator>John Graham-Cumming</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[Go coverage with external tests]]></title>
            <link>https://blog.cloudflare.com/go-coverage-with-external-tests/</link>
            <pubDate>Tue, 19 Jan 2016 18:19:59 GMT</pubDate>
            <description><![CDATA[ The Go test coverage implementation is quite ingenious: when asked to, the Go compiler will preprocess the source so that when each code portion is executed a bit is set in a coverage bitmap. ]]></description>
            <content:encoded><![CDATA[ <p>The Go test coverage implementation is <a href="https://blog.golang.org/cover">quite ingenious</a>: when asked to, the Go compiler will preprocess the source so that when each code portion is executed a bit is set in a coverage bitmap. This is integrated in the <code>go test</code> tool: <code>go test -cover</code> enables it and <code>-coverprofile=</code> allows you to write a profile to then inspect with <code>go tool cover</code>.</p><p>This makes it very easy to get unit test coverage, but <b>there's no simple way to get coverage data for tests that you run against the main version of your program, like end-to-end tests</b>.</p><p>The proper fix would involve adding <code>-cover</code> preprocessing support to <code>go build</code>, and exposing the coverage profile maybe as a <code>runtime/pprof.Profile</code>, but as of Go 1.6 there’s no such support. Here instead is a hack we've been using for a while in the test suite of <a href="/tag/rrdns/">RRDNS</a>, our custom Go DNS server.</p><p>We create a <b>dummy test</b> that executes <code>main()</code>, we put it behind a build tag, compile a binary with <code>go test -c -cover</code> and then run only that test instead of running the regular binary.</p><p>Here's what the <code>rrdns_test.go</code> file looks like:</p>
            <pre><code>// +build testrunmain

package main

import "testing"

func TestRunMain(t *testing.T) {
	main()
}</code></pre>
            <p>We compile the binary like this</p>
            <pre><code>$ go test -coverpkg="rrdns/..." -c -tags testrunmain rrdns</code></pre>
            <p>And then when we want to collect coverage information, we execute this instead of <code>./rrdns</code> (and run our test battery as usual):</p>
            <pre><code>$ ./rrdns.test -test.run "^TestRunMain$" -test.coverprofile=system.out</code></pre>
            <p>You must return from <code>main()</code> cleanly for the profile to be written to disk; in RRDNS we do that by catching SIGINT. You can still use command line arguments and standard input normally, just note that you will get two lines of extra output from the test framework.</p><p>Finally, since you probably also run unit tests, you might want to merge the coverage profiles with <a href="https://github.com/wadey/gocovmerge">gocovmerge</a> (from <a href="https://github.com/golang/go/issues/6909#issuecomment-124185553">issue #6909</a>):</p>
            <pre><code>$ go get github.com/wadey/gocovmerge
$ gocovmerge unit.out system.out &gt; all.out
$ go tool cover -html all.out</code></pre>
            <p>If finding creative ways to test big-scale network services sounds fun, know that <a href="https://www.cloudflare.com/join-our-team/">we are hiring in London, San Francisco and Singapore</a>.</p> ]]></content:encoded>
            <category><![CDATA[RRDNS]]></category>
            <category><![CDATA[DNS]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[Programming]]></category>
            <category><![CDATA[Go]]></category>
            <category><![CDATA[Best Practices]]></category>
            <guid isPermaLink="false">285AT2igoBQiRZFlDLnGsZ</guid>
            <dc:creator>Filippo Valsorda</dc:creator>
        </item>
        <item>
            <title><![CDATA[Creative foot-shooting with Go RWMutex]]></title>
            <link>https://blog.cloudflare.com/creative-foot-shooting-with-go-rwmutex/</link>
            <pubDate>Thu, 29 Oct 2015 21:26:36 GMT</pubDate>
            <description><![CDATA[ Hi, I'm Filippo and today I managed to surprise myself! (And not in a good way.)

I'm developing a new module ("filter" as we call them) for RRDNS, CloudFlare's Go DNS server.  ]]></description>
            <content:encoded><![CDATA[ <p>Hi, I'm Filippo and today I managed to surprise myself! (And not in a good way.)</p><p>I'm developing a new module ("filter" as we call them) for <a href="/tag/rrdns/">RRDNS</a>, CloudFlare's Go DNS server. It's a rewrite of the authoritative module, the one that adds the IP addresses to DNS answers.</p><p>It has a table of CloudFlare IPs that looks like this:</p>
            <pre><code>type IPMap struct {
	sync.RWMutex
	M map[string][]net.IP
}</code></pre>
            <p>It's a global filter attribute:</p>
            <pre><code>type V2Filter struct {
	name       string
	IPTable    *IPMap
	// [...]
}</code></pre>
            
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4YvPr9fRpSXLyFVZ4BL2lr/b11623aba2d210ffac4dcc6a11f43b32/1280px-Mexican_Standoff.jpg" />
            
            </figure><p><a href="https://www.flickr.com/photos/28293006@N05/8144747570">CC-BY-NC-ND image by Martin SoulStealer</a></p><p>The table changes often, so a background goroutine periodically reloads it from our distributed key-value store, acquires the lock (<code>f.IPTable.Lock()</code>), updates it and releases the lock (<code>f.IPTable.Unlock()</code>). This happens every 5 minutes.</p><p>Everything worked in tests, including multiple and concurrent requests.</p><p>Today we deployed to an off-production test machine and everything worked. For a few minutes. Then RRDNS stopped answering queries for the beta domains served by the new code.</p><p>What. _That worked on my laptop_™.</p><p>Here's the IPTable consumer function. You can probably spot the bug.</p>
            <pre><code>func (f *V2Filter) getCFAddr(...) (result []dns.RR) {
	f.IPTable.RLock()
	// [... append IPs from f.IPTable.M to result ...]
	return
}</code></pre>
            <p><code>f.IPTable.RUnlock()</code> is never called. Whoops. But it's an RLock, so multiple <code>getCFAddr</code> calls should work, and only table reloading should break, no? Instead <code>getCFAddr</code> started blocking after a few minutes. To the docs!</p><p><i>To ensure that the lock eventually becomes available, a blocked Lock call excludes new readers from acquiring the lock.</i> <a href="https://golang.org/pkg/sync/#RWMutex.Lock">https://golang.org/pkg/sync/#RWMutex.Lock</a></p><p>So everything worked and RLocks piled up until the table reload function ran, then the pending Lock call caused all following RLock calls to block, breaking RRDNS answer generation.</p><p>In tests the table reload function never ran while answering queries, so <code>getCFAddr</code> kept piling up RLock calls but never blocked.</p><p>No customers were affected because A) the release was still being tested on off-production machines and B) no real customers run on the new code yet. Anyway it was a interesting way to cause a deferred deadlock.</p><p>In closing, there's probably space for a better tooling here. A static analysis tool might output a listing of all Lock/Unlock calls, and a dynamic analysis tool might report still [r]locked Mutex at the end of tests. (Or maybe these tools already exist, in which case let me know!)</p><p><i>Do you want to help (introduce </i><code><i>:)</i></code><i> and) fix bugs in the DNS server answering more than 50 billion queries every day? </i><a href="https://www.cloudflare.com/join-our-team"><i>We are hiring in London, San Francisco and Singapore!</i></a></p> ]]></content:encoded>
            <category><![CDATA[RRDNS]]></category>
            <category><![CDATA[Bugs]]></category>
            <category><![CDATA[DNS]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[Programming]]></category>
            <category><![CDATA[Go]]></category>
            <guid isPermaLink="false">5iwarGrOuKY1ZIhN7o19u9</guid>
            <dc:creator>Filippo Valsorda</dc:creator>
        </item>
        <item>
            <title><![CDATA[DNS parser, meet Go fuzzer]]></title>
            <link>https://blog.cloudflare.com/dns-parser-meet-go-fuzzer/</link>
            <pubDate>Thu, 06 Aug 2015 13:40:40 GMT</pubDate>
            <description><![CDATA[ Here at CloudFlare we are heavy users of the github.com/miekg/dns Go DNS library and we make sure to contribute to its development as much as possible. Therefore when Dmitry Vyukov published go-fuzz and started to uncover tens of bugs in the Go standard library, our task was clear. ]]></description>
            <content:encoded><![CDATA[ <p>Here at CloudFlare we are heavy users of the <a href="https://github.com/miekg/dns"><code>github.com/miekg/dns</code></a> Go DNS library and we make sure to contribute to its development as much as possible. Therefore when <a href="https://github.com/dvyukov">Dmitry Vyukov</a> published go-fuzz and started to uncover tens of bugs in the Go standard library, our task was clear.</p>
    <div>
      <h3>Hot Fuzz</h3>
      <a href="#hot-fuzz">
        
      </a>
    </div>
    <p>Fuzzing is the technique of <i>testing software by continuously feeding it inputs that are automatically mutated</i>. For C/C++, the wildly successful <a href="http://lcamtuf.coredump.cx/afl/">afl-fuzz</a> tool by Michał Zalewski uses instrumented source coverage to judge which mutations pushed the program into new paths, <i>eventually hitting many rarely-tested branches</i>.</p><p><a href="https://github.com/dvyukov/go-fuzz"><i>go-fuzz</i></a><i> applies the same technique to Go programs</i>, instrumenting the source by rewriting it (<a href="/go-has-a-debugger-and-its-awesome/">like godebug does</a>). An interesting difference between afl-fuzz and go-fuzz is that the former normally operates on file inputs to unmodified programs, while the latter asks you to <i>write a Go function and passes inputs to that</i>. The former usually forks a new process for each input, the latter keeps calling the function without restarting often.</p><p>There is no strong technical reason for this difference (and indeed afl recently gained the ability to behave like go-fuzz), but it's likely due to the <i>different ecosystems</i> in which they operate: Go programs often expose <i>well-documented, well-behaved APIs</i> which enable the tester to write a good wrapper that doesn't contaminate state across calls. Also, Go programs are often easier to dive into and <i>more predictable</i>, thanks obviously to GC and memory management, but also to the general community repulsion towards unexpected global states and side effects. On the other hand many legacy C code bases are so intractable that the easy and stable file input interface is worth the performance tradeoff.</p><p>Back to our DNS library. RRDNS, our in-house DNS server, uses <code>github.com/miekgs/dns</code> for all its parsing needs, and it has proved to be up to the task. However, it's a bit fragile on the edge cases and has a track record of panicking on malformed packets. Thankfully, this is Go, not <a href="/a-deep-look-at-cve-2015-5477-and-how-cloudflare-virtual-dns-customers-are-protected/">BIND</a> C, and we can afford to <code>recover()</code> panics without worrying about ending up with insane memory states. Here's what we are doing</p>
            <pre><code>func ParseDNSPacketSafely(buf []byte, msg *old.Msg) (err error) {
	defer func() {
		panicked := recover()

		if panicked != nil {
			err = errors.New("ParseError")
		}
	}()

	err = msg.Unpack(buf)

	return
}</code></pre>
            <p>We saw an opportunity to make the library more robust so we wrote this initial simple fuzzing function:</p>
            <pre><code>func Fuzz(rawMsg []byte) int {
    msg := &amp;dns.Msg{}

    if unpackErr := msg.Unpack(rawMsg); unpackErr != nil {
        return 0
    }

    if _, packErr = msg.Pack(); packErr != nil {
        println("failed to pack back a message")
        spew.Dump(msg)
        panic(packErr)
    }

    return 1
}</code></pre>
            <p>To create a corpus of initial inputs we took our stress and regression test suites and used <code>github.com/miekg/pcap</code> to write a file per packet.</p>
            <pre><code>package main

import (
	"crypto/rand"
	"encoding/hex"
	"log"
	"os"
	"strconv"

	"github.com/miekg/pcap"
)

func fatalIfErr(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func main() {
	handle, err := pcap.OpenOffline(os.Args[1])
	fatalIfErr(err)

	b := make([]byte, 4)
	_, err = rand.Read(b)
	fatalIfErr(err)
	prefix := hex.EncodeToString(b)

	i := 0
	for pkt := handle.Next(); pkt != nil; pkt = handle.Next() {
		pkt.Decode()

		f, err := os.Create("p_" + prefix + "_" + strconv.Itoa(i))
		fatalIfErr(err)
		_, err = f.Write(pkt.Payload)
		fatalIfErr(err)
		fatalIfErr(f.Close())

		i++
	}
}</code></pre>
            
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1JJf54JXErYsYRprnQO8nk/aec6c0359fc16d482d96bea2d37e8c3c/11597106396_a1927f8c71_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/jdhancock/11597106396/in/photolist-iENcGh-5GuU8g-4G3SzJ-cybzvf-ej9ytf-5PT2gy-2wCHkp-oTNLKN-4T5TVk-pikg74-64fbtb-64fbny-6iPZrk-6WSbWA-gTwR9P-6JEbMJ-uS5Qoe-p3LoLt-8rTRPb-gzJBbc-6u4Ko7-4uXbz8-bX4rtL-6HoBT8-cybFb7-pDtnkY-doskG2-a9tSqx-3NX4E-978gS2-4iW5fs-4VhKK2-7EpKqc-7EtB6Y-7EtAiN-7EpH54-7EpGgX-poTg8-55WEef-qfzP-dt83Gq-naDJvs-aCKhDG-drR492-aTSFS6-aTSEER-aTSC2t-aTSAUR-qqFXz2-ftsXnd">image</a> by <a href="https://www.flickr.com/photos/jdhancock/">JD Hancock</a></p><p>We then compiled our <code>Fuzz</code> function with go-fuzz, and launched the fuzzer on a lab server. The first thing go-fuzz does is minimize the corpus by throwing away packets that trigger the same code paths, then it starts mutating the inputs and passing them to <code>Fuzz()</code> in a loop. The mutations that don't fail (<code>return 1</code>) and <i>expand code coverage</i> are kept and iterated over. When the program panics, a small report (input and output) is saved and the program restarted. If you want to learn more about go-fuzz watch <a href="https://www.youtube.com/watch?v=a9xrxRsIbSU">the author's GopherCon talk</a> or read <a href="https://github.com/dvyukov/go-fuzz">the README</a>.</p><p><i>Crashes, mostly "index out of bounds", started to surface.</i> go-fuzz becomes pretty slow and ineffective when the program crashes often, so while the CPUs burned I started fixing the bugs.</p><p>In some cases I just decided to change some parser patterns, for example <a href="https://github.com/miekg/dns/commit/b5133fead4c0571c20eea405a917778f011dde02">reslicing and using <code>len()</code> instead of keeping offsets</a>. However these can be potentially disrupting changes—I'm far from perfect—so I adapted the Fuzz function to keep an eye on the differences between the old and new, fixed parser, and crash if the new parser started refusing good packets or changed its behavior:</p>
            <pre><code>func Fuzz(rawMsg []byte) int {
    var (
        msg, msgOld = &amp;dns.Msg{}, &amp;old.Msg{}
        buf, bufOld = make([]byte, 100000), make([]byte, 100000)
        res, resOld []byte

        unpackErr, unpackErrOld error
        packErr, packErrOld     error
    )

    unpackErr = msg.Unpack(rawMsg)
    unpackErrOld = ParseDNSPacketSafely(rawMsg, msgOld)

    if unpackErr != nil &amp;&amp; unpackErrOld != nil {
        return 0
    }

    if unpackErr != nil &amp;&amp; unpackErr.Error() == "dns: out of order NSEC block" {
        // 97b0a31 - rewrite NSEC bitmap [un]packing to account for out-of-order
        return 0
    }

    if unpackErr != nil &amp;&amp; unpackErr.Error() == "dns: bad rdlength" {
        // 3157620 - unpackStructValue: drop rdlen, reslice msg instead
        return 0
    }

    if unpackErr != nil &amp;&amp; unpackErr.Error() == "dns: bad address family" {
        // f37c7ea - Reject a bad EDNS0_SUBNET family on unpack (not only on pack)
        return 0
    }

    if unpackErr != nil &amp;&amp; unpackErr.Error() == "dns: bad netmask" {
        // 6d5de0a - EDNS0_SUBNET: refactor netmask handling
        return 0
    }

    if unpackErr != nil &amp;&amp; unpackErrOld == nil {
        println("new code fails to unpack valid packets")
        panic(unpackErr)
    }

    res, packErr = msg.PackBuffer(buf)

    if packErr != nil {
        println("failed to pack back a message")
        spew.Dump(msg)
        panic(packErr)
    }

    if unpackErrOld == nil {

        resOld, packErrOld = msgOld.PackBuffer(bufOld)

        if packErrOld == nil &amp;&amp; !bytes.Equal(res, resOld) {
            println("new code changed behavior of valid packets:")
            println()
            println(hex.Dump(res))
            println(hex.Dump(resOld))
            os.Exit(1)
        }

    }

    return 1
}</code></pre>
            <p>I was pretty happy about the robustness gain, but since we used the <code>ParseDNSPacketSafely</code> wrapper in RRDNS I didn't expect to find security vulnerabilities. I was wrong!</p><p>DNS names are made of labels, usually shown separated by dots. In a space saving effort, labels can be replaced by pointers to other names, so that if we know we encoded <code>example.com</code> at offset 15, <code>www.example.com</code> can be packed as <code>www.</code> + <i>PTR(15)</i>. What we found is <a href="https://github.com/FiloSottile/dns/commit/b364f94">a bug in handling of pointers to empty names</a>: when encountering the end of a name (<code>0x00</code>), if no label were read, <code>"."</code> (the empty name) was returned as a special case. Problem is that this special case was unaware of pointers, and it would instruct the parser to resume reading from the end of the pointed-to empty name instead of the end of the original name.</p><p>For example if the parser encountered at offset 60 a pointer to offset 15, and <code>msg[15] == 0x00</code>, parsing would then resume from offset 16 instead of 61, causing a infinite loop. This is a potential Denial of Service vulnerability.</p>
            <pre><code>A) Parse up to position 60, where a DNS name is found

| ... |  15  |  16  |  17  | ... |  58  |  59  |  60  |  61  |
| ... | 0x00 |      |      | ... |      |      | -&gt;15 |      |

-------------------------------------------------&gt;     

B) Follow the pointer to position 15

| ... |  15  |  16  |  17  | ... |  58  |  59  |  60  |  61  |
| ... | 0x00 |      |      | ... |      |      | -&gt;15 |      |

         ^                                        |
         ------------------------------------------      

C) Return a empty name ".", special case triggers

D) Erroneously resume from position 16 instead of 61

| ... |  15  |  16  |  17  | ... |  58  |  59  |  60  |  61  |
| ... | 0x00 |      |      | ... |      |      | -&gt;15 |      |

                 --------------------------------&gt;   

E) Rinse and repeat</code></pre>
            <p>We sent the fixes privately to the library maintainer while we patched our servers and we <a href="https://github.com/miekg/dns/pull/237">opened a PR</a> once done. (Two bugs were independently found and fixed by Miek while we released our RRDNS updates, as it happens.)</p>
    <div>
      <h3>Not just crashes and hangs</h3>
      <a href="#not-just-crashes-and-hangs">
        
      </a>
    </div>
    <p>Thanks to its flexible fuzzing API, go-fuzz lends itself nicely not only to the mere search of crashing inputs, but <i>can be used to explore all scenarios where edge cases are troublesome</i>.</p><p>Useful applications range from checking output validation by adding crashing assertions to your <code>Fuzz()</code> function, to comparing the two ends of a unpack-pack chain and even comparing the behavior of two different versions or implementations of the same functionality.</p><p>For example, while preparing our <a href="/tag/dnssec/">DNSSEC</a> engine for launch, I faced a weird bug that would happen only on production or under stress tests: <i>NSEC records that were supposed to only have a couple bits set in their types bitmap would sometimes look like this</i></p>
            <pre><code>deleg.filippo.io.  IN  NSEC    3600    \000.deleg.filippo.io. NS WKS HINFO TXT AAAA LOC SRV CERT SSHFP RRSIG NSEC TLSA HIP TYPE60 TYPE61 SPF</code></pre>
            <p>The catch was that our "pack and send" code <i>pools </i><code><i>[]byte</i></code><i> buffers to reduce GC and allocation churn</i>, so buffers passed to <code>dns.msg.PackBuffer(buf []byte)</code> can be "dirty" from previous uses.</p>
            <pre><code>var bufpool = sync.Pool{
    New: func() interface{} {
        return make([]byte, 0, 2048)
    },
}

[...]

    data := bufpool.Get().([]byte)
    defer bufpool.Put(data)

    if data, err = r.Response.PackBuffer(data); err != nil {</code></pre>
            <p>However, <code>buf</code> not being an array of zeroes was not handled by some <code>github.com/miekgs/dns</code> packers, including the NSEC rdata one, that would <i>just OR present bits, without clearing ones that are supposed to be absent</i>.</p>
            <pre><code>case `dns:"nsec"`:
    lastwindow := uint16(0)
    length := uint16(0)
    for j := 0; j &lt; val.Field(i).Len(); j++ {
        t := uint16((fv.Index(j).Uint()))
        window := uint16(t / 256)
        if lastwindow != window {
            off += int(length) + 3
        }
        length = (t - window*256) / 8
        bit := t - (window * 256) - (length * 8)

        msg[off] = byte(window) // window #
        msg[off+1] = byte(length + 1) // octets length

        // Setting the bit value for the type in the right octet
---&gt;    msg[off+2+int(length)] |= byte(1 &lt;&lt; (7 - bit)) 

        lastwindow = window
    }
    off += 2 + int(length)
    off++
}</code></pre>
            <p>The fix was clear and easy: we benchmarked a few different ways to zero a buffer and updated the code like this</p>
            <pre><code>// zeroBuf is a big buffer of zero bytes, used to zero out the buffers passed
// to PackBuffer.
var zeroBuf = make([]byte, 65535)

var bufpool = sync.Pool{
    New: func() interface{} {
        return make([]byte, 0, 2048)
    },
}

[...]

    data := bufpool.Get().([]byte)
    defer bufpool.Put(data)
    copy(data[0:cap(data)], zeroBuf)

    if data, err = r.Response.PackBuffer(data); err != nil {</code></pre>
            <p>Note: <a href="https://github.com/golang/go/commit/f03c9202c43e0abb130669852082117ca50aa9b1">a recent optimization</a> turns zeroing range loops into <code>memclr</code> calls, so once 1.5 lands that will be much faster than <code>copy()</code>.</p><p>But this was a boring fix! Wouldn't it be nicer if we could trust our library to work with any buffer we pass it? Luckily, this is exactly what coverage based fuzzing is good for: <i>making sure all code paths behave in a certain way</i>.</p><p>What I did then is write a <code>Fuzz()</code> function that would first parse a message, and then pack it to two different buffers: one filled with zeroes and one filled with <code>0xff</code>. <i>Any differences between the two results would signal cases where the underlying buffer is leaking into the output.</i></p>
            <pre><code>func Fuzz(rawMsg []byte) int {
    var (
        msg         = &amp;dns.Msg{}
        buf, bufOne = make([]byte, 100000), make([]byte, 100000)
        res, resOne []byte

        unpackErr, packErr error
    )

    if unpackErr = msg.Unpack(rawMsg); unpackErr != nil {
        return 0
    }

    if res, packErr = msg.PackBuffer(buf); packErr != nil {
        return 0
    }

    for i := range res {
        bufOne[i] = 1
    }

    resOne, packErr = msg.PackBuffer(bufOne)
    if packErr != nil {
        println("Pack failed only with a filled buffer")
        panic(packErr)
    }

    if !bytes.Equal(res, resOne) {
        println("buffer bits leaked into the packed message")
        println(hex.Dump(res))
        println(hex.Dump(resOne))
        os.Exit(1)
    }

    return 1
}</code></pre>
            <p>I wish here, too, I could show a PR fixing all the bugs, but go-fuzz did its job even too well and we are still triaging and fixing what it finds.</p><p>Anyway, once the fixes are done and go-fuzz falls silent, we will be free to drop the buffer zeroing step without worry, with no need to audit the whole codebase!</p><p><i>Do you fancy fuzzing the libraries that serve 43 billion queries per day? We are </i><a href="https://www.cloudflare.com/join-our-team"><i>hiring</i></a><i> in London, San Francisco and Singapore!</i></p> ]]></content:encoded>
            <category><![CDATA[RRDNS]]></category>
            <category><![CDATA[DNS]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[Tools]]></category>
            <category><![CDATA[Go]]></category>
            <guid isPermaLink="false">7zu5Cq14O6t3QJfjOHY6b7</guid>
            <dc:creator>Filippo Valsorda</dc:creator>
        </item>
        <item>
            <title><![CDATA[Quick and dirty annotations for Go stack traces]]></title>
            <link>https://blog.cloudflare.com/quick-and-dirty-annotations-for-go-stack-traces/</link>
            <pubDate>Mon, 03 Aug 2015 11:26:04 GMT</pubDate>
            <description><![CDATA[ CloudFlare’s DNS server, RRDNS, is entirely written in Go and typically runs tens of thousands goroutines. Since goroutines are cheap and Go I/O is blocking we run one goroutine per file descriptor we listen on and queue new packets for processing. ]]></description>
            <content:encoded><![CDATA[ <p>CloudFlare’s DNS server, <a href="/tag/rrdns/">RRDNS</a>, is entirely written in Go and typically runs tens of thousands goroutines. Since goroutines are cheap and Go I/O is blocking we run one goroutine per file descriptor we listen on and queue new packets for processing.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2v4jReMMfDFsc62GnuXpFo/13aafcf00d9d9b425cdf294f62fa7f76/6372385465_014a4e56af_z.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/wiredforsound23/6372385465/">image</a> by <a href="https://www.flickr.com/photos/wiredforsound23/">wiredforlego</a></p><p>When there are thousands of goroutines running, debug output quickly becomes difficult to interpret. For example, last week I was tracking down a problem with a file descriptor and wanted to know what its listening goroutine was doing. <i>With 40k stack traces, good luck figuring out which one is having trouble.</i></p><p>Go stack traces include parameter values, but most Go types are (or are implemented as) pointers, so what you will see passed to the goroutine function is just a meaningless memory address.</p><p>We have a couple options to make sense of the addresses: get a heap dump at the same time as the stack trace and cross-reference the pointers, or have a debug endpoint that prints a goroutine/pointer -&gt; IP map. Neither are seamless.</p>
    <div>
      <h3>Underscore to the rescue</h3>
      <a href="#underscore-to-the-rescue">
        
      </a>
    </div>
    <p>However, we know that <i>integers are shown in traces</i>, so what we did is first <i>convert IPv4 addresses to their uint32 representation</i>:</p>
            <pre><code>// addrToUint32 takes a TCPAddr or UDPAddr and converts its IP to a uint32.
// If the IP is v6, 0xffffffff is returned.
func addrToUint32(addr net.Addr) uint32 {
       var ip net.IP
       switch addr := addr.(type) {
       case *net.TCPAddr:
               ip = addr.IP
       case *net.UDPAddr:
               ip = addr.IP
       case *net.IPAddr:
               ip = addr.IP
       }
       if ip == nil {
               return 0
       }
       ipv4 := ip.To4()
       if ipv4 == nil {
               return math.MaxUint32
       }
       return uint32(ipv4[0])&lt;&lt;24 | uint32(ipv4[1])&lt;&lt;16 | uint32(ipv4[2])&lt;&lt;8 | uint32(ipv4[3])
}</code></pre>
            <p>And then <i>pass the IPv4-as-uint32 to the listening goroutine as an </i><code><i>_</i></code><i> parameter</i>. Yes, as a parameter with name <code>_</code>; it's known as the <a href="https://golang.org/ref/spec#Blank_identifier">blank identifier</a> in Go.</p>
            <pre><code>// PacketUDPRead is a goroutine that listens on a specific UDP socket and reads
// in new requests
// The first parameter is the int representation of the listening IP address,
// and it's passed just so it will appear in stack traces
func PacketUDPRead(_ uint32, conn *net.UDPConn, ...) { ... }

go PacketUDPRead(addrToUint32(conn.LocalAddr()), conn, ...)</code></pre>
            <p>Now when we get a stack trace, we can just look at the first bytes, convert them back to dotted notation, and know on what IP the goroutine was listening.</p>
            <pre><code>goroutine 42 [IO wait]:
	[...]
	/.../request.go:195 +0x5d
rrdns/core.PacketUDPRead(0xc27f000001, 0x2b6328113ad8, 0xc20801ecc0, 0xc208044308, 0xc208e99280, 0xc208ad8180, 0x12a05f200)
	/.../server.go:119 +0x35a
created by rrdns/core.PacketIO
	/.../server.go:230 +0x8be</code></pre>
            <p><code>0xc27f000001</code> -&gt; remove alignment byte -&gt; <code>0x7f000001</code> -&gt; <code>127.0.0.1</code></p><p>Obviously you can do the same with any piece of information you can represent as an <code>int</code>.</p><p><i>Are you interested in taming the goroutines that run the web? We're </i><a href="https://www.cloudflare.com/join-our-team"><i>hiring</i></a><i> in London, San Francisco and Singapore!</i></p> ]]></content:encoded>
            <category><![CDATA[RRDNS]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[DNS]]></category>
            <category><![CDATA[Go]]></category>
            <category><![CDATA[Programming]]></category>
            <guid isPermaLink="false">2Eu6vhCtFVL0I002N3mpV2</guid>
            <dc:creator>Filippo Valsorda</dc:creator>
        </item>
        <item>
            <title><![CDATA[Setting Go variables from the outside]]></title>
            <link>https://blog.cloudflare.com/setting-go-variables-at-compile-time/</link>
            <pubDate>Wed, 01 Jul 2015 13:26:37 GMT</pubDate>
            <description><![CDATA[ CloudFlare's DNS server, RRDNS, is written in Go and the DNS team used to generate a file called version.go in our Makefile. version.go looked something like this. ]]></description>
            <content:encoded><![CDATA[ <p>CloudFlare's DNS server, <a href="/tag/rrdns/">RRDNS</a>, is written in Go and the DNS team used to generate a file called <code>version.go</code> in our Makefile. <code>version.go</code> looked something like this:</p>
            <pre><code>// THIS FILE IS AUTOGENERATED BY THE MAKEFILE. DO NOT EDIT.

// +build	make

package version

var (
	Version   = "2015.6.2-6-gfd7e2d1-dev"
	BuildTime = "2015-06-16-0431 UTC"
)</code></pre>
            <p>and was used to embed version information in RRDNS. It was built inside the Makefile using <code>sed</code> and <code>git describe</code> from a template file. It worked, but was pretty ugly.</p><p>Today we noticed that another Go team at CloudFlare, the <a href="/tag/data/">Data</a> team, had <b>a much smarter way to bake version numbers into binaries using the </b><code><b>-X</b></code><b> linker option</b>.</p><p>The <code>-X</code> <a href="https://golang.org/cmd/ld/">Go linker option</a>, which you can set with <code>-ldflags</code>, sets the value of a string variable in the Go program being linked. You use it like this: <code>-X main.version 1.0.0</code>.</p><p>A simple example: let's say you have this source file saved as <code>hello.go</code>.</p>
            <pre><code>package main

import "fmt"

var who = "World"

func main() {
    fmt.Printf("Hello, %s.\n", who)
}</code></pre>
            <p>Then you can use <code>go run</code> (or other build commands like <code>go build</code> or <code>go install</code>) with the <code>-ldflags</code> option to modify the value of the <code>who</code> variable:</p>
            <pre><code>$ go run hello.go
Hello, World.
$ go run -ldflags="-X main.who CloudFlare" hello.go
Hello, CloudFlare.</code></pre>
            <p>The format is <code>importpath.name string</code>, so it's possible to set the value of any string anywhere in the Go program, not just in main. Note that from Go 1.5 the syntax has <a href="https://tip.golang.org/cmd/link/">changed</a> to <code>importpath.name=string</code>. The old style is still supported but the linker will complain.</p><p>I was worried this would not work with external linking (<a href="https://docs.google.com/document/d/1nr-TQHw_er6GOQRsF6T43GGhFDelrAP0NqSS_00RgZQ/view">for example when using cgo</a>) but as we can see with <code>-ldflags="-linkmode=external -v"</code> the Go linker runs first anyway and takes care of our <code>-X</code>.</p>
            <pre><code>$ go build -x -ldflags="-X main.who CloudFlare -linkmode=external -v" hello.go
WORK=/var/folders/v8/xdj2snz51sg2m2bnpmwl_91c0000gn/T/go-build149644699
mkdir -p $WORK/command-line-arguments/_obj/
cd /Users/filippo/tmp/X
/usr/local/Cellar/go/1.4.2/libexec/pkg/tool/darwin_amd64/6g -o $WORK/command-line-arguments.a -trimpath $WORK -p command-line-arguments -complete -D _/Users/filippo/tmp/X -I $WORK -pack ./hello.go
cd .
/usr/local/Cellar/go/1.4.2/libexec/pkg/tool/darwin_amd64/6l -o hello -L $WORK -X main.hi hi -linkmode=external -v -extld=clang $WORK/command-line-arguments.a
# command-line-arguments
HEADER = -H1 -T0x2000 -D0x0 -R0x1000
searching for runtime.a in $WORK/runtime.a
searching for runtime.a in /usr/local/Cellar/go/1.4.2/libexec/pkg/darwin_amd64/runtime.a
 0.06 deadcode
 0.07 pclntab=284969 bytes, funcdata total 49800 bytes
 0.07 dodata
 0.08 symsize = 0
 0.08 symsize = 0
 0.08 reloc
 0.09 reloc
 0.09 asmb
 0.09 codeblk
 0.09 datblk
 0.09 dwarf
 0.09 sym
 0.09 headr
host link: clang -m64 -gdwarf-2 -Wl,-no_pie,-pagezero_size,4000000 -o hello -Qunused-arguments /var/folders/v8/xdj2snz51sg2m2bnpmwl_91c0000gn/T//go-link-mFNNCD/000000.o /var/folders/v8/xdj2snz51sg2m2bnpmwl_91c0000gn/T//go-link-mFNNCD/000001.o /var/folders/v8/xdj2snz51sg2m2bnpmwl_91c0000gn/T//go-link-mFNNCD/go.o -g -O2 -g -O2 -lpthread
 0.17 cpu time
33619 symbols
64 sizeof adr
216 sizeof prog
23412 liveness data</code></pre>
            <p><i>Do you want to work next to Go developers that can always make you learn a new trick? </i><a href="https://www.cloudflare.com/join-our-team"><i>We are hiring in London, San Francisco and Singapore</i></a><i>.</i></p> ]]></content:encoded>
            <category><![CDATA[RRDNS]]></category>
            <category><![CDATA[Programming]]></category>
            <category><![CDATA[Go]]></category>
            <category><![CDATA[Reliability]]></category>
            <guid isPermaLink="false">7JoU9nV9zNjoGpJYgiusvV</guid>
            <dc:creator>Filippo Valsorda</dc:creator>
        </item>
        <item>
            <title><![CDATA[Go has a debugger—and it's awesome!]]></title>
            <link>https://blog.cloudflare.com/go-has-a-debugger-and-its-awesome/</link>
            <pubDate>Thu, 18 Jun 2015 11:14:00 GMT</pubDate>
            <description><![CDATA[ Something that often, uh... bugs Go developers is the lack of a proper debugger. Builds are ridiculously fast and easy, but sometimes it would be nice to just set a breakpoint and step through that endless if chain or print a bunch of values without recompiling ten times. ]]></description>
            <content:encoded><![CDATA[ <p>Something that often, uh... <i>bugs</i><a href="#fn1">[1]</a> Go developers is the <b>lack of a proper debugger</b>. Sure, builds are ridiculously fast and easy, and <code>println(hex.Dump(b))</code> is your friend, but sometimes it would be nice to just set a breakpoint and step through that endless <code>if</code> chain or print a bunch of values without recompiling ten times.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1PlA0CeyPc2zJ6Ai6u9f9u/77f31929ad59993a59bb24367a46d852/12294903084_3a3d128ae7_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/62766743@N07/12294903084/in/photolist-jJsAkE-hiHrhB-9TNjzG-9TMKnB-9TKuyt-9TKuQx-4rHRku-9TNj1L-dCD4Ay-bbk7in-ngEQwy-q577yv-qmsFPs-qXFbRy-dCMyqk-rmqu1H-tncWw9-fzkCLf-54MZxq-9ZCivM-fdC6b-5jvVQ7-q4YkxA-2vVkpu-aY6pnx-9TNiVC-j8TKCC-9TNji3-dKjVwD-eRrMtP-dVJA3D-bwjW2u-ohnZh9-iRdXBy-dWXXKe-fdT8VT-ePmAs-ecdQqy-ieu7sA-iFi5z-j6m1Qs-ncgQ2q-7W3hJi-r17FpD-ekipUs-jYbRdy-ckWNBh-gT4VL-9TNjvC-9TNjpL">image</a> by <a href="https://www.flickr.com/photos/62766743@N07/">Carl Milner</a></p><p>You <i>could</i> try to use some dirty gdb hacks that will work if you built your binary with a certain linker and ran it on some architectures when the moon was in a waxing crescent phase, but let's be honest, it isn't an enjoyable experience.</p><p>Well, worry no more! <a href="https://github.com/mailgun/godebug">godebug</a> is here!</p><p><b>godebug is an awesome cross-platform debugger</b> created by the Mailgun team. You can read <a href="http://blog.mailgun.com/introducing-a-new-cross-platform-debugger-for-go/">their introduction</a> for some under-the-hood details, but here's the cool bit: instead of wrestling with half a dozen different ptrace interfaces that would not be portable, <b>godebug rewrites your source code</b> and injects function calls like <code>godebug.Line</code> on every line, <code>godebug.Declare</code> at every variable declaration, and <code>godebug.SetTrace</code> for breakpoints (i.e. wherever you type <code>_ = "breakpoint"</code>).</p><p>I find this solution brilliant. What you get out of it is a (possibly cross-compiled) debug-enabled binary that you can drop on a staging server just like you would with a regular binary. When a breakpoint is reached, the program will stop inline and wait for you on stdin. <b>It's the single-binary, zero-dependencies philosophy of Go that we love applied to debugging.</b> Builds everywhere, runs everywhere, with no need for tools or permissions on the server. It even compiles to JavaScript with gopherjs (check out the Mailgun post above—show-offs ;) ).</p><p>You might ask, "But does it get a decent runtime speed or work with big applications?" Well, the other day I was seeing RRDNS—our in-house Go DNS server—hit a weird branch, so I placed a breakpoint a couple lines above the <i>if</i> in question, <b>recompiled the whole of RRDNS with godebug instrumentation</b>, dropped the binary on a staging server, and replayed some DNS traffic.</p>
            <pre><code>filippo@staging:~$ ./rrdns -config config.json
-&gt; _ = "breakpoint"
(godebug) l

    q := r.Query.Question[0]

--&gt; _ = "breakpoint"

    if !isQtypeSupported(q.Qtype) {
        return
(godebug) n
-&gt; if !isQtypeSupported(q.Qtype) {
(godebug) q
dns.Question{Name:"filippo.io.", Qtype:0x1, Qclass:0x1}
(godebug) c</code></pre>
            <p>Boom. The request and the debug log paused (make sure to terminate any timeout you have in your tools), waiting for me to step through the code.</p><p>Sold yet? Here's how you use it: simply run <code>godebug {build|run|test}</code> instead of <code>go {build|run|test}</code>. <a href="https://github.com/mailgun/godebug/pull/32/commits">We adapted godebug</a> to resemble the go tool as much as possible. Remember to use <code>-instrument</code> if you want to be able to step into packages that are not <i>main</i>.</p><p>For example, here is part of the RRDNS Makefile:</p>
            <pre><code>bin/rrdns:
ifdef GODEBUG
	GOPATH="${PWD}" go install github.com/mailgun/godebug
	GOPATH="${PWD}" ./bin/godebug build -instrument "${GODEBUG}" -o bin/rrdns rrdns
else
	GOPATH="${PWD}" go install rrdns
endif

test:
ifdef GODEBUG
	GOPATH="${PWD}" go install github.com/mailgun/godebug
	GOPATH="${PWD}" ./bin/godebug test -instrument "${GODEBUG}" rrdns/...
else
	GOPATH="${PWD}" go test rrdns/...
endif</code></pre>
            <p>Debugging is just a <code>make bin/rrdns GODEBUG=rrdns/...</code> away.</p><p>This tool is still young, but in my experience, perfectly functional. The UX could use some love if you can spare some time (as you can see above it's pretty spartan), but it should be easy to build on what's there already.</p>
    <div>
      <h2>About source rewriting</h2>
      <a href="#about-source-rewriting">
        
      </a>
    </div>
    <p>Before closing, I'd like to say a few words about the technique of source rewriting in general. It powers many different Go tools, like <a href="https://blog.golang.org/cover">test coverage</a>, <a href="https://github.com/dvyukov/go-fuzz">fuzzing</a> and, indeed, debugging. It's made possible primarily by Go’s blazing-fast compiles, and it enables amazing cross-platform tools to be built easily.</p><p>However, since it's such a handy and powerful pattern, I feel like <b>there should be a standard way to apply it in the context of the build process</b>. After all, all the source rewriting tools need to implement a subset of the following features:</p><ul><li><p>Wrap the main function</p></li><li><p>Conditionally rewrite source files</p></li><li><p>Keep global state</p></li></ul><p>Why should every tool have to reinvent all the boilerplate to copy the source files, rewrite the source, make sure stale objects are not used, build the right packages, run the right tests, and interpret the CLI..? Basically, all of <a href="https://github.com/mailgun/godebug/blob/f8742f647adb8ee17a1435de3b1929d36df590c8/cmd.go">godebug/cmd.go</a>. And what about <a href="http://getgb.io/">gb</a>, for example?</p><p>I think we need a framework for Go source code rewriting tools. (Spoiler, spoiler, ...)</p><p><i>If you’re interested in working on Go servers at scale and developing tools to do it better, remember </i><a href="https://www.cloudflare.com/join-our-team"><i>we’re hiring in London, San Francisco, and Singapore</i></a><i>!</i></p><hr /><hr /><ol><li><p>I'm sorry. <a href="#fnref1">↩︎</a></p></li></ol> ]]></content:encoded>
            <category><![CDATA[RRDNS]]></category>
            <category><![CDATA[Tools]]></category>
            <category><![CDATA[DNS]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[Programming]]></category>
            <category><![CDATA[Go]]></category>
            <category><![CDATA[Developers]]></category>
            <guid isPermaLink="false">7rlszh5ZEwkE3JfCjkJkZv</guid>
            <dc:creator>Filippo Valsorda</dc:creator>
        </item>
        <item>
            <title><![CDATA[The weird and wonderful world of DNS LOC records]]></title>
            <link>https://blog.cloudflare.com/the-weird-and-wonderful-world-of-dns-loc-records/</link>
            <pubDate>Tue, 01 Apr 2014 01:19:00 GMT</pubDate>
            <description><![CDATA[ A cornerstone of CloudFlare's infrastructure is our ability to serve DNS requests quickly and handle DNS attacks. To do both those things we wrote our own authoritative DNS server called RRDNS in Go.  ]]></description>
            <content:encoded><![CDATA[ <p>A cornerstone of CloudFlare's infrastructure is our ability to serve DNS requests quickly and <a href="/deep-inside-a-dns-amplification-ddos-attack">handle DNS attacks</a>. To do both those things we wrote our own authoritative DNS server called <a href="/the-story-of-a-little-dns-easter-egg">RRDNS</a> in Go. Because of it we've been able to fight off DNS attacks, and be consistenly one of the <a href="/cloudflare-fastest-free-dns-among-fastest-dns">fastest</a> DNS providers on the web.</p><p>Implementing an authoritative DNS server is a large task. That's in part because DNS is a very old standard (<a href="http://www.ietf.org/rfc/rfc1035.txt">RFC 1035</a> dates to 1987), in part because as DNS has developed it has grown into a more and more complex system, and in part because what's written in the RFCs and what happens in the real-world aren't always the same thing.</p><p>One little used type of DNS record is the LOC (or location). It allows you to specify a physical location. CloudFlare handles millions of DNS records; of those just 743 are LOCs. Nevertheless, it's possible to set up a LOC record in the CloudFlare DNS editor.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/SE3YNqdqCWTZjCq2X3204/6350156b41c21658e2c1cafe7780ae4b/480px-Trinity_Site_Obelisk_National_Historic_Landmark.jpg" />
            
            </figure><p>My site <a href="https://web.archive.org/web/20140329092052/http://geekatlas.com/">geekatlas.com</a> has a LOC record as an Easter Egg. Here's how it's configured in the CloudFlare DNS settings:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2Qe1yA3xIACsdf36XEi1oQ/1a078bd649abd88e5b382cab36f748b9/Screen_Shot_2014-03-27_at_11.34.24.png" />
            
            </figure><p>When you operate at CloudFlare scale the little-used nooks and crannies turn out to be important. And even though there are only 743 LOC records in our entire database, at least one customer contacted support to find out why their LOC record wasn't being served.</p><p>And that sent me into the RRDNS source code to find out why.</p><p>The answer was simple. Although RRDNS had code for receiving requests for LOC records, creating response packets containing LOC data, there was a missing link. The CloudFlare DNS server stores the LOC record as a string (such as the <code>33 40 31 N 106 28 29 W 10m</code> above) and no one had written the code to parse that and turn it into the internal format. Oops.</p><p>The textual LOC format and the binary, on-the-wire, format are described in <a href="https://tools.ietf.org/rfc/rfc1876.txt">RFC 1876</a> and it's one of many RFCs that updated the original 1987 standard. RFC 1876 is from 1996.</p><p>The textual format is fairly simple. Here's what the RFC says:</p>
            <pre><code>The LOC record is expressed in a primary file in the following format:

owner TTL class LOC ( d1 [m1 [s1]] {"N"|"S"} d2 [m2 [s2]]
                           {"E"|"W"} alt["m"] [siz["m"] [hp["m"]
                           [vp["m"]]]] )

where:

   d1:     [0 .. 90]            (degrees latitude)
   d2:     [0 .. 180]           (degrees longitude)
   m1, m2: [0 .. 59]            (minutes latitude/longitude)
   s1, s2: [0 .. 59.999]        (seconds latitude/longitude)
   alt:    [-100000.00 .. 42849672.95] BY .01 (altitude in meters)
   siz, hp, vp: [0 .. 90000000.00] (size/precision in meters)

If omitted, minutes and seconds default to zero, size defaults to 1m,
horizontal precision defaults to 10000m, and vertical precision
defaults to 10m.  These defaults are chosen to represent typical
ZIP/postal code area sizes, since it is often easy to find
approximate geographical location by ZIP/postal code.</code></pre>
            <p>So, there are required latitude, longitude and altitude and three optional values for the size of the location and precision information. Pretty simple.</p><p>Then there's the on-the-wire format. Unlike a TXT record the LOC record data is parsed and turned into a fixed size binary format. Back to RFC 1876:</p>
            <pre><code>  MSB                                           LSB
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  0|        VERSION        |         SIZE          |
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  2|       HORIZ PRE       |       VERT PRE        |
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  4|                   LATITUDE                    |
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  6|                   LATITUDE                    |
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  8|                   LONGITUDE                   |
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 10|                   LONGITUDE                   |
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 12|                   ALTITUDE                    |
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 14|                   ALTITUDE                    |
   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+</code></pre>
            <p>So, 32 bits of latitude, longitude and altitude and then three 8 bit values for the size and precision. The latitude and longitude values have a pretty simple encoding that treats the 32 bits as an unsigned integer:</p>
            <pre><code>The latitude of the center of the sphere described by the SIZE field, expressed as a 32-bit integer, most significant octet first (network standard byte order), in thousandths of a second of arc.  2^31 represents the equator; numbers above that are north latitude.</code></pre>
            <p>And the altitude can be below sea-level but still unsigned:</p>
            <pre><code>The altitude of the center of the sphere described by the SIZE field, expressed as a 32-bit integer, most significant octet first (network standard byte order), in centimeters, from a base of 100,000m below the [WGS 84] reference spheroid used by GPS.</code></pre>
            <p>But the 8 bit values use a very special encoding that allows a wide range of approximate values to be packed into 8 bits and also be human-readable when dumped out in hex!</p>
            <pre><code>The diameter of a sphere enclosing the described entity, in centimeters, expressed as a pair of four-bit unsigned integers, each ranging from zero to nine, with the most significant four bits representing the base and the second number representing the power of ten by which to multiply the base.  This allows sizes from 0e0 (&lt;1cm) to 9e9 (90,000km) to be expressed.  This representation was chosen such that the hexadecimal representation can be read by eye; 0x15 = 1e5.</code></pre>
            <p>For example, the value <code>0x12</code> means <code>1 * 10^2</code> or 100cm. <code>0x99</code> means <code>9 * 10^9</code> or 90,000,000m. The smallest value that can be represented is 1cm (it's <code>0x10</code>). So, in just 8 bits there's a range values from 1cm to larger than the diameter of Jupiter.</p><p>To fix this I wrote a parser for the LOC text record type (and associated tests). It can be found <a href="https://gist.github.com/jgrahamc/9807839">here</a>.</p><p>We've now rolled out the fix and all the existing LOC records are being served by RRDNS. For example, my <code>geekatlas.com</code> LOC record can be queried like this:</p>
            <pre><code>$ dig geekatlas.com LOC
; &lt;&lt;&gt;&gt; DiG 9.8.3-P1 &lt;&lt;&gt;&gt; geekatlas.com LOC
;; global options: +cmd
;; Got answer:
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 2997
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:    
;geekatlas.com.         IN  LOC

;; ANSWER SECTION:
geekatlas.com.      299 IN  LOC 33 40 31.000 N 106 28 29.000 W 10.00m 1m 10000m 10m

;; Query time: 104 msec
;; SERVER: 192.168.14.1#53(192.168.14.1)
;; WHEN: Tue Apr  1 14:13:48 2014
;; MSG SIZE  rcvd: 59</code></pre>
            <p></p> ]]></content:encoded>
            <category><![CDATA[RRDNS]]></category>
            <category><![CDATA[DNS]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[Attacks]]></category>
            <category><![CDATA[Go]]></category>
            <guid isPermaLink="false">5aav5kAWuJGhGea0pOkie7</guid>
            <dc:creator>John Graham-Cumming</dc:creator>
        </item>
        <item>
            <title><![CDATA[What we've been doing with Go]]></title>
            <link>https://blog.cloudflare.com/what-weve-been-doing-with-go/</link>
            <pubDate>Mon, 11 Nov 2013 01:00:00 GMT</pubDate>
            <description><![CDATA[ Almost two years ago CloudFlare started working with Go. What started as an experiment on one network and concurrency heavy project has turned into full, production use of Go for multiple services. ]]></description>
            <content:encoded><![CDATA[ <p>Almost two years ago CloudFlare started working with Go. What started as an experiment on one network and concurrency heavy project has turned into full, production use of Go for multiple services. Today Go is at the heart of CloudFlare's services including handling compression for high-latency HTTP connections, our entire DNS infrastructure, SSL, load testing and more.</p><p>I first wrote about CloudFlare's use of <a href="/go-at-cloudflare">Go back in July 2012</a>. At that time there was only one CloudFlare project, <a href="https://www.cloudflare.com/railgun">Railgun</a>, written in Go, but others were starting to germinate around the company. Today we have many major projects in Go. So, we celebrate Go's <a href="http://blog.golang.org/4years">4th birthday</a> with a short list of interesting things we've written in Go.</p>
    <div>
      <h3>RRDNS</h3>
      <a href="#rrdns">
        
      </a>
    </div>
    <p>RRDNS is a DNS proxy that was written to help scale CloudFlare's DNS infrastructure. Our DNS was <a href="/cloudflare-fastest-free-dns-among-fastest-dns">already very fast</a> and we wanted to make it faster, more reliable and resilient to attack.</p><p>RRDNS provides response rate limiting to stop DNS attacks, caching to lower the load on the database, load balancing to detect downed upstreams, seamless binary upgrade (with no service interruption), CNAME flattening and more. It is built on a modular framework that allows the implementation of each behaviour to exist in separately maintained modules.</p><p>This modularity was trivial to enforce with interfaces, allowing each module to remain strictly self-contained but retain the flexibility of implementation (some use cgo, others have background workers). A goroutine is dedicated to each request to force isolation where panics are recovered and logged instead of crashing the server.</p><p>The guarantees needed to avoid leaving the server in a bad state when handling panics would be impossible without the defer mechanism Go provides. Other language features simplified the complexity of writing new modules; garbage collection allows us to avoid complex reference counting schemes and concentrate on the business logic. Managing the concurrent requests' access to shared data was also easy, either by wrapping this in a goroutine or using read-write locks.</p>
    <div>
      <h3>Railgun</h3>
      <a href="#railgun">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4WoNHpcKK14wLSsSifQYQA/f3f1098e66124cf8185ab2d5ea1fd0f6/railgun.png.scaled500_1.png" />
            
            </figure><p>Railgun is CloudFlare's compression technology that's used to speed up connections between CloudFlare's data centers and origin web servers (especially when there is high latency between them). It's 100% written in Go and performs on the fly compression of web pages (and other textual assets) against recent versions of those pages to send the absolute minimum data possible.</p><p>Railgun also helps cache <a href="/cacheing-the-uncacheable-cloudflares-railgun-73454">previously uncacheable</a> assets (such as dynamically generated web pages) by spotting the often small changes between web pages over time, or the small changes between different users. Railgun is now widely used by CloudFlare customers to create responsive web sites wherever the end user is in the world.</p><p>It is now widely used by CloudFlare customers and <a href="https://www.cloudflare.com/cloudflare-partners-self-serve-program-open-beta/">hosting partners</a> and achieves impressive <a href="/railgun-in-the-real-world">real world speedups</a>, including faster TTFB and better page load time, and <a href="/railgun-gives-our-ecommerce-sites-the-edge">bandwidth savings</a> which translate into additional savings for people using services like AWS.</p>
    <div>
      <h3>Red October</h3>
      <a href="#red-october">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5bgG5mznimQuyVwyYePpnb/278dfca284fd8d75acde787f39942bee/The_Hunt_for_Red_October-1.jpg" />
            
            </figure><p>Red October is a cryptographically secure implementation of the <a href="https://en.wikipedia.org/wiki/Two-man_rule">two-man rule</a> control mechanism. It is a software-based encryption and decryption server. The server allows authorized individuals to encrypt a payload in such a way that no one individual can decrypt it. To decrypt the payload, at least two authorized individuals must be logged into the server. The decryption of the payload is cryptographically tied to the login credentials of the authorized individuals and is only kept in memory for the duration of the decryption.</p><p>We'll be using Red October to secure very sensitive material (such as private encryption keys) so that no single CloudFlare employee (or single attacker) can get access to them. In coming months we'll write more about the cryptographic underpinnings of keeping CloudFlare secure.</p>
    <div>
      <h3>SSL Bundler</h3>
      <a href="#ssl-bundler">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4ISeaNc9XgwhFEpdVP8Mce/33527712a89e3fa7bef47095259f00a9/chain.jpg.scaled500_1.jpg" />
            
            </figure><p>The SSL Bundler allows us to take a customer's own <a href="https://www.cloudflare.com/application-services/products/ssl/">SSL certificate</a> and compute the <a href="/what-we-just-did-to-make-ssl-even-faster">fastest, shortest chain of intermediate certificates</a> that can be used to verify the connection. When someone uploads a custom SSL certificate, we use our directory of intermediate certificates to build all the possible chains from the uploaded cert to a trusted browser root. We then rank these chains based on a number of factors including:</p><ol><li><p>The length of the certificate chain</p></li><li><p>The ubiquity of the root certificate in browsers and other clients</p></li><li><p>The security of each step in the chain (e.g., does their Extended Key Usage include Server Authentication)</p></li><li><p>The length of the validity period of all the steps in the chain</p></li></ol><p>The result is a server bundle that is small, fast and strong while having ubiquitous browser and client support. We then present that chain of certificates when an SSL connection is made so that the browser can securely verify the SSL connection as quickly as possible.</p>
    <div>
      <h3>And that's not all</h3>
      <a href="#and-thats-not-all">
        
      </a>
    </div>
    <p>We're also experimenting with Go-based software like CoreOS (we're working with their go-raft library) and Docker. We have internal tools for load testing written in Go for Kyoto Tycoon, HTTP servers, SPDY and memcached. And we've open-sourced our <a href="https://github.com/cloudflare/go-stream">Go stream processing library</a>, a Go wrapper for <a href="https://github.com/cloudflare/golog">high-performance syslogging</a>, our changes to Go <a href="https://github.com/cloudflare/gokabinet">bindings for Kyoto Cabinet</a>, and a tool for <a href="https://github.com/cloudflare/gurl">'curling' SPDY</a> sites. And, of course, we've been contributing directly to Go itself.</p><p>All in all Go is one of the main languages in use at CloudFlare and from here it looks like it has a bright future.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3nLQBFNBDHtGXjroUxDBbE/81eeb7497ee1b27c25cfdc36be62718d/Screen_Shot_2013-11-11_at_9.04.31_PM.png" />
            
            </figure><p>Happy 4th Birthday Go!</p><p>(And, yes, we're <a href="https://www.cloudflare.com/join-our-team">hiring Go programmers</a> in London and San Francisco)</p> ]]></content:encoded>
            <category><![CDATA[RRDNS]]></category>
            <category><![CDATA[Go]]></category>
            <category><![CDATA[Railgun]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[Speed & Reliability]]></category>
            <category><![CDATA[Speed]]></category>
            <category><![CDATA[Birthday Week]]></category>
            <category><![CDATA[Product News]]></category>
            <guid isPermaLink="false">6ak1VHCm9sHvuEl8nH4xB4</guid>
            <dc:creator>John Graham-Cumming</dc:creator>
        </item>
        <item>
            <title><![CDATA[The story of a little DNS easter egg]]></title>
            <link>https://blog.cloudflare.com/the-story-of-a-little-dns-easter-egg/</link>
            <pubDate>Tue, 27 Aug 2013 00:10:00 GMT</pubDate>
            <description><![CDATA[ About a year ago, we realized that CloudFlare's current DNS infrastructure had some challenges. We were using PowerDNS, an open source DNS server that is popular with hosting providers.  ]]></description>
            <content:encoded><![CDATA[ <p></p><p>About a year ago, we realized that CloudFlare's current DNS infrastructure had some challenges. We were using PowerDNS, an open source DNS server that is popular with hosting providers. We'd chosen PowerDNS four years ago for several reasons: 1) it was reasonably fast as an authoritative DNS server; 2) it seamlessly allowed us to add new records without rebooting; and 3) it allowed us to write custom backends that tied in to the rest of our system and allowed us to quickly update DNS records.</p><p>While PowerDNS got us a long way, it started to run into issues as we scaled and dealt with an increasing number of large denial of service attacks. There were three main challenges. First, PowerDNS when under large in-bound DDoS loads would consume excessive resources and occasionally fall over. Second, and more insidious, because the version of PowerDNS we were using did not have abuse detection and rate limiting, we were increasingly seeing attempts at using CloudFlare authoritative DNS network to launch reflection attacks against others. And, third, it was very difficult to extend PowerDNS and add any sort of application logic which kept us from doing interesting things... like adding Easter Eggs.</p>
    <div>
      <h3>Enter RRDNS</h3>
      <a href="#enter-rrdns">
        
      </a>
    </div>
    <p>To their credit, the PowerDNS community responded to the first two problems with some efforts at rate limiting and other abuse detection. However, because of CloudFlare's unique needs, we realized the only real solution to what we needed was a custom build authoritative name server. About nine months ago, we began the creation of what we affectionately refer to as RRDNS.</p><p>Today, every DNS query to CloudFlare runs through RRDNS, and we have eliminated PowerDNS from our stack. We're planning a more significant blog post on the technical details of RRDNS and how we build its attack detection and prevention. This, however, is a quick story of how the ease of adding application logic to RRDNS allowed us to create a couple fun Easter Eggs.</p>
    <div>
      <h3>Easter Eggs</h3>
      <a href="#easter-eggs">
        
      </a>
    </div>
    <p>RRDNS is fully extensible in a modular framework. This allows us to easily add application logic to our name servers, allowing them to respond more dynamically based on the requests they receive. Over time, using this extensibility we plan to add features like DNSSEC. In the meantime, Ian, one of our engineers, wrote a quick extension to demonstrate the functionality.</p><p>DNS has many common records such as A, AAAA, CNAME, TXT, MX, etc. One of the largely deprecated records is the CH (<a href="http://en.wikipedia.org/wiki/Chaosnet">Chaos</a>) protocol. Ian decided to allow you to query for CloudFlare's current job listings via a DNS request. He wrote 15 lines of code as an extension to RRDNS. He pulled the listings dynamically from our RSS feed of job listings and returned them if you ran a particular query for the CH record for jobs.cloudflare directly against one of our DNS servers. Here's the output:</p>
            <pre><code>$ dig ch jobs.cloudflare @emma.ns.cloudflare.com TXT 
;; Truncated, retrying in TCP mode.  
; &lt;&lt;&gt;&gt; DiG 9.8.3-P1 &lt;&lt;&gt;&gt; ch jobs.cloudflare @emma.ns.cloudflare.com  
;; global options: +cmd  
;; Got answer:  
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 28339  
;; flags: qr aa rd; QUERY: 1, ANSWER: 21, AUTHORITY: 0, ADDITIONAL: 0  
;; WARNING: recursion requested but not available  
;; QUESTION SECTION:  
;jobs.cloudflare. &gt; CH &gt; A  
;; ANSWER SECTION:  
jobs.cloudflare. &gt; 86400 &gt; CH &gt; TXT &gt; "Content Marketer, San Francisco, CA"  
jobs.cloudflare. &gt; 86400 &gt; CH &gt; TXT &gt; "Customer Support Leader, San Francisco, CA"  
jobs.cloudflare. &gt; 86400 &gt; CH &gt; TXT &gt; "General Marketer, San Francisco, CA"  
jobs.cloudflare. &gt; 86400 &gt; CH &gt; TXT &gt; "Marketing Analytics Engineer, San Francisco, CA"  
jobs.cloudflare. &gt; 86400 &gt; CH &gt; TXT &gt; "Talent, San Francisco, CA"  
jobs.cloudflare. &gt; 86400 &gt; CH &gt; TXT &gt; "Build Engineer, San Francisco, CA"  
jobs.cloudflare. &gt; 86400 &gt; CH &gt; TXT &gt; "DDoS Engineer, San Francisco, CA"  
jobs.cloudflare. &gt; 86400 &gt; CH &gt; TXT &gt; "Database Engineer, San Francisco, CA"  
jobs.cloudflare. &gt; 86400 &gt; CH &gt; TXT &gt; "Front End Developer, San Francisco, CA"  
jobs.cloudflare. &gt; 86400 &gt; CH &gt; TXT &gt; "Integration Developer, San Francisco, CA"  
jobs.cloudflare. &gt; 86400 &gt; CH &gt; TXT &gt; "JavaScript Performance Engineer, San Francisco, CA"  
jobs.cloudflare. &gt; 86400 &gt; CH &gt; TXT &gt; "PHP Developer, San Francisco, CA"  
jobs.cloudflare. &gt; 86400 &gt; CH &gt; TXT &gt; "Product Manager, San Francisco, CA"  
jobs.cloudflare. &gt; 86400 &gt; CH &gt; TXT &gt; "SDK Engineer, San Francisco, CA"  
jobs.cloudflare. &gt; 86400 &gt; CH &gt; TXT &gt; "Systems Engineer, London, United Kingdom"  
jobs.cloudflare. &gt; 86400 &gt; CH &gt; TXT &gt; "Systems Engineer, San Francisco, CA"  
jobs.cloudflare. &gt; 86400 &gt; CH &gt; TXT &gt; "Network Engineer, San Francisco, CA"  
jobs.cloudflare. &gt; 86400 &gt; CH &gt; TXT &gt; "Technical Operations Engineer, San Francisco, CA"  
jobs.cloudflare. &gt; 86400 &gt; CH &gt; TXT &gt; "Technical Operations Engineer, London, United Kingdom"  
jobs.cloudflare. &gt; 86400 &gt; CH &gt; TXT &gt; "Technical Support Engineer, London, United Kingdom"  
jobs.cloudflare. &gt; 86400 &gt; CH &gt; TXT &gt; "Technical Support Engineer, San Francisco, CA"  
;; Query time: 16 msec  
;; SERVER: 2400:cb00:2049:1::adf5:3a70#53(2400:cb00:2049:1::adf5:3a70)  
;; WHEN: Mon Aug 26 19:42:26 2013  
;; MSG SIZE &amp;nbsp;rcvd: 1122</code></pre>
            <p>The power of this isn't a new way for you to tell what job listings we have. Instead, it is that we can easily embed dynamic application logic into our DNS system. For an even more useless, albeit fun Easter Egg, try querying for the CH record for whois.cloudflare against one of our name servers. You may need to expand the size of your terminal window for full effect.</p>
    <div>
      <h3>All Fun &amp; Games Until Someone Gets Hurt</h3>
      <a href="#all-fun-games-until-someone-gets-hurt">
        
      </a>
    </div>
    <p>One of my first questions when I saw these Easter Eggs was: can someone now use these to in order to use CloudFlare's network to amplify a DNS reflection attack.</p><p>Thankfully, Ian had already thought of this and built in a safeguard. DNS reflection attacks rely on the attacker spoofing the source IP of the victim when querying a DNS server. Since most DNS requests are sent over UDP, which has no handshake, it is possible to cause DNS servers to respond to the spoofed source.</p><p>If you look at the response to the query above, the first line of the response reads:</p>
            <pre><code>;; Truncated, retrying in TCP mode.</code></pre>
            <p>Because RRDNS is highly flexible, Ian was able to force it when getting one of the Easter Egg-generating queries to respond back with a 0-byte UDP response and the DNS message truncated flag. This causes the client making the DNS request to retry via TCP. Since TCP has a handshake as part of its protocol, it prevents the source IP from being forged. Since the UDP response is smaller than the original query, and since the TCP response will only be sent to a source IP that has been verified with a full handshake, the risk of the Easter Eggs being used to amplify a DNS reflection attack is eliminated.</p><p>It doesn't take very much thought to see how we could use this extensibility to better defend against some of the DNS attacks we see, both those directed at us and also those using us to target others. Over the next few weeks we'll dive into more of the technical details behind RRDNS. Until then, enjoy the Easter Eggs.</p> ]]></content:encoded>
            <category><![CDATA[DNS]]></category>
            <category><![CDATA[Reliability]]></category>
            <category><![CDATA[Attacks]]></category>
            <category><![CDATA[RRDNS]]></category>
            <guid isPermaLink="false">fm2Q8fbgUCBYHzhwNHfwW</guid>
            <dc:creator>Matthew Prince</dc:creator>
        </item>
        <item>
            <title><![CDATA[CloudFlare: Fastest Free DNS, Among Fastest DNS Period]]></title>
            <link>https://blog.cloudflare.com/cloudflare-fastest-free-dns-among-fastest-dns/</link>
            <pubDate>Mon, 07 Jan 2013 05:38:00 GMT</pubDate>
            <description><![CDATA[ CloudFlare runs one of the largest networks of DNS servers in the world. Over the last few months, we've invested in making our DNS as fast and responsive as possible. We were happy to see these efforts pay off in third-party DNS test results. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>CloudFlare runs one of the largest networks of <a href="https://www.cloudflare.com/dns">DNS servers</a> in the world. Over the last few months, we've invested in making our DNS as fast and responsive as possible. We were happy to see these efforts pay off in third-party DNS test results.</p><p>The good folks at SolveDNS conduct a <a href="http://www.solvedns.com/dns-comparison/2012/12">monthly survey</a> of the fastest DNS providers in the world. CloudFlare has regularly been in the top-5 fastest DNS providers. This month we're up to number two, with SolveDNS's tests showing an average 4.51ms response time. That's just a hair behind number one (at 4.38ms) and almost twice as fast as number three (at 8.85ms). And, unlike most the other DNS providers in the top-10, CloudFlare's fast <a href="/a-brief-anycast-primer">Anycast DNS</a> service is provided even for our free plans.</p><p>Lest you think we're resting on our laurels, we've got a major DNS release (which we've dubbed RRDNS) scheduled for the next few months that we think will allow us to squeeze a bit more speed out of our DNS lookups. We're shooting for number one!</p> ]]></content:encoded>
            <category><![CDATA[Speed & Reliability]]></category>
            <category><![CDATA[RRDNS]]></category>
            <category><![CDATA[DNS]]></category>
            <category><![CDATA[Speed]]></category>
            <guid isPermaLink="false">2yVzuZuXZc93eUtU8tB8FL</guid>
            <dc:creator>Matthew Prince</dc:creator>
        </item>
    </channel>
</rss>