-
Notifications
You must be signed in to change notification settings - Fork 18k
net/ip: ParsePrefix with IPv6 zone should return an error #51899
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
Comments
Thanks for creating this @mdlayher, and I'm glad you found an actual reference to prefixes with zones. As a kind of user story, here's what led me to bothered by the current behaviour: I'm writing a library to help people extract the correct client IP from It's written using I ended up adding an explicit check for zones and returning an error, to help my future self from introducing the bug. So the current behaviour adds some burden for those of us writing libraries that use I know that the current behaviour is working as documented, but (as I said in the blog post) I think a lot of people simply won't see the documentation. Because:
(FWIW, I prefer @mdlayher's "parse prefix zones for any type of IPv6 address prefix" option.) |
I'm torn on this. My main worry is that using zones for anything higher level than very low-level networking configuration (e.g. IPv6 autoconfiguration, DHCPv6, dynamic routing protocols) is almost certainly a mistake on the part of the person using zones. In the original IPv6 designs, zones were going to be a much more generally useful thing, but these days their only use is to disambiguate link-local communication, and in turn link-local communication should only be used as a stepping stone towards configuring globally-scoped IPv6. So, when we designed netaddr, we tried to find a legitimate use for scoped prefixes, and concluded that the only beneficiaries would be malicious inputs trying to confuse code that wasn't written with scope-awareness. That's how we ended up with the scope stripping behavior for prefixes. We had to keep zones for single IPs, since that is definitely both necessary and useful for things like CoreRAD, which have to wrestle with link-local communication. (Unfortunately, IMO, because I'd have loved to lose zones entirely) The thing I'm torn on is whether the use cases in this bug are a legitimately useful/necessary use of zones in prefixes, or if we're arguing about supporting a hypothetical edge case for completeness, at the cost of making mainstream uses of the package harder. In particular, I would like us to not consider the existence of an RFC as proof that something is necessary or useful. Especially in IPv6, which has gone through decades of redesign and refinement, there are a lot of RFCs out there that encourage what we now know to be bad ideas. So, an RFC alone should not be our guide as to how APIs should behave, because if we did that, we'd end up with a lot of really whacky behavior all over the place. Currently, our only example of wanting to use zones in prefixes is a library for use in HTTP, where I would argue zones should never be appearing in the first place. What's the failure mode of the current behavior? IIUC, it causes false negatives, that is, source IPs that should be trusted end up not being trusted, because of the zone mismatch. Is that correct? If that's the extent of the impact, then my preference would be to treat this as a documentation issue, and make it more explicit that netip Prefixes cannot have zone specifiers. If there is a compelling reason to force all users of netip.Prefix to care about zone specifiers, then I think I would reluctantly advocate for consistency and allowing them for all prefixes, rather than hardcoding an exception for On top of all the above, we'll have to consider the Go 1 compatibility promise: now that a release exists in which Prefixes strip zones, I don't think we can silently change the behavior of existing prefix constructors. So, if we do want to support that, do we end up having to create
|
Another variation on not supporting zones that I would prefer to the current beahviour: Have ParsePrefix return an error if there's a zone present. This is the same as the net.ParseCIDR behaviour, but may still be unpalatable as it's a behaviour change for ParsePrefix. |
Silently dropping zones seems like the worst of all worlds: Incorrect and surprising. While having ParsePrefix return an error if a zone is present is a behavior change, the current behavior is documented as parsing RFC 4291 notation and RFC 4291 does not (unless I'm missing something) allow for zones in prefixes. Therefore I think it's reasonable to say that accepting prefixes with zones is simply a bug, and ParsePrefix should return an error for this condition just as ParseCIDR does. |
https://www.rfc-editor.org/rfc/rfc4291.html#section-2.3 Interesting, I suppose I had never bothered to check the docs for ParseCIDR since I've been pretty intimately familiar with its use. You're correct: section 2.3 here makes no mention of IPv6 zones at all and simiply says:
Since updating |
Change https://go.dev/cl/396299 mentions this issue: |
EDIT 2022-03-29: Go is documented to comply with https://www.rfc-editor.org/rfc/rfc4291.html#section-2.3 which makes no mention of IPv6 prefix + zone syntax.
Leaving the rest of this message alone for historical context.
What version of Go are you using (
go version
)?Go 1.18, tip
Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?linux/amd64, but n/a.
What did you do?
Attempted to parse a link-local IPv6 address prefix with zone:
fe80::%2/64
https://go.dev/play/p/EeZwl0aah3q
What did you expect to see?
net.ParseCIDR
: no error, valid*net.IPNet
with zonenetip.ParsePrefix
: no error, valid*netip.Prefix
with zoneWhat did you see instead?
net.ParseCIDR
: error:invalid CIDR address: fe80::%2/64
netip.ParsePrefix
: no error,fe80::/64
returned with zone strippedThis was brought to my attention by a blog and associated thread on reddit:
https://old.reddit.com/r/golang/comments/tkf9rm/a_tiny_flaw_in_gos_netip_design/
https://adam-p.ca/blog/2022/03/go-netip-flaw/
While working on
inet.af/netaddr
which ultimately becamenet/netip
, I don't believe we were able to find any evidence of an IPv6 prefix with associated zone. However, that evidence turned up today while I was doing further research:RFC 4007: IPv6 Scoped Address Architecture, March 2005
https://datatracker.ietf.org/doc/html/rfc4007#section-11.7
Note that the prefix
fe80::%2/64
should be considered valid, and thus both the current behaviors ofnet.ParseCIDR
andnetip.ParsePrefix
are incorrect. I believe this was an oversight on my part during the development ofinet.af/netaddr
, as I was the primary user of IPv6 link-local addresses with zones. However, I have not run into a need to use IPv6 prefixes with zones as of yet.Either way, I believe both functions should be updated to handle this case as appropriate.
In addition, RFC6874, Section 1 (https://datatracker.ietf.org/doc/html/rfc6874#section-1) says:
I don't believe the status quo has changed in the 9 years since that RFC, and would suggest that we do one of the following:
ip.IsLinkLocalUnicast() == true
or IP is contained infe80::/10
EDIT: as a data point, since
net/netip
already accepts the following, even given the RFC text above, I am in favor of option 1.I do think this should be fixed for link-local addresses at a minimum though. If we agree this should be done, I'm happy to fix this in both
net
andnet/netip
./cc @bradfitz @danderson @josharian @ianlancetaylor @neild
The text was updated successfully, but these errors were encountered: