Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fully enable IPv6 by configuring DNS (both DHCPv6 Stateless and RDNSS) #166

Merged

Conversation

sgryphon
Copy link
Contributor

There are two main IPv6 DNS systems, DHCPv6 Stateless and RDNSS, used in different networks; this change enables both of them, as a network may have either one (or both). In an IPv4-only network, these options will simply be ignored.

This is part of the fix for espressif/arduino-esp32#9143

Previously IPv6 was enabled and assigned addresses, via autoconfig Router Advertisement (RA), but did not enable DNS, without which it cannot connect via host names on an IPv6-only network, so was not very useful.

There were some mitigations, e.g. you could statically configure DNS, or if running in a dual-stack network then the IPv4 DNS will return results (including IPv6 addresses), however applications should automatically work across all network types, so the options in this change should be enabled.

With IPv6 DNS options on in libs, and the other improvements so far in DNS (espressif/arduino-esp32#9439), we have IPv6-only to IPv6-only connections now working:

Network Dual-Stack IPv6 IPv4 TLS Dual-Stack
IPv4 (Shadow) Yes Not Possible Yes Yes
Dual-stack+NAT64 (Astral) IPv4 Yes Yes Yes
IPv6+NAT64 (Wildspace) IPv4 fail Yes IPv4 fail IPv4 fail

There are still a few issues to fix in Arduino-ESP32 to get all configurations working:

  1. DNS server addresses are not being displayed correctly, i.e. does not support IPv6. Internally in LWIP they are IPv6 (because they are working), just not displayed correctly. Should be a relatively easy fix, I will work on.
  2. Dual-stack and NAT64 scenarios do not work, as LWIP DNS has fixed preference for IPv4, which an IPv6-only network can't reach. These are marked IPv4 fail in the table above.

To properly fix this second issue requires my patch to LWIP, espressif/esp-lwip#66

In the meanwhile, I can add a workaround in Arduino-ESP32, based on the code in my ESP-IDF examples updates: espressif/esp-idf#13250

Here is IPv6 - IPv6 working:

[ 32097][I][Core2Logger.cpp:198] log(): [Core2Logger] CORE2: Button 2, scenario 1, v0.1.0-156-gaf345f5
[ 32110][I][Core2Logger.cpp:198] log(): [Core2Logger] CORE2: Global IPv6 2407:8800:bc61:1300:a3a:f2ff:fe65:db28
[ 32125][I][Core2Logger.cpp:198] log(): [Core2Logger] CORE2: IPv4 0.0.0.0
[ 32132][I][Core2Logger.cpp:198] log(): [Core2Logger] CORE2: Link-Local IPv6 fe80::a3a:f2ff:fe65:db28%st1
sta: <UP>
      ether 08:3A:F2:65:DB:28
      inet 0.0.0.0 netmask 0.0.0.0 broadcast 255.255.255.255
      gateway 0.0.0.0 dns 253.124.226.94
      inet6 fe80::a3a:f2ff:fe65:db28%st1 type LINK_LOCAL
      inet6 2407:8800:bc61:1300:a3a:f2ff:fe65:db28 type GLOBAL
      inet6 fd7c:e25e:67e8:0:a3a:f2ff:fe65:db28 type UNIQUE_LOCAL
[ 32169][I][Core2Logger.cpp:198] log(): [Core2Logger] CORE2: DNS0 253.124.226.94
[ 32184][I][Core2Logger.cpp:198] log(): [Core2Logger] CORE2: DNS1 0.0.0.0
[ 32191][I][Core2Logger.cpp:198] log(): [Core2Logger] CORE2: URL: http://v6.ipv6-test.com/api/myip.php
[ 32204][D][HTTPClient.cpp:303] beginInternal(): protocol: http, host: v6.ipv6-test.com port: 80 url: /api/myip.php
[ 32214][D][HTTPClient.cpp:598] sendRequest(): request type: 'GET' redirCount: 0

[ 32258][D][NetworkManager.cpp:81] hostByName(): DNS found IPv6 2001:41d0:701:1100::29c8
[ 32711][D][HTTPClient.cpp:1170] connect():  connected to v6.ipv6-test.com:80
[ 33334][D][HTTPClient.cpp:1321] handleHeaderResponse(): code: 200
[ 33340][D][HTTPClient.cpp:1328] handleHeaderResponse(): Transfer-Encoding: chunked
[ 33348][D][HTTPClient.cpp:642] sendRequest(): sendRequest code=200

[ 33354][D][HTTPClient.cpp:388] disconnect(): still data in buffer (2), clean up.

[ 33362][D][HTTPClient.cpp:393] disconnect(): tcp keep open for reuse
[ 33368][I][Core2Logger.cpp:198] log(): [Core2Logger] CORE2: response=<2407:8800:bc61:1300:a3a:f2ff:fe65:db28>
[ 33383][I][Core2Logger.cpp:176] success(): [Core2Logger] Success

Failure from IPv6-only to dual-stack host, because DNS is returning an IPv4 address, which can't be reached from the IPv6-only network:

[ 10642][I][Core2Logger.cpp:198] log(): [Core2Logger] CORE2: Button 1, scenario 0, v0.1.0-156-gaf345f5
[ 10655][I][Core2Logger.cpp:198] log(): [Core2Logger] CORE2: Global IPv6 2407:8800:bc61:1300:a3a:f2ff:fe65:db28
[ 10670][I][Core2Logger.cpp:198] log(): [Core2Logger] CORE2: IPv4 0.0.0.0
[ 10677][I][Core2Logger.cpp:198] log(): [Core2Logger] CORE2: Link-Local IPv6 fe80::a3a:f2ff:fe65:db28%st1
sta: <UP>
      ether 08:3A:F2:65:DB:28
      inet 0.0.0.0 netmask 0.0.0.0 broadcast 255.255.255.255
      gateway 0.0.0.0 dns 253.124.226.94
      inet6 fe80::a3a:f2ff:fe65:db28%st1 type LINK_LOCAL
      inet6 2407:8800:bc61:1300:a3a:f2ff:fe65:db28 type GLOBAL
      inet6 fd7c:e25e:67e8:0:a3a:f2ff:fe65:db28 type UNIQUE_LOCAL
[ 10714][I][Core2Logger.cpp:198] log(): [Core2Logger] CORE2: DNS0 253.124.226.94
[ 10729][I][Core2Logger.cpp:198] log(): [Core2Logger] CORE2: DNS1 0.0.0.0
[ 10736][I][Core2Logger.cpp:198] log(): [Core2Logger] CORE2: URL: http://v4v6.ipv6-test.com/api/myip.php
[ 10749][D][HTTPClient.cpp:303] beginInternal(): protocol: http, host: v4v6.ipv6-test.com port: 80 url: /api/myip.php
[ 10760][D][HTTPClient.cpp:598] sendRequest(): request type: 'GET' redirCount: 0

[ 10796][D][NetworkManager.cpp:88] hostByName(): DNS found IPv4 51.75.78.103
[ 10804][E][NetworkClient.cpp:258] connect(): connect on fd 48, errno: 118, "Host is unreachable"
[ 10813][D][HTTPClient.cpp:1163] connect(): failed connect to v4v6.ipv6-test.com:80
[ 10820][W][HTTPClient.cpp:1486] returnError(): error(-1): connection refused
[ 10827][E][Core2Logger.cpp:192] log(): [Core2Logger] CORE2: HTTP GET error -1: connection refused

@sgryphon
Copy link
Contributor Author

sgryphon commented Apr 1, 2024

The PR is also up to fix IPv6-only DNS resolution of dual-stack addresses, by -- if we have a public scope address then checking IPv6 first. espressif/arduino-esp32#9443

The fix requires IPv6 DNS to be enabled (this PR) to be useful.

With both changes applied, then almost all IPv6 scenarios work.

Network Dual-Stack IPv6 IPv4 TLS Dual-Stack
IPv4 (Shadow) Yes Not Possible Yes Yes
Dual-stack+NAT64 (Astral) IPv4 Yes Yes Yes
IPv6+NAT64 (Wildspace) Yes Yes NAT64 fail

The only one that doesn't work is TLS, which requires the ESP-LWIP fix.

@me-no-dev
Copy link
Member

can you please remove the unrelated changes

@sgryphon
Copy link
Contributor Author

sgryphon commented Apr 3, 2024

can you please remove the unrelated changes

Are you talking about the additional logging in the scripts (as echo rather than just a comment)?

I was using them to understand the build. Actually, I still can't get it working with my alternate LWIP fix branch -- it gets some strange compile issue related to BlueTooth that seems to have nothing to do with my changes.

But I can easily remove them from the PR here. Probably later this evening (my time, which is Brisbane +10)

@me-no-dev
Copy link
Member

Sure thing! Remove them and I will merge it

… and RDNSS)

