1
0
Fork 0
You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
blog/output/forgetting-dns6.html

376 lines
19 KiB
HTML

1 year ago
<!doctype html>
<html>
<head>
<meta charset=utf-8>
<meta name=generator content="Pelican 4.9.1">
1 year ago
<meta name=author content="LEdoian">
<meta name=description content="My personal webpage">
<meta name=referrer content=no-referrer>
10 months ago
<link rel=stylesheet href="./theme/css/theme.css">
1 year ago
<title>Do not forget about IPv6 DNS LEdoian's Blog</title>
</head>
<body>
<header>
<h1>LEdoian's Blog</h1>
</header>
<div id=main>
<nav>
<div>
<!-- Main navigation -->
<!-- TODO! -->
</div>
<div>
<h2>Categories</h2>
<ul>
10 months ago
<li><a href="./category/networking.html">networking</a></li>
9 months ago
<li><a href="./category/queer.html">queer</a></li>
10 months ago
<li><a href="./category/talks.html">talks</a></li>
<li><a href="./category/technology.html">technology</a></li>
9 months ago
<li><a href="./category/til.html">til</a></li>
1 year ago
</ul>
<h2>Tags</h2>
<ul>
6 months ago
<li><a href="./tag/gender.html">gender</a></li>
<li><a href="./tag/identity.html">identity</a></li>
<li><a href="./tag/linux.html">linux</a></li>
7 months ago
<li><a href="./tag/lifehack.html">lifehack</a></li>
<li><a href="./tag/software.html">software</a></li>
9 months ago
<li><a href="./tag/relationships.html">relationships</a></li>
9 months ago
<li><a href="./tag/print.html">print</a></li>
9 months ago
<li><a href="./tag/comics.html">comics</a></li>
10 months ago
<li><a href="./tag/ipv6-only.html">ipv6-only</a></li>
<li><a href="./tag/dns.html">dns</a></li>
<li><a href="./tag/meta.html">meta</a></li>
<li><a href="./tag/infrastructure.html">infrastructure</a></li>
<li><a href="./tag/smrst.html">smršť</a></li>
<li><a href="./tag/trains.html">trains</a></li>
<li><a href="./tag/software-engineering.html">software-engineering</a></li>
1 year ago
</ul>
</div>
<div>
<h2>Stalk me also at</h2>
TODO!
<h2>I stalk</h2>
TODO!
</nav>
<main>
<div>
6 months ago
<div class="details"><time datetime="2024-01-24T03:20:00+01:00">2024-01-24 03:20</time></div>
1 year ago
<h1>Do not forget about IPv6 DNS</h1>
<p>Do you think IPv6-only internet works OK? I am going to tell you that it does
not, but it is not immediately visible. TL;DR: The internet can be broken also
by forgetting to add AAAA records of the <em>nameservers</em>. This creates IPv4
requirement for the resolving even when the target is reachable using IPv6.</p>
<div class="section" id="quick-recap">
<h2>Quick recap</h2>
<p>Connecting to a website is easy, right? You type in the name, you get the front page.</p>
<div class="figure">
10 months ago
<object data="./images/forgetting-dns6/image1.svg" style="width: 50%;" type="image/svg+xml"></object>
1 year ago
<p class="caption">This is a very naïve idea of connecting to a server.</p>
</div>
<p>OK, it is a bit harder: the computer needs an IP address, so we need to use
this magic box called DNS. The flow looks something like this:</p>
<div class="figure">
10 months ago
<object data="./images/forgetting-dns6/image2.svg" style="width: 50%;" type="image/svg+xml"></object>
1 year ago
<p class="caption">Slightly better, now we at least know the machine-readable address.</p>
</div>
1 year ago
<p>And for IPv6-only everything on the picture has to have IPv6 connectivity and AAAA DNS records.</p>
1 year ago
<div class="section" id="reaching-ipv4-land-from-ipv6-only">
<h3>Reaching IPv4 land from IPv6-only</h3>
1 year ago
<p>There are few^H^H^Hmany sites that still only support IPv4. To reach them, we
need someone who can reach both the IPv4- and IPv6-land to go there on our
behalf a proxy. This proxy can be ad-hoc (I often use <tt class="docutils literal">ssh <span class="pre">-D</span></tt>) or there
1 year ago
are well-known protocols like NAT64 with DNS64 to do that in a standard and
lightweight manner. <a class="footnote-reference" href="#nat44" id="footnote-reference-1">[1]</a>
In that case, the connection looks like this:</p>
<div class="figure">
10 months ago
<object data="./images/forgetting-dns6/image3.svg" style="width: 100%;" type="image/svg+xml"></object>
1 year ago
<p class="caption">And now we can reach the whole internet.</p>
</div>
<p>You might already know that you need some workaround like this to reach GitHub.
1 year ago
What I think you might not know, you need similar workaround to reach the Wikipedia.</p>
<p>Disclaimer: I like Wikipedia and this is not meant to shame them, just use as
an example. I am aware of several other sites suffering from the same problem,
including at least one IPv6 test. <a class="footnote-reference" href="#test-aaaa" id="footnote-reference-2">[2]</a> (It would be nice if they added
the missing piece in the puzzle, though.)</p>
1 year ago
</div>
</div>
<div class="section" id="enter-dns">
<h2>Enter DNS</h2>
<p>Our picture has one unexplored magic box: the DNS. As per the definition (which
I just made up and was not bothered to even fully formulate):</p>
10 months ago
<blockquote>
yada yada distributed database of records attached to the strings domain
names. The records hold various information about the domain depending on the type.</blockquote>
1 year ago
<p>There are three interesting types of records: A records give IPv4 addresses,
1 year ago
AAAA give IPv6 addresses and NS give names of servers who know about the
1 year ago
particular subtree of the database. And to actually resolve the final AAAA
1 year ago
record the (recursive) resolver starts at the <em>root zone</em> and tries to find
1 year ago
the answer. <a class="footnote-reference" href="#dns-simplification" id="footnote-reference-3">[3]</a> The resolution algorithm can be visualised like this:</p>
<div class="figure">
10 months ago
<object data="./images/forgetting-dns6/image4.svg" style="width: 100%;" type="image/svg+xml"></object>
1 year ago
<p class="caption">Yeah, it's a mess.</p>
</div>
<p>There is one extra tricky bit: the NS records contain <em>names</em>, not addresses,
1 year ago
so when resolving we need <em>two</em> queries for each layer (very simplified):
1 year ago
first we ask for the final domain (<tt class="docutils literal">blog.ledoian.cz</tt>) and get a NS record
(when the server does not have the answer) and then we need to ask for the A or
AAAA record of the name from that record, so that we can connect to the server
10 months ago
mentioned in the NS record. (This allows a nameserver to be made redundant
and/or reside on other types of network.)</p>
1 year ago
<p>You might start to see the issue. When the DNS was just a black box, we could
paint the whole picture green and call it a day. And from the regular user's
point of view, that is the case, just use some public DNS like 1.1.1.1, 8.8.8.8
or 9.9.9.9. Oh, right, I meant these easy-to-remember addresses:
2606:4700:4700::1111, 2001:4860:4860::8888 and 2620:fe::fe, respectively. The
1 year ago
point is, they will give you the answer because they are dual-stack, not IPv6-only.</p>
1 year ago
<p>In a way, those servers (or other dual-stack resolvers) act like another proxy,
similar to the SSH, NAT64 and NAT44 ones mentioned earlier. This may not be
much of a problem for many people. But if you have any reason to use your own
recursive DNS server (privacy reasons, DNSSEC validation, ISP provides bad
service, you are the ISP, …) <em>inside</em> an IPv6-only network, you <em>will</em> have
issues. <a class="footnote-reference" href="#dns-behind-nat64" id="footnote-reference-4">[4]</a></p>
</div>
<div class="section" id="example-wikipedia">
<h2>Example: Wikipedia</h2>
<p>Let's now see this in action. You know Wikipedia, right? And you can reach
Wikipedia on IPv6, right? It has an AAAA record (don't mind the CNAME, that
means that the server is really called some other way):</p>
<pre class="literal-block">
$ dig en.wikipedia.org AAAA
[…]
en.wikipedia.org. 18737 IN CNAME dyna.wikimedia.org.
dyna.wikimedia.org. 323 IN AAAA 2a02:ec80:600:ed1a::1
</pre>
<p>And this record does work:</p>
<pre class="literal-block">
$ ncat --ssl 2a02:ec80:600:ed1a::1 443 &lt;&lt;GO
GET /wiki/Main_Page HTTP/1.1
Host: en.wikipedia.org
GO
HTTP/1.1 200 OK
[…]
content-language: en
content-type: text/html; charset=UTF-8
content-length: 98078
&lt;!DOCTYPE html&gt;
[…]
</pre>
<p>But we can dig deeper: let's see what servers we are really asking:</p>
<pre class="literal-block">
$ dig en.wikipedia.org AAAA +trace
; &lt;&lt;&gt;&gt; DiG … &lt;&lt;&gt;&gt; en.wikipedia.org AAAA +trace
;; global options: +cmd
. 78918 IN NS e.root-servers.net.
. 78918 IN NS f.root-servers.net.
. 78918 IN NS g.root-servers.net.
. 78918 IN NS h.root-servers.net.
. 78918 IN NS i.root-servers.net.
. 78918 IN NS j.root-servers.net.
. 78918 IN NS k.root-servers.net.
. 78918 IN NS l.root-servers.net.
. 78918 IN NS m.root-servers.net.
. 78918 IN NS a.root-servers.net.
. 78918 IN NS b.root-servers.net.
. 78918 IN NS c.root-servers.net.
. 78918 IN NS d.root-servers.net.
;; Received 525 bytes from … in 0 ms
org. 172800 IN NS c0.org.afilias-nst.info.
org. 172800 IN NS a2.org.afilias-nst.info.
org. 172800 IN NS a0.org.afilias-nst.info.
org. 172800 IN NS b0.org.afilias-nst.org.
org. 172800 IN NS b2.org.afilias-nst.org.
org. 172800 IN NS d0.org.afilias-nst.org.
;; Received 788 bytes from 202.12.27.33#53(m.root-servers.net) in 24 ms
wikipedia.org. 3600 IN NS ns0.wikimedia.org.
wikipedia.org. 3600 IN NS ns1.wikimedia.org.
wikipedia.org. 3600 IN NS ns2.wikimedia.org.
;; Received 658 bytes from 2001:500:48::1#53(b2.org.afilias-nst.org) in 20 ms
en.wikipedia.org. 86400 IN CNAME dyna.wikimedia.org.
;; Received 94 bytes from 208.80.153.231#53(ns1.wikimedia.org) in 132 ms
</pre>
<p>Hey, there are IPv4 addresses in there! I know, this is cheating, the output is
1 year ago
from a dual-stack machine. But we can still simulate IPv6-only resolution
1 year ago
by adding <tt class="docutils literal"><span class="pre">-6</span></tt> flag:</p>
<pre class="literal-block">
$ dig en.wikipedia.org AAAA +trace -6
; &lt;&lt;&gt;&gt; DiG … &lt;&lt;&gt;&gt; en.wikipedia.org AAAA +trace -6
;; global options: +cmd
. 78915 IN NS d.root-servers.net.
. 78915 IN NS e.root-servers.net.
. 78915 IN NS f.root-servers.net.
. 78915 IN NS g.root-servers.net.
. 78915 IN NS h.root-servers.net.
. 78915 IN NS i.root-servers.net.
. 78915 IN NS j.root-servers.net.
. 78915 IN NS k.root-servers.net.
. 78915 IN NS l.root-servers.net.
. 78915 IN NS m.root-servers.net.
. 78915 IN NS a.root-servers.net.
. 78915 IN NS b.root-servers.net.
. 78915 IN NS c.root-servers.net.
;; Received 525 bytes from … in 0 ms
org. 172800 IN NS d0.org.afilias-nst.org.
org. 172800 IN NS c0.org.afilias-nst.info.
org. 172800 IN NS b2.org.afilias-nst.org.
org. 172800 IN NS a0.org.afilias-nst.info.
org. 172800 IN NS b0.org.afilias-nst.org.
org. 172800 IN NS a2.org.afilias-nst.info.
;; Received 816 bytes from 2001:500:2::c#53(c.root-servers.net) in 8 ms
wikipedia.org. 3600 IN NS ns0.wikimedia.org.
wikipedia.org. 3600 IN NS ns1.wikimedia.org.
wikipedia.org. 3600 IN NS ns2.wikimedia.org.
couldn't get address for 'ns0.wikimedia.org': not found
couldn't get address for 'ns1.wikimedia.org': not found
couldn't get address for 'ns2.wikimedia.org': not found
dig: couldn't get address for 'ns0.wikimedia.org': no more
</pre>
<p>Some of those IPv4 addresses were benign the respective servers are reachable
1 year ago
both using IPv4 and IPv6 address or there is an alternative server that is
1 year ago
reachable using IPv6. That is the case for the root nameserver in the second
case, we used C, which has IPv6 address (2001:500:2::c). In fact, the M server
also has IPv6 address, but dig chose the IPv4 one (it should not matter):</p>
<pre class="literal-block">
$ dig m.root-servers.net AAAA
[…]
m.root-servers.net. 77991 IN AAAA 2001:dc3::35
</pre>
<p>But the latter case is the bigger issue. For the domain <tt class="docutils literal">wikipedia.org</tt> there
are three nameservers:</p>
<pre class="literal-block">
$ dig wikipedia.org NS -6
[…]
wikipedia.org. 86400 IN NS ns0.wikimedia.org.
wikipedia.org. 86400 IN NS ns1.wikimedia.org.
wikipedia.org. 86400 IN NS ns2.wikimedia.org.
</pre>
1 year ago
<p>This is the last answer that we could get on an IPv6-only network, because none of
these three servers has AAAA record (some of them may have IPv6 address unknown to us):</p>
1 year ago
<pre class="literal-block">
$ dig ns0.wikimedia.org AAAA
[…]
;; Got answer:
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 59468
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
</pre>
<p>The NOERROR status says the domain name exists, but we got zero answers for
AAAA records. This is the case for all three nameservers. And here is the
ultimate picture of what is happening and what goes wrong.</p>
<div class="figure">
10 months ago
<object data="./images/forgetting-dns6/image5.svg" style="width: 100%;" type="image/svg+xml"></object>
1 year ago
<p class="caption">The breakage in action</p>
</div>
<p>Also note that the connection from the laptop to the DNS resolver may in fact
consist of a chain of several (caching, non-recursive) DNS resolvers, so that
the final DNS resolver can have dual-stack connectivity.</p>
</div>
<div class="section" id="the-problems-with-this-state">
<h2>The problems with this state</h2>
<p>So, what is the deal. We <em>just</em> need to have a dual-stack DNS resolver
1 year ago
somewhere, and that's it, no? Well, yes but actually yes.</p>
1 year ago
<p>There are two problems with this: First, this means that any new ISP needs to
have <em>at least some</em> IPv4 address, even if they intend to just use IPv6
services. IPv4 addresses are scarce, <a class="reference external" href="https://blog.apnic.net/2021/12/16/opinion-ipv4-address-markets/">expensive</a> and small
blocks <a class="reference external" href="https://labs.ripe.net/author/stephen_strowes/visibility-of-ipv4-and-ipv6-prefix-lengths-in-2019/">don't route well</a>,
which is not great both from the
new ISP's and from overal routing's point of view. It also hinders IPv6
deployment and postpones IPv4 abandonment, needlessly.</p>
<p>The second issue is that this is not very visible. We are building IPv6 world,
1 year ago
but deep inside it still relies on IPv4, which might lead to great surprise
1 year ago
when we start cutting off IPv4 internet. And it might lead to false sense of
having IPv6 deployed, which is not true to the whole extent.</p>
<p>Insert &quot;It was DNS&quot; meme here.</p>
</div>
<div class="section" id="solution">
<h2>Solution</h2>
<p>The solution of this state is simple: get IPv6 connectivity to your
authoritative DNS server (or use another) and do not forget to add an AAAA
1 year ago
record for it in DNS. If the DNS server already has IPv6 it is probably just
a matter of adding a single line to the zone file (and a second one for the DNSSEC
1 year ago
signature), which should not be a big deal.</p>
<p>Unfortunately, this needs to be done for the whole DNS chain.
Especially domain names at universities are infamous for very nested domains.
1 year ago
A domain name may look like
1 year ago
<tt class="docutils literal"><span class="pre">machine.department.location.faculty.university.some-common.suffix</span></tt>. That
1 year ago
tree is deep and so is the resolution of this problem.</p>
1 year ago
</div>
<div class="section" id="amusing-bug-of-almost-good-deployment">
<h2>Amusing bug of almost good deployment</h2>
1 year ago
<p>We have seen there may be multiple NS records for a domain and thus
1 year ago
multiple nameservers. This is good for redundancy. But this does not mean that
the servers will have the same records they are only supposed to give
10 months ago
equivalent answers (as far as I know).</p>
1 year ago
<p>I have come across a silly misconfiguration: a domain which has several
nameservers, which serve a <em>slightly</em> different set of NS records for its
subdomain. Specifically, the servers which were only reachable using IPv4 were
<em>exactly</em> the servers that knew about one additional nameserver for the
subdomain, which, incidentally, was the <em>only</em> one that was IPv6-capable.</p>
<p>So, while all the correct records were present in DNS (somewhat/somewhere), this still
1 year ago
meant that IPv6-only resolution was doomed to fail because the IPv6 nameserver
10 months ago
chain was broken. (This has already been fixed.)</p>
1 year ago
<hr class="docutils" />
<table class="docutils footnote" frame="void" id="nat44" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#footnote-reference-1">[1]</a></td><td>This is very much the same as when you try to reach the
IPv4-public-land from IPv4-private-land, that is, from a private range of IP
1 year ago
addresses. This is called either just NAT, or NAT44 to denote IPv4-to-IPv4 NAT.</td></tr>
1 year ago
</tbody>
</table>
<table class="docutils footnote" frame="void" id="test-aaaa" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#footnote-reference-2">[2]</a></td><td>There are several more tests that do not even have the AAAA
record, lol.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="dns-simplification" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
1 year ago
<tr><td class="label"><a class="fn-backref" href="#footnote-reference-3">[3]</a></td><td>In my example, there is a single recursive DNS
resolver external to my machine in order not to complicate it too much.
The real deployment is often trickier.</td></tr>
1 year ago
</tbody>
</table>
<table class="docutils footnote" frame="void" id="dns-behind-nat64" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#footnote-reference-4">[4]</a></td><td>I have not yet tried to run a recursive DNS in a network
with DNS64 and NAT64. Could be fun :-D My wild guess is that I would need
CLAT (i.e. the full 464XLAT deployment) to make that work, since the
resolver is connecting directly to IPv4 addresses and would need to learn to
use NAT64 to resolve them. (The CLAT could be built right into the resolver,
though).</td></tr>
</tbody>
</table>
</div>
</div>
</main>
</div> <!-- #main -->
<footer>
<hr>
Written using Pelican 4.9.1 by LEdoian.
1 year ago
</footer>
</body>
</html>