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

IPNetwork.Contains for IPv4 networks should match IPv4-Mapped IPv6 Addresses #98427

Closed
hacst opened this issue Feb 14, 2024 · 7 comments · Fixed by #103381
Closed

IPNetwork.Contains for IPv4 networks should match IPv4-Mapped IPv6 Addresses #98427

hacst opened this issue Feb 14, 2024 · 7 comments · Fixed by #103381
Labels
area-System.Net in-pr There is an active PR which will close this issue when it is merged
Milestone

Comments

@hacst
Copy link

hacst commented Feb 14, 2024

Background and motivation

Dual stack applications in .NET see connecting IPv4 addresses as IPv4-Mapped IPv6 Addresses. This is problematic when combined with the IPNetworks.Contains function specifying IPv4 networks. E.g. if I want to let the user provide a CIDR string for disallowing access I might write something like:

var disallowed = IPNetwork.Parse(disallowedCidrString);
if (disallowed.Contains(remoteIp)) {
  // Deny
} else {
  // Allow
}

As the user wants to deny an IPv4 range they write something like "10.0.0.8/8". However this creates problems because it will produce an IPv4 Network that will not match the dual stack Ipv4 mapped ipv6 address.

My interpretation is that the IPv4-Mapped IPv6 Address is actually an IPv4 address and hence should be matchable using a IPv4 IPNetwork. Under this assumption a change to the IPNetwork.Contains implementation as proposed here could prevent such confusions.

ps: I was unsure whether reporting this as an API Suggestion is correct as this does not change the visible API. However as it would be an API Behavior change it seemed to be the most fitting category. Let me know if this was incorrect.

API Proposal

No visible changes except maybe to documentation. My suggestion would be to make the Contains function use IPAddress.IsIPv4MappedToIPv6 to identify that it is actually passed an IPv4 address to make contains behave as expected.

API Usage

var address = IPAddress.Parse("::ffff:10.0.0.12");
var network = IPNetwork.Parse("10.0.0.0/8");

Debug.Assert(network.Contains(address));

Alternative Designs

Handling this as a developer without the proposed change certainly is possible by inspecting the address and network at the point of comparison to work around the existing behavior. However it has to be done carefully to get it right. E.g. simply trying to always match using a IPv6 network would fail if the server configuration was changed to bind only to IPv4.

Risks

Existing usage might in some way expect IPv6 addresses to never get be reported as being contained in IPv4 networks. I cannot think of actual use-case for this though.

@hacst hacst added the api-suggestion Early API idea and discussion, it is NOT ready for implementation label Feb 14, 2024
@ghost ghost added the untriaged New issue has not been triaged by the area owner label Feb 14, 2024
@ghost
Copy link

ghost commented Feb 14, 2024

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

Issue Details

Background and motivation

Dual stack applications in .NET see connecting IPv4 addresses as IPv4-Mapped IPv6 Addresses. This is problematic when combined with the IPNetworks.Contains function specifying IPv4 networks. E.g. if I want to let the user provide a CIDR string for disallowing access I might write something like:

var disallowed = IPNetwork.Parse(disallowedCidrString);
if (disallowed.Contains(remoteIp)) {
  // Deny
} else {
  // Allow
}

As the user wants to deny an IPv4 range they write something like "10.0.0.8/8". However this creates problems because it will produce an IPv4 Network that will not match the dual stack Ipv4 mapped ipv6 address.

My interpretation is that the IPv4-Mapped IPv6 Address is actually an IPv4 address and hence should be matchable using a IPv4 IPNetwork. Under this assumption a change to the IPNetwork.Contains implementation as proposed here could prevent such confusions.

ps: I was unsure whether reporting this as an API Suggestion is correct as this does not change the visible API. However as it would be an API Behavior change it seemed to be the most fitting category. Let me know if this was incorrect.

API Proposal

No visible changes except maybe to documentation. My suggestion would be to make the Contains function use IPAddress.IsIPv4MappedToIPv6 to identify that it is actually passed an IPv4 address to make contains behave as expected.

API Usage

var address = IPAddress.Parse("::ffff:10.0.0.12");
var network = IPNetwork.Parse("10.0.0.0/8");

Debug.Assert(network.Contains(address));

Alternative Designs

Handling this as a developer without the proposed change certainly is possible by inspecting the address and network at the point of comparison to work around the existing behavior. However it has to be done carefully to get it right. E.g. simply trying to always match using a IPv6 network would fail if the server configuration was changed to bind only to IPv4.

Risks

Existing usage might in some way expect IPv6 addresses to never get be reported as being contained in IPv4 networks. I cannot think of actual use-case for this though.

Author: hacst
Assignees: -
Labels:

api-suggestion, area-System.Net

Milestone: -

@antonfirsov
Copy link
Member

antonfirsov commented Feb 14, 2024

Apart from being a breaking change, the proposed behavior would contradict the semantics of IPAddress.Equals and the difference between the two methods could be counter-intuitive to some users. Another option to address this is to introduce a separate overload, eg. Contains(IPAddress, bool) or Contains(IPAddress, SomeComparisonMethodSelectorEnum).

@wfurt @MihaZupan thoughts/preferences?

@hacst
Copy link
Author

hacst commented Feb 14, 2024

That makes a lot of sense. Especially if it allows having something similar for IPAddress equality comparisons.

@wfurt
Copy link
Member

wfurt commented Feb 15, 2024

IPAddress has IPAddress.MapToIPv6 but IPNetwork does not. If somebody wants to treat dual mode same as IPv4 it seems easy for the IPAddress.Equals. Maybe we could use some helpers for handling the duality.

@MihaZupan
Copy link
Member

IMO users aren't generally creating IPv4-mapped IPv6 addresses themselves, this is more of an implementation detail of dual mode sockets.
E.g. someone connects to your Kestrel server over IPv4, but IPNetwork.Contains(HttpContext.Connection.RemoteIpAddress) fails because it's mapped to IPv6.

From a usability perspective, I would prefer if we treated such addresses as IPv4 for the purposes of IPNetwork.Contains. I think we should consider the breaking change to the existing overload.

@antonfirsov
Copy link
Member

antonfirsov commented Feb 21, 2024

IPAddress has IPAddress.MapToIPv6 but IPNetwork does not. If somebody wants to treat dual mode same as IPv4 it seems easy for the IPAddress.Equals. Maybe we could use some helpers for handling the duality.

I don't know what helpers did you mean, but I think it's easier to map the IPAddress to be tested with Contains(address), than the IPNetwork. But now I tend to agree with OP and #98427 (comment), and I think we should consider changing the default behavior in 9.0. If we decide not to do it, we should document it providing examples for the mapping.

@antonfirsov antonfirsov removed the untriaged New issue has not been triaged by the area owner label Feb 21, 2024
@antonfirsov antonfirsov added this to the 9.0.0 milestone Feb 21, 2024
@antonfirsov antonfirsov removed the api-suggestion Early API idea and discussion, it is NOT ready for implementation label Feb 21, 2024
@antonfirsov antonfirsov changed the title [API Proposal]: IPNetwork.Contains for IPv4 networks should match IPv4-Mapped IPv6 Addresses IPNetwork.Contains for IPv4 networks should match IPv4-Mapped IPv6 Addresses Feb 21, 2024
@wfurt
Copy link
Member

wfurt commented Feb 22, 2024

I'm ok if we choose to change the behavior @antonfirsov. But I wanted to explore other options as well if we are concerned about compatibiliyty.

@dotnet-policy-service dotnet-policy-service bot added the in-pr There is an active PR which will close this issue when it is merged label Jun 12, 2024
@github-actions github-actions bot locked and limited conversation to collaborators Jul 18, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Net in-pr There is an active PR which will close this issue when it is merged
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants