I have a VirtualBox VM installed on my machine and as such there is an ethernet adapter that appears for it. I'm enumerating through the list of my machine's IP address via the following:
public string GetLocalIpAddress()
{
try
{
string strHostName = Dns.GetHostName();
// Then using host name, get the IP address list..
IPHostEntry ipEntry = Dns.GetHostEntry(strHostName);
foreach (IPAddress ip in ipEntry.AddressList)
{
if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
return string.Format("({0})", ip.ToString());
}
}
}
catch(Exception e)
{
Global.ApplicationLog.AddApplicationLog(EnumAppEventTypes.SYSTEM_ERROR, e.ToString());
}
return "";
}
My problem is that the virtual machine's ethernet adapter also catches on the condition:
if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
Is there a way of picking out my machine's local ip address and disregarding my virtual machine's?
I'm refining Andrej Arh's answer, as the IP Address reported by GatewayAddresses can also be "0.0.0.0" instead of just null:
public static string GetPhysicalIPAdress()
{
foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
{
var addr = ni.GetIPProperties().GatewayAddresses.FirstOrDefault();
if (addr != null && !addr.Address.ToString().Equals("0.0.0.0"))
{
if (ni.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 || ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
{
foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
{
if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
{
return ip.Address.ToString();
}
}
}
}
}
return String.Empty;
}
Use WMI and check ConnectorPresent property for physical device.
public static string GetPhysicalIPAdress()
{
foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
{
if (ConnectorPresent(ni))
{
if (ni.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 || ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
{
foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
{
if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
return ip.Address.ToString();
}
}
}
}
}
return string.Empty;
}
private static bool ConnectorPresent(NetworkInterface ni)
{
ManagementScope scope = new ManagementScope(#"\\localhost\root\StandardCimv2");
ObjectQuery query = new ObjectQuery(String.Format(
#"SELECT * FROM MSFT_NetAdapter WHERE ConnectorPresent = True AND DeviceID = '{0}'", ni.Id));
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
ManagementObjectCollection result = searcher.Get();
return result.Count > 0;
}
There is one option. VM IP don't have Default Gateway, so, exclude all IP's without Default Gateway.
foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
{
var addr = ni.GetIPProperties().GatewayAddresses.FirstOrDefault();
if (addr != null)
{
if (ni.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 || ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
{
Console.WriteLine(ni.Name);
foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
{
if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
Console.WriteLine(ip.Address.ToString());
}
}
}
}
}
You can disregard the Ethernet adapter by its name. As the VM Ethernet adapter is represented by a valid NIC driver, it is fully equivalent to the physical NIC of your machine from the OS's point of view.
Related
I can't find code to find the proper IP address to use to open a TCP/IP server port on my machine.
The problem occurs because I have many network adapters. I have some Virtual Machine(s) (for example: HyperV / VirtualBox / VmWare) which create virtual network adapter and each one has its one IPAddress. So how to avoid those IPAddress (proper network card) and find the only one used to access the internet for real?
When I try to find the proper IP Address, I get the virtual network adapter card Ip Adress instead of the physical one using this code:
IPAddress properIpAddress = null;
NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface networkInterface in interfaces)
{
var ipProps = networkInterface.GetIPProperties();
foreach (var ip in ipProps.UnicastAddresses)
{
if ((networkInterface.OperationalStatus == OperationalStatus.Up) && (ip.Address.AddressFamily == AddressFamily.InterNetwork))
{
if (ip.Address.ToString() == "127.0.0.1")
{
continue;
}
properIpAddress = ip.Address;
// Console.Out.WriteLine(ip.Address.ToString() + "|" + networkInterface.Description.ToString());
Debug.WriteLine(ip.Address.ToString() + "|" + networkInterface.Description.ToString());
break;
}
}
if (properIpAddress != null)
{
break;
}
}
The real solution is to not search for an adapter in the first place.
Just use IPAddress.Any to listen on all interfaces at the given port.
using(TcpListener tcpListener = new TcpListener(IPAddress.Any, somePortNumber))
{
// some code
}
I've been using the following code for this. It gets you the IP that an outgoing connection would use:
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0))
{
socket.Connect("8.8.8.8", 65530);
IPEndPoint endPoint = socket.LocalEndPoint as IPEndPoint;
return endPoint.Address;
}
Note however, that it does open a socket - so maybe one should cache the result.
I'm now using this code which works fine for me but I'm not sure it is bullet proof.
I share my code as reference because I haven't found something that worked for me, other that this:
IPAddress properIpAddress = null;
NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface networkInterface in interfaces)
{
var ipProps = networkInterface.GetIPProperties();
foreach (var ip in ipProps.UnicastAddresses)
{
if ((networkInterface.OperationalStatus == OperationalStatus.Up)
&& (ip.Address.AddressFamily == AddressFamily.InterNetwork)
&& (ipProps.IsDnsEnabled || ipProps.IsDynamicDnsEnabled))
{
if (ip.Address.ToString() == "127.0.0.1")
{
continue;
}
properIpAddress = ip.Address;
// Console.Out.WriteLine(ip.Address.ToString() + "|" + networkInterface.Description.ToString());
Debug.WriteLine(ip.Address.ToString() + "|" + networkInterface.Description.ToString());
break;
}
}
if (properIpAddress != null)
{
break;
}
}
I want to identify individual Azure app service machines so that I can record info in a database. I was thinking I would use the local ip address of the machine using the function below but I get an empty string returned back. The code works for VM's but not for app services. Any thoughts (especially if these are eventually behind a load balancer and running identical code. (any string is ok... it doesn't have to be an ip address)
public static string GetLocalIpAddress()
{
UnicastIPAddressInformation mostSuitableIp = null;
var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (var network in networkInterfaces)
{
if (network.OperationalStatus != OperationalStatus.Up)
continue;
var properties = network.GetIPProperties();
if (properties.GatewayAddresses.Count == 0)
continue;
foreach (var address in properties.UnicastAddresses)
{
if (address.Address.AddressFamily != AddressFamily.InterNetwork)
continue;
if (IPAddress.IsLoopback(address.Address))
continue;
if (!address.IsDnsEligible)
{
if (mostSuitableIp == null)
mostSuitableIp = address;
continue;
}
// The best IP is the IP got from DHCP server
if (address.PrefixOrigin != PrefixOrigin.Dhcp)
{
if (mostSuitableIp == null || !mostSuitableIp.IsDnsEligible)
mostSuitableIp = address;
continue;
}
return address.Address.ToString();
}
}
return mostSuitableIp != null
? mostSuitableIp.Address.ToString()
: "";
}
Background:
My program starts up and it must obtain the IP address of the machine it is running on.
It is the "server" in a client-server architecture that receives incoming tcp-ip messages.
I should also add the machine :
Has multi-ip addresses available
Is running Windows 2008 R2 Server
Here is the code that obtains the IP address:
public bool IsNetworkAvailable
{
get
{
return System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable();
}
}
public string thisIP { get; private set; }
public void GetThisIP()
{
if (!string.IsNullOrEmpty(thisIP))
{
return;
}
thisIP = "*";
if (IsNetworkAvailable)
{
using (System.Net.Sockets.Socket socket = new System.Net.Sockets.Socket(
System.Net.Sockets.AddressFamily.InterNetwork,
System.Net.Sockets.SocketType.Dgram, 0))
{
socket.Connect("11.0.1.5", 65530);
System.Net.IPEndPoint endPoint = socket.LocalEndPoint as System.Net.IPEndPoint;
thisIP = endPoint.Address.ToString();
}
}
}
Here is the error message:
(0x80004005): A socket operation was attempted to an unreachable network 11.0.1.5:65530
at System.Net.Sockets.Socket.Connect(IPAddress[] addresses, Int32 port)
SOLUTION:
I have changed my code to what rodcesar.santos suggested in this:
Get local IP address
here is my (modified) code (and it works)
System.Net.NetworkInformation.UnicastIPAddressInformation mostSuitableIp = null;
var networkInterfaces = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
foreach (var network in networkInterfaces)
{
if (network.OperationalStatus != System.Net.NetworkInformation.OperationalStatus.Up)
{
continue;
}
var properties = network.GetIPProperties();
if (properties.GatewayAddresses.Count == 0)
{
continue;
}
if (mostSuitableIp != null)
{
break;
}
foreach (var address in properties.UnicastAddresses)
{
if (address.Address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork)
{
continue;
}
if (System.Net.IPAddress.IsLoopback(address.Address))
{
continue;
}
if (mostSuitableIp == null && address.IsDnsEligible)
{
mostSuitableIp = address;
break;
}
}
}
thisIP = mostSuitableIp != null ? mostSuitableIp.Address.ToString() : "";
After reading the accepted answer # A socket operation was attempted to an unreachable host,
I assume that the specific client-computer than receives this error has a somewhat faulty network.
Quoting #Stephen Cleary
This error indicates that the network was not connected or not configured correctly. It is definitely an error on the client machine, not your server.
There isn't much you can do to "solve" the problem. Pretty much all you can do is upgrade the client's network drivers and check for connection problems (maybe they're barely within wireless range, or the Ethernet cable is missing its locking tab).
System.Net.NetworkInformation.UnicastIPAddressInformation mostSuitableIp = null;
var networkInterfaces = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
foreach (var network in networkInterfaces)
{
if (network.OperationalStatus != System.Net.NetworkInformation.OperationalStatus.Up)
{
continue;
}
var properties = network.GetIPProperties();
if (properties.GatewayAddresses.Count == 0)
{
continue;
}
if (mostSuitableIp != null)
{
break;
}
foreach (var address in properties.UnicastAddresses)
{
if (address.Address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork)
{
continue;
}
if (System.Net.IPAddress.IsLoopback(address.Address))
{
continue;
}
if (mostSuitableIp == null && address.IsDnsEligible)
{
mostSuitableIp = address;
break;
}
}
}
thisIP = mostSuitableIp != null ? mostSuitableIp.Address.ToString() : "";
If we have multiple network interfaces with the same DNS suffix on a given machine, how do I programatically determine which network interface traffic will be routed over?
For example, I am connected to my companies network via ethernet in office, and connected to the companies network via VPN from inside the office. This sounds stupid, but with the way our networks are connected, if the internal link to our datacenter goes down - I VPN from inside the office to continue development.
Our software has logic to determine our "local ip address" and uses that for authentication logic elsewhere. I know from practice that all my traffic is routed over the VPN when connected - but am struggling with what the correct implementation in code is for robustly choosing the IP address of the adapter with the highest priority.
What I have right now is:
var unicastIpAddressInformation = NetworkInterface.GetAllNetworkInterfaces()
.Where(nic => nic.OperationalStatus == OperationalStatus.Up
&& nic.NetworkInterfaceType != NetworkInterfaceType.Loopback // ...ignore the loopback NIC as we don't want 127.0.0.1 (1 of 2)
&& nic.Name.IndexOf("loopback", StringComparison.OrdinalIgnoreCase) == -1 // ...ignore the loopback NIC as we don't want 127.0.0.1 (2 of 2)
&& nic.Name.IndexOf("virtual", StringComparison.OrdinalIgnoreCase) == -1 // ... ignore virtual NICs so that VMs don't conflict with IP resolution
)
.Select(n => n.GetIPProperties())
// All developer network connections should have the my-company-internal.com suffix
.Where(ipp => ipp.DnsSuffix.ToLowerInvariant().IndexOf("my-company-internal.com", StringComparison.OrdinalIgnoreCase) >= 0)
.Where(ipp => ipp.UnicastAddresses.Any(u => u.Address.AddressFamily == AddressFamily.InterNetwork))
// Is this order by correct?
.OrderByDescending(ipp => ipp.GetIPv4Properties().Index)
.SelectMany(ipp => ipp.UnicastAddresses.Where(ip => ip.Address.AddressFamily == AddressFamily.InterNetwork))
.FirstOrDefault();
I know with the IPV4Properties.Index - it is only populated when IPv4 is enabled; I don't know if corresponds to priority or metric, and whether or not they are guaranteed to be distinct.
I had the same problem here a few weeks ago. I figured out that the NIC priority is persisted in Windows Registry, and there are a few PowerShell scripts that can give you the NIC order, but not the IP addresses. So, I've written the code below and it worked for me. You can use it to see additional info like dns suffix, gateway address and plus.
You just have to call RMSNetUtils.GetTopIpv4Ip(string.Empty)
public class RMSNetUtils
{
private static string _linkagePath = #"SYSTEM\CurrentControlSet\Services\Tcpip\Linkage";
private static string _interfacesPath = #"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\";
private static List<string> GetBindingsPriority()
{
using (var bindMasterKey = Registry.LocalMachine.OpenSubKey(_linkagePath))
{
var bind = (string[]) bindMasterKey.GetValue("Bind");
var deviceList = bind.Select(x => $#"{_interfacesPath}{x.Replace("\\Device\\", string.Empty)}")
.ToList();
var result = new List<string>();
foreach (var device in deviceList)
{
using (var bindKey = Registry.LocalMachine.OpenSubKey(device))
{
var fixIP = (string[])bindKey.GetValue("IPAddress");
if (fixIP != null)
{
result.Add( fixIP.FirstOrDefault());
continue;
}
var dhcpIp = bindKey.GetValue("DhcpIPAddress");
if (dhcpIp != null)
{
result.Add((string) dhcpIp);
}
}
}
return result;
}
}
private static List<NICInformation> GetFilteredBindings()
{
var bindings = GetBindingsPriority();
var nicsInfo = GetIpList(GetInterNetworkAdapters());
var result = new List<NICInformation>();
foreach (var bind in bindings)
{
var nicInfo = nicsInfo.FirstOrDefault(y => string.Compare(y.IPv4, bind) == 0);
if(nicInfo!= null)
result.Add(nicInfo);
}
return result;
}
private static IEnumerable<IPAddress> GetInterNetworkAdapters()
{
IPHostEntry local = Dns.GetHostEntry(string.Empty);
return (from ipa in local.AddressList
where ipa.AddressFamily == AddressFamily.InterNetwork
select ipa);
}
public static string GetFirstIpv4Ip()
{
return GetFirstIpv4Ip(String.Empty);
}
private static List<NICInformation> GetIpList(IEnumerable<IPAddress> ips)
{
var ipAddresses = ips.Select(x => x.ToString()).ToList();
var result = new List<NICInformation>();
foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
{
if (ni.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 ||
ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
{
foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
{
if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
{
var ipStr = ip.Address.ToString();
if (ipAddresses.Contains(ipStr))
{
var nic = new NICInformation();
nic.IPv4 = ip.Address.ToString();
nic.Mask = ip.IPv4Mask.ToString();
nic.DnsSuffix = ni.GetIPProperties().DnsSuffix;
var gateway = ni.GetIPProperties().GatewayAddresses.FirstOrDefault();
if(gateway!=null)
nic.Gateway = gateway.Address.ToString();
result.Add(nic);
}
}
}
}
}
return result;
}
public static string GetTopIpv4Ip(string hostName)
{
if (!string.IsNullOrEmpty(hostName))
return GetFirstIpv4Ip(hostName);
var item = GetFilteredBindings().FirstOrDefault();
return item == null ? hostName : item.IPv4;
}
public static string GetFirstIpv4Ip(string hostName)
{
var ip = string.Empty;
try
{
IPHostEntry local = Dns.GetHostEntry(hostName);
var result = GetInterNetworkAdapters().FirstOrDefault();
return result != null ? result.ToString() : hostName;
}
catch (SocketException ex)
{
ip = hostName;
}
return ip;
}
}
public class NICInformation
{
public string DnsSuffix {get;set;}
public string IPv4 {get;set; }
public string Gateway {get;set;}
public string Mask {get;set;}
}
I got a problem synchronizing the "IP address and Description".
The objective is this:
Get the IP address and what is the description?
Example:
| Atheros Azx1234 Wireless Adapter |
|192.168.1.55 |
But the outcome is not what I expected...
This is my code feel free to try...
private void button1_Click(object sender, EventArgs e)
{
NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
IPHostEntry host;
host = Dns.GetHostEntry(Dns.GetHostName());
foreach (NetworkInterface adapter in interfaces)
{
foreach (IPAddress ip in host.AddressList)
{
if ((adapter.OperationalStatus.ToString() == "Up") && // I have a problem with this condition
(ip.AddressFamily == AddressFamily.InterNetwork))
{
MessageBox.Show(ip.ToString(), adapter.Description.ToString());
}
}
}
}
How can I fix this problem?
The problem in your code is that you do not use the associated IP addresses
for the given adapter. Instead of matching all IP addresses to every adapter
use only the IP addresses associated with the current adapter:
NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (var adapter in interfaces)
{
var ipProps = adapter.GetIPProperties();
foreach (var ip in ipProps.UnicastAddresses)
{
if ((adapter.OperationalStatus == OperationalStatus.Up)
&& (ip.Address.AddressFamily == AddressFamily.InterNetwork))
{
Console.Out.WriteLine(ip.Address.ToString() + "|" + adapter.Description.ToString());
}
}
}