espressif / esp-lwip

Fork of lwIP (https://savannah.nongnu.org/projects/lwip/) with ESP-IDF specific patches
Other
85 stars 129 forks source link

fix(dns): Dynamic DNS sorting (RFC 6724) to work in IPv6-only network (IDFGH-12553) #66

Open sgryphon opened 7 months ago

sgryphon commented 7 months ago

To address issue: https://github.com/espressif/esp-idf/issues/13255

Also useful is setting up to configure the option via KConfig (a separate PR to the main esp-idf repository).

This fix adds an option to dynamically set the order of DNS results based on RFC 6724, to return the best destination address based on the available source addresses, allowing a device with both IPv4 and IPv6 enabled to work in any network configuration, including IPv4-only, IPv6-only, and dual-stack.

Without the option there is a static ordering preferring IPv4, which means on an IPv6-only network, a dual-stack destination returns the IPv4 address, which fails. Setting the static preference to IPv6 would have the opposite problem. A dynamic sort, based on available source addresses, is required to work on all networks.

The dynamic sorting only applies if you have both IPv6 and IPv4 enabled.

Summary of behaviour:

  1. If the destination is single stack, it will use the available address.
  2. If you are on a single stack network, connecting to a general address, it will use that network (IPv6 or IPv4).
    • Any IPv6 link-local address you get does not count for global scope
  3. On a dual stack network, connecting to a dual-stack host:
    • If the destination is a general IPv6 (including DNS64/NAT64) then it will be used
    • Otherwise the IPv4 address will be used

Other IPv6 addresses (Toredo, ULA, etc) will still be used if there is no IPv4 address (see step 1), but if there is also an IPv4 address then the IPv4 address will be used in preference.

Replaces PR https://github.com/espressif/esp-lwip/pull/65 that had a very basic implementation (not full RFC 6724).

sgryphon commented 5 months ago

Testing with Arduino-ESP32.

I have built a version of the Arduino-ESP32 libraries with the fix included, coupled with some fixes in the Arduino-ESP32 project.

The results work with most networks and destinations, although there are still issues with TLS / HTTPS. (Most production systems should be using TLS):

Network Dual-Stack IPv6 IPv4 TLS Dual-Stack
IPv4 (Shadow) IPv4 not possible Yes Yes
IPv6 disabled, Dual-stack+NAT64 IPv4 not possible Yes Yes
Dual-stack+NAT64 (Astral) IPv6 Yes NAT64-IPv4 fail
IPv6+NAT64 (Wildspace) IPv6 Yes NAT64-IPv4 fail

Tests were done using a custom sample app with an M5Stack Core2, https://github.com/sgryphon/iot-demo-build/tree/feature/arduino-esp32-v3-update/m5stack/m5unified_wifi_https

PlatformIO was used to build, with the following custom configuration:

platform = https://github.com/sgryphon/platform-espressif32.git#sgryphon/add-esp32-arduino-libs
platform_packages = 
  platformio/framework-arduinoespressif32-libs @ https://github.com/sgryphon/esp32-arduino-libs.git#sgryphon/test-fix-ipv6-lwip-and-config
  platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git