espressif / esp-thread-br

Espressif Thread Border Router SDK
Apache License 2.0
91 stars 18 forks source link

NAT64 example/documentation appears wrong (TZ-966) #73

Open sgryphon opened 2 weeks ago

sgryphon commented 2 weeks ago

The page about NAT64 https://github.com/espressif/esp-thread-br/blob/48b2e47/docs/en/codelab/nat64.rst

Has the following:

For visiting HTTP servers with domain names, the DNS server shall be first configured on the Thread CLI device:

dns64server 8.8.8.8

However this appears to be wrong. If the endpoint, the Thread CLI device, has only IPv6, and no knowledge of IPv4, then "8.8.8.8" would be meaningless.

It is also the address for normal Google DNS, not Google DNS64, which is 2001:4860:4860::6464, see https://developers.google.com/speed/public-dns/docs/dns64

So, I would expect (I have not tested), something more like:

> dns64server 2001:4860:4860::6464

If the device has only IPv6 connectivity, and is given the details of the Google DNS64 server, then when the device makes a request for a host such as v4.ipv6-test.com it will be able to connect to the DNS IPv6 address, and receive the IPv6 response 64:ff9b::334b:4e67 (the command line equivalent is nslookup v4.ipv6-test.com).

The end device can then do the equivalent of:

> curl https://v4.ipv6-test.com/api/myip.php
220.240.255.134

Which will do the IPv6 DNS lookup, then make an IPv6 request to 64:ff9b::334b:4e67, i.e. the client device only deals in IPv6.

The border gateway/NAT64 device then translates the NAT64 address to an IPv4 address (the NAT64 box does have an IPv4 address), and gets the result. The result returned from the ipv6-test.com server is a good test function as it shows the client's address (from the server's point of view), i.e. the public IPv4 address of the NAT64 device.

This is also useful for testing the IPv6 address connectivity:

> curl https://v6.ipv6-test.com/api/myip.php
2407:8800:bc61:1340:7da8:c35c:fc69:94a6

Note, if dns64server 8.8.8.8 does work, but dns64server 2001:4860:4860::6464 does not, then it suggests there is something seriously wrong with your implementation, as it would appear to be relying on IPv4 and using the wrong Google DNS server. Make sure you are testing in an IPv6 only network (with only the NAT64 device having IPv4).

chshu commented 4 days ago

@sgryphon The term dns64server here might be misleading, but if you check its implementation here: dns64, you'll see the actual logic:

It takes an IPv4 address and combines it with the NAT64 prefix to form an IPv6 address, which is then configured as the DNS server. The Thread device will use this IPv6 DNS server address (NAT64 prefix + IPv4 DNS server) to make DNS queries, these queries are reformatted by NAT64 in the Thread BR, allowing them to be sent to the actual IPv4 address configured by this dns64server command.

In this scenario, we assume that public IPv6 connectivity is not available, and NAT64 is required at all times.

sgryphon commented 3 days ago

Ah, thanks for the pointer to the implementation. Yes, I can see how it takes an IPv4 address and converts it to a NAT64 address to use as a DNS server.

I had a search for dns_setserver in the source code, and there doesn't appear to be any way to set it other than via an IPv4 address, i.e. you only support IPv4 DNS, which still seems a bit strange for a protocol that is founded on IPv6.

My suggestion would be to allow the DNS server to be set correctly, so you you can support IPv6 end-to-end scenarios as well (i.e. where you have end-to-end IPv6 network connectivity but may still need to access IPv4 only destinations).

i.e. add a command like the following that can set any DNS server:

dnsserver 2001:4860:4860::6464

It would be important to be able to set either an IPv6 or IPv4 DNS server, so that you can support IPv6 only networks. It would be strange for an IPv6 technology such as thread to not support IPv6 only networks.

Note that you could use this command to replicate the behaviour of the existing command by doing the NAT64 conversion yourself (although the automatic conversion might be nicer), e.g.

dnsserver 64:ff9b::808:808

Also note that IPv4 DNS servers generally won't give back NAT64 addresses, i.e. 8.8.8.8 will only give back the IPv4 address result (and a native IPv6 if available), so you may not find them that useful for NAT64. DNS servers that support NAT64 (i.e. give back the NAT64 converted result), such as Google DNS64, are generally only available via IPv6.

PS C:\Users\sgryp> nslookup v4.ipv6-test.com 64:ff9b::808:808
Server:  UnKnown
Address:  64:ff9b::808:808

Non-authoritative answer:
Name:    v4.ipv6-test.com
Address:  51.75.78.103

PS C:\Users\sgryp> nslookup v4.ipv6-test.com 2001:4860:4860::6464
Server:  dns64.dns.google
Address:  2001:4860:4860::6464

Non-authoritative answer:
Name:    v4.ipv6-test.com
Addresses:  64:ff9b::334b:4e67
          51.75.78.103

Should I change the title of this issue, to support IPv6 DNS, or raise a new issue?