My entire home setup and ISP connection is dual stack and most of my traffic, apart from some legacy devices, uses IPv6. HA works fine in this environment and I can access it locally and remotely via the web or companion app via either IPv4 or IPv6.
However… I have just been experimenting with webhook triggers, sending the trigger message to the local HA endpoint using the ‘curl’ command from a system on the same LAN as the HA host. This system has the same IPv6 prefix as the HA host so is ‘local’ but the webhook only triggers if I force curl to use IPv4 (curl -4), if it uses IPv6 the trigger does not fire.
This seems like a bug? HA 2026.1.3.
UPDATE: Yes, this is a serious bug. HA is not correctly performing the ‘is local’ determination for IPv6 addresses. My HA instance is listening on the following addresses:
So incoming IPv4 requests where the subnet of the source address = 1.0.200.0/24 and incoming IPv6 requests where the prefix of the source address matches fe80::/10, fd00::/64 or 2a02:390:62fb:1::/64 should be treated as ‘local’ but in fact for IPv6 only requests from fe80::/10 and fd00::64 are treated as local. requests originating from 2a02:390:62fb:1::/64 are not treated as local. This is incorrect.
I have not worked with IPv6 over curl, but many other software apps require IPv6 addresses to be typed in a certain way to detect them as IPv6 addresses and not just a normal URL with a domain name.
Many software apps use brackets, but check the documentation.
There are various sorts of ‘f’ addresses, the two most common are link local addresses (fe80::/10), which are fundamental to IPv6 but which are not typically used by applications, and unique local addresses (fd00::/8) which are not commonly used but which can be used by applications. Certainly link local addresses should be considered as ‘local’ by HA but as these are not used by application that is somewhat irrelevent.
Most IPv6 addresses are global unicast addresses (2000::/3) and that is what my network uses internally. The ‘is local’ determination should work as follows:
HA gets all the IPv6 addresses and prefix lengths for all interfaces on which it is listening and uses this to build a list of IPv6 ‘local’ prefixes. This is a one off operation at the time HA starts up.
When a request arrives HA extracts the source address from the IP packet and then checks it against the list of ‘local’ prefixes; if there is a match then the request is considered local, otherwise it is not.
That;s the only meaningful way to check this for IPv6.
I’m aware of how IPv6 addresses should be represented in URLs etc. but that is not relevant here because:
I am using a hostname in the URL (my DNS resolves it to both IPv4 and IPv6 addresses).
The URL, or any address specified as part of a curl command, is irrelevant in determining if the request ‘is local’ or not. That can only be reliably done by comparing the source IP address (v4 or v6) subnet / prefix (extracted from the incoming IP packet) with a list of ‘local’ subnets/prefixes derived from the addresses of the interfaces it is listening on.
They are.
The applications do not care about what the address type is. It is just an IPv6 address to them.
The address type only affect the network gear in relation to routing.
Well no, not really. Let me expand further. Yes, applications can use link local addresses, and in some cases they may explicitly choose to do so, though that should be rare as link local addresses are (a) limited and (b) often hard to determine for a destination. Most real-world applications will get the IPv6 address of a destination (something they wish to connect to) using DNS lookups or other forms of name to address resolution typically via the standard OS library functions such as getaddrinfo(). Typically this resolution does not return link-local addresses (though it may in some cases). Similarly, although an application may choose the address from which it’s traffic originates (hosts typically have several IPv6 addresses of different types and scopes) most commonly this is determined by the host OS network stack.
The rules governing all of this are laid out in RFC 6724
In ipv4, what deems an address as “local” is indeed comparing the origin address to a fixed list of non-internet routable subnets, e.g 10.0.0.0/8 or 192.168.0.0/16.
Aren’t the ipv6 local addresses exactly that?
The functional key as to what a “local” address is is that they cannot be reached from outside the local LAN, and I think (but I never really dug into ipv6, tbh) that the “local” ipv6 adresses are exactly that.
IPv6 have two types of local addresses.
These two types of addresses will be dropped by any router on the public internet.
The one type of local IPv6 addresses is a link-local one, which can not even be routed internally. Some of the network subnets may exist on several interfaces, but they are in fact different networks.
The other type of local IPv6 addresses is an unique local address (ULA) which can be routed internally.
Then there are the global reachable addresses, which can still be placed in the local network.
Well yes and no. ULAs are not commonly used and in general are discouraged. Similarly link-local addresses are not easy to use from an application standpoint. The real question is what does HA mean by ‘is local’ and what is the intent / usage of that? It could be one of (at least) two things:
Strictly means that the request originated from a ‘local’ address based purely on IPv4 and IPv6 ‘local’ address rules. Fine for IPv4, as local network devices rarely if ever will have ‘non local’ addresses. Not so useful for IPv6 in typical network architectures since generally ‘local’ devices (and the HA host) will have GUAs and LLAs only, and requests will preferentially be sent from / received on the GUAs.
Means that the request originates from a device on the ‘local network’ (i.e. the sane subnet that HA is on). This means that HA needs to go a little further for IPv6 to determine if the origin address is ‘local’ (as per my description several posts above). Most software I have encountered does this correctly but HA seems to be lacking when it comes to IPv6.
My expectation for any kind of ‘is local’ determination would be (2) above as it is the most appropriate, most correct and most useful one. (1) is okay for IPv4 but really is not sufficient for IPv6.
All the address types in IPv6 is used and quite often.
In IPv6 it is the issues is often knowing the address when trying to connect from another device.
Addresses can be be static set, managed by several types of DHCP, auto-templated based on the MAC address of the NIC and just randomly generated and a NIC can have more than one IP address and it can be a mix of one or more of the way it is made up.
Coming from IPv4 with static IPs on devices IPv6 can be a challenge, because of the above, but many devices use discovery protocols and therefore the IPv6 address is often not that important.
Discovery protocols are just hard to handle in VLANs, even with IPv4 and IPv6 does not make it easier in any way.
That is why people recommend a flat network with IPv6, like in relation with Matter.
It requires deep understanding of not just the TCP/IP protocols, but also on the protocols running on top of them and especially the discovery protocols.
That being said.
HA was a long time about getting on the IPv6 bandwagon and it is probably not near the front in anyway still, so if there is issues, then I am not surprised.
I tried to switch to an IPv6 -only setup, but HA was actually the only part of my devices that I could not get to work with IPv6 only.
You can’t argue with the code in terms of what it does. Whether that is what it should do is definitely open for debate in my opinion, in terms of what is actually useful. Sigh.
I’ve opened an issue on Github against HA core so I’ll be interested to see what the developers have to say.
Yeah, still not convinced.
The idea behind “local” is “not coming from internet”, so considering a global address, be it denied from internet by other means, as local would feel wrong to me.
You are missing/misunderstanding a key point. Traffic from a GUA does not necessarily come from the Internet.
Consider a GUA prefix of 2a02:390:62fb:1::/64 (my main home network). Only systems within that network can have addresses with this prefix; it is globally unique and provided by my ISP (well actually they provide me a unique /48 and I segment that into a bunch of /64s). HA is part of this subnet and has an IPv6 GUA within that prefix. other systems on that network likewise. So if traffic arrives at HA with an origin address within that subnet it is by definition local and cannot possibly have come from the Internet.
This is my point; for IPv6 the definition of ‘local’ as used for IPv4 is insufficient and compromises functionality.
If I understand what you say, in ipv4 terms, it would be like you using a private network in the public range, say, 88.98.99.0/24, and expect HA to consider 88.98.99.100 as local because it would “detect” that it is your private network based upon what addresses it listen on?
Not technically impossible, ofc, but not part of any standard I know of.
BTW, on my openwrt router, the “.lan” hosts resolve to the ULA, which, again, makes sense to me.
I am not really sure what you are discussing.
In both IPv4 and IPv6 the devices do not really care about if an address is in an address range that is reserved as local or not.
The device just detect if it is within its subnet or not. If it is not in the subnet, then it will send to a router in the subnet instead.
IPv6 a LLA addresses is somewhat special though, because it is actually possible to have two network interfaces where devices with the same LLA exist even though the devices are not physical the same.
Other than that it is just an IPv6 address in the TCP/IP related POV and LLA, ULA or GUA is not important.
These things can however be important once you start to put protocols on top of IPv6, like mDNS or SSDP.
Actually yes, that is how network works.
I once had my network running with just public IPv4 addresses on all machines.
It was a special circumstance that allowed me to do it, because IPv4 addresses were scarce already back then and it would probably never be possible again.