<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="/feeds.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:base="https://chameth.com/">
    <title>Chameth.com - posts like break-everything-fuzz-testing, ipv6-docker-routing but not debugging-beyond-the-debugger, finding-an-awkward-bug-with-claude-code, why-you-should-be-using-https</title>
    <subtitle>Personal homepage of Chris Smith</subtitle>
    <link href="https://chameth.com/feeds/posts/like/break-everything-fuzz-testing,ipv6-docker-routing/unlike/debugging-beyond-the-debugger,finding-an-awkward-bug-with-claude-code,why-you-should-be-using-https/" rel="self"/>
    <link href="https://chameth.com/"/>
    <icon>https://chameth.com/favicon.png</icon>
    <updated>2026-01-29T00:00:00Z</updated>
    <id>https://chameth.com/</id>
    <author>
        <name>Chris Smith</name>
    </author>
    <entry>
        <title>An interesting Tailscale + Docker gotcha</title>
        <link href="https://chameth.com/tailscale-docker-gotcha/"/>
        <updated>2026-01-29T00:00:00Z</updated>
        <id>https://chameth.com/tailscale-docker-gotcha/</id>
        <content xml:lang="en" type="html">&lt;p&gt;As I’ve &lt;a href=&#34;https://chameth.com/how-i-use-tailscale/&#34;&gt;written&lt;/a&gt; &lt;a href=&#34;https://chameth.com/avoiding-the-consequences-of-dumb-laws-with-tailscale/&#34;&gt;about&lt;/a&gt; &lt;a href=&#34;https://chameth.com/exposing-game-servers-over-tailscale/&#34;&gt;before&lt;/a&gt;, I use &lt;a href=&#34;https://tailscale.com/&#34;&gt;Tailscale&lt;/a&gt; for a lot of things. I thought I had it set up in a reasonably secure manner, but I recently noticed a problem.&lt;/p&gt;
&lt;p&gt;I use Tailscale’s ACLs to limit what each node can access, based on the tags I apply to it. So an &lt;code&gt;app&lt;/code&gt; node can’t access anything via Tailscale, while an &lt;code&gt;integration&lt;/code&gt; or &lt;code&gt;server&lt;/code&gt; node can access things tagged with either &lt;code&gt;app&lt;/code&gt; or &lt;code&gt;integration&lt;/code&gt;. This is expressed pretty simply in the Tailscale ACL JSON:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;tagOwners&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-c1&#34;&gt;// Servers that can be SSH&amp;#39;d into
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;tag:server&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-c1&#34;&gt;// Applications that are exposed on tailscale but never connect out
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;tag:app&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-c1&#34;&gt;// Things which talk to other services over tailscale (connecting to apps etc)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;tag:integration&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;grants&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-c1&#34;&gt;// Users can access everything
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;src&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;autogroup:member&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;dst&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;*&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;ip&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;  &lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;*&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-c1&#34;&gt;// Servers and integrations can access integrations and apps
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;src&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;tag:server&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;tag:integration&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;dst&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;tag:integration&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;tag:app&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;ip&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;  &lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;*&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Over the past week I’ve been setting up a private &lt;a href=&#34;https://forgejo.org/&#34;&gt;Forgejo&lt;/a&gt; instance behind Tailscale, complete with an actions runner that runs things using a docker-in-docker container. I didn’t want the runner knowing anything about Tailscale, so I had it configured to speak to Forgejo direct over HTTP (&lt;code&gt;forgejo:3000&lt;/code&gt;) instead of using full Tailscale HTTPS URL that I use when accessing it (&lt;code&gt;http://git.example-net.ts.net/&lt;/code&gt;)&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a class=&#34;footnote-ref&#34; href=&#34;#fn:1&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Everything was going fine, until I forgot to do that translation… and it worked. My Forgejo action runners could access anything on my tailnet. I run several things on Tailscale that just have authentication turned off, on the basis that only authorised devices can access them. Things like the admin interface for this website. I definitely didn’t intend for any workflow I run on my git server to have access to edit my website!&lt;/p&gt;
&lt;p&gt;This wasn’t just limited to Forgejo, either. Any docker container I was running could access the tailnet. In hindsight it’s fairly obvious why: the host is running Tailscale, connected as a node tagged with my &lt;code&gt;server&lt;/code&gt; tag. That creates a &lt;code&gt;tailscale0&lt;/code&gt; interface, and automagically sets up iptables rules to route Tailscale traffic over the interface. Docker also automagically sets up iptables rules to bridge traffic, and apparently these two sets of rules interact in such a way that traffic from Docker containers is allowed to route via the &lt;code&gt;tailscale0&lt;/code&gt; interface.&lt;/p&gt;
&lt;p&gt;I say it’s fairly obvious in hindsight — there’s no reason why Docker would special case any particular host interface after all — but it still feels pretty surprising. Because both bits of software inject their own iptables rules, I never really had a good mental model for how they interact. The host Tailscale node was a completely separate building block to Docker. It would be a pain to use either of them if they didn’t do these rules, but it’s also one of the reasons I don’t really like “magical” things&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a class=&#34;footnote-ref&#34; href=&#34;#fn:2&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;There are lots of ways to fix this, but none of them feel particularly great. You can configure both Tailscale and Docker to not automatically fiddle with iptables and handle the rules yourself, but I really hate dealing with iptables&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a class=&#34;footnote-ref&#34; href=&#34;#fn:3&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;. As a stopgap I did hold my nose and add some iptables rules to drop traffic to the &lt;code&gt;tailscale0&lt;/code&gt; interface if it originated from the IP ranges that Docker was configured to use:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;iptables -I DOCKER-USER -s 192.168.0.0/16 -o tailscale0 -j DROP
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;iptables -I DOCKER-USER -s 172.17.0.0/12 -o tailscale0 -j DROP
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;DOCKER-USER&lt;/code&gt; chain is a nice little escape hatch; it comes before the main auto-generated &lt;code&gt;DOCKER&lt;/code&gt; chain, and Docker leaves the rules in it alone.&lt;/p&gt;
&lt;p&gt;So I added these rules, and felt pretty good about myself, and then… everything started breaking in weird ways. After some debugging I realised the problem was DNS&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a class=&#34;footnote-ref&#34; href=&#34;#fn:4&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;. The server’s DNS resolver is &lt;code&gt;100.100.100.100&lt;/code&gt;, a special Tailscale address. This is so that it can resolve tailnet hostnames via &lt;a href=&#34;https://tailscale.com/kb/1081/magicdns&#34;&gt;MagicDNS&lt;/a&gt; (and so I don’t have to configure my custom DNS servers manually on each device; Tailscale does it for me). My new iptables rules inadvertently dropped all the DNS packets coming from docker containers. D’oh.&lt;/p&gt;
&lt;p&gt;Obviously the solution here is to double down and add MORE iptables rules:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;iptables -I DOCKER-USER -s 192.168.0.0/16 -d 100.100.100.100 -o tailscale0 -j ACCEPT
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;iptables -I DOCKER-USER -s 172.17.0.0/12 -d 100.100.100.100 -o tailscale0 -j ACCEPT
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This got DNS working again, but it all feels a bit gross. Not least because to actually make these persist you need to use &lt;code&gt;iptables-save&lt;/code&gt;, and then you also get all the rules that both Docker and Tailscale have inserted. I came across &lt;a href=&#34;https://github.com/giangi/iptables-docker-filter&#34;&gt;a script&lt;/a&gt; to filter out the Docker ones, but… yuck&lt;sup id=&#34;fnref:5&#34;&gt;&lt;a class=&#34;footnote-ref&#34; href=&#34;#fn:5&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;I realised a cleaner idea might just be to lock down what &lt;code&gt;server&lt;/code&gt; tagged nodes could access within Tailscale itself. That way I can avoid touching iptables at all. It’s handy to be able to &lt;code&gt;curl&lt;/code&gt; services from the host when debugging, but it’s not really necessary. So I removed that access, and… stuff broke again. I’m using my Forgejo instance as a registry for some of the docker images I run, so the docker daemon needs to be able to reach it. I ended up making a new tag for &lt;code&gt;infrastructure&lt;/code&gt;, which can be accessed from &lt;code&gt;server&lt;/code&gt; devices. This does still allow all the docker containers to reach Forgejo, but I already have it set up with appropriate access controls and public/private repository splits. Forgejo is a service designed to run publicly, so this seems a reasonable trade-off for convenience. I used the &lt;code&gt;tests&lt;/code&gt; feature of Tailscale’s ACL config to make sure I’d got the rules right:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;tests&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-c1&#34;&gt;// Servers can only access infrastructure
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;src&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt;   &lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;tag:server&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;proto&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;tcp&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;allow&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;				&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;tag:infrastructure:8080&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-nt&#34;&gt;&amp;#34;deny&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;				&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;100.84.16.43:8080&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;				&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;me@example.com:8080&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;				&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;tag:server:8080&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;				&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;tag:app:8080&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;				&lt;span class=&#34;chroma-s2&#34;&gt;&amp;#34;tag:integration:8080&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The whole situation still feels a bit messy. If I ever get around to switching to nftables I might loop back and manually craft some rules for routing traffic, instead of leaving Tailscale and Docker to do their own thing.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr/&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;I discovered later on that logging into the container registry at &lt;code&gt;forgejo:3000&lt;/code&gt; actually issued a redirect to &lt;code&gt;https://git.example-net.ts.net/&lt;/code&gt; so this was all basically for naught… &lt;a class=&#34;footnote-backref&#34; href=&#34;#fnref:1&#34; role=&#34;doc-backlink&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;I didn’t use Tailscale’s MagicDNS for a long time just because the word “magic” put me off. Only when I eventually got around to learning how it worked, and seeing that it wasn’t really that magical under the hood, did I change my mind. &lt;a class=&#34;footnote-backref&#34; href=&#34;#fnref:2&#34; role=&#34;doc-backlink&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;nftables seems far better in lots of ways, but I can’t really be bothered migrating. Maybe next time I reimage the server for whatever reason… &lt;a class=&#34;footnote-backref&#34; href=&#34;#fnref:3&#34; role=&#34;doc-backlink&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34;&gt;
&lt;p&gt;It’s always DNS… &lt;a class=&#34;footnote-backref&#34; href=&#34;#fnref:4&#34; role=&#34;doc-backlink&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:5&#34;&gt;
&lt;p&gt;Again, nftables would almost certainly help here. It actually has (gasp) configuration files. But again, I really didn’t want to spend the time migrating. &lt;a class=&#34;footnote-backref&#34; href=&#34;#fnref:5&#34; role=&#34;doc-backlink&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</content>
    </entry>
    <entry>
        <title>Adventures in IPv6 routing in Docker</title>
        <link href="https://chameth.com/ipv6-docker-routing/"/>
        <updated>2022-10-24T00:00:00Z</updated>
        <id>https://chameth.com/ipv6-docker-routing/</id>
        <content xml:lang="en" type="html">&lt;p&gt;One of the biggest flaws in Docker’s design is that it wasn’t created with IPv6 in mind. Out of the box Docker assigns
each container a private IPv4 address, and they won’t be able to reach IPv6-only services. While incoming connections
might work, the containers won’t know the correct remote IP address which can cause problems for some applications.
This situation is obviously suboptimal in the current day and age. It’s a bit like not supporting HTTPS on a website —
you might not have any issues because of it immediately, but you’re fighting against the currents of progress and are
making life worse for your users.&lt;/p&gt;
&lt;p&gt;Thankfully, it’s now relatively easy to make Docker behave a lot nicer. The
&lt;a href=&#34;https://github.com/robbertkl/docker-ipv6nat&#34;&gt;docker-ipv6nat&lt;/a&gt; project has been around since 2016, and uses an IPv6
overlay network and some iptables magic to route traffic to and from containers in a sensible fashion. It uses NAT
to emulate the behaviour Docker employs for IPv4 traffic; while using NAT with IPv6 is an anathema, I think it makes
sense for containers. You could give each container a publicly routable IPv6 address, but that brings with it a lot
of headaches: you’re basically going to be forced to implement service discovery and some kind of DNS management to
deal with the fact that your containers will be popping up on randomly assigned IP addresses. That is completely
overkill for people running a small number of services on one or two physical boxes; and if it’s not overkill for you
then you’re probably already looking at more complicated orchestration solutions like Kubernetes.&lt;/p&gt;
&lt;p&gt;More recently, similar functionality has been built into the Docker daemon itself. You can now
&lt;a href=&#34;https://docs.docker.com/config/daemon/ipv6/&#34;&gt;edit the config file to enable ipv6&lt;/a&gt; and each container will be
assigned an address in the range specified when it uses the default bridge network. This gives more-or-less the same
functionality of docker-ipv6nat — you lose a little flexibility as you can’t disable IPv6 on the default bridge, but
that’s a very worthy trade for having the functionality built-in.&lt;/p&gt;
&lt;p&gt;So far this all seems very simple. Hardly worthy of being called an “adventure”. Enter stage left: the wicked witch of
destination address selection…&lt;/p&gt;
&lt;!--more--&gt;
&lt;h3 id=&#34;destination-address-selection-and-you&#34;&gt;Destination address selection and you&lt;/h3&gt;
&lt;p&gt;When a computer program tries to connect to an address such as &lt;code&gt;google.com&lt;/code&gt;, it first resolves it in to an IP address.
That’s DNS 101, but what happens if the address resolves to multiple IP addresses? For example, &lt;code&gt;google.com&lt;/code&gt; resolves
to both &lt;code&gt;142.250.74.206&lt;/code&gt; and &lt;code&gt;2a00:1450:4001:82b::200e&lt;/code&gt;. You might just assume there’s a simple
“prefer IPv4 / prefer IPv6” toggle somewhere that decides, but it’s actually a lot more complicated. With IPv6, devices
are likely to have many addresses - a link-local address, a unique local address, a normal public address, various
privacy addresses, and so on. To deal with this, a number of RFCs define a series of rules that most implementations
follow. These are called the &lt;em&gt;destination address selection rules&lt;/em&gt;. &lt;a href=&#34;https://www.rfc-editor.org/rfc/rfc6724&#34;&gt;RFC6724&lt;/a&gt;
gives the rules as:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Avoid unusable destinations&lt;/li&gt;
&lt;li&gt;Prefer matching scope&lt;/li&gt;
&lt;li&gt;Avoid deprecated addresses&lt;/li&gt;
&lt;li&gt;Prefer home addresses&lt;/li&gt;
&lt;li&gt;Prefer matching label&lt;/li&gt;
&lt;li&gt;Prefer higher precedence&lt;/li&gt;
&lt;li&gt;Prefer native transport&lt;/li&gt;
&lt;li&gt;Prefer smaller scope&lt;/li&gt;
&lt;li&gt;Use the longest matching prefix&lt;/li&gt;
&lt;li&gt;Otherwise, leave the order unchanged&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Applying these rules will re-order the list of IP addresses such that (in theory) the most likely one to work will be
first. Most of them are fairly niche rules; the ones that do the heavy lifting are rules 5 and 6, which rely on a policy
table to make their decisions. The policy table ‘SHOULD’ be configurable by system administrators to allow them to tweak
how traffic is routed. In the absence of an admin-provided policy table, the RFC gives the following defaults:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Prefix&lt;/th&gt;
&lt;th&gt;Precedence&lt;/th&gt;
&lt;th&gt;Label&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;::1/128&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;50&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;Loopback address&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;::/0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Any IPv6 address&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;::ffff:0:0/96&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;35&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;IPv4 addresses mapped as v6 addresses&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;2002::/16&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;6-to-4 gateways&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;2001::/32&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Toredo tunnels&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fc00::/7&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;Unique Local Addresses (ULAs)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;::/96&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;IPv4 compatible addresses (deprecated)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fec0::/10&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;Site-local addresses (deprecated)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;3ffe::/16&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;6bone (deprecated)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The policy table is a bit complex, but you can see that normal IPv6 addresses are preferred (have a higher precedence)
over IPv4 addresses, which are preferred over the various tunnels, local addresses, and various deprecated ranges.&lt;/p&gt;
&lt;p&gt;We can see the result of this when I run &lt;code&gt;ping google.com&lt;/code&gt; on a box that has a native IPv6 connection as well as a
native IPv4 connection:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;PING google.com(fra07s29-in-x200e.1e100.net (2a00:1450:4001:802::200e)) 56 data bytes
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;64 bytes from fra24s01-in-x0e.1e100.net (2a00:1450:4001:802::200e): icmp_seq=1 ttl=119 time=5.11 ms
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;64 bytes from fra24s01-in-x0e.1e100.net (2a00:1450:4001:802::200e): icmp_seq=2 ttl=119 time=5.28 ms
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;64 bytes from fra07s29-in-x200e.1e100.net (2a00:1450:4001:802::200e): icmp_seq=3 ttl=119 time=5.31 ms
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;^C
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;--- google.com ping statistics ---
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;3 packets transmitted, 3 received, 0% packet loss, time 2003ms
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;rtt min/avg/max/mdev = 5.114/5.235/5.311/0.086 ms
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The address selection in this instance has been a result of rule 6: the IPv6 address has a higher precedence (40) than
the IPv4 address (35).&lt;/p&gt;
&lt;p&gt;However, if I run the same command in an IPv6-enabled Ubuntu container then it seems to prefer the IPv4 address:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;PING google.com (172.217.16.206) 56(84) bytes of data.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;64 bytes from fra16s08-in-f206.1e100.net (172.217.16.206): icmp_seq=1 ttl=59 time=4.86 ms
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;64 bytes from fra16s08-in-f14.1e100.net (172.217.16.206): icmp_seq=2 ttl=59 time=4.86 ms
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;64 bytes from fra16s08-in-f14.1e100.net (172.217.16.206): icmp_seq=3 ttl=59 time=5.03 ms
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;^C
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;--- google.com ping statistics ---
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;3 packets transmitted, 3 received, 0% packet loss, time 2003ms
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;rtt min/avg/max/mdev = 4.860/4.916/5.027/0.078 ms
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If I force &lt;code&gt;ping&lt;/code&gt; to use IPv6 with the &lt;code&gt;-6&lt;/code&gt; flag then it works the same as on the host, but when left to its own devices
it prefers IPv4. What’s going on there? The key difference between the Docker container and the host is that the host’s
network interfaces have public addresses, but the container has a private IPv4 address (&lt;code&gt;172.19.0.7&lt;/code&gt;) and a private
IPv6 address (&lt;code&gt;fd00:dead:beef::7&lt;/code&gt;). My first reaction to this was to think “Ah yes, fc00::/7 has a lower precedence
than native IPv4, that makes sense”, but that’s not quite right. These are the &lt;em&gt;destination&lt;/em&gt; address selection rules;
rule 6 doesn’t care about the source addresses. This is actually rule 5 at work: the label of source IPv6 address is
&lt;code&gt;13&lt;/code&gt;, but the label of the destination address is &lt;code&gt;1&lt;/code&gt;; meanwhile both the source and destination IPv4 addresses are &lt;code&gt;4&lt;/code&gt;.
This sorts the IPv4 address before the IPv6 one, and rule 6 becomes irrelevant.&lt;/p&gt;
&lt;h3 id=&#34;adjusting-the-policy-table&#34;&gt;Adjusting the policy table&lt;/h3&gt;
&lt;p&gt;Thankfully, the RFC says the policy table should be configurable by system administrators, so those of us who are doing
unorthodox things like NAT’ing IPv6 can customise the behaviour to fit our weird environments. The configuration is
done via the &lt;a href=&#34;https://man.archlinux.org/man/gai.conf.5.en&#34;&gt;/etc/gai.conf&lt;/a&gt; file (‘gai’ standing for &lt;code&gt;getaddrinfo&lt;/code&gt;, the
function in the standard library responsible for dealing with all these rules). The &lt;code&gt;gai.conf&lt;/code&gt; file by default (if it
exists) will likely just contain comments and examples; if there are no uncommented “label” or “precedence” lines then
the library will use its built-in defaults based on the RFC requirements.&lt;/p&gt;
&lt;p&gt;To make our container happy, we need to cause &lt;code&gt;fd00::/8&lt;/code&gt; to have the same label as a public IPv6 address. To do this we
can uncomment the default labels in &lt;code&gt;gai.conf&lt;/code&gt; and then add a single extra line, like so:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt; label ::1/128       0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt; label ::/0          1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt; label 2002::/16     2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt; label ::/96         3
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt; label ::ffff:0:0/96 4
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt; label fec0::/10     5
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt; label fc00::/7      6
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt; label 2001:0::/32   7
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-gi&#34;&gt;+label fd00::/8      1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Because &lt;code&gt;fd00::/8&lt;/code&gt; has a longer prefix than &lt;code&gt;fc00::/7&lt;/code&gt; it will match our addresses and give them a label of &lt;code&gt;1&lt;/code&gt;, the
same as a public IPv6 address would get. This makes rule 5 leave it alone, and the default precedence table used by
the standard library will put the IPv6 address above the IPv4 address. (They don’t bother giving &lt;code&gt;fc00::/7&lt;/code&gt; a separate
precedence as listed in the RFC because rule 5 would have already de-prioritised those addresses, as we discovered.)&lt;/p&gt;
&lt;p&gt;Making this small change to the &lt;code&gt;gai.conf&lt;/code&gt; file in our Ubuntu container makes it start preferring the IPv6 address
for &lt;code&gt;google.com&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;PING google.com(fra16s65-in-x0e.1e100.net (2a00:1450:4001:806::200e)) 56 data bytes
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;64 bytes from fra15s29-in-x0e.1e100.net (2a00:1450:4001:806::200e): icmp_seq=1 ttl=118 time=5.00 ms
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;64 bytes from fra15s29-in-x0e.1e100.net (2a00:1450:4001:806::200e): icmp_seq=2 ttl=118 time=5.10 ms
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;64 bytes from fra16s65-in-x0e.1e100.net (2a00:1450:4001:806::200e): icmp_seq=3 ttl=118 time=5.08 ms
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;^C
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;--- google.com ping statistics ---
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;3 packets transmitted, 3 received, 0% packet loss, time 2004ms
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;rtt min/avg/max/mdev = 5.002/5.058/5.098/0.040 ms
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A fairly complicated problem, but a simple fix!&lt;/p&gt;
&lt;h3 id=&#34;but-wait-theres-more&#34;&gt;But wait, there’s more…&lt;/h3&gt;
&lt;p&gt;Unfortunately, this fix won’t work on containers that use alpine. And that is a &lt;em&gt;lot&lt;/em&gt; of containers. Alpine uses
&lt;a href=&#34;https://musl.libc.org/&#34;&gt;musl&lt;/a&gt; as its standard library, rather than the much more common
&lt;a href=&#34;https://www.gnu.org/software/libc/&#34;&gt;glibc&lt;/a&gt;. There is very little documentation on the subject, but if you browse
the source code for musl you will see that it doesn’t implement any way at all to configure the policy tables. In
&lt;a href=&#34;https://git.musl-libc.org/cgit/musl/tree/src/network/lookup_name.c?id=63402be229facae2d0de9c5943a6ed25246fd021&#34;&gt;network/lookup_name.c&lt;/a&gt;
we can see the sorting logic:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-cm&#34;&gt;/* The following implements a subset of RFC 3484/6724 destination
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-cm&#34;&gt;	 * address selection by generating a single 31-bit sort key for
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-cm&#34;&gt;	 * each address. Rules 3, 4, and 7 are omitted for having
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-cm&#34;&gt;	 * excessive runtime and code size cost and dubious benefit.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-cm&#34;&gt;	 * So far the label/precedence table cannot be customized. */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;cnt&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;family&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;buf&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;family&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;key&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;sockaddr_in6&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;sa6&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;da6&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sin6_family&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;AF_INET6&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sin6_scope_id&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;buf&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;scopeid&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sin6_port&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;65535&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;sockaddr_in&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;sa4&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;da4&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sin_family&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;AF_INET&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sin_port&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;65535&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sa&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;da&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-kt&#34;&gt;socklen_t&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;salen&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;dalen&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;family&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;AF_INET6&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-nf&#34;&gt;memcpy&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;da6&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sin6_addr&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;s6_addr&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;buf&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;addr&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;16&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-n&#34;&gt;da&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;da6&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;dalen&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-k&#34;&gt;sizeof&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;da6&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-n&#34;&gt;sa&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sa6&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;salen&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-k&#34;&gt;sizeof&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;sa6&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;chroma-k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-nf&#34;&gt;memcpy&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sa6&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sin6_addr&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;s6_addr&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;				&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-se&#34;&gt;\0\0\0\0\0\0\0\0\0\0\xff\xff&lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;12&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-nf&#34;&gt;memcpy&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;da6&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sin6_addr&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;s6_addr&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;12&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;buf&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;addr&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-nf&#34;&gt;memcpy&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;da6&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sin6_addr&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;s6_addr&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;				&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-se&#34;&gt;\0\0\0\0\0\0\0\0\0\0\xff\xff&lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;12&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-nf&#34;&gt;memcpy&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;da6&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sin6_addr&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;s6_addr&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;12&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;buf&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;addr&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-nf&#34;&gt;memcpy&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;da4&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sin_addr&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;buf&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;addr&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-n&#34;&gt;da&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;da4&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;dalen&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-k&#34;&gt;sizeof&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;da4&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-n&#34;&gt;sa&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sa4&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;salen&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-k&#34;&gt;sizeof&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;sa4&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;chroma-k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;policy&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;dpolicy&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-nf&#34;&gt;policyof&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;da6&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sin6_addr&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;dscope&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-nf&#34;&gt;scopeof&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;da6&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sin6_addr&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;dlabel&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;dpolicy&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;label&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;dprec&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;dpolicy&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;prec&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;prefixlen&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;fd&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-nf&#34;&gt;socket&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;family&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;SOCK_DGRAM&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;SOCK_CLOEXEC&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;IPPROTO_UDP&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;fd&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;chroma-nf&#34;&gt;connect&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;fd&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;da&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;dalen&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;				&lt;span class=&#34;chroma-n&#34;&gt;key&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;|=&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;DAS_USABLE&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;				&lt;span class=&#34;chroma-k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;chroma-nf&#34;&gt;getsockname&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;fd&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;sa&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;salen&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;					&lt;span class=&#34;chroma-k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;family&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;AF_INET&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;chroma-nf&#34;&gt;memcpy&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;						&lt;span class=&#34;chroma-n&#34;&gt;sa6&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sin6_addr&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;s6_addr&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;12&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;						&lt;span class=&#34;chroma-o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sa4&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sin_addr&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;					&lt;span class=&#34;chroma-k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;dscope&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;chroma-nf&#34;&gt;scopeof&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sa6&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sin6_addr&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;						&lt;span class=&#34;chroma-n&#34;&gt;key&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;|=&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;DAS_MATCHINGSCOPE&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;					&lt;span class=&#34;chroma-k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;dlabel&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;chroma-nf&#34;&gt;labelof&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sa6&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sin6_addr&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;						&lt;span class=&#34;chroma-n&#34;&gt;key&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;|=&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;DAS_MATCHINGLABEL&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;					&lt;span class=&#34;chroma-n&#34;&gt;prefixlen&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-nf&#34;&gt;prefixmatch&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sa6&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sin6_addr&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;						&lt;span class=&#34;chroma-o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;da6&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sin6_addr&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;				&lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-nf&#34;&gt;close&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;fd&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-n&#34;&gt;key&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;|=&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;dprec&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;DAS_PREC_SHIFT&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-n&#34;&gt;key&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;|=&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;15&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;dscope&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;DAS_SCOPE_SHIFT&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-n&#34;&gt;key&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;|=&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;prefixlen&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;DAS_PREFIX_SHIFT&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-n&#34;&gt;key&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;|=&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;MAXADDRS&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;DAS_ORDER_SHIFT&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-n&#34;&gt;buf&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;sortkey&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-nf&#34;&gt;qsort&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;buf&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;cnt&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-k&#34;&gt;sizeof&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;buf&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;addrcmp&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can see if the address labels match, the sort key is adjusted using the &lt;code&gt;DAS_MATCHINGLABEL&lt;/code&gt; constant. But where
do the labels come from? For that we need to investigate the &lt;code&gt;policyof&lt;/code&gt; func:&lt;/p&gt;
&lt;pre class=&#34;chroma-chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;chroma-k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;chroma-k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;policy&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-kt&#34;&gt;unsigned&lt;/span&gt; &lt;span class=&#34;chroma-kt&#34;&gt;char&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;addr&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;16&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-kt&#34;&gt;unsigned&lt;/span&gt; &lt;span class=&#34;chroma-kt&#34;&gt;char&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;mask&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-kt&#34;&gt;unsigned&lt;/span&gt; &lt;span class=&#34;chroma-kt&#34;&gt;char&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;prec&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;label&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;defpolicy&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;[]&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-se&#34;&gt;\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1&lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;15&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mh&#34;&gt;0xff&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;50&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-se&#34;&gt;\0\0\0\0\0\0\0\0\0\0\xff\xff&lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;11&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mh&#34;&gt;0xff&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;35&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;4&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-se&#34;&gt;\x20\2&lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mh&#34;&gt;0xff&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;30&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-se&#34;&gt;\x20\1&lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mh&#34;&gt;0xff&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;5&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-se&#34;&gt;\xfc&lt;/span&gt;&lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mh&#34;&gt;0xfe&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;13&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-cp&#34;&gt;#if 0&lt;/span&gt;&lt;span class=&#34;chroma-c&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-c&#34;&gt;	/* These are deprecated and/or returned to the address
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-c&#34;&gt;	 * pool, so despite the RFC, treating them as special
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-c&#34;&gt;	 * is probably wrong. */
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-c&#34;&gt;	{ &amp;#34;&amp;#34;, 11, 0xff, 1, 3 },
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-c&#34;&gt;	{ &amp;#34;\xfe\xc0&amp;#34;, 1, 0xc0, 1, 11 },
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-c&#34;&gt;	{ &amp;#34;\x3f\xfe&amp;#34;, 1, 0xff, 1, 12 },
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-cp&#34;&gt;#endif
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-cm&#34;&gt;/* Last rule must match all addresses to stop loop. */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;chroma-s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;40&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;chroma-k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;chroma-k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;policy&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;chroma-nf&#34;&gt;policyof&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;chroma-k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;in6_addr&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;chroma-mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-nf&#34;&gt;memcmp&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;s6_addr&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;defpolicy&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;addr&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;defpolicy&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-k&#34;&gt;continue&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;chroma-p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;s6_addr&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;defpolicy&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;chroma-o&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;defpolicy&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;mask&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		    &lt;span class=&#34;chroma-o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;defpolicy&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;addr&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;defpolicy&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;			&lt;span class=&#34;chroma-k&#34;&gt;continue&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;		&lt;span class=&#34;chroma-k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;chroma-n&#34;&gt;defpolicy&lt;/span&gt;&lt;span class=&#34;chroma-o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;chroma-n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;chroma-p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;	&lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;chroma-line&#34;&gt;&lt;span class=&#34;chroma-cl&#34;&gt;&lt;span class=&#34;chroma-p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So the &lt;code&gt;policyof&lt;/code&gt; func simply uses the &lt;code&gt;defpolicy&lt;/code&gt; array to find the policy that applies to an address. This &lt;code&gt;defpolicy&lt;/code&gt;
array contains a number of hardcoded entries which correspond exactly to the ones provided in the RFC. The one causing
us problems is &lt;code&gt;{ &amp;#34;\xfc&amp;#34;, 0, 0xfe, 3, 13 }&lt;/code&gt; which matches &lt;code&gt;fc00::/7&lt;/code&gt; addresses.&lt;/p&gt;
&lt;p&gt;Unfortunately, without recompiling musl from source there’s not much we can do to address this directly. The only way
we can make the containers work as desired is to give them a different address range. Ideally this would be a range
that you control and that is otherwise not used, but there’s a good chance you won’t have such a range. One possible
alternative is the &lt;code&gt;2001:db8::/32&lt;/code&gt; range which is reserved for documentation purposes. This doesn’t feature in any of
the policy tables, so is treated like a normal public IPv6 address. It doesn’t feel great to misuse a reserved range
like that, but it’s probably the least of all evils, at least until musl allows configuring the policy table.&lt;/p&gt;
</content>
    </entry>
    <entry>
        <title>How to break everything by fuzz testing</title>
        <link href="https://chameth.com/break-everything-fuzz-testing/"/>
        <updated>2020-04-26T00:00:00Z</updated>
        <id>https://chameth.com/break-everything-fuzz-testing/</id>
        <content xml:lang="en" type="html">&lt;figure class=&#34;image left&#34;&gt;
  &lt;picture&gt;
      &lt;source srcset=&#34;https://chameth.com/break-everything-fuzz-testing/chimp.avif&#34; type=&#34;image/avif&#34;/&gt;
      &lt;source srcset=&#34;https://chameth.com/break-everything-fuzz-testing/chimp.webp&#34; type=&#34;image/webp&#34;/&gt;
      &lt;img src=&#34;https://chameth.com/break-everything-fuzz-testing/chimp.jpg&#34; alt=&#34;Chimp sat at a typewriter&#34; loading=&#34;lazy&#34; width=&#34;300&#34; height=&#34;239&#34;/&gt;
  &lt;/picture&gt;
  &lt;figcaption&gt;&lt;p&gt;Fuzz testing is a bit like the infinite monkey theorem, but instead of Shakespeare you get crashes.&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Fuzz testing, if you’re not aware, is a form of testing that uses procedurally generated random
inputs to see how a program behaves. For instance, if you were fuzz testing a web page renderer
you might generate a bunch of HTML - some valid, and some not - and make sure the rendering
process didn’t unexpectedly crash.&lt;/p&gt;
&lt;p&gt;Fuzz testing doesn’t readily lend itself to all types of software, but it particularly shines
in cases where some kind of complex user input is accepted and processed in some way - like
the aforementioned web page renderer. I was recently adding a library to parse EXIF data to
images to an Internet-facing service and realised it was a perfect opportunity to do some fuzz
testing. Even if I didn’t find any issues, I’d improve my confidence that the library was safe
enough to expose to the Internet.&lt;/p&gt;
&lt;h3 id=&#34;breaking-my-exif-library&#34;&gt;Breaking my EXIF library&lt;/h3&gt;
&lt;p&gt;I wrote a quick harness to run &lt;a href=&#34;https://github.com/dvyukov/go-fuzz&#34;&gt;go-fuzz&lt;/a&gt; on the library,
and gave it some pre-existing demo files as sample input. The way go-fuzz works is that it
instruments your code and then mutates the inputs to try to improve the coverage. For example,
if I had some sample data that had an EXIF tag with a value of 1 then go-fuzz might change it
to a 2 and see if the code follows a different path. In most cases it won’t but when it does,
they tend to be very interesting cases.&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;One of the first issues that go-fuzz found was that some values in a maker note field would cause
the library to panic (i.e., crash). This happened because there was a check to see if the first
six characters were “Nikon” and a null byte, without first checking to see if there were actually
six characters available. This is a kind of bug that doesn’t happen much with “real” data - as
the field is either not present or completed correctly - but could easily be exploited once this
code is exposed to the Internet.&lt;/p&gt;
&lt;p&gt;Another interesting bug that go-fuzz found was that if a tag had a particularly large count, the
library would try to allocate an obscene amount of memory and die. There was already a check in
the code that was meant to avoid this exact scenario, but go-fuzz managed to find a way around
it. Each tag has a size (for example an integer tag takes a fixed number of bytes) and a count;
the existing check multiplied the two together and made sure that the result wasn’t too large.
For most cases this was fine but go-fuzz found a case where the count was so large that when
multiplied by the size of the tag it overflowed the integer and became negative, thus passing
the sanity check but then subsequently failing when it came around to actually allocating the
memory.&lt;/p&gt;
&lt;p&gt;The final bug of note that go-fuzz found was the most interesting. EXIF data is stored in IFDs
(“Image File Directories”), and each IFD provides what is effectively a pointer (a byte offset)
to the next one. The EXIF library already had a check to make sure that these didn’t loop, but
it only checked the immediately preceding IFD - so if IFD 1 linked to IFD 2, it would catch IFD 2
linking back to IFD 1 and break the loop with an error. Go-fuzz found that having three interlinked
IFDs had the same issue, though, and the guard code wasn’t triggered. This created an infinite
loop, maxing out a CPU core until the process was eventually killed - one of the worst kind of
bugs you could have in an Internet-facing service which doesn’t deal with private data! The fix
for this was fairly straightforward - I just made the library keep a record of the previously
visited IFDs and bail out if it found a loop.&lt;/p&gt;
&lt;h3 id=&#34;breaking-my-ide&#34;&gt;Breaking my IDE&lt;/h3&gt;
&lt;p&gt;When go-fuzz detects an issue it outputs not only the details of the problem (the stack trace,
error message, and so forth) but also the input that generated the problem. This is useful for
reproducing and making sure the issue is fixed, but it also makes it really easy to write
a test to ensure that the behaviour never regresses in the future.&lt;/p&gt;
&lt;p&gt;As I was working through fixing the bugs that go-fuzz found, I dutifully added new tests where
needed. After adding the sample input with looping IFDs to the project, I switched to IDEA to
write a test to use it. I clicked on the input file to copy the file name, and then the entire
IDE hung and had to be restarted. Uh oh! When I restarted IDEA, it immediately began indexing
the project and again hung. It turns out IDEA parses EXIF data (presumably, even if it does
nothing else with the data, to get the rotation property for images), and the library they use -
an independent one written on Java - had the same bug as the Go library I was using.&lt;/p&gt;
&lt;p&gt;In order to stop IDEA from indexing the file and becoming unusable I renamed it from a ‘.tif’
extension to ‘.dat’, and everything went back to normal. I thought I’d best report the bug to
JetBrains, though, so they could put a proper fix in.&lt;/p&gt;
&lt;h3 id=&#34;breaking-youtrack&#34;&gt;Breaking YouTrack&lt;/h3&gt;
&lt;p&gt;JetBrains use their own issue tracker called YouTrack for reporting bugs in IDEA. I dutifully
went over and described the problem, attaching the log files from the IDE, a description of how
the file was malformed, and carefully selected the .dat version of the file to upload so that it
wouldn’t cause anyone else the same immediate problem.&lt;/p&gt;
&lt;p&gt;After trying to upload the file I got a strange error back. Uh oh! I submitted the IDEA issue as
it stood, unable to see if the attachments had even uploaded, and went and wrote up an issue for
YouTrack itself about the error message. While I was doing that, YouTrack seemed to slow down and
become really annoying to use. I had a sinking feeling the exact same thing was probably
happening as with IDEA and my library - but this time YouTrack had content-sniffed the file
instead of relying on the file extension. In hindsight, I should’ve put the file in a passworded
archive to ensure no automated tools got hold of it. I marked the issue as a security problem as in
a service like YouTrack it presents a denial-of-service opportunity&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a class=&#34;footnote-ref&#34; href=&#34;#fn:1&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; (remember when I said it was
one of the worst kinds of bugs you could have in an Internet-facing service?…)&lt;/p&gt;
&lt;p&gt;Shortly after I raised my YouTrack ticket, a notice appeared at the top of the page saying they
were investigating the current performance issues. Uh oh! I was holding out hope that this was
unrelated to me uploading the buggy dat file, but the timing all seemed a bit suspect. I shot
support an e-mail saying I think I might be the root cause for their performance issues and
linked to the ticket. In the time it took me to e-mail them, the entire site had been
put into maintenance mode. I got an e-mail back a few hours later confirming the outage
was in fact all my fault, as I’d feared. Within the space of days the JetBrains security team
had fixed the issue in YouTrack, which was a pretty nice turnaround.&lt;/p&gt;
&lt;p&gt;So if you were trying to access YouTrack at the start of March and couldn’t - I’m sorry, I didn’t
mean to! Also, if you’re building an Internet-facing service that takes user input you should
really consider running a fuzz tester against it!&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr/&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;“We have a problem”. “Remember, there are no such things as problems,
only opportunities”. “Well then we have a DDoS opportunity.”
– &lt;a href=&#34;https://twitter.com/J4vv4D/status/671090709588496384&#34;&gt;@J4vv4d&lt;/a&gt; &lt;a class=&#34;footnote-backref&#34; href=&#34;#fnref:1&#34; role=&#34;doc-backlink&#34;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</content>
    </entry>
</feed>