There are two main IPv6 DNS systems, DHCPv6 Stateless and RDNSS, used in different networks; this change enables both of them.

Previously IPv6 was enabled and assigned addresses, via autoconfig Router Advertisement (RA), but did not enable DNS, without which it cannot connect via host names on an IPv6-only network, so was not very useful.

There were some mitigations, e.g. you could statitically configure DNS, or if running in a dual-stack network then the IPv4 DNS will return results (including IPv6 addresses), however applications should automatically work across all network types, so the options in this change should be enabled.
@sgryphon sgryphon force-pushed the sgryphon/fix-enabled-ipv6-dns-options branch from cb996d8 to 4a8aa2e Compare April 3, 2024 21:04
@sgryphon
Copy link
Contributor Author

sgryphon commented Apr 3, 2024

Sure thing! Remove them and I will merge it

Actually, it was a small change, just reordering the commits, so just force pushed the change.

@me-no-dev me-no-dev merged commit e1e13da into espressif:master Apr 3, 2024
sgryphon added a commit to sgryphon/esp32-arduino-lib-builder that referenced this pull request Apr 6, 2024
…x IPv6 TLS (espressif#166)

TLS / HTTPS uses the hostname (for certificate validation) to directly look up
DNS. This change enables the RFC6724 destination address selection in LWIP DNS,
to return IPv6 addresses from DNS when a public IPv6 source is available, or
otherwise return IPv4.

i.e. Destination address selection is dynamci depending on what addresses are
available to send from.

Without this, LWIP is hard coded to prefer IPv4, which means when an IPv6-only
device tries to contact a dual-stack (or DNS64) server, it will get the IPv4
address (that can't be used). The config change fixes that.
sgryphon added a commit to sgryphon/esp32-arduino-lib-builder that referenced this pull request Apr 7, 2024
…x IPv6 TLS (espressif#166)

TLS / HTTPS uses the hostname (for certificate validation) to directly look up
DNS. This change enables the RFC6724 destination address selection in LWIP DNS,
to return IPv6 addresses from DNS when a public IPv6 source is available, or
otherwise return IPv4.

i.e. Destination address selection is dynamci depending on what addresses are
available to send from.

Without this, LWIP is hard coded to prefer IPv4, which means when an IPv6-only
device tries to contact a dual-stack (or DNS64) server, it will get the IPv4
address (that can't be used). The config change fixes that.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants