Add IPv6 support for Espressif#9436
Conversation
Otherwise, it was not possible to interact with a v6 address, as `lwip_getaddrinfo` wouldn't resolve it.
* metro esp32s2 only, because that's what I had handy
* nothing is started at boot; I hung it on `start_dhcp()` which is dubious
* I get a stateless address (which doesn't seem to work) and a dhcpv6 address (which does)
```
>>> wifi.radio.ipv6_addresses
('FE80::7EDF:A1FF:FE00:518C', 'FD5F:3F5C:FE50:0:7EDF:A1FF:FE00:518C')
```
* depending whether a v4 or v6 dns server is configured, DNS resolution breaks
wrong ipv4_dns is first 4 bytes of the v6 dns server address:
```
>>> wifi.radio.ipv4_dns
253.95.63.92
```
* I can connect to a v4 or v6 SSH server on the local network and read its banner
>>> s.close(); s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM); s.connect(("fd5f:3f5c:fe50:0:6d9:f5ff:fe1f:ce10", 22))
*** len[0]=28
*** len=28 family=10 port=5632
>>> s.recv_into(buf)
40
>>> bytes(buf)
b'SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u3\r\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
only tested recvfrom_into as can't bind() v6 addresses yet wifi workflow may be broken by this or maybe it was broken before
.. & make web workflow bind to v6 if available. Binding v6 "any" address also allows v4 connections
to accomodate multiple servers some day
* v6 on by default * dhcp can start v4 & v6 separately * self documenting property for v4 & v6 support * v4 support is always on .. for now
|
|
Other modules & libraries may need to be updated in order to support v6. For instance, do adafruit_requests & adafruit_ntp work properly with v6 addresses & names? Since our focus is on v6 for matter support, I did not investigate this or file issues. |
|
good news! this does seem to set ipv6 mdns records: |
tannewt
left a comment
There was a problem hiding this comment.
A few questions. It all looks pretty good. Thanks for figuring this out!
|
I don't have an in-depth understanding of IPv6, so I could be off-base on this. Do we know if the It could be that the DHCP server will take care of this, but's that's dependent on the DHCP server implementation (https://media.defense.gov/2023/Jan/18/2003145994/-1/-1/1/CSI_IPv6_security_guidance_.PDF, p.2). |
|
I'm happy to change this to default v6 off until we understand the ramifications better. @tannewt say the word |
|
Found this:
This is probably the original SLAAC mechanism, and may be a permanent address embedding the hardware MAC address (could be verified with testing). Addendum: >>> import wifi, os
>>>
>>> wifi.radio.connect(os.getenv("WIFI_SSID"), os.getenv("WIFI_PASSWORD"))
>>> wifi.radio.addresses
('192.168.6.243',)
>>> wifi.radio.start_dhcp()
>>> ':'.join('%02X' % _ for _ in wifi.radio.mac_address)
'F4:12:FA:RE:DA:CT'
>>> wifi.radio.addresses
('FE80::F612:FAFF:FERE:DACT', 'FD41:2E18:D0BA:9740:F612:FAFF:FERE:DACT', '192.168.6.243')
# ^^^^:^^. ^^:^^^^. ^^^^:^^. ^^:^^^^Indeed, the IPv6 address contains the hardware MAC address (with a slight algorithmic manipulation common to SLAAC IPv6 creation). So I would encourage keeping IPv6 off by default. A partial workaround......could be to initially, and then periodically, randomize the MAC address: mac = bytearray()
for _ in range(0, 6):
mac.append(random.randrange(0, 256))
mac[0] = mac[0] | 0b00000010 # local on, if desired
mac[0] = mac[0] & 0b11111110 # multicast off
wifi.radio.mac_address = macHowever, even with the partial workaround, the SLAAC IPv6 address still contains the local network prefix. |
Default off is fine with me. That'll make its use explicit which will make more sense if we throw an exception to say it is unsupported. |
* don't enable ipv6 by default due to privacy concerns * move list of board support for ipv6 to socketpool documentation * removed wifi.supports_ipvx properties * throw an exception when start_dhcp_client(ipv6=True) but not supported
|
OK, default is now off, non-standard attributes in wifi module are removed, and attempting to enable v6 dhcp when not supported gets an exception. |
tannewt
left a comment
There was a problem hiding this comment.
Looks great! Thank you for digging into this.
What works:
presently you have tostart_dhcpto get v6 addressesAddresses & ping:
I added name resolution to wifi ping (espressif only):
NTP manually:
http manually:
Todo (some may end up as subsequent PRs):
wifi.radio.start_dhcp()but not on wifi workflow. not sure where dhcp4 is started{start,stop}_dhcp_clientto gain 2 kwarg-only arguments, defaulting to trueFuture PRs: