<?xml version="1.0" encoding="iso-8859-1"?>
        <?xml-stylesheet type="text/css" href="http://www.miek.nl/blog/"?>
<rss version="2.0"
 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 xmlns:dc="http://purl.org/dc/elements/1.1/"
 xmlns:admin="http://webns.net/mvcb/"
 xmlns:atom="http://www.w3.org/2005/Atom"
>
<channel>
<title>Filed under: go | Miek</title>
<atom:link href="http://www.miek.nl/blog/archives/go/index-rss.xml" rel="self" type="application/rss+xml" />
<link>http://www.miek.nl/blog</link>
<description>Thoughts on (technical) stuff</description>
<dc:language>en-us</dc:language>
<dc:creator>Miek Gieben</dc:creator>
<dc:date>2012-02-04T04:15:11+01:00</dc:date>
<admin:generatorAgent rdf:resource="http://nanoblogger.sourceforge.net" />

<item>
<link>http://www.miek.nl/blog/archives/2012/01/28/dns_fingerprinting/index.html</link>
<guid isPermaLink="true">http://www.miek.nl/blog/archives/2012/01/28/dns_fingerprinting/index.html</guid>
<title>DNS Fingerprinting</title>
<dc:date>2012-01-28T16:03:46+01:00</dc:date>
<dc:creator>Miek Gieben</dc:creator>
<dc:subject> go, dns(sec)</dc:subject>
<description><![CDATA[<h2>Announcing FP</h2>

<p><em>The</em> tool for DNS fingerprinting is <a href="https://github.com/kirei/fpdns">fpdns</a>, which is Perl based.
In recent times development seems to have picked up, but a little competition never hurt
anyone, so I wrote <code>fp</code> in Go. Fp is also a fingerprint program for DNS servers. Its aim is to
be more readable then <code>fpdns</code> is (was?). And make it more easy to add new server types.</p>

<h2>Help needed!</h2>

<p>Do you have some old(er) nameserver laying around that can be queried? Does your (sick) mind
know of a few extra evil queries that can be sent to nameservers? If so, please contact
me: <code>query@evilquery.nl</code>. I want to get to a point where <code>fp</code> sends about 10 queries that
can be used to identify a server. </p>

<h2>Fingerprint</h2>

<p>A fingerprint in <code>fp</code> looks like this:</p>

<pre><code>.,CH,TXT,QUERY,NOERROR,qr,aa,tc,RD,ra,ad,cd,z,1,0,0,0,DO,4097,NSID
</code></pre>

<p>It has 20 fields, which are:</p>

<ol>
<li>Domain name, <code>.</code> in this example;</li>
<li>Class, <code>CH</code> here;</li>
<li>Type, <code>TXT</code> here;</li>
<li>Opcode, <code>QUERY</code>;</li>
<li>Rcode, <code>NOERROR</code>;</li>
<li>Query response, <code>qr</code>, lowercase means false (not set), uppercase means true;</li>
<li>Authoritative, <code>aa</code>, lowercase. Thus not set here;</li>
<li>Truncated, <code>tc</code>, not set;</li>
<li>Recursion Desired, <code>RD</code>, uppercase, thus set;</li>
<li>Recursion Available, <code>ra</code>;</li>
<li>Authenticated Data, <code>ad</code>;</li>
<li>Checking Disabled, <code>cd</code>;</li>
<li>Zero, <code>z</code>;</li>
<li>Question section length, 1 here;</li>
<li>Answer section length, 0;</li>
<li>Authoritative section length, 0;</li>
<li>Additional section length, 0;</li>
<li>DNSSEC OK, <code>DO</code> (uppercase, thus set);</li>
<li>UDP bufsize, set to 4097;</li>
<li>NSID, uppercase: request NSID (or NSID was set).</li>
</ol>

<p>These fingerprints are also used in <em>creating</em> the DNS queries that are send to nameserver(s)
being tested.</p>

<p>A full nameserver fingerprint consists out of multiple of these fingerprints. Right now
<code>fp</code> fires off 3 queries to test a server, so each nameserver fingerprint <em>must</em> also
consist out of 3 fingerprints. The nameserver <a href="https://github.com/miekg/godns/tree/master/examples/fp/data/Bind9">fingerprint of BIND9</a>
looks like:</p>

<pre><code># BIND9 fingerprints
.,CH,TXT,QUERY,REFUSED,QR,aa,tc,RD,ra,ad,cd,z,1,0,0,1,DO,4096,NSID
auThoRs.bInD.,CH,TXT,QUERY,NOERROR,QR,AA,tc,rd,ra,ad,cd,z,1,15,1,0,do,0,nsid
bind.,NONE,SOA,NOTIFY,REFUSED,QR,aa,tc,RD,ra,ad,cd,z,1,0,0,0,do,0,nsid
</code></pre>

<p>When <code>fp</code> is extended with an extra fingerprint, this BIND9 fingerprint also
needs to get an extra fingerprint.</p>

<h2>Trying it yourself</h2>

<p>As said, Currently <code>fp</code> only uses three queries, but this is expected to be increased in the
near future. In the <a href="https://github.com/miekg/godns/tree/master/examples/fp/data">data directory</a>, 
the file <code>q</code> holds the fingerprints of the queries to ask. Currently
<a href="https://github.com/miekg/godns/tree/master/examples/fp/data/q">it</a> looks like this:</p>

<pre><code># These are the queries that we ask the nameserver being identified
#
# The order is important, as the data files of the known nameservers are compared
# in this order.
.,CH,TXT,QUERY,NOERROR,qr,aa,tc,RD,ra,ad,cd,z,1,0,0,0,DO,4097,NSID
auThoRs.bInD.,CH,TXT,QUERY,NOERROR,qr,aa,tc,rd,ra,ad,cd,z,1,0,0,0,do,0,nsid
bind.,NONE,SOA,NOTIFY,NOERROR,qr,AA,tc,RD,ra,ad,cd,Z,1,0,0,0,do,0,nsid
</code></pre>

<p>A local run looks like this (this is abbreviated):</p>

<pre><code>% ./fp @localhost
Server type     Diffs       Fingerprint         Recevied
Bind9   0 .,CH,TXT,QUERY,REFUSED,QR,aa,tc,RD,ra,ad,cd,z,1,0,0,1,DO,4096,NSID .,CH,TXT,QUERY,REFUSED,QR,aa,tc,RD,ra,ad,cd,z,1,0,0,1,DO,4096,NSID
Bind9   0 auThoRs.bInD.,CH,TXT,QUERY,NOERROR,QR,AA,tc,rd,ra,ad,cd,z,1,15,1,0,do,0,nsid auThoRs.bInD.,CH,TXT,QUERY,NOERROR,QR,AA,tc,rd,ra,ad,cd,z,1,15,1,0,do,0,nsid
Bind9   0 bind.,NONE,SOA,NOTIFY,REFUSED,QR,aa,tc,RD,ra,ad,cd,z,1,0,0,0,do,0,nsid bind.,NONE,SOA,NOTIFY,REFUSED,QR,aa,tc,RD,ra,ad,cd,z,1,0,0,0,do,0,nsid
        =
Differences:    0

Nsd3    2 .,CH,TXT,QUERY,NOERROR,QR,aa,tc,RD,ra,ad,cd,z,1,0,0,1,DO,4096,nsid .,CH,TXT,QUERY,REFUSED,QR,aa,tc,RD,ra,ad,cd,z,1,0,0,1,DO,4096,NSID
Nsd3    3 auThoRs.bInD.,CH,TXT,QUERY,NOERROR,QR,aa,tc,rd,ra,ad,cd,z,1,0,0,0,do,0,nsid auThoRs.bInD.,CH,TXT,QUERY,NOERROR,QR,AA,tc,rd,ra,ad,cd,z,1,15,1,0,do,0,nsid
Nsd3    6 .,CLASS0,TYPE0,NOTIFY,NXDOMAIN,QR,AA,tc,RD,ra,ad,cd,z,0,0,0,0,do,0,nsid bind.,NONE,SOA,NOTIFY,REFUSED,QR,aa,tc,RD,ra,ad,cd,z,1,0,0,0,do,0,nsid
            =
Differences:    11
</code></pre>

<p>What do you see here? On the left the nameserver type we're testing, then a number. This number represent the number of <em>differences</em> with the
stored fingerprint for this server. When this number is zero, it means the reply from the unknown server is an <em>exact</em> match with
one of the stored fingerprints. In general, the lower the number, the more exact the hit was.
For <code>bind9</code> in the example above, the accumulated number of differences is zero. This indicates the server is probably a BIND9 server.</p>

<p>For <code>nsd3</code> the story is completely different. The accumulated number of differences is 11, so this server probably isn't a NSD3 server.</p>

<h3>Report</h3>

<p>With, <code>-report</code> fp will just show the fingerprint of a nameserver. If the server is positively identified, the finger
print can be added to <code>fp</code>:</p>

<pre><code>% ./fp -report @localhost
# Fingerprint of &lt;Nameserver&gt; &lt;version&gt;
# Supplied by &lt;Name&gt; on &lt;Date&gt;
#
.,CH,TXT,QUERY,REFUSED,QR,aa,tc,RD,ra,ad,cd,z,1,0,0,1,DO,4096,NSID
auThoRs.bInD.,CH,TXT,QUERY,NOERROR,QR,AA,tc,rd,ra,ad,cd,z,1,15,1,0,do,0,nsid
bind.,NONE,SOA,NOTIFY,REFUSED,QR,aa,tc,RD,ra,ad,cd,z,1,0,0,0,do,0,nsid
</code></pre>]]></description>

</item>
<item>
<link>http://www.miek.nl/blog/archives/2012/01/23/super-short_guide_to_getting_q/index.html</link>
<guid isPermaLink="true">http://www.miek.nl/blog/archives/2012/01/23/super-short_guide_to_getting_q/index.html</guid>
<title>Super-short guide to getting q</title>
<dc:date>2012-01-23T18:07:43+01:00</dc:date>
<dc:creator>Miek Gieben</dc:creator>
<dc:subject> go, dns(sec)</dc:subject>
<description><![CDATA[<p>Get the latest version (called <code>weekly</code>) of Go:</p>

<ol>
<li><p>Get Go: <code>hg clone -u release https://go.googlecode.com/hg/ go</code>
Note the directory you have downloaded it to and set 
$GOROOT to it: <code>export GOROOT=$PWD/go</code>.
Add the GOROOT bin directory to your path: <code>PATH=$PATH:$GOROOT/bin</code></p></li>
<li><p>Update Go to the latest weekly: <code>cd $GOROOT; hg pull; hg update weekly</code></p></li>
<li><p>Compile Go: <code>cd $GOROOT/src ; ./all.bash</code></p>

<p>Install missing commands (gcc, sed, bison, etc.) if needed.</p></li>
</ol>

<p>The latest Go is now installed.</p>

<h2>Install GoDNS</h2>

<ol>
<li>Get GoDNS: <code>cd ~; git clone git://github.com/miekg/godns.git</code></li>
<li>Compile it: <code>cd godns; make ; make install</code></li>
<li>Compile the examples; <code>cd examples; make ; make install</code></li>
<li>Query with q: <code>q mx miek.nl</code></li>
<li>Report bugs</li>
</ol>]]></description>

</item>
<item>
<link>http://www.miek.nl/blog/archives/2011/08/28/learning_go_for_e-readers/index.html</link>
<guid isPermaLink="true">http://www.miek.nl/blog/archives/2011/08/28/learning_go_for_e-readers/index.html</guid>
<title>Learning Go for E-readers</title>
<dc:date>2011-08-28T20:45:10+01:00</dc:date>
<dc:creator>Miek Gieben</dc:creator>
<dc:subject> go</dc:subject>
<description><![CDATA[<p>Thanks to a patch from Thomas Kappler I can now offer two types of PDFs, 
one for A4 pages and one for E-readers, like the kindle. </p>

<p>The E-reader variant is suffixed with <code>-kindle</code>:</p>

<ul>
<li><a href="http://miek.nl/files/go/20110828-go-kindle.pdf">Learning Go for E-readers</a></li>
<li><a href="http://miek.nl/files/go/20110828-go.pdf">Learning Go A4 paper</a></li>
</ul>]]></description>

</item>
<item>
<link>http://www.miek.nl/blog/archives/2011/08/12/vim_setup/index.html</link>
<guid isPermaLink="true">http://www.miek.nl/blog/archives/2011/08/12/vim_setup/index.html</guid>
<title>VIM setup</title>
<dc:date>2011-08-12T09:04:13+01:00</dc:date>
<dc:creator>Miek Gieben</dc:creator>
<dc:subject> go, linux</dc:subject>
<description><![CDATA[<p>After several years I decided to use a different color scheme for VIM.
Also I'm going for force myself to use VIM's folding abilities and use
<code>make</code> from within VIM.</p>

<p>For good measure I also want to use Omni-completion when writing Go
code:</p>

<p><img width="600" src="http://www.miek.nl/gfx/2011/omni.jpg" alt="omni completion screenshot"/> </p>

<p>Btw, this screenshots also shows the <code>solarized</code> (dark) colorscheme.</p>

<h1>Coloring</h1>

<p>Google for <code>solarized</code>. In my <code>.vimrc</code>:</p>

<pre><code>let g:solarized_termcolors=256
colorscheme solarized
</code></pre>

<h1>Make from VIM</h1>

<p>Use <code>:make</code> inside the editor and jump through the errors with:</p>

<pre><code>:cn         // next compile error
:cp         // previous compile error
</code></pre>

<p>There are more options, but I want to be able to remember them...</p>

<h1>Folding</h1>

<p>Settings in <code>.vimrc</code>:</p>

<pre><code>" folding settings
set foldmethod=indent
set foldnestmax=10
set nofoldenable
set foldlevel=0
</code></pre>

<p>And the commands that I will probably use most often:</p>

<pre><code>zM          // close all folds
zR          // open all folds

za          // toggle fold under cursor
zA          // toggle fold under cursor recursively
</code></pre>

<p>Other important ones:</p>

<pre><code>zo          // open fold under cursor
zO          // open all under cursor recursively

zc          // close fold under cursor
zC          // close all under cursor recursively
</code></pre>

<h1>Spell checking</h1>

<p>Setting in <code>.vimrc</code>:</p>

<pre><code>" toggle spelling control-E -&gt; en, control-N -&gt; dutch (nederlands)                   
map     &lt;C-E&gt;    :setlocal spell! spelllang=en&lt;CR&gt;
imap    &lt;C-E&gt;    &lt;ESC&gt;:setlocal spell! spelllang=en&lt;CR&gt;i
map     &lt;C-N&gt;    :setlocal spell! spelllang=nl&lt;CR&gt;
imap    &lt;C-N&gt;    &lt;ESC&gt;:setlocal spell! spelllang=nl&lt;CR&gt;i
</code></pre>

<p>Commands to use (this is the only one I use)</p>

<pre><code>z=          // Show corrections for a word
</code></pre>

<h1>Toggle switches</h1>

<p>Switches for paste-mode, cursorline, numbering  disable search highlighting.</p>

<pre><code>set pastetoggle=&lt;F7&gt;

" search hilight
map     &lt;F8&gt;   :nohlsearch&lt;CR&gt;
imap    &lt;F8&gt;   &lt;ESC&gt;:nohlsearch&lt;CR&gt;a
vmap    &lt;F8&gt;   &lt;ESC&gt;:nohlsearch&lt;CR&gt;gv

" numbering
map     &lt;F10&gt;   :set nu!&lt;CR&gt;
imap    &lt;F10&gt;   &lt;ESC&gt;:set nu!&lt;CR&gt;i
vmap    &lt;F10&gt;   &lt;ESC&gt;:set nu!&lt;CR&gt;gv

" toggle cursorline
map     &lt;F9&gt;   :set cursorline!&lt;CR&gt;
imap    &lt;F9&gt;   &lt;ESC&gt;:set cursorline!&lt;CR&gt;
</code></pre>

<h1>Omni completion (Go specific)</h1>

<p>See <a href="https://github.com/nsf/gocode">https://github.com/nsf/gocode</a>. After
you've installed that, you can use <code>control-X control-O</code> to bring up
the omni completion window. With the VIM files in <code>go/misc/vim</code> you also
have the following commands:</p>

<pre><code>    :Fmt                // Gofmt your code
    :Import strings     // add package 'strings' to the import list
    :Drop strings       // drop package 'strings' from the import list
</code></pre>]]></description>

</item>
<item>
<link>http://www.miek.nl/blog/archives/2011/08/01/chaining_proxies/index.html</link>
<guid isPermaLink="true">http://www.miek.nl/blog/archives/2011/08/01/chaining_proxies/index.html</guid>
<title>Chaining proxies</title>
<dc:date>2011-08-01T20:38:42+01:00</dc:date>
<dc:creator>Miek Gieben</dc:creator>
<dc:subject> go, dns(sec)</dc:subject>
<description><![CDATA[<p>Online signing is cool, but slow. Caching queries in a reverse proxy is
nice, but useless for something like NSD. But what
if you want to do online signing in a fast way?</p>

<blockquote>
  <p>Enter: proxy chaining.</p>
</blockquote>

<p>I already showed <a href="http://www.miek.nl/blog/archives/2011/01/24/funkensign/index.html">FunkenSign</a> (example code
is quite old though)
and yesterday <a href="http://www.miek.nl/blog/archives/2011/07/31/reverse_dns_proxy/index.html">FunkenShield</a>.</p>

<p>What if you combine the two? That gives the best of both worlds:</p>

<ul>
<li>Online signing;</li>
<li>Caching;</li>
<li>And it adheres to the true Unix philosophy: do one thing,  and do one thing well.</li>
</ul>

<p>So lets get some figures again.</p>

<h1>Nameserver</h1>

<p>First start the nameserver:</p>

<pre><code>cd _examples/ns &amp;&amp; make
GOMAXPROCS=10 ./ns      # listens on port 8053
</code></pre>

<h1>Online signing proxy</h1>

<p>Next we start our online signing proxy. This proxy only signs answers to questions for
<code>c.miek.nl.</code>, and leaves other questions alone.</p>

<p>We listen on port 8054 and use the nameserver we started on port 8053:</p>

<pre><code>cd examples/funkensturm &amp;&amp; make -f Makefile_sign
# save the exe
cp funkensturm funkensturm_sign
# start it
GOMAXPROCS=10 ./funkensturm_sign -rserver=127.0.0.1:8053 -sserver=127.0.0.1:8054
</code></pre>

<h1>Reverse proxy</h1>

<p>And lastly the reverse proxy. It listens on port 8055 and forwards queries to 8054.</p>

<pre><code>make -f Makefile_rproxy
cp funkensturm funkensturm_rproxy
GOMAXPROCS=10 ./funkensturm_rproxy -rserver=127.0.0.1:8054 -sserver=127.0.0.1:8055
</code></pre>

<h1>Numbers</h1>

<p>So we have:</p>

<pre><code>caching proxy -&gt; signing proxy -&gt; nameserver
</code></pre>

<p>And for queryperf we create a data file with three queries:</p>

<ol>
<li>a.miek.nl A</li>
<li>a.miek.nl AAAA</li>
<li>c.miek.nl A  </li>
</ol>

<p>Where the answer to 3 will include a generated signature.</p>

<p>So lets query the nameserver on port 8053:</p>

<pre><code>./queryperf -d data -s 127.0.0.1 -p 8053 -l 2 
Queries per second:   7298.194728 qps
</code></pre>

<p>7000+ qps; a normal number.
Next directly query the online signing proxy on port 8054:</p>

<pre><code>./queryperf -d data -s 127.0.0.1 -p 8054 -l 2
Queries per second:   205.991306 qps
</code></pre>

<p>205 qps... that's onine signing for you: <code>S L O W</code>.</p>

<p>Next we use the caching proxy which caches the answers, 
we query on port 8055:</p>

<pre><code>./queryperf -d data -s 127.0.0.1 -p 8055 -l 2
Queries per second:   28521.826761 qps
</code></pre>

<p>Thats again more like it. </p>

<p>So we have <em>fast</em> online signing in a <em>clean</em> way. </p>

<p>Note: (excluding godns) the combined line count is
197 lines for <code>ns</code> and 450 for <code>funkensturm</code>.</p>]]></description>

</item>
<item>
<link>http://www.miek.nl/blog/archives/2011/07/31/reverse_dns_proxy/index.html</link>
<guid isPermaLink="true">http://www.miek.nl/blog/archives/2011/07/31/reverse_dns_proxy/index.html</guid>
<title>Reverse DNS proxy</title>
<dc:date>2011-07-31T16:09:20+01:00</dc:date>
<dc:creator>Miek Gieben</dc:creator>
<dc:subject> go, dns(sec)</dc:subject>
<description><![CDATA[<p>Have a slow nameserver and want to spice things up? How about a reverse DNS
proxy? For lack of a cool name I chose the name <em>FunkenShield</em>. It's (of course)
in the early stages, but it works quite nicely already.</p>

<p>This is done with the framework of 
<a href="http://www.miek.nl/blog/archives/2011/01/23/funkensturm_a_versatile_dns_proxy/index.html">FunkenSturm</a>.
Which is part of <a href="http://github.com/miekg/godns">GoDNS</a>.</p>

<h1>How it works:</h1>

<blockquote>
  <p>You place FunkenShield in front of your nameserver and it will cache the binary packets
coming from your server in a local cache. </p>
</blockquote>

<p>It is written in <a href="http://www.golang.org">Go</a>, and the beauty of it is that Go compiles
to static executables, so I can give you (or you can compile it yourself) the <em>exe</em> and
you can experiment with it yourself.</p>

<h1>Some numbers</h1>

<p><a href="http://github.com/miekg/godns">GoDNS</a> is a library that helps you create DNS software. In
this library some example programs are included, among other, a simple nameserver. Currently
this nameserver works with 1 zone, namely "miek.nl". If you run it, it defaults to listening
on port 8053:</p>

<pre><code>% ./ns      # start the nameserver

&lt;other terminal&gt;

% dig @127.0.0.1 -p 8053 mx miek.nl
&lt;snip&gt;
;; QUESTION SECTION:
;miek.nl.                       IN      MX

;; ANSWER SECTION:
miek.nl.                345600  IN      MX      20 mail.atoom.net.
miek.nl.                345600  IN      MX      40 mx-ext.tjeb.nl.

;; AUTHORITY SECTION:
&lt;snip&gt;

;; ADDITIONAL SECTION:
miek.nl.                0       IN      TXT     "Proudly served by Go: http://www.golang.org"
</code></pre>

<p>So that works. But how fast is it? This <em>queryperf</em> asks two questions: "A a.miek.nl" and "AAAA a.miek.nl":</p>

<pre><code>% ./queryperf -d data -s 127.0.0.1 -p 8053 -l 10
&lt;snip&gt;
Queries per second:   3079.260741 qps
</code></pre>

<p>Hmmm, only about 3000. Lets spice things up a bit and utilize Go's multicore features:</p>

<pre><code>% GOMAXPROCS=20 ./ns 
% ./queryperf -d data -s 127.0.0.1 -p 8053 -l 10
Queries per second:   7124.942077 qps
</code></pre>

<p>More than doubled. Nice, but still nothing to make <a href="http://www.nlnetlabs.nl/projects/nsd">NSD</a> afraid.</p>

<blockquote>
  <p>Enter FunkenShield</p>
</blockquote>

<p>We run FunkenShield on port 8054, and allow it to have a multitude of goroutines. Note: "./ns" is
still running. If FunkenShield has a cache miss it still needs to ask the nameserver.</p>

<pre><code>% cd _examples/funkensturm &amp;&amp; make -f Makefile_rproxy
% GOMAXPROCS=20 ./funkensturm -rserver 127.0.0.1:8053 -sserver 127.0.0.1:8054
% ./queryperf -d data -s 127.0.0.1 -p 8054 -l 10        # port = 8054!
Queries per second:   27506.219188 qps
</code></pre>

<p>W00t! </p>

<blockquote>
  <p>27506 qps. </p>
</blockquote>

<p>27000+ qps is not bad for a nameserver. </p>]]></description>

</item>
<item>
<link>http://www.miek.nl/blog/archives/2011/07/18/on_programming_languages_and_programmers/index.html</link>
<guid isPermaLink="true">http://www.miek.nl/blog/archives/2011/07/18/on_programming_languages_and_programmers/index.html</guid>
<title>On programming languages and programmers</title>
<dc:date>2011-07-18T13:02:23+01:00</dc:date>
<dc:creator>Miek Gieben</dc:creator>
<dc:subject> go, programming</dc:subject>
<description><![CDATA[<p>Very well written email message from Geoff Teale
on the <a href="http://groups.google.com/group/golang-nuts/">golang mailing list</a> on programmers and
progamming languages
(<a href="http://groups.google.com/group/golang-nuts/browse_thread/thread/350bf027bd803af1#">thread</a>).</p>

<blockquote>
  <p>To summarise a long presentation I gave to non-programmers:</p>

<ul>
<li>There are 12 million programmers in the world</li>
<li>The majority of those programmers are scarcely qualified</li>
<li>Most technology decisions are made by a combination of following the crowd
and a false understanding of risk.</li>
<li>The high cost and failure rate in software development is no coincidence.</li>
</ul>

<p>Remember the Stevie Wonder rule - "When you believe in something you don't
understand then you suffer".   In this case that means "Perhaps making
programming language decisions based on what 12 million powerless idiots are
doing isn't the golden road to glory and great hacks."</p>

<p>Go is a genuine attempt to improve the state of systems programing language
beyond the point they reached in the early 1970s.  As a result the sort of
people using it are mostly that small community of people who understand and
care about the concerns that drive such a development.</p>

<p>You're not going to catch those 12 million people unless you can market heavily
enough the idea that their future income depend on jobs/contacts built around
go, but that goal just draws resources and energy away from making the language
better.</p>

<p>Arguably Java also suffers from it's large community of corporate drones.   The
slavish tendency to build baroque, mausoleums of intricate classes, dense with
state and dripping with verbose XML is a reflection of the unthinking insanity
of the 12 million.</p>

<p>I'd rather a tiny community use the language well, built successful
applications and organically grew the user base whilst establishing a clean,
sane library base that might later be used to improve the lives of a wider
population of programmers.</p>

<p>I've said more than enough, I'll trundle back to the twelve million and take my
punishment now.</p>
</blockquote>]]></description>

</item>
<item>
<link>http://www.miek.nl/blog/archives/2011/07/06/go_dns_update/index.html</link>
<guid isPermaLink="true">http://www.miek.nl/blog/archives/2011/07/06/go_dns_update/index.html</guid>
<title>Go DNS (update)</title>
<dc:date>2011-07-06T08:41:57+01:00</dc:date>
<dc:creator>Miek Gieben</dc:creator>
<dc:subject> go, dns(sec)</dc:subject>
<description><![CDATA[<p>I'm finally back to coding Go DNS and making it work with
the latest Go releases. Also the API has changed quite significantly
since the last time I blogged about it.</p>

<p>So this I will detail
<a href="https://github.com/miekg/godns/blob/master/_examples/key2ds/key2ds.go">key2ds</a> which is small utility that queries
a zone and print any DNSKEY records as DS records on the fly, to show the new API and
some sample usage.</p>

<pre><code>% ./key2ds sidn.nl
sidn.nl.    0   IN  DS  42033 8 1 343F74674D36C9B5BE2CEB2C401AC4EDEB2A05B2
sidn.nl.    0   IN  DS  42033 8 2 BF985EC0738FACC89EE0B12FBD9261827C59191D9EA6A9BDFF55F9BDF3DBBFF3
sidn.nl.    0   IN  DS  39274 8 1 E79E031DFDE8E68EF1E2C6CA0943C2CC0DED1889
sidn.nl.    0   IN  DS  39274 8 2 8E8A8CFB40FD0C30BFA82E53752E1C257DAFB7B6206D12B9EDA43AF3EAB2157D
</code></pre>

<p>This util uses synchronous queries. I will explain the <code>main</code>-function:</p>

<pre><code>func main() {
        conf, err := dns.ClientConfigFromFile("/etc/resolv.conf")
        if len(os.Args) != 2 || err != nil {
                fmt.Printf("%s DOMAIN\n", os.Args[0])
                os.Exit(1)
        }
</code></pre>

<p>Read the resolver config from <code>/etc/resolv.conf</code> and check if
enough parameters have been given.</p>

<pre><code>    m := new(dns.Msg)
    m.SetQuestion(os.Args[1], dns.TypeDNSKEY)
</code></pre>

<p>Prepare a new dns message to send to the other side. I'm interested in
the <code>DNSKEY</code>s for the name given on the command line.</p>

<pre><code>    // Set EDNS0's Do bit
    e := new(dns.RR_OPT)
    e.Hdr.Name = "."
    e.Hdr.Rrtype = dns.TypeOPT
    e.SetUDPSize(2048)
    e.SetDo()
    m.Extra = append(m.Extra, e)
</code></pre>

<p>This is DNSSEC so I must prepare an EDNS0 section, which is
nothing more than adding an OPT RR to the additional section. I'm
pondering making EDNS0 easier and provide a few helper functions (ideas welcome!).
For now the whole OPT RR must be defined from scratch.</p>

<pre><code>    c := dns.NewClient()
    r := c.Exchange(m, conf.Servers[0])
    if r == nil {
            fmt.Printf("*** no answer received for %s\n", os.Args[1])
            os.Exit(1)
    }
</code></pre>

<p>Create a new client and use <code>Exchange()</code> to perform send the query and 
wait for the reply. Note that we only use the first server defined
in <code>/etc/resolv.conf</code>. (There is room for some improvements :-) )</p>

<pre><code>    if r.Rcode != dns.RcodeSuccess {
            fmt.Printf(" *** invalid answer name %s after DNSKEY query for %s\n", os.Args[1], os.Args[1])
            os.Exit(1)
    }
</code></pre>

<p>If anything is wrong with the answer I bail out here.</p>

<pre><code>    for _, k := range r.Answer {
            if key, ok := k.(*dns.RR_DNSKEY); ok {
</code></pre>

<p>Loop through the answer section and check each RR to see
if it is a DNSKEY record with a type check.</p>

<pre><code>                    ds := key.ToDS(dns.HashSHA1)
                    ds.Hdr.Ttl = 0
                    fmt.Printf("%v\n", ds)
</code></pre>

<p>For each DNSKEY convert it to a SHA1 DS records with <code>ToDS()</code></p>

<pre><code>                        ds = key.ToDS(dns.HashSHA256)
                        ds.Hdr.Ttl = 0
                        fmt.Printf("%v\n", ds)
                }
        }
}
</code></pre>

<p>And do the same for SHA256 and print that too.</p>]]></description>

</item>
<item>
<link>http://www.miek.nl/blog/archives/2011/07/05/go_dns_update/index.html</link>
<guid isPermaLink="true">http://www.miek.nl/blog/archives/2011/07/05/go_dns_update/index.html</guid>
<title>Go DNS (update)</title>
<dc:date>2011-07-05T21:45:45+01:00</dc:date>
<dc:creator>Miek Gieben</dc:creator>
<dc:subject> go</dc:subject>
<description><![CDATA[<p>I'm finally back to coding Go DNS and making it work with
the latest Go releases. Also the API has changed quite significantly
since the last time I blogged about it.</p>

<p>I will detail
<a href="https://github.com/miekg/godns/blob/master/_examples/key2ds/key2ds.go">key2ds</a> which is small utility that queries
a zone and print any DNSKEY records as DS records on the fly.</p>

<pre><code>% ./key2ds sidn.nl
sidn.nl.    0   IN  DS  42033 8 1 343F74674D36C9B5BE2CEB2C401AC4EDEB2A05B2
sidn.nl.    0   IN  DS  42033 8 2 BF985EC0738FACC89EE0B12FBD9261827C59191D9EA6A9BDFF55F9BDF3DBBFF3
sidn.nl.    0   IN  DS  39274 8 1 E79E031DFDE8E68EF1E2C6CA0943C2CC0DED1889
sidn.nl.    0   IN  DS  39274 8 2 8E8A8CFB40FD0C30BFA82E53752E1C257DAFB7B6206D12B9EDA43AF3EAB2157D
</code></pre>

<p>This util uses synchronous queries. I will detail the <code>main</code>-function:</p>

<pre><code>func main() {
        conf, err := dns.ClientConfigFromFile("/etc/resolv.conf")
        if len(os.Args) != 2 || err != nil {
                fmt.Printf("%s DOMAIN\n", os.Args[0])
                os.Exit(1)
        }
</code></pre>

<p>Read the resolver config from <code>/etc/resolv.conf</code> and check if
enough parameters have been given.</p>

<pre><code>    m := new(dns.Msg)
    m.SetQuestion(os.Args[1], dns.TypeDNSKEY)
</code></pre>

<p>Prepare a new dns message to send to the other side. I'm interested in
the <code>DNSKEY</code>s for name given on the command line.</p>

<pre><code>    // Set EDNS0's Do bit
    e := new(dns.RR_OPT)
    e.Hdr.Name = "."
    e.Hdr.Rrtype = dns.TypeOPT
    e.SetUDPSize(2048)
    e.SetDo()
    m.Extra = append(m.Extra, e)
</code></pre>

<p>This is DNSSEC so I must prepare an EDNS0 section, which is
nothing more than adding an OPT RR to the Additional section. I'm
pondering making EDNS0 easier and provide a few helper functions. For
now the whole OPT RR must be defined from scratch.</p>

<pre><code>    c := dns.NewClient()
    r := c.Exchange(m, conf.Servers[0])
    if r == nil {
            fmt.Printf("*** no answer received for %s\n", os.Args[1])
            os.Exit(1)
    }
</code></pre>

<p>Create a new client and use <code>Exchange()</code> to perform send the query and 
wait for the reply. Note that we only use the first server defined
in <code>/etc/resolv.conf</code>. (There is room for some improvements :) )</p>

<pre><code>    if r.Rcode != dns.RcodeSuccess {
            fmt.Printf(" *** invalid answer name %s after DNSKEY query for %s\n", os.Args[1], os.Args[1])
            os.Exit(1)
    }
</code></pre>

<p>If anything is wrong with the answer I bail out here.</p>

<pre><code>    for _, k := range r.Answer {
            if key, ok := k.(*dns.RR_DNSKEY); ok {
</code></pre>

<p>Loop through the answer section and check each RR to see
if it is a DNSKEY record with a type check.</p>

<pre><code>                    ds := key.ToDS(dns.HashSHA1)
                    ds.Hdr.Ttl = 0
                    fmt.Printf("%v\n", ds)
</code></pre>

<p>For each DNSKEY convert it to a SHA1 DS records with <code>ToDS()</code></p>

<pre><code>                        ds = key.ToDS(dns.HashSHA256)
                        ds.Hdr.Ttl = 0
                        fmt.Printf("%v\n", ds)
                }
        }
}
</code></pre>

<p>And do the same for SHA256 and print that too.</p>]]></description>

</item>
<item>
<link>http://www.miek.nl/blog/archives/2011/05/15/nluug_go_presentatie/index.html</link>
<guid isPermaLink="true">http://www.miek.nl/blog/archives/2011/05/15/nluug_go_presentatie/index.html</guid>
<title>NLUUG Go presentatie</title>
<dc:date>2011-05-15T10:17:37+01:00</dc:date>
<dc:creator>Miek Gieben</dc:creator>
<dc:subject> dutch, go</dc:subject>
<description><![CDATA[<p>Dit <a href="http://www.miek.nl/downloads/2011/NLUUG-Go.pdf">zijn de slides</a> van de presentatie 
die ik afgelopen donderdag heb gegeven op de 
<a href="http://www.nluug.nl/activiteiten/events/vj11/abstracts/ab30.html">NLUUG voorjaars
conferentie</a>.</p>]]></description>

</item>
</channel>
</rss>

