tailscale / tailscale/tailscale

FR: implement DNS64 for 4via6 subnet routing

Open
#5,392 7 comments 9 reactions 0 assignees View on GitHub
dns fr L2 Few P2 Aggravating T0 New feature
Dominant language
Go
Stars
36.5k
Forks
3.2k
Avg merge
2d 3h
Merged PRs (30d)
123

Description

### What are you trying to do?

I'm using Tailscale as an identity-aware proxy to provide access to a non-public environment in AWS. I have a subnet router deployed in the VPC, advertising routes to the VPC's CIDR (`10.0.0.0/16`). I also have my Tailnet configured with split DNS to send queries for the environment's domain (`example.com`) to the VPC's resolver (`10.0.0.2`). This is working as advertised. Machines on my Tailnet send a DNS query through the subnet router to the VPC's resolver, which resolves `example.com` from the alias A record for an internal load balancer; a set of IPv4 addresses in the `10.0.0.0/16` range come back in the response, and the HTTP request that follows is properly routed through the subnet router and into the VPC.

I would like to expand this setup to provide access to another non-public environment in a different VPC. Both VPCs are using the same CIDR (`10.0.0.0/16`), so this seems like a use case for Tailscale's 4via6 routing. I'm excited about the 4via6 feature, and I'm interested to try it out while it's in alpha/beta.

I can have the subnet routers in both VPCs advertise 4via6 routes:
* the subnet router in the first VPC would advertise a route to `fd7a:115c:a1e0:b1a:0:1:a00:0/112` for site 1
* the subnet router in the second VPC would advertise a route to `fd7a:115c:a1e0:b1a:0:2:a00:0/112` for site 2

I would update my Tailnet's DNS configuration like this:
* queries for `example.com` are sent to `fd7a:115c:a1e0:b1a:0:1:a00:2`, which maps to `10.0.0.2` in site 1
* queries for `example.net` are sent to `fd7a:115c:a1e0:b1a:0:2:a00:2`, which maps to `10.0.0.2` in site 2

The problem is that the VPC resolvers respond with IPv4 addresses. There's nothing in this setup that would translate IPv4 addresses in an A-record response into their corresponding 4via6 IPv6 addresses in a AAAA-record response. So with this setup, users in my Tailnet would be able to resolve the private IPv4 addresses of the load balancers in both sites, but since those addresses are not mapped to their 4via6 counterparts, the resulting traffic would not be properly routed.

Clearly, I need to add something.

### How should we solve this?

I'm not entirely sure how this should work, but I think I'm asking for [DNS64](https://datatracker.ietf.org/doc/html/rfc6147) functionality in Tailscale's resolver. Tailscale is already handling some other DNS things, so this functionality seems like it fits.

### What is the impact of not solving this?

The 4via6 feature solves a problem at the IP level, but the problem I've described here is at the DNS level. Without this feature, 4via6 would only be useful for IP-only use cases, or for users that are okay with manually maintaining 4via6 addresses in a DNS zone.

I think implementing this feature would enable a complete identity-aware proxy solution for access to protected environments, powered by Tailscale.

### Anything else?

The [DNS64](https://datatracker.ietf.org/doc/html/rfc6147) spec seems to define the behavior I'm looking for in this issue. Clients in my Tailnet are constrained to be IPv6-only because they need to deal exclusively in 4via6 address space, and servers in my VPC are IPv4-only. The spec [describes](https://datatracker.ietf.org/doc/html/rfc6147#page-7) "DNS64 in stub-resolver mode" where translation happens on the initiator endpoint; that sounds like something happening in Tailscale's resolver. If I were to roll my own solution, it would likely be what the spec calls "DNS64 in DNS recursive-resolver mode," adding a recursive resolver somewhere between my clients and servers that would do the 4via6 mapping.

[AWS supports DNS64](https://docs.aws.amazon.com/vpc/latest/userguide/nat-gateway-nat64-dns64.html), but that's for a scenario where IPv6-only clients _inside_ the VPC are talking to IPv4-only clients _outside_ the VPC. I'm trying to do the inverse: IPv6 clients _outside_ the VPC (i.e., in my Tailnet) talking to IPv4-only clients _inside_ the VPC.

I had considered writing a small DNS resolver that would use [`tsaddr.MapVia`](https://pkg.go.dev/tailscale.com@v1.28.0/net/tsaddr#MapVia) to translate IPv4 addresses in a DNS response to their IPv4 counterparts. It would be configured with a site ID and IPv4 prefixes indicating which addresses should be mapped (so only addresses within `10.0.0.0/16` would be translated in my example), and everything else would be sent to an upstream resolver.

Then I learned (thanks, [O'Reilly](https://www.oreilly.com/library/view/dns-and-bind/9781449308025/ch04.html)!) that `bind` supports DNS64. So perhaps I could run a `bind` server with config like the following, and have my Tailnet split DNS traffic to `bind` for `example.com` and `example.net`. This is presently the strongest option I'm aware of (and perhaps a good addition to Tailscale docs on 4via6), but it means I need to run `bind` somewhere.

Here's a `bind` config snippet that I think would work for my example:

```bind
# site 1
dns64 fd7a:115c:a1e0:b1a:0:1::/96 {
mapped { 10.0/16; };
};

# site 2
dns64 fd7a:115c:a1e0:b1a:0:2::/96 {
mapped { 10.0/16; };
};
```

I would have to use this config on a single `bind` server in my Tailnet, outside of the target VPCs, or I would run a `bind` server in each VPC with config only relevant to that VPC. Either way, I would need to step outside of Tailscale to complete the solution.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.