Blocking mixed IPv6 formatting in System.Net.IPAddress class - c#

I was searching an answer but I can't find it.
I am using something like this
if (IPAddress.TryParse(val, out parsedOutput))
{
// ip address
parsedOk = true;
}
I am passing as val a string which looks like this: 0:0:0:0:0:0:1111:0
I am getting in parsedOutput this: ::17.17.0.0
Is there any way to get something like this: ::1111:0 instead of this "mixed" ipv4/ipv6 value?

The notation is actually correct according to RFC 5952 (A Recommendation for IPv6 Address Text Representation). In section 5 it says:
Addresses such as IPv4-Mapped IPv6 addresses, ISATAP
[RFC5214], and IPv4-translatable
addresses
[ADDR-FORMAT]
have IPv4 addresses embedded in the low-order 32 bits of the address.
These addresses have a special representation that may mix hexadecimal
and dot decimal notations. The decimal notation may be used only for
the last 32 bits of the address. For these addresses, mixed notation
is RECOMMENDED if the following condition is met: the address can be
distinguished as having IPv4 addresses embedded in the lower 32 bits
solely from the address field through the use of a well-known prefix.
Such prefixes are defined in
[RFC4291] and
[RFC2765] at the time of this
writing.
The IPv6 address you show is an IPv4-Compatible IPv6 Address. Its use is now deprecated, but it is still an IPv6 Address with Embedded IPv4 Addresses according to RFC 4291 section 2.5.5. The parsed output is therefore correct and recommended.

Solution: It's the string you are trying to parse. IPv6 addresses must have something in the first portion of the address, so if you were to throw in something like 2000 in there like this: 2000:0:0:0:0:0:1111:0 it will parse it correctly. It has to do with the way IPv6 address are understood by the computer.

Related

Why IPAddress.Parse("192.168.001.001") works while IPAddress.Parse("192.168.001.009") don't?

I'm stuck trying to parse IP addresses from a API result where each of the four pats of the IPv4 Address comes prefixed with 0 (zeroes). Something like this:
127.000.000.001 instead of 127.0.0.1
I started getting parse errors when trying to parse 192.168.001.009. It also fails for 192.168.001.008, but works for 007, 006, 005 up to 001!!!
It also fails for 192.168.001.018, but works for .017, .016 down to 010!
It works for 192.168.001.8 or .8 and also 192.168.001.18 and .19...
Is this a bug in the CLR? Or am I missing something stupid?
Just try:
IPAddress.Parse("192.168.001.007"); // works
IPAddress.Parse("192.168.001.87"); // works
IPAddress.Parse("192.168.001.008"); // throws exception
IPAddress.Parse("192.168.001.19"); // works
IPAddress.Parse("192.168.001.019"); // throws exception
// and so on!
The numbers, since they are starting with 0, are being interpreted as octal instead of decimal. These are not C# literals, so it's up to the library to interpret it one way or another.
A simple way to test it would be to construct an IP ending in ".010", parse it, and you'll see that it was parsed as an ip ending in .8.
A possible quick and dirty solution would be to search for the regex /\.0*/ and replace it with "."
You can find more information on the wikipedia entry for Dot-decimal-notation:
A popular implementation of IP networking, originating in 4.2BSD, contains a function inet_aton() for converting IP addresses in character strings representation to internal binary storage. In addition to the basic four-decimals format and full 32-bit addresses, it also supported intermediate syntaxes of octet.24bits (e.g. 10.1234567; for Class A addresses) and octet.octet.16bits (e.g. 172.16.12345; for Class B addresses). It also allowed the numbers to be written in hexadecimal and octal, by prefixing them with 0x and 0, respectively. These features continue to be supported by software until today, even though they are seen as non-standard. But this also means addresses where an IP address component is written with a leading zero digit may be interpreted differently by different programs: some will ignore the leading zero, some will interpret the number as octal.
This is probably because 00X or 0XY are considered octal numbers which allows only digits 0 through 7. Digits 8 and 9 are an error.

How to determine if string is an IP address? [duplicate]

I have a function that returns if a given ip address is valid or not using the IPAddress class. I was testing it and it returns valid(true) even when I pass "0123456" or "11111" or "99999" without a dot as argument. I wrote it in VB.net and C# with the same result.
// C#
public bool CheckIpAddress(string ipAddr)
{
IPAddress ip = null;
return IPAddress.TryParse(ipAddr,out ip);
}
// VB.net
Public Function CheckIpAddress(ipAddr As String) As Boolean
Dim ip As IPAddress = Nothing
Return Net.IPAddress.TryParse(ipAddr, ip)
End Function
Could somebody explain me why is this happening. I have matched my code with some sources through the internet and is fine.
IP Address is just 32 bit number, so 11111 is definitely a correct IP Address. Dots in IP Address are there just to make reading them easier for humans. They are not required.
IP addresses are binary numbers, but they are usually stored in text files and displayed in human-readable notations, such as 172.16.254.1 (for IPv4), and 2001:db8:0:1234:0:567:8:1 (for IPv6).
from IP address - Wikipedia
That's why IPAddress.TryParse returns true.
It's even described on MSDN: IPAddress.Parse Method
The number of parts (each part is separated by a period) in ipString determines how the IP address is constructed. A one part address is stored directly in the network address. A two part address, convenient for specifying a class A address, puts the leading part in the first byte and the trailing part in the right-most three bytes of the network address. A three part address, convenient for specifying a class B address, puts the first part in the first byte, the second part in the second byte, and the final part in the right-most two bytes of the network address.
There is also an example (see the first one):
1 -- "65536" 0.0.255.255
2 -- "20.2" 20.0.0.2
2 -- "20.65535" 20.0.255.255
3 -- "128.1.2" 128.1.0.2
If you want to validate against a pattern, you should instead be using a RegEx.
This code should help:
Match match = Regex.Match(input, #"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$");
if (match.Success)
{
Console.WriteLine("It is a valid IP Address");
}
Since this had a vb.net tag
Public Function CheckIpAddress(ipAddr As String) As Boolean
Dim parts() As String = ipAddr.Split(New Char() {"."c}, StringSplitOptions.RemoveEmptyEntries)
Dim rv As Boolean
If parts.Length <> 4 Then
rv = False
Else
Dim anIP As Net.IPAddress
If Net.IPAddress.TryParse(ipAddr, anIP) Then
rv = True
Else
rv = False
End If
End If
Return rv
End Function

How to validate ip address in C#

I'm doing an application that uses IP address. I have to validate them to start from at least 1.0.0.1 but with the codes below it accepts 0.0.0.0:
\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b
I also tried changing it to:
\b(25[0-5]|2[0-4][0-9]|[01]?[1-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b
This code does not accept 0.0.0.0 but does not accept 100.0.0.0 to 109.0.0.0 either.
Can someone help?
Use
IPAddress addr = IPAddress.TryParse(str);
Then, if that worked get the numbers using
addr.GetAddressBytes();
and then check the byte values for the correct conditions using normal if-cases.
Save yourself the pain! Convert to a string, split on the dot character and check whether each of the 4 segments is in the range 0 or 1 to 255.
Otherwise if you use RegexBuddy (which is a fantastic app for RegEx) it has a bunch of IP address examples in the Library inc for 0.0.0.0 to 255.255.255.255:
\b(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\b
Try using this,
ValidIpAddressRegex = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$";

Read X-Forwarded-For header

I want to read the value of the X-Forwarded-For header value in a request.
I've tried
HttpContext.Current.Request.Headers["X-Forwarded-For"].Split(new char[] { ',' }).FirstOrDefault();
in C#.
OR do I need to split the header by ":" and the take the second string?
I am asking this because, Wikipedia says
The general format of the field is:
X-Forwarded-For: client1, proxy1, proxy2
The format that you get in return is client1, proxy1, proxy2
So you split it with the comma, and get the first to see the ip of your client.
If helps, this is a simple way of getting the user's IP address, considering the X_FORWARDED_FOR header
var forwardedFor = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
var userIpAddress = String.IsNullOrWhiteSpace(forwardedFor) ?
Request.ServerVariables["REMOTE_ADDR"] : forwardedFor.Split(',').Select(s => s.Trim()).FirstOrDefault();
Don't forget that X-Forwarded-For can contain whatever client writes there. It can contain XSS or SQL-injection inside.
Sometimes the first may contain one of the local (private) reserved addresses which is not useful. Also the first position(s) are open to to spoofing.
Update - April 2018: Sampling the cases of a live production website where the first address is local (private) indicates some configuration issue on the end user's network or his ISP. The cases are occurring only rarely (<1%) and consistently for the same end users.
The answer below suggests walking from right to left until you hit a public address. Not sure anyone actually does this but it points out the issue.
https://husobee.github.io/golang/ip-address/2015/12/17/remote-ip-go.html

IP address parsing in .NET

I'm using IPAddress.TryParse() to parse IP addresses. However, it's a little too permissive (parsing "1" returns 0.0.0.1). I'd like to limit the input to dotted octet notation. What's the best way to do this?
(Note: I'm using .NET 2.0)
Edit
Let me clarify:
I'm writing an app that will scan a range of IPs looking for certain devices (basically a port scanner). When the user enters "192.168.0.1" for the starting address, I want to automatically fill in "192.168.0.255" as the ending address. The problem is that when they type "1", it parses as "0.0.0.1" and the ending address fills in as "0.0.0.255" - which looks goofy.
If you are interested in parsing the format, then I'd use a regular expression. Here's a good one (source):
bool IsDottedDecimalIP(string possibleIP)
{
Regex R = New Regex(#"\b(?:\d{1,3}\.){3}\d{1,3}\b");
return R.IsMatch(possibleIP) && Net.IPAddress.TryParse(possibleIP, null);
}
That regex doesn't catch invalid IPs but does enforce your pattern. The TryParse checks their validity.
An IP address is actually a 32 bit number - it is not xxx.xxx.xxx.xxx - that's just a human readable format for the same. So IP address 1 is actually 0.0.0.1.
EDIT: Given the clarification, you could either go with a regex as has been suggested, or you could format the short cuts to your liking, so if you want "1" to appears as "1.0.0.0". you could append that and still use the parse method.

Categories

Resources