Get Ip Address WPF and C# Display Issue - c#

anyone know why when I run this code
IPHostEntry
IPHost = System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName());
foreach
(var
ipAddress in
IPHost.AddressList)
{
IPlabel.Content = ipAddress;
}
It returns it in a format of: 2001:1:9d39:6 ...?
Id be looking to get this in format of IPv4: xxx.xxx.xxx.xxx
Not sure if theirs a duplicate post or not, I've been looking for quite some time. I might not be using the right search key words
Appreciate any help &or post you folks could provide.

I believe this has been answered here?
Getting the ip-address
// return the first IPv4, non-dynamic/link-local, non-loopback address
public static IPAddress GetIPAddress()
{
IPAddress[] hostAddresses = Dns.GetHostAddresses("");
foreach (IPAddress hostAddress in hostAddresses)
{
if (hostAddress.AddressFamily == AddressFamily.InterNetwork &&
!IPAddress.IsLoopback(hostAddress) && // ignore loopback addresses
!hostAddress.ToString().StartsWith("169.254.")) // ignore link-local addresses
return hostAddress;
}
return null; // or IPAddress.None if you prefer
}

Related

Why IP Address return value 127.0.0.1?

I try type ipconfig on cmd.exe and ip address ="172.24.70.68"
But If i get IP of this PC, it return IP: 127.0.0.1
This my code get IP Address:
IPAddress ip = null;
IPAddress mask = null;
//++**********************************
// Get IP
//--**********************************
strHostName = Dns.GetHostName();
IPHostEntry iphe = Dns.GetHostEntry(strHostName);
foreach (IPAddress ipheal in iphe.AddressList)
{
if (ipheal.AddressFamily ==AddressFamily.InterNetwork)
{
ip = ipheal;
break;
}
}
Why IP Address return value 127.0.0.1?
Some other PCs, it getting IP is ok.
Try not to get the address via DNS, which may be deceiving or simply not working if for example there are no DNS records for the computer, but via the adapter settings, which is essentially the same ipconfig does.
You can get all of the adapters with NetworkInterface.GetAllNetworkInterfaces(). The NetworkInterfaceType property let's you filter for Ethernet adapters as well as exclude the loop back adapter. You can also filter only for adapters in a particular status, e.g. up, with the OperationalStatus property.
You can then loop through all the unicast addresses of the adapter and pick one of the IPv4 addresses from it, for example the first one encountered. Of course, if you have more adapters or addresses on one adapter this might still not be the one you're looking for. In that case you need to define how to recognize the one you want and implement that accordingly.
IPAddress ip = null;
IPAddress mask = null;
foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces())
{
bool found = false;
if (networkInterface.NetworkInterfaceType == NetworkInterfaceType.Ethernet
&& networkInterface.OperationalStatus == OperationalStatus.Up
&& networkInterface.NetworkInterfaceType != NetworkInterfaceType.Loopback)
{
foreach (UnicastIPAddressInformation unicastIPAddressInformation in networkInterface.GetIPProperties().UnicastAddresses)
{
if (unicastIPAddressInformation.Address.AddressFamily == AddressFamily.InterNetwork)
{
ip = unicastIPAddressInformation.Address;
mask = unicastIPAddressInformation.IPv4Mask;
found = true;
break;
}
}
}
if (found)
{
break;
}
}
You need to use forwarder Header
.net core example
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardLimit = 2;
options.KnownProxies.Add(IPAddress.Parse("127.0.10.1"));
options.ForwardedForHeaderName = "X-Forwarded-For-My-Custom-Header-Name";
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor |
ForwardedHeaders.XForwardedProto;
});

Removing the port from a IP string that is IPv6 safe in C#

I need the IP without port on users that make requests in a rest API running on ASP.NET MVC. It seems the way to get the address is a combination of these:
HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]
HttpContext.Current.Request.UserHostAddress;
Which give me a string with IP:Port
IPV4 is simple, but from reading I expect IPV6 will give me something like this:
[1fff:0:a88:85a3::ac1f]:8001
IPAddress.Parse can handle IPv6 with port but not IPv4 with port which is strange.
I could inspect the string to see what kind of address it is, but I feel like there should be a better way.
Any ideas?
Here is my makeshift version in the mean time
public string StripPortFromEndPoint(string endPoint)
{
var splitList = endPoint.Split(':');
if (splitList.Length > 2)
{
endPoint = IPAddress.Parse(endPoint).ToString();
}
else if (splitList.Length == 2)
{
endPoint = splitList[0];
}
else
{
throw new ParseException("No port separator found",0);
}
return endPoint;
}

Get the Default Gateway

I'm writing a program that shows the user their IP address, Subnet mask and Default gateway. I can get the first two, but for the last one, this is what I turned up:
GatewayIPAddressInformationCollection gwc =
System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()[0].GetIPProperties().GatewayAddresses;
That, of course, returns a collection of GatewayIPAddressInformation. So, if a computer has multiple gateways, how can I determine which is the default gateway?
In practice, I've only ever seen this collection contain a single entry, but since it's implemented as a collection, it stands to reason that some computers contain multiple gateways, none of which are marked as "Default". So is there a way to determine the default or is it all just guesswork?
It will probably be the first valid and enabled gateway address of the first enabled network interface:
public static IPAddress GetDefaultGateway()
{
return NetworkInterface
.GetAllNetworkInterfaces()
.Where(n => n.OperationalStatus == OperationalStatus.Up)
.Where(n => n.NetworkInterfaceType != NetworkInterfaceType.Loopback)
.SelectMany(n => n.GetIPProperties()?.GatewayAddresses)
.Select(g => g?.Address)
.Where(a => a != null)
// .Where(a => a.AddressFamily == AddressFamily.InterNetwork)
// .Where(a => Array.FindIndex(a.GetAddressBytes(), b => b != 0) >= 0)
.FirstOrDefault();
}
I've also added some further commented checks which have been pointed out as useful by other people here. You can check the AddressFamily one to distinguish between IPv4 and IPv6. The latter one can be used to filter out 0.0.0.0 addresses.
The above solution will give you a valid/connected interface, and is good enough for 99% of situations. That said, if you have multiple valid interfaces that traffic can be routed through, and you need to be 100% accurate, the way to do this uses GetBestInterface to find an interface for routing to a specific IP address. This additionally handles the case where you might have a specific address range routed through a different adapter (e.g. 10.*.*.* going through a VPN, everything else going to your router)
[DllImport("iphlpapi.dll", CharSet = CharSet.Auto)]
private static extern int GetBestInterface(UInt32 destAddr, out UInt32 bestIfIndex);
public static IPAddress GetGatewayForDestination(IPAddress destinationAddress)
{
UInt32 destaddr = BitConverter.ToUInt32(destinationAddress.GetAddressBytes(), 0);
uint interfaceIndex;
int result = GetBestInterface(destaddr, out interfaceIndex);
if (result != 0)
throw new Win32Exception(result);
foreach (var ni in NetworkInterface.GetAllNetworkInterfaces())
{
var niprops = ni.GetIPProperties();
if (niprops == null)
continue;
var gateway = niprops.GatewayAddresses?.FirstOrDefault()?.Address;
if (gateway == null)
continue;
if (ni.Supports(NetworkInterfaceComponent.IPv4))
{
var v4props = niprops.GetIPv4Properties();
if (v4props == null)
continue;
if (v4props.Index == interfaceIndex)
return gateway;
}
if (ni.Supports(NetworkInterfaceComponent.IPv6))
{
var v6props = niprops.GetIPv6Properties();
if (v6props == null)
continue;
if (v6props.Index == interfaceIndex)
return gateway;
}
}
return null;
}
These two examples could be wrapped up into a helper class and used in the appropriate cases: that you do, or do not have a destination address in mind already.
The first IP address returned by traceroute command will be the gateway .You can use this fact for getting gateway.A nice implementation of tracerout can be found here:
TraceRoute and Ping in C#
according to #midspace's comment on #caesay's answer this is a better answer:
public static IPAddress GetDefaultGateway()
{
var gateway_address = NetworkInterface.GetAllNetworkInterfaces()
.Where(e => e.OperationalStatus == OperationalStatus.Up)
.SelectMany(e => e.GetIPProperties().GatewayAddresses)
.FirstOrDefault();
if (gateway_address == null) return null;
return gateway_address.Address;
}
I'm warning that it's not a complete solution, if your'e looking for the main interface responsible for the internet access, you should combine other approaches like using win32 API GetBestInterface to find the best interface to connect to a destination address.
you can find example usage here: http://www.pinvoke.net/default.aspx/iphlpapi.getbestinterface
I've just come across this and will be using the following code - basically it looks for interfaces that aren't loopback and are up and have gateways and unicast addresses. From the interface I then get a non transient IPV4 address.
public static class NetworkInterfaces
{
public static NetworkInterface GetDefaultInterface()
{
var interfaces = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
foreach (var intf in interfaces)
{
if (intf.OperationalStatus != OperationalStatus.Up)
{
continue;
}
if (intf.NetworkInterfaceType == NetworkInterfaceType.Loopback)
{
continue;
}
var properties = intf.GetIPProperties();
if (properties == null)
{
continue;
}
var gateways = properties.GatewayAddresses;
if ((gateways == null) || (gateways.Count == 0))
{
continue;
}
var addresses = properties.UnicastAddresses;
if ((addresses == null) || (addresses.Count == 0))
{
continue;
}
return intf;
}
return null;
}
public static IPAddress GetDefaultIPV4Address(NetworkInterface intf)
{
if (intf == null)
{
return null;
}
foreach (var address in intf.GetIPProperties().UnicastAddresses)
{
if (address.Address.AddressFamily != AddressFamily.InterNetwork)
{
continue;
}
if (address.IsTransient)
{
continue;
}
return address.Address;
}
return null;
}
}
I know this is a slightly older question but, I had just come upon the need to retrieve the IPV4 address of the local gateway. The accepted answer doesn't quite fit the bill when it comes to my own system so, I modified it to suite and I'm sure others will be able to use this solution, too.
Since I don't yet have enough rep to comment, I'm forced to add this as a "question":
public static IPAddress GetDefaultGateway()
{
IPAddress result = null;
var cards = NetworkInterface.GetAllNetworkInterfaces().ToList();
if (cards.Any())
{
foreach (var card in cards)
{
var props = card.GetIPProperties();
if (props == null)
continue;
var gateways = props.GatewayAddresses;
if (!gateways.Any())
continue;
var gateway =
gateways.FirstOrDefault(g => g.Address.AddressFamily.ToString() == "InterNetwork");
if (gateway == null)
continue;
result = gateway.Address;
break;
};
}
return result;
}
Been looking for one weird trick to determine the local IP address?
Yet do it very robustly vs. the earlier methods?
[See end for response to #caesay]
This may be what you are looking for.
using (var s = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Dgram,ProtocolType.Udp))
{
s.Bind( new System.Net.IPEndPoint(System.Net.IPAddress.Any,0));
s.Connect("google.com",0);
var ipaddr = s.LocalEndPoint as System.Net.IPEndPoint;
var addr = ipaddr.Address.ToString();
Console.WriteLine(addr);
}
That will create a UDP socket, but will not send data on it.
You can then see what local interface and address the socket was bound to.
You must supply an IP address or hostname where I used google.com, that will
be used by the OS to determine which interface the socket will be bound to,
and what IP address you will find using this method.
For 99%+ of IP addresses or hostnames you use, you will get the interface+address to be used for traffic over the default route.
While this is a little obtuse, I suspect it is more reliable than the methods above where people use the PInvoke call and scan through the structures to see if they can find the interface.
I certainly found it more robust on my 3x double interface systems than scanning through the results of NetworkInterface.GetAllNetworkInterfaces() using heuristics to try to figure out the default interface address.
[Update/response to #caesay 2/6/2019]
#caesay Has made an excellent point here, so I have switched the sample from using UdpClient to Socket, and explicitly called Socket.Connect() after Bind(). I have also reviewed the Framework source for Connect() and LocalEndPoint, and both call their corresponding Win32 OS system call immediately without deferring or being lazy about calling into the OS. The Win32 bind page says "The application can use getsockname after calling bind to learn the address and the port that has been assigned to the socket. If the Internet address is equal to INADDR_ANY or in6addr_any, getsockname cannot necessarily supply the address until the socket is connected".
This condition is now explicitly addressed, and having reviewed the Framework source, the IP address should always be available after the Connect() call.
NetworkInterface[] allNICs = NetworkInterface.GetAllNetworkInterfaces();
foreach (var nic in allNICs)
{
var ipProp = nic.GetIPProperties();
var gwAddresses = ipProp.GatewayAddresses;
if (gwAddresses.Count > 0 &&
gwAddresses.FirstOrDefault(g => g.Address.AddressFamily == AddressFamily.InterNetwork) != null)
{
localIP = ipProp.UnicastAddresses.First(d => d.Address.AddressFamily == AddressFamily.InterNetwork).Address;
}
}
Debug.Print(localIP.ToString());
(Just after posting I noticed an earlier answer that mentioned the idea of using traceroute. I probably wouldn't have responded if I'd seen that. But I have included complete/compact code.)
Here's a different approach that finds the default gateway by using a traceroute type method. Ping an address on the internet (or other network you want to get to) with a TTL of 1, and let ping tell you what the first hop IP address was. That ought to be the gateway you're looking for.
I suppose this could go wrong if the gateway was configured not to reply to pings, but I don't think I've ever heard of a network set up that way.
Note: This routine kind-of even works if you pass it an IPV6 address. The potential issue is that it seems to return an IPV6 address with Global scope, rather than Link-Local scope. I don't have enough experience using IPV6 to know if that's good or bad. But I do know that the Windows ipconfig command displays the Link-Local IPV6 addresses of the interface gateway.
using System.Net
using System.Net.NetworkInformation
// ping internet address with ttl=1 and return address of host where ttl expired
public static IPAddress FindDefaultGateway(IPAddress netaddr = null)
{
// user can provide an ip address that exists on the network they want to connect to,
// or this routine will default to 1.1.1.1 (IP of a popular internet dns provider)
if (netaddr is null)
netaddr = IPAddress.Parse("1.1.1.1");
PingReply reply = default;
using var ping = new Ping();
var options = new PingOptions(1, true); // ttl=1, dont fragment=true
try {
// I arbitrarily used a 200ms timeout; tune as you see fit.
reply = ping.Send(netaddr, 200, new byte[0], options);
}
catch (PingException) {
System.Diagnostics.Debug.WriteLine("Gateway not available");
return default;
}
if (reply.Status != IPStatus.TtlExpired) {
System.Diagnostics.Debug.WriteLine("Gateway not available");
return default;
}
return reply.Address;
}
I think that you should iterate over this collection and show all the Gateways, since if there are many gateways to an adapter they are all considered Default to that adapter

Resolve HostName to IP

I have been through a lot of googling for this, I found a lot of examples none of which was working for me. This is a simple issue which I feel has a simple answer without defining new classes\modules etc...
My code is this :
Console.WriteLine ("Please enter an IP address or hostname");
string host = Console.ReadLine ();
***IP = resolved "host"***
Socket s = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
s.Connect (IP, 80);
s.close();
How do I actually resolve the IP variable?
You can simply use the DNS class to do so:
IPHostEntry hostEntry;
hostEntry= Dns.GetHostEntry(host);
//you might get more than one ip for a hostname since
//DNS supports more than one record
if (hostEntry.AddressList.Length > 0)
{
var ip = hostEntry.AddressList[0];
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
s.Connect(ip, 80);
}
string howtogeek = "www.howtogeek.com";
IPAddress[] addresslist = Dns.GetHostAddresses(howtogeek);
foreach (IPAddress theaddress in addresslist)
{
Console.WriteLine(theaddress.ToString());
}
from howtogeek
Please take the note that accepted answer can resolve to IPv6. I attempted to connect to service that does not accept IPv6 as input string.
Therefore try this snippet if you care to get IPv4:
using System.Linq;
string host = "google.com";
Dns.GetHostEntry(host).AddressList.First(addr => addr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
This is the method I use to resolve a hostname to IPv4 and / or IPv6.
using System.Net:
// A host can have multiple IP addresses!
public static IPAddress[] GetIPsByName(string hostName, bool ip4Wanted, bool ip6Wanted)
{
// Check if the hostname is already an IPAddress
IPAddress outIpAddress;
if (IPAddress.TryParse(hostName, out outIpAddress) == true)
return new IPAddress[] { outIpAddress };
//<----------
IPAddress[] addresslist = Dns.GetHostAddresses(hostName);
if (addresslist == null || addresslist.Length == 0)
return new IPAddress[0];
//<----------
if (ip4Wanted && ip6Wanted)
return addresslist;
//<----------
if (ip4Wanted)
return addresslist.Where(o => o.AddressFamily == AddressFamily.InterNetwork).ToArray();
//<----------
if (ip6Wanted)
return addresslist.Where(o => o.AddressFamily == AddressFamily.InterNetworkV6).ToArray();
//<----------
return new IPAddress[0];
}
If all you want is to resolve a string that could represent either a hostname OR an IP address, you probably want to use System.Net.Dns.GetHostAddresses() rather than System.Net.Dns.GetHostEntry().
GetHostAddresses() skips the DNS lookup if the string parses to an IP address already, while GetHostEntry() will do a reverse lookup for the hostname.
https://learn.microsoft.com/en-us/dotnet/api/system.net.dns.gethostaddresses
The IpAddress has the appropriate method for parsing hostname to IpAddress.
IPAddress addr = IPAddress.Parse(hostName)

IPv4 remote address in WCF

Related to How to get the IP address of a WCF remote endpoint?
I am using this code to retrieve the remote IP address when a workflow method is invoked:
private static string GetRemoteIP()
{
var oc = OperationContext.Current;
var mp = oc.IncomingMessageProperties;
var remp = mp[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
return remp == null ? "(unknown)" : remp.Address;
}
However, the address I get back is "::1". I don't want the IPv6 address, I want the IPv4 one (127.0.0.1) - any way of forcing this?
No, I don't think so. You basically just read out a property set by the client at the time of the call. Your only option would be to instruct the client (through some config) to use IPv4 instead of IPv6 at all times (i.e. turn off IPv6 all together).
I'm not aware of any WCF setting to enforce that - you'd have to dig into the network stack and see if there's any way to make it use IPv4 addresses instead of IPv6.
You're seeing ::1 because you're connecting to the service by resolving the name "localhost" instead of addressing it as "127.0.0.1". Modern versions of Windows that have the IPv6 stack enabled will use IPv6 first.
You can disable the IPv6 stack, but that's roughly the same as making like an ostrich and sticking your head in the sand. IPv6 is here, and people are using it on their networks, so your application should be prepared to support it.
The workaround proposed by Murat will not work.
The MSDN says - if you pass the IP address to the GetHostAddresses method this address is returned in an array without querying the DNS.
To get it working you will need to query for the host name first, using GetHostEntry method. And then, using the host name, use GetHostAddresses. However, even the GetHostEntry may have the list of addresses that will be enough for you.
Here is a workaround: (You can store the values in a hashtable to avoid multiple DNS operations)
static string GetClientIP()
{
var context = OperationContext.Current;
var mp = context.IncomingMessageProperties;
var propName = RemoteEndpointMessageProperty.Name;
var prop = (RemoteEndpointMessageProperty) mp[propName];
string remoteIP = prop.Address;
if(remoteIP.IndexOf(":") > -1)
{
IPAddress[] addresses = Dns.GetHostAddresses(remoteIP);
for (int i = 0; i < addresses.Length; i++)
{
if(addresses[i].ToString().IndexOf(".")>-1)
return addresses[i].ToString();
}
return remoteIP;
}
else
{
return remoteIP;
}
}
You could use AddressFamily.InterNetwork == address.AddressFamily and AddressFamily.InterNetworkV6 as a test instead of looking for ":" or "." in the addresses strings.

Categories