I want to find the ip that my computer connects to the internet correctly.I have questions about a few things I have tried.
Firstly :
foreach(NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces()) {
var addr = ni.GetIPProperties().GatewayAddresses.FirstOrDefault();
if (addr != null && ni.OperationalStatus == OperationalStatus.Up) {
switch (ni.NetworkInterfaceType) {
case NetworkInterfaceType.Wireless80211:
case NetworkInterfaceType.Ethernet:
{
foreach(UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses) {
if (ip.Address.AddressFamily == AddressFamily.InterNetwork) {
return ip.Address.ToString();
}
}
break;
}
}
}
}
When I tried the code above, if my computer has a virtual adapter installed (for example vpn), the vpn adapter is also detected as ethernet and operational status up. When I run vpn, there are two strings ip like (192.168.1.24 and 25.25.1.150).
As a result of this error, I decided to find the name of my computer and ping it and find a rope with the returned result.
like the code below:
int timeout = 10000;
Ping ping = new Ping();
try {
PingReply pingreply = ping.Send(Environment.MachineName.ToString(), timeout);
if (pingreply.Status == IPStatus.Success) {
return pingreply.Address.ToString();
}
}
catch(Exception ex) {
LogHelper.WriteErrorLog(ex);
return String.Empty;
}
return String.Empty;
The code above works fine, but there are a few things I can't be sure of. Is there a possibility that the hostname with the second code will be return null? If there are two computer names in the same domain(can be possible?), can I get the correct result from the ping result? Is there any other way than these two codes find correctly under all circumstances? Thank you.
I'm trying to get the user's IP address from ASP.NET MVC 5. I've looked up various examples, such as these:
https://stackoverflow.com/a/740431/177416
https://stackoverflow.com/a/20194511/177416
https://stackoverflow.com/a/3003254/177416
They've all produced the same result: the user is considered internal to the network. I've had friends try their phones (which are not on the network). Here's my latest attempt:
private static Logger _logger = LogManager.GetCurrentClassLogger();
public static bool IsIpInternal()
{
var ipAddress = HttpContext.Current.Request.UserHostAddress;
var logEvent = new LogEventInfo(LogLevel.Info, _logger.Name, ipAddress);
_logger.Log(logEvent);
try
{
if (ipAddress != null)
{
var ipParts = ipAddress.Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries)
.Select(int.Parse).ToArray();
var isDebug = System.Diagnostics.Debugger.IsAttached;
if (ipParts[0] == 10)
{
return true;
}
}
}
catch (Exception e)
{
logEvent = new LogEventInfo(LogLevel.Error, _logger.Name, e.Message);
_logger.Log(logEvent);
return false;
}
return false;
}
The log is showing 10.xxx.xx.xxx for all requests (based on the log). This is an internal address rather than the IP of the client connecting to the web app. The IsIpInternal() returns true always. What am I doing wrong?
Note that I'm ignoring 192.168.x.x and 172.16.xxx.xxx addresses as being internal.
If your web site is behind a load balancer, it is a common problem for the load balancer's IP address to appear when you are expecting the client's IP address. That is because in reality the load balancer is the only client that the web application knows is talking to it.
There are two ways to deal with this:
You can configure the load balancer to add an additional HTTP header (x-forwarded-for) that specifies the original IP address. You will need to modify your web site to look at this header instead of the UserHostAddress, like this:
//var clientIP = HttpContext.Current.Request.UserHostAddress;
var clientIP = HttpContext.Current.Request.Headers["x-forwarded-for"];
Note: The x-forwarded-for header can actually return a comma-delimited list of IP addresses in some cases. So to be compatible with such an occurence, you might write this instead:
var clientIP = HttpContext.Current.Request.Headers["x-forwarded-for"].Split(',')[0];
You can configure certain LBs to pass through the client IP by copying the IP header packet. For Citrix Netscaler, see this article for more information.
I have an program in production environment where I like to have a window to open, when a remote assistance are started on the pc, so the person connecting to the pc have some more options. But i can't find anything if this is possible? If so any idea how to detect it?
This can be done but I find it tricky and I generally avoid this. See How to detect RDC from C#.net for more info.
To start RDP listens on port 3389 so something like this should work.
int port = 3389;
using (var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(#"SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp", false))
{
if (key != null)
{
object value = key.GetValue("PortNumber");
if (value != null) port = Convert.ToInt32(value);
}
}
But the port number can be configured so this isn't the best way.
Then there is Pinvoke and Cassia. with Cassia you could do something like:
public bool IsComputerUsedByTS()
{
var tsMgr = new TerminalServicesManager();
var localSvr = tsMgr.GetLocalServer();
var sessions = localSvr.GetSessions();
foreach(var session in sessions)
{
if(session.ConnectionState == ConnectionState.Active ||
session.ConnectionState == ConnectionState.Connected) //Add more states you want to check for as needed
{
return true;
}
}
return false;
}
And last but not least:
System.Windows.Forms.SystemInformation.TerminalServerSession
This uses a forms import but is a very simple solution. If you run your program in a remote desktop environment, this returns true.
I have written the following code to get the IPv4 address of my machine. When we deploy this code on the server, this code gives me the IP address of the server, but not the machines IP on which application running?
public string getIpAddress()
{
try
{
string myHost = System.Net.Dns.GetHostName();
string myIP = null;
for (int i = 0; i <= System.Net.Dns.GetHostEntry(myHost).AddressList.Length - 1; i++)
{
if (System.Net.Dns.GetHostEntry(myHost).AddressList[i].IsIPv6LinkLocal == false)
{
myIP = System.Net.Dns.GetHostEntry(myHost).AddressList[i].ToString();
}
}
return myIP;
}
catch (Exception)
{
throw;
}
}
This is the expected behavior as this code is running on the server side.
However, if you want to get the client IP address, you can still do it by using the Request object. (See this post for more details or check on google for examples)
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