<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>dns on SLXH.nl</title><link>https://slxh.nl/tags/dns/</link><description>Recent content in dns on SLXH.nl</description><generator>Hugo -- gohugo.io</generator><language>en-GB</language><lastBuildDate>Thu, 22 Dec 2016 17:33:07 +0100</lastBuildDate><atom:link href="https://slxh.nl/tags/dns/index.xml" rel="self" type="application/rss+xml"/><item><title>NAT64 performance</title><link>https://slxh.nl/blog/2021/nat64-performance/</link><pubDate>Wed, 31 Mar 2021 20:07:06 +0200</pubDate><guid>https://slxh.nl/blog/2021/nat64-performance/</guid><description type="html">&lt;p>This post is an update of &lt;a href="https://slxh.nl/blog/NAT64%20for%20servers">my previous post about NAT64&lt;/a>.
That post describes the following setup:&lt;/p>
&lt;pre>&lt;code> IPv4 IPv4
Internet ────── Router ────── NAT64
IPv6 │ │ IPv6
└────────── Host
IPv6
&lt;/code>&lt;/pre></description><content:encoded>&lt;p>This post is an update of &lt;a href="https://slxh.nl/blog/NAT64%20for%20servers">my previous post about NAT64&lt;/a>.
That post describes the following setup:&lt;/p>
&lt;pre>&lt;code> IPv4 IPv4
Internet ────── Router ────── NAT64
IPv6 │ │ IPv6
└────────── Host
IPv6
&lt;/code>&lt;/pre>&lt;p>This has the following components in the network:&lt;/p>
&lt;ul>
&lt;li>A &lt;em>router&lt;/em> that routes IPv6 and routes or NATs IPv4.&lt;/li>
&lt;li>A &lt;em>NAT64&lt;/em> server that performs thanslation of IPv4 and IPv6.&lt;/li>
&lt;li>A &lt;em>host&lt;/em> that only has IPv6 connectivity.&lt;/li>
&lt;/ul>
&lt;p>The is to use the NAT64 server both ways:
the NAT64 server is used for IPv4 connectivity (looking at you, GitHub),
and to reach the IPv6-only hosts over IPv4.&lt;/p>
&lt;p>Currently, I still use &lt;a href="http://www.litech.org/tayga/">Tayga&lt;/a> for this setup.
The main downside of Tayga is it&amp;rsquo;s (low) performance.
This performance is the main reason various hosts in my network still have
an IPv4 address.
I have also replaced my home router with a &lt;a href="https://www.pcengines.ch/apu3c2.htm">PCEngines APU&lt;/a>,
which should perform much better than the Edgerouter Lite it replaced.&lt;/p>
&lt;h2 id="alternatives">Alternatives&lt;/h2>
&lt;p>There are various alternatives to Tayga:&lt;/p>
&lt;ul>
&lt;li>OpenBSD&amp;rsquo;s &lt;a href="https://www.openbsd.org/faq/pf/filter.html">PF&lt;/a> (using &lt;a href="https://man.openbsd.org/pf.conf.5#af-to">af-to&lt;/a>).&lt;/li>
&lt;li>&lt;a href="https://www.jool.mx">Jool&lt;/a> can perform both (stateful) NAT64 and (stateless) &lt;a href="https://tools.ietf.org/html/rfc7915">SIIT&lt;/a>.&lt;/li>
&lt;li>&lt;a href="https://github.com/keiichishima/map646">map646&lt;/a> only performs stateless NAT64.&lt;/li>
&lt;/ul>
&lt;p>The latter two have been compared against Tayga in &lt;a href="https://link.springer.com/article/10.1007/s11235-020-00681-x">this paper&lt;/a>,
which found the following performance:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Solution&lt;/th>
&lt;th style="text-align:right">frame/s&lt;/th>
&lt;th style="text-align:right">Mbps (est.)&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Jool&lt;/td>
&lt;td style="text-align:right">230000&lt;/td>
&lt;td style="text-align:right">2760&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Tayga&lt;/td>
&lt;td style="text-align:right">120000&lt;/td>
&lt;td style="text-align:right">1440&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>map646&lt;/td>
&lt;td style="text-align:right">60000&lt;/td>
&lt;td style="text-align:right">720&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Note that the throughput for Tayga is significantly greater than I was able to
achieve in my previous post (252 Mbps).
Additionally, the performance of Jool looks &lt;em>interesting&lt;/em>&amp;hellip;&lt;/p>
&lt;h2 id="test-setup">Test setup&lt;/h2>
&lt;p>The following devices are used for testing the performance of Tayga, Jool and PF:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>&lt;/th>
&lt;th style="text-align:left">PCEngines APU&lt;/th>
&lt;th style="text-align:left">Ryzen 2600X&lt;/th>
&lt;th style="text-align:left">Ryzen 4650G&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>CPU&lt;/td>
&lt;td style="text-align:left">&lt;a href="https://www.amd.com/en/system/files?file=2017-06/g-series-soc-product-brief.pdf">AMD GX-412&lt;/a>&lt;/td>
&lt;td style="text-align:left">&lt;a href="https://www.amd.com/en/products/cpu/amd-ryzen-5-2600x">AMD Ryzen 5 2600X&lt;/a>&lt;/td>
&lt;td style="text-align:left">&lt;a href="https://www.amd.com/en/products/apu/amd-ryzen-5-pro-4650g">AMD Ryzen 5 PRO 4650G&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>NIC&lt;/td>
&lt;td style="text-align:left">&lt;a href="https://ark.intel.com/content/www/us/en/ark/products/64404/intel-ethernet-controller-i211-at.html">Intel i211AT&lt;/a>&lt;/td>
&lt;td style="text-align:left">&lt;a href="https://ark.intel.com/content/www/us/en/ark/products/88209/intel-ethernet-converged-network-adapter-x550-t2.html">Intel X550-T2&lt;/a>&lt;/td>
&lt;td style="text-align:left">&lt;a href="https://www.mellanox.com/products/ethernet-adapters/connectx-3-pro">Mellanox ConnectX-3 EN&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>RAM&lt;/td>
&lt;td style="text-align:left">2GB DDR3-1333&lt;/td>
&lt;td style="text-align:left">32GB DDR4-3200&lt;/td>
&lt;td style="text-align:left">32GB DDR4-3200&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Both the PCEngines APU and the Ryzen2600X are used as NAT64 device,
while the Ryzen 4650G is used to measure performance.&lt;/p>
&lt;p>Fresh installations of OpenBSD 6.8 and Debian Bullseye are used for
the tests. No performance tuning is done.&lt;/p>
&lt;p>Tests are performed using iPerf3 using a single TCP flow
on a single link (in full duplex).
The best of three measurements is used as the result.&lt;/p>
&lt;p>A few notes:&lt;/p>
&lt;ul>
&lt;li>Note that these numbers do not include overhead from Ethernet, IP or TCP (5-6%).&lt;/li>
&lt;li>The network, and the devices, may be somewhat in use.&lt;/li>
&lt;li>Only a single full-duplex link is used.&lt;/li>
&lt;/ul>
&lt;p>This means that the results below should be taken with a grain of salt.&lt;/p>
&lt;h2 id="different-types-of-nat">Different types of NAT&lt;/h2>
&lt;p>Tayga, Jool and PF work differently:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Tayga and PF (and Jool in NAT64 mode) masquerade the original IP.
Tayga can do so using an (optional) dynamic pool, and static mappings.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>PF also masquerades the IPv6 address in the NAT46 flow.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Jool (in SIIT mode) does a stateless translation between IPs.
This means that the original IP also has to be one from the pool.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Jool (in SIIT mode) translates &lt;em>all&lt;/em> IPv4 traffic.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>Example translations for NAT64:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>&lt;/th>
&lt;th>Orig From&lt;/th>
&lt;th>Orig To&lt;/th>
&lt;th>NAT From&lt;/th>
&lt;th>NAT To&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Tayga&lt;/td>
&lt;td>*&lt;/td>
&lt;td>64:ff9b::10.64.0.10&lt;/td>
&lt;td>10.64.0.0/24&lt;/td>
&lt;td>10.64.0.10&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Jool&lt;/td>
&lt;td>64:ff9b::10.64.1.10&lt;/td>
&lt;td>64:ff9b::10.64.0.10&lt;/td>
&lt;td>10.64.1.10&lt;/td>
&lt;td>10.64.0.10&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>PF&lt;/td>
&lt;td>*&lt;/td>
&lt;td>64:ff9b::10.64.0.10&lt;/td>
&lt;td>10.64.0.1&lt;/td>
&lt;td>10.64.0.10&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Example translations for NAT46:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>&lt;/th>
&lt;th>Orig From&lt;/th>
&lt;th>Orig To&lt;/th>
&lt;th>NAT From&lt;/th>
&lt;th>NAT To&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Tayga&lt;/td>
&lt;td>10.64.1.10&lt;/td>
&lt;td>10.64.0.10&lt;/td>
&lt;td>2001:db8::10.64.1.10&lt;/td>
&lt;td>2001:db8::10.64.0.10&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Jool&lt;/td>
&lt;td>10.64.1.10&lt;/td>
&lt;td>10.64.0.10&lt;/td>
&lt;td>2001:db8::10.64.1.10&lt;/td>
&lt;td>2001:db8::10.64.0.10&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>PF&lt;/td>
&lt;td>*&lt;/td>
&lt;td>10.64.0.10&lt;/td>
&lt;td>2001:db8::1&lt;/td>
&lt;td>2001:db8::10.64.0.10&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="results">Results&lt;/h2>
&lt;p>Performance on the PCEngines APU in Mbps:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:left">&lt;/th>
&lt;th style="text-align:right">IPv4&lt;/th>
&lt;th style="text-align:right">IPv6&lt;/th>
&lt;th style="text-align:right">NAT64&lt;/th>
&lt;th style="text-align:right">NAT46&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:left">Tayga&lt;/td>
&lt;td style="text-align:right">903&lt;/td>
&lt;td style="text-align:right">887&lt;/td>
&lt;td style="text-align:right">199&lt;/td>
&lt;td style="text-align:right">197&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">Jool&lt;/td>
&lt;td style="text-align:right">-&lt;/td>
&lt;td style="text-align:right">869&lt;/td>
&lt;td style="text-align:right">805&lt;/td>
&lt;td style="text-align:right">825&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">PF&lt;/td>
&lt;td style="text-align:right">646&lt;/td>
&lt;td style="text-align:right">488&lt;/td>
&lt;td style="text-align:right">572&lt;/td>
&lt;td style="text-align:right">444&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Performance on the Ryzen 2600X in Mbps:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:left">&lt;/th>
&lt;th style="text-align:right">IPv4&lt;/th>
&lt;th style="text-align:right">IPv6&lt;/th>
&lt;th style="text-align:right">NAT64&lt;/th>
&lt;th style="text-align:right">NAT46&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:left">Tayga&lt;/td>
&lt;td style="text-align:right">8478&lt;/td>
&lt;td style="text-align:right">8361&lt;/td>
&lt;td style="text-align:right">2971&lt;/td>
&lt;td style="text-align:right">2807&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">Jool&lt;/td>
&lt;td style="text-align:right">-&lt;/td>
&lt;td style="text-align:right">7819&lt;/td>
&lt;td style="text-align:right">8193&lt;/td>
&lt;td style="text-align:right">8091&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">PF&lt;/td>
&lt;td style="text-align:right">6292&lt;/td>
&lt;td style="text-align:right">5006&lt;/td>
&lt;td style="text-align:right">2354&lt;/td>
&lt;td style="text-align:right">5440&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>As a bonus: performance of Jool in a container on the Ryzen 4650G in Mbps:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:left">&lt;/th>
&lt;th style="text-align:right">IPv4&lt;/th>
&lt;th style="text-align:right">IPv6&lt;/th>
&lt;th style="text-align:right">NAT64&lt;/th>
&lt;th style="text-align:right">NAT46&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:left">Jool&lt;/td>
&lt;td style="text-align:right">15216&lt;/td>
&lt;td style="text-align:right">14406&lt;/td>
&lt;td style="text-align:right">14426&lt;/td>
&lt;td style="text-align:right">10097&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>This means the performance of the solutions,
when compared to the line rate,
is as follows:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:left">Solution&lt;/th>
&lt;th style="text-align:left">Platform&lt;/th>
&lt;th style="text-align:right">NAT64&lt;/th>
&lt;th style="text-align:right">NAT46&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:left">Tayga&lt;/td>
&lt;td style="text-align:left">PCEngines APU&lt;/td>
&lt;td style="text-align:right">21%&lt;/td>
&lt;td style="text-align:right">21%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">Tayga&lt;/td>
&lt;td style="text-align:left">Ryzen 2600X&lt;/td>
&lt;td style="text-align:right">31%&lt;/td>
&lt;td style="text-align:right">29%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">PF&lt;/td>
&lt;td style="text-align:left">PCEngines APU&lt;/td>
&lt;td style="text-align:right">50%&lt;/td>
&lt;td style="text-align:right">47%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">PF&lt;/td>
&lt;td style="text-align:left">Ryzen 2600X&lt;/td>
&lt;td style="text-align:right">25%&lt;/td>
&lt;td style="text-align:right">58%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">Jool&lt;/td>
&lt;td style="text-align:left">PCEngines APU&lt;/td>
&lt;td style="text-align:right">85%&lt;/td>
&lt;td style="text-align:right">88%&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">Jool&lt;/td>
&lt;td style="text-align:left">Ryzen 2600X&lt;/td>
&lt;td style="text-align:right">88%&lt;/td>
&lt;td style="text-align:right">86%&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="conclusion">Conclusion&lt;/h2>
&lt;p>While Tayga claims that it &amp;ldquo;can saturate gigabit Ethernet on modest PC hardware&amp;rdquo;,
this is clearly not the case for the &amp;lsquo;modest&amp;rsquo; PCEngines APU.
However, on a modern desktop CPU all solutions were able to attain performance
exceeding 1 Gbps.&lt;/p>
&lt;p>The clear winner in terms of performance is Jool,
which is able to achieve almost 90% line rate on both platforms.&lt;/p>
&lt;!-- raw HTML omitted -->
&lt;!-- raw HTML omitted --></content:encoded></item><item><title>PGP and DNS</title><link>https://slxh.nl/blog/2016/pgp-and-dns/</link><pubDate>Thu, 22 Dec 2016 17:33:07 +0100</pubDate><guid>https://slxh.nl/blog/2016/pgp-and-dns/</guid><description type="html">&lt;p>Recently, I looked at all the ways GnuPG can retrieve PGP keys from the internet to see which of these methods are actually useful.
This blog post describes a summary of my conclusions.&lt;/p></description><content:encoded>&lt;p>Recently, I looked at all the ways GnuPG can retrieve PGP keys from the internet to see which of these methods are actually useful.
This blog post describes a summary of my conclusions.&lt;/p>
&lt;p>GnuPG modern (2.1.16) can retrieve keys from the internet using the following mechanisms:&lt;/p>
&lt;ul>
&lt;li>&lt;code>cert&lt;/code>: a DNS CERT PGP record as defined in &lt;a href="https://www.rfc-editor.org/info/rfc4398">RFC-4398&lt;/a>&lt;/li>
&lt;li>&lt;code>pka&lt;/code>: a DNS CERT IPGP record, also defined in &lt;a href="https://www.rfc-editor.org/info/rfc4398">RFC-4398&lt;/a> &lt;em>or&lt;/em> a DNS TXT record,
depending on the version of GnuPG.
This uses an HTTP request to a location defined in the record to retrieve the key.&lt;/li>
&lt;li>&lt;code>dane&lt;/code>: a DNS OPENPGPKEY record, as defined in &lt;a href="https://www.rfc-editor.org/info/rfc7929">RFC-7929&lt;/a>.&lt;/li>
&lt;li>&lt;code>wkd&lt;/code>: via an HTTP GET to a file in the &lt;code>.well-known&lt;/code> (&lt;a href="https://tools.ietf.org/html/rfc5785">RFC-5785&lt;/a>) directory.
This is experimental and defined in &lt;a href="https://datatracker.ietf.org/doc/draft-koch-openpgp-webkey-service/">a RFC draft&lt;/a>.&lt;/li>
&lt;li>&lt;code>keyserver&lt;/code>: The common way to retrieve keys via &lt;em>keyservers&lt;/em>.&lt;/li>
&lt;/ul>
&lt;p>So next to the common way to retrieve keys (which I will not discuss) there are four other mechanisms:
two fully relying on DNS, one using a mix of DNS and HTTP(S) and one only using HTTP(S).&lt;/p>
&lt;p>For testing the DNS records I used a PowerDNS (4.0.1) server on a DNSSEC signed domain (which I recommend).
Note that DNSSEC is not required (not even for the DANE mechanism).&lt;/p>
&lt;h2 id="cert-record">CERT record&lt;/h2>
&lt;p>The CERT record is quite straightforward:
it is a data record in which one can place the base64 encoded information for a public key.
This data (which I will call &lt;code>[DATA]&lt;/code>) can be generated with:&lt;/p>
&lt;pre>&lt;code>gpg --export-options export-minimal --export F4DFA1D665C135D6 | base64 -w0
&lt;/code>&lt;/pre>
&lt;p>Which results in the same data as what is contained in an ASCII-armored key (except for line endings), which is formatted like:&lt;/p>
&lt;pre>&lt;code>-----BEGIN PGP PUBLIC KEY BLOCK-----
[DATA]
=[checksum]
-----END PGP PUBLIC KEY BLOCK-----
&lt;/code>&lt;/pre>&lt;p>The DNS record for the identity &lt;code>asdf at slxh.eu&lt;/code> looks like any the following:&lt;/p>
&lt;pre>&lt;code>asdf.slxh.eu. 86400 IN CERT PGP 0 0 [DATA]
&lt;/code>&lt;/pre>
&lt;p>Where &lt;code>PGP&lt;/code> can be replaced by the number &lt;code>3&lt;/code>.
This is required for PowerDNS.&lt;/p>
&lt;p>The record is quite straight forward and it works, but only for a single key:&lt;/p>
&lt;pre>&lt;code>$ gpg2 -v --auto-key-locate=clear,cert,local --locate-keys &amp;lt;address&amp;gt;
...
gpg: auto-key-locate found fingerprint 646B0F089DD5022CF5BA29F9F4DFA1D665C135D6
gpg: automatically retrieved '&amp;lt;address&amp;gt;' via DNS CERT
&lt;/code>&lt;/pre>
&lt;p>Pros:&lt;/p>
&lt;ul>
&lt;li>Easy to set up&lt;/li>
&lt;/ul>
&lt;p>Cons:&lt;/p>
&lt;ul>
&lt;li>Large record which needs to be transferred over TCP&lt;/li>
&lt;li>Not located at a nice place in the DNS&lt;/li>
&lt;li>Only retrieves public keys from a single record (but a single record can contain multiple keys)&lt;/li>
&lt;/ul>
&lt;h2 id="dane-openpgp-record">DANE: OPENPGP record&lt;/h2>
&lt;p>The &lt;code>dane&lt;/code> mechanism works in a similar way to CERT, but it uses a well-defined location.
The record looks like (see the CERT section for generating &lt;code>[DATA]&lt;/code>):&lt;/p>
&lt;pre>&lt;code>7a5b775b45836845e91cb23b59ed7ff45d1732c7aa8415952beeb7d2._openpgpkey.slxh.eu 86400 IN OPENPGPKEY [DATA]
&lt;/code>&lt;/pre>
&lt;p>The compatibility format can also be generated by &lt;code>gpg2&lt;/code>:&lt;/p>
&lt;pre>&lt;code>gpg --export-options export-dane --export F4DFA1D665C135D6
&lt;/code>&lt;/pre>
&lt;p>Which results in:&lt;/p>
&lt;pre>&lt;code>$ORIGIN _openpgpkey.slxh.eu.
7a5b775b45836845e91cb23b59ed7ff45d1732c7aa8415952beeb7d2 TYPE61 \# 1695 (
98330457e504ee16092b06010401da470f01010740752c0c3aa3bf6841a33076
...
34d3c8c4f8aaa94f53e10daff07633d2a3eea38dbd409d44d9600d9a755a0e
)
&lt;/code>&lt;/pre>
&lt;p>Pros:&lt;/p>
&lt;ul>
&lt;li>Easy to setup with software that accepts the output of &lt;code>gpg2&lt;/code>&lt;/li>
&lt;li>Well defined location&lt;/li>
&lt;/ul>
&lt;p>Cons:&lt;/p>
&lt;ul>
&lt;li>Large record which needs to be transferred over TCP&lt;/li>
&lt;li>Only retrieves public keys from a single record (but a single record can contain multiple keys)&lt;/li>
&lt;/ul>
&lt;h2 id="pka--public-key-association">PKA: Public Key Association&lt;/h2>
&lt;p>The PKA record in GnuPG 2.1.16 uses the CERT IPGP record to store the fingerprint of the public key and a location where the key can be retrieved.
The record has its own location and local part of the email address is hashed.
There is also &lt;a href="http://www.gushi.org/make-dns-cert/HOWTO.html">a TXT variant&lt;/a>, but GnuPG does not use this for lookups any more.&lt;/p>
&lt;p>GnuPG also has options for automatically doing lookups and increasing trust if the fingerprint matches on verification:&lt;/p>
&lt;pre>&lt;code>--verify-options parameters
...
pka-lookups
Enable PKA lookups to verify sender addresses. Note that PKA is based on DNS, and
so enabling this option may disclose information on when and what signatures are
verified or to whom data is encrypted. This is similar to the &amp;quot;web bug&amp;quot; described
for the --auto-key-retrieve option.
pka-trust-increase
Raise the trust in a signature to full if the signature passes PKA validation.
This option is only meaningful if pka-lookups is set.
&lt;/code>&lt;/pre>
&lt;p>GnuPG can also create the DNS record for you:&lt;/p>
&lt;pre>&lt;code>gpg --export-options export-pka --export F4DFA1D665C135D6
&lt;/code>&lt;/pre>
&lt;p>Which shows the required records for zone files:&lt;/p>
&lt;pre>&lt;code>$ORIGIN _pka.slxh.eu
yyjm39f54qomwmcejnmojaspwa86esqj TYPE37 \# 26 0006 0000 00 14 646B0F089DD5022CF5BA29F9F4DFA1D665C135D6
&lt;/code>&lt;/pre>
&lt;p>This output, however, is only for compatibility purposes and does not contain a URL for key retrieval.&lt;/p>
&lt;p>The actual format can be generated from this information (I have made &lt;a href="https://slxh.nl/blog/files/ipgp.sh">a script&lt;/a> that does just that).
The regular record looks like:&lt;/p>
&lt;pre>&lt;code>yyjm39f54qomwmcejnmojaspwa86esqj._pka.slxh.eu 3600 IN CERT 6 0 0 FGRrDwid1QIs9bop+fTfodZlwTXW
&lt;/code>&lt;/pre>
&lt;p>With a provided URL, in this case &lt;code>https://slxh.eu/keys/pgp/65C135D6&lt;/code>, it becomes:&lt;/p>
&lt;pre>&lt;code>yyjm39f54qomwmcejnmojaspwa86esqj._pka.slxh.eu 3600 IN CERT 6 0 0 FGRrDwid1QIs9bop+fTfodZlwTXWaHR0cHM6Ly9zbHhoLmV1L2tleXMvcGdwLzY1QzEzNUQ2
&lt;/code>&lt;/pre>
&lt;p>The &lt;code>6&lt;/code> may be replaced with &lt;code>IPGP&lt;/code>.&lt;/p>
&lt;p>The lookup of the fingerprint works.
The retrieval of the key, however, does not:
instead of using the provided URL it asks the server for a key with a specific URL (a PKS lookup),
resulting in a &lt;em>Page Not Found&lt;/em> error.
This means that &lt;code>gpg&lt;/code> does use the server specified in the record but ignores the URL,
resulting in &lt;code>gpg&lt;/code> claiming there are no keys to be retrieved.
A solution to this is to simply use a keyserver (like &lt;a href="https://sks-keyservers.net">https://sks-keyservers.net&lt;/a>) in the record.&lt;/p>
&lt;p>In my opinion this record is most useful for simply verifying the fingerprint,
in which case the URL is not needed.&lt;/p>
&lt;p>Pros:&lt;/p>
&lt;ul>
&lt;li>Easy to setup with software that accepts the output of &lt;code>gpg2&lt;/code>&lt;/li>
&lt;li>Can automatically improve trust&lt;/li>
&lt;li>Small DNS record&lt;/li>
&lt;li>Well defined location&lt;/li>
&lt;/ul>
&lt;p>Cons&lt;/p>
&lt;ul>
&lt;li>Does not retrieve the key from the specified location but from a keyserver instead.&lt;/li>
&lt;li>Only retrieves the key for a single record&lt;/li>
&lt;/ul>
&lt;h2 id="wkd-web-key-directory">WKD: Web Key Directory&lt;/h2>
&lt;p>The &lt;em>Web Key Directory&lt;/em> mechanism leverages the &lt;code>.well-known&lt;/code> directory to store keys.
Exporting to this location is relatively easy:&lt;/p>
&lt;pre>&lt;code>$ gpg2 --with-wkd-hash -k F4DFA1D665C135D6
pub ed25519/F4DFA1D665C135D6 2016-09-23 [SC] [expires: 2018-09-23]
646B0F089DD5022CF5BA29F9F4DFA1D665C135D6
uid [ full ] ...
yyjm39f54qomwmcejnmojaspwa86esqj@slxh.eu
...
$ gpg --export F4DFA1D665C135D6 &amp;gt; yyjm39f54qomwmcejnmojaspwa86esqj
&lt;/code>&lt;/pre>
&lt;p>Note that the key cannot be ASCII-armored.&lt;/p>
&lt;p>The created file (&lt;code>yyjm39f54qomwmcejnmojaspwa86esqj&lt;/code>) then needs to be placed on the webserver for slxh.eu, so that it is accessible at: &lt;a href="https://slxh.eu/.well-known/openpgpkey/hu/yyjm39f54qomwmcejnmojaspwa86esqj">https://slxh.eu/.well-known/openpgpkey/hu/yyjm39f54qomwmcejnmojaspwa86esqj&lt;/a>&lt;/p>
&lt;p>The export can contain multiple public keys,
but in that case &lt;code>gpg2&lt;/code> will throw an error (&lt;code>No fingerprint&lt;/code>) while still importing the keys.
Also: only the identities for which a lookup was done are imported.&lt;/p>
&lt;p>Pros:&lt;/p>
&lt;ul>
&lt;li>Easy to setup&lt;/li>
&lt;li>No cumbersome DNS record&lt;/li>
&lt;li>Well defined location&lt;/li>
&lt;/ul>
&lt;p>Cons&lt;/p>
&lt;ul>
&lt;li>Only retrieves the identity for which a lookup was done&lt;/li>
&lt;/ul>
&lt;h2 id="conclusion">Conclusion&lt;/h2>
&lt;p>All of the provided methods have drawbacks.
Here is what I recommend:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Primarily use WKD, it is easy to maintain and works the best.
Additional security can be provided by using DNSSEC and HTTPS (and DANE/TLSA).&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Use OPENPGPKEY over CERT PGP.
OPENPGPKEY does everything that CERT PGP does, but better.
Security is provided by DNSSEC.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Use PKA only for storing fingerprints.
Using it when verifying keys might be useful.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="update-2017-02-16">Update 2017-02-16&lt;/h2>
&lt;p>GnuPG 2.1.18 &lt;a href="https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=commit;h=88dc3af3d4ae1afe1d5e136bc4c38bc4e7d4cd10">added a DNS lookup to WKD&lt;/a> via a SRV record.
The given example is:&lt;/p>
&lt;pre>&lt;code>_openpgpkey._tcp IN SRV 0 0 0 wkd.foo.org.
IN SRV 0 0 0 wkd.example.net.
IN SRV 0 0 4711 wkd.example.org.
&lt;/code>&lt;/pre>&lt;p>Which would fetch from:&lt;/p>
&lt;pre>&lt;code>https://wkd.example.org:4711/.well-known/openpgpkey/submission-address
&lt;/code>&lt;/pre>
&lt;p>Explained as follows:&lt;/p>
&lt;blockquote>
&lt;p>Note that the first two &lt;code>SRV&lt;/code> records won&amp;rsquo;t be used because &lt;code>foo.org&lt;/code> and
&lt;code>example.net&lt;/code> do not match &lt;code>example.org&lt;/code>. We require that the target host
is identical to the domain or be a subdomain of it. This is so that
an attacker modifying the &lt;code>SRV&lt;/code> records needs to setup a server in a
sub-domain of the actual domain and can&amp;rsquo;t use an arbitrary domain.
Whether this is a sufficient requirement is not clear and needs
further discussion.&lt;/p>
&lt;/blockquote>
&lt;p>These changes add some flexibility to WKD lookups.
The requirement to have the server as subdomain makes sense,
but note that when an attacker has full control of the DNS this is circumvented without much hassle.&lt;/p></content:encoded></item><item><title>NAT64 for servers</title><link>https://slxh.nl/blog/2016/nat64-for-servers/</link><pubDate>Wed, 23 Nov 2016 16:06:17 +0100</pubDate><guid>https://slxh.nl/blog/2016/nat64-for-servers/</guid><description type="html">&lt;p>This post details the setup of the additional steps required to deploy a IPv6-only server bedind &lt;a href="https://en.wikipedia.org/wiki/NAT64">NAT64&lt;/a> with &lt;a href="http://www.litech.org/tayga/">Tayga&lt;/a>.&lt;/p></description><content:encoded>&lt;p>This post details the setup of the additional steps required to deploy a IPv6-only server bedind &lt;a href="https://en.wikipedia.org/wiki/NAT64">NAT64&lt;/a> with &lt;a href="http://www.litech.org/tayga/">Tayga&lt;/a>.&lt;/p>
&lt;p>This post uses the &lt;em>documentation prefix&lt;/em> (&lt;code>2001:db8::/32&lt;/code>),
replace this with your own prefix.
This can be a ULA prefix.&lt;/p>
&lt;p>The basis is explained in a post by &lt;a href="https://blog.luukhendriks.eu/2015/12/01/ipv6-only-network-at-home.html">Luuk Hendriks&lt;/a>.&lt;/p>
&lt;h2 id="goal">Goal&lt;/h2>
&lt;p>The goal is to reach an IPv6-only webserver behind a dual stack router.
This is done by using NAT64 on a third device to reach the server.&lt;/p>
&lt;pre>&lt;code> IPv4 IPv4
Internet ────── Router ────── Tayga
IPv6 │ │ IPv6
└────────── Server
IPv6
&lt;/code>&lt;/pre>&lt;p>In this case, the Router is an &lt;em>Edgerouter Lite&lt;/em> and
the Tayga and webserver are running on the same physical device in separate LXC containers.&lt;/p>
&lt;h2 id="unbound">Unbound&lt;/h2>
&lt;p>The main difference in the setup is that I use Unbound instead of PowerDNS.
The configuration is really simple, in &lt;code>/etc/unbound/unbound.conf.d/dns64.conf&lt;/code>:&lt;/p>
&lt;pre>&lt;code>server:
module-config: &amp;quot;dns64 validator iterator&amp;quot;
dns64-prefix: 2001:db8:64::/96
&lt;/code>&lt;/pre>&lt;h2 id="tayga">Tayga&lt;/h2>
&lt;p>For the two-way NAT, the Tayga configuration requires static-mappings:&lt;/p>
&lt;pre>&lt;code># Main config
tun-device nat64
prefix 2001:db8:64::/96
ipv4-addr 10.64.0.1
dynamic-pool 10.64.0.0/24
data-dir /var/spool/tayga
# Static mappings
map 10.64.0.10 2001:db8::10 # Server 1
map 10.64.0.11 2001:db8::11 # Server 2
&lt;/code>&lt;/pre>&lt;p>I have used a subnet (&lt;code>2001:db8:64::/96&lt;/code>) above as prefix.
This allow access to local (RFC1918) IPv4 addresses through NAT64.
If this is not needed, use the &lt;em>Well-Known Prefix&lt;/em>: &lt;code>64:ff9b::/96&lt;/code>.&lt;/p>
&lt;p>The mapping is simple: create an IPv4 address inside the &lt;em>dynamic pool&lt;/em> and map that to the IPv6 address that needs to be reached.&lt;/p>
&lt;h2 id="route">Route&lt;/h2>
&lt;p>In a regular setup, the IPv4 range is only required internally on the host running Tayga.
For this setup, however, the &lt;code>10.64.0.0/24&lt;/code> range needs to be routed to the device running Tayga.&lt;/p>
&lt;p>Just like the &lt;a href="https://blog.luukhendriks.eu/2015/12/01/ipv6-only-network-at-home.html">linked post&lt;/a>, I use an Edgerouter.
The following route needs to be added:&lt;/p>
&lt;pre>&lt;code>set protocols static route 10.64.0.0/24 next-hop 10.0.0.64 distance 1
&lt;/code>&lt;/pre>&lt;p>Where &lt;code>10.0.0.64&lt;/code> is the IPv4 address of the device running Tayga.&lt;/p>
&lt;p>After this route is setup, it should be possible to ping the devices mapped in Tayga.&lt;/p>
&lt;h2 id="port-forwards">Port forwards&lt;/h2>
&lt;p>If the mappings work, it should now be possible to forward ports to the mapped addresses.
For a webserver this would be:&lt;/p>
&lt;pre>&lt;code>edit port-forward rule 10
set description &amp;quot;HTTP(S)&amp;quot;
set forward-to address 10.64.0.10
set original-port 80,443
set protocol tcp
&lt;/code>&lt;/pre>&lt;p>If everything went well the webserver should now be reachable from the IPv4-WAN address,
while only having an IPv6 address.&lt;/p>
&lt;h2 id="final-notes">Final notes&lt;/h2>
&lt;p>I have not noticed any drawbacks to this setup except for performance.
The results of some measurements from a computer in my network to the server show that the NAT transition has a performance of about 250 Mbps.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>From&lt;/th>
&lt;th>To&lt;/th>
&lt;th>(Mbps)&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;/td>
&lt;td>IPv4&lt;/td>
&lt;td>IPv6&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>IPv4&lt;/td>
&lt;td>927&lt;/td>
&lt;td>252&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>IPv6&lt;/td>
&lt;td>199&lt;/td>
&lt;td>918&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>This means that the main bottleneck is the performance of Tayga,
though this only matters with internet connections faster than 250 Mbps.&lt;/p></content:encoded></item><item><title>X.509 IPsec on EdgeOS</title><link>https://slxh.nl/blog/2015/x.509-ipsec-on-edgeos/</link><pubDate>Thu, 31 Dec 2015 13:13:50 +0100</pubDate><guid>https://slxh.nl/blog/2015/x.509-ipsec-on-edgeos/</guid><description type="html">&lt;p>Configuring X.509 based IPsec on an Edgerouter running EdgeOS.&lt;/p></description><content:encoded>&lt;p>Configuring X.509 based IPsec on an Edgerouter running EdgeOS.&lt;/p>
&lt;h2 id="preparation">Preparation&lt;/h2>
&lt;p>Create a directory in &lt;code>/config&lt;/code> for persistent storage of the certificates.
Eg:&lt;/p>
&lt;pre>&lt;code>mkdir /config/ipsec
cd /config/ipsec
&lt;/code>&lt;/pre>
&lt;h2 id="generation-of-certificates">Generation of Certificates&lt;/h2>
&lt;p>For IPsec to work reliably, you need three certificate files:&lt;/p>
&lt;ul>
&lt;li>CA-certificate: &lt;code>ca.crt&lt;/code>, obtain this from your CA.&lt;/li>
&lt;li>Server certificate: &lt;code>server.crt&lt;/code>&lt;/li>
&lt;li>Server private key: &lt;code>server.key&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>Running a CA is outside of the scope of this document,
though a script (&lt;code>/usr/lib/ssl/misc/CA.sh&lt;/code>) is provided to make it very easy.
There are &lt;a href="https://blog.laslabs.com/2013/06/configure-openvpn-with-x-509-ubiquiti-edgerouter-lite/">other blog posts&lt;/a> documenting this.
Personally, I prefer to use the &lt;code>openssl&lt;/code> commands directly.
I also advise to run the following as root (&lt;code>sudo -i&lt;/code>).&lt;/p>
&lt;p>First, generate a &lt;em>certificate signing request&lt;/em> (CSR) for the CA to sign,
replace the subject with your own values:&lt;/p>
&lt;pre>&lt;code>openssl req -new -newkey 4096 -nodes -out server.csr \
-keyout server.pem \
-subj &amp;quot;/C=NL/ST=/L=/O=SLXH/CN=ipsec.slxh.nl&amp;quot;
&lt;/code>&lt;/pre>
&lt;p>This private key needs to be converted to a RSA private key
for the IPsec daemon on EdgeOS:&lt;/p>
&lt;pre>&lt;code>openssl rsa -in server.pem -out server.key
&lt;/code>&lt;/pre>
&lt;p>Change the permissions on the files:&lt;/p>
&lt;pre>&lt;code>chmod u=r,go= server.pem server.key
chown root: server.pem server.key
&lt;/code>&lt;/pre>
&lt;p>This CSR can now be signed by your CA.
After you get the signed certificate, place in next to the private keys.&lt;/p>
&lt;h2 id="ipsec-on-edgeos">IPsec on EdgeOS&lt;/h2>
&lt;p>Follow the instructions provided &lt;a href="https://help.ubnt.com/hc/en-us/articles/204959404-EdgeMAX-Set-up-L2TP-over-IPsec-VPN-server">by Ubiquiti&lt;/a> or the ones found &lt;a href="https://community.ubnt.com/t5/EdgeMAX/Edgemax-L2TP-Server-Setup-For-Client-Use/td-p/891812">on their forum&lt;/a>,
with the following exceptions:&lt;/p>
&lt;pre>&lt;code>set vpn l2tp remote-access ipsec-settings authentication mode x509
set vpn l2tp remote-access ipsec-settings authentication x509 ca-cert-file /config/ipsec/ca.crt
set vpn l2tp remote-access ipsec-settings authentication x509 server-cert-file /config/ipsec/server.crt
set vpn l2tp remote-access ipsec-settings authentication x509 server-key-file /config/ipsec/server.key
&lt;/code>&lt;/pre>
&lt;p>Adding a certificate revocation list (CRL) is optional, but advised:&lt;/p>
&lt;pre>&lt;code>set vpn l2tp remote-access ipsec-settings authentication x509 crl-file /config/ipsec/ca.crl
&lt;/code>&lt;/pre>
&lt;p>Commit and save:&lt;/p>
&lt;pre>&lt;code>commit
save
&lt;/code>&lt;/pre>
&lt;h2 id="firewall">Firewall&lt;/h2>
&lt;p>Again, follow the instructions provided &lt;a href="https://help.ubnt.com/hc/en-us/articles/204959404-EdgeMAX-Set-up-L2TP-over-IPsec-VPN-server">by Ubiquiti&lt;/a>.
It can also be configured in the CLI (check the rule numbers first):&lt;/p>
&lt;pre>&lt;code>edit firewall name WAN_LOCAL rule 23
set action accept
set description &amp;quot;L2TP/IPsec&amp;quot;
set destination port isakmp,l2f,4500
set protocol udp
exit
edit firewall name WAN_LOCAL rule 24
set action accept
set description &amp;quot;ESP (IPsec)&amp;quot;
set protocol esp
commit
save
&lt;/code>&lt;/pre>
&lt;p>IPsec should now be working.&lt;/p></content:encoded></item></channel></rss>