15

Imagine a situation, I have PC with two lan cards, one is connected to internet another is connected to local network, how can I detect IP which is connected to internet with C# ?

Lukas Šalkauskas
  • 14,191
  • 20
  • 61
  • 77

16 Answers16

13

Try this:

static IPAddress getInternetIPAddress()
{
    try
    {
        IPAddress[] addresses = Dns.GetHostAddresses(Dns.GetHostName());
        IPAddress gateway = IPAddress.Parse(getInternetGateway());
        return findMatch(addresses, gateway);
    }
    catch (FormatException e) { return null; }
}

static string getInternetGateway()
{
    using (Process tracert = new Process())
    {
        ProcessStartInfo startInfo = tracert.StartInfo;
        startInfo.FileName = "tracert.exe";
        startInfo.Arguments = "-h 1 208.77.188.166"; // www.example.com
        startInfo.UseShellExecute = false;
        startInfo.RedirectStandardOutput = true;
        tracert.Start();

        using (StreamReader reader = tracert.StandardOutput)
        {
            string line = "";
            for (int i = 0; i < 9; ++i)
                line = reader.ReadLine();
            line = line.Trim();
            return line.Substring(line.LastIndexOf(' ') + 1);
        }
    }
}

static IPAddress findMatch(IPAddress[] addresses, IPAddress gateway)
{
    byte[] gatewayBytes = gateway.GetAddressBytes();
    foreach (IPAddress ip in addresses)
    {
        byte[] ipBytes = ip.GetAddressBytes();
        if (ipBytes[0] == gatewayBytes[0]
            && ipBytes[1] == gatewayBytes[1]
            && ipBytes[2] == gatewayBytes[2])
        {
            return ip;
        }
    }
    return null;
}

Note that this implementation of findMatch() relies on class C matching. If you want to support class B matching, just omit the check for ipBytes[2] == gatewayBytes[2].

Edit History:

  • Updated to use www.example.com.
  • Updated to include getInternetIPAddress(), to show how to use the other methods.
  • Updated to catch FormatException if getInternetGateway() failed to parse the gateway IP. (This can happen if the gateway router is configured such that it doesn't respond to traceroute requests.)
  • Cited Brian Rasmussen's comment.
  • Updated to use the IP for www.example.com, so that it works even when the DNS server is down.
Hosam Aly
  • 41,555
  • 36
  • 141
  • 182
  • 1
    This depends on the resolution of www.example.com. If it resolves to a local host (e.g. from etc/hosts), the code above will not work as expected. – Brian Rasmussen Feb 05 '09 at 14:46
  • @Brian, thanks for the note. I have no idea why anyone would do that, but it's a valid point. – Hosam Aly Feb 05 '09 at 14:49
  • Thanks Hosam. I took the freedom to use your answer in this thread: http://stackoverflow.com/questions/19591675/find-out-the-active-local-ip/19591861#19591861. Including the mentioning of you being the author. – Marco Oct 25 '13 at 17:49
  • @Serv Thanks for telling me. But you replaced example.com's IP with its domain, missing the point of the last note in my answer. – Hosam Aly Oct 26 '13 at 20:19
  • Yeah was a fault on my part, because the loop run into a null exception and I just changed that at first instead of chaning the loop counter downwards. – Marco Oct 26 '13 at 20:43
11

I suggest this simple code since tracert is not always effective and whatsmyip.com is not specially designed for that purpose :

private void GetIP()
{
    WebClient wc = new WebClient();
    string strIP = wc.DownloadString("http://checkip.dyndns.org");
    strIP = (new Regex(@"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b")).Match(strIP).Value;
    wc.Dispose();
    return strIP;
}
Hassen
  • 860
  • 2
  • 11
  • 23
9

The internet connection must be on the same IP network as the default gateway.

There's really foolproof no way to tell from the IP address if you can reach the "internet" or not. Basically you can communicate with your own IP network. Everything else has to go through a gateway. So if you can't see the gateway, you're confined to the local IP network.

The gateway, however, depends on other gateways, so even if you can access the gateway, you may not be able to reach some other network. This can be due to e.g. filtering or lack of routes to the desired networks.

Actually, it makes little sense to talk about the internet in this sense, as you will probably never be able to reach the entire internet at any given moment. Therefore, find out what you need to be able to reach and verify connectivity for that network.

Brian Rasmussen
  • 114,645
  • 34
  • 221
  • 317
  • I believe it's "as the default gateway for the internet connection". I had a machine where the default (primary) NIC was connected to the data center, and the secondary NIC was the internet. So you should select the gateway that connects you to the internet. – Hosam Aly Feb 05 '09 at 12:02
  • 1
    The point is there's really no way to be sure, but you at least have to be able to see the default gateway to get outside the local IP network. – Brian Rasmussen Feb 05 '09 at 12:06
  • I think there is a way to be sure. Take a look at my answer: http://stackoverflow.com/questions/515436#515607 – Hosam Aly Feb 05 '09 at 14:08
  • @Hosam - what I meant about "no way to be sure" was that it makes little sense to speak about the internet as something you either can or cannot access, cause even with outside access you may not be able to access the site IP addresses you need. – Brian Rasmussen Feb 05 '09 at 14:31
  • @Brian, you're right. I didn't think about this case. But the OP was asking about general internet connectivity, so I didn't think about blocked websites. Thanks for the clarification. – Hosam Aly Feb 05 '09 at 14:46
6

This is my attempt to get the default IPv4 address without having to resort to DNS or external process calls to commands like ipconfig and route. Hopefully the next version of .Net will provide access to the Windows routing table.

public static IPAddress GetDefaultIPv4Address()
{
    var adapters = from adapter in NetworkInterface.GetAllNetworkInterfaces()
                   where adapter.OperationalStatus == OperationalStatus.Up &&
                    adapter.Supports(NetworkInterfaceComponent.IPv4)
                    && adapter.GetIPProperties().GatewayAddresses.Count > 0 &&
                    adapter.GetIPProperties().GatewayAddresses[0].Address.ToString() != "0.0.0.0"
                   select adapter;

     if (adapters.Count() > 1)
     {
          throw new ApplicationException("The default IPv4 address could not be determined as there are two interfaces with gateways.");
     }
     else
     {
         UnicastIPAddressInformationCollection localIPs = adapters.First().GetIPProperties().UnicastAddresses;
         foreach (UnicastIPAddressInformation localIP in localIPs)
         {
            if (localIP.Address.AddressFamily == AddressFamily.InterNetwork &&
                !localIP.Address.ToString().StartsWith(LINK_LOCAL_BLOCK_PREFIX) &&
                !IPAddress.IsLoopback(localIP.Address))
            {
                return localIP.Address;
            }
        }
    }

    return null;
}
sipsorcery
  • 30,273
  • 24
  • 104
  • 155
2

A hacky way is to fetch and scrape one of the many 'What Is My IP' type websites.

xyz
  • 27,223
  • 29
  • 105
  • 125
  • 1
    This is actually the only correct solution yet - if you want to do this the proper way, you need to set up a tiny web service that echoes the calling IP address back to the caller – Ana Betts Feb 05 '09 at 15:11
  • @Paul: your idea is nice, except that it wouldn't work behind NAT. – Hosam Aly Feb 07 '09 at 06:21
2

Not 100% accurate (some ISPs don't give you public IP addresses), but you can check if the IP address is on one of the ranges reserved for private addresses. See http://en.wikipedia.org/wiki/Classful_network

Artelius
  • 48,337
  • 13
  • 89
  • 105
  • I know of a network where all the computers are dual-homed. The NICs with Internet access are 172.22.x.x (private IPs), while the NICs on a private LAN are 126.x.x.x (public IPs). – Gabe Dec 17 '10 at 06:29
1

Here is an article which could be helpful:

How to Retrieve "Network Interfaces" in C#

The following code is used to retrieve the "network interfaces" in C#. You may recognize the "network interfaces" as "Network and Dial-up Connections": You can access them by using "Start > Setting > Network and Dial-up Connections". C# does not provide a simple way of retrieving this list.

splattne
  • 102,760
  • 52
  • 202
  • 249
1

I found a solution:

IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
Console.WriteLine(ipProperties.HostName);

        foreach (NetworkInterface networkCard in NetworkInterface.GetAllNetworkInterfaces())
        {
            foreach (GatewayIPAddressInformation gatewayAddr in networkCard.GetIPProperties().GatewayAddresses)
            {
                Console.WriteLine("Information: ");
                Console.WriteLine("Interface type: {0}", networkCard.NetworkInterfaceType.ToString());
                Console.WriteLine("Name: {0}", networkCard.Name);
                Console.WriteLine("Id: {0}", networkCard.Id);
                Console.WriteLine("Description: {0}", networkCard.Description);
                Console.WriteLine("Gateway address: {0}", gatewayAddr.Address.ToString());
                Console.WriteLine("IP: {0}", System.Net.Dns.GetHostByName(System.Net.Dns.GetHostName()).AddressList[0].ToString());
                Console.WriteLine("Speed: {0}", networkCard.Speed);
                Console.WriteLine("MAC: {0}", networkCard.GetPhysicalAddress().ToString());
            }
        }
Lukas Šalkauskas
  • 14,191
  • 20
  • 61
  • 77
  • 1
    That code doesn't return the IP associated with the specified network card -- For me it returns the IP of my Windows Mobile device (instead of my wired or Wi-Fi connection) – Rowland Shaw Feb 05 '09 at 12:38
  • Yeah sure, because I choose [0], but in other way you can choose it by network card ID, or name, or MAC, or gateway by network interface. – Lukas Šalkauskas Feb 05 '09 at 13:15
  • But the question was "how can I detect IP which is connected to internet with C# ?", and this code doesn't. – Rowland Shaw Feb 05 '09 at 20:53
0

Use tracert. The first hop should always be on the same subnet as your internet NIC.

example from command prompt.

tracert google.com

the first line is 10.0.0.254 and my nic has the ip of 10.0.2.48. Then it is a simple exercise of parsing the output from tracert.

Esben Skov Pedersen
  • 4,437
  • 2
  • 32
  • 46
0

An alternative solution (that is probably more accurate) is to use the Windows route command. Here is some code that works for me on Windows Vista:

static string getInternetConnectionIP()
{
    using (Process route = new Process())
    {
        ProcessStartInfo startInfo = route.StartInfo;
        startInfo.FileName = "route.exe";
        startInfo.Arguments = "print 0.0.0.0";
        startInfo.UseShellExecute = false;
        startInfo.RedirectStandardOutput = true;
        route.Start();

        using (StreamReader reader = route.StandardOutput)
        {
            string line;
            do
            {
                line = reader.ReadLine();
            } while (!line.StartsWith("          0.0.0.0"));

            // the interface is the fourth entry in the line
            return line.Split(new char[] { ' ' },
                              StringSplitOptions.RemoveEmptyEntries)[3];
        }
    }
}
Hosam Aly
  • 41,555
  • 36
  • 141
  • 182
0

I already search that, i found it in this codeplex project http://www.codeplex.com/xedus. It a none working P2P freeware but there is a class that use the right API to get the lan card witch has the internet ip

Polo
  • 1,770
  • 4
  • 18
  • 29
0

For a quick hack (that will certainly become broken with elaborate LAN configurations or IPv6), get a list of all IPs the current machine has, and strip out all IP:s that match any of the following:

10.*
127.*          // <- Kudos to Brian for spotting the mistake
172.[16-31].*
192.168.*
Henrik Paul
  • 66,919
  • 31
  • 85
  • 96
0

Here's a 2022 implementation for getting either the public IPv4 or IPv6 address that your system is using on the Internet when making a default connection. It uses the currently free internet service/api described at https://www.ipify.org. Basically their API just returns a simple string with nothing but your IP address.
Note that I'm using the latest .Net SDK to build this. (Aug '22). Some small changes might(?) be needed to run on older versions.

Code would be used like so:

IPAddress ipv4 = await WanIp.GetV4Async(); // return v4 address or IPAddress.None
IPAddress ipv6 = await WanIp.GetV6Async(); // return v6 address or IPAddress.None
IPAddress ip = await WanIp.GetIpAsync(); // might return either v4 or v6
using System.Net;
using System.Net.Http;
using System.Net.Sockets;
using System.Net.Threading.Tasks;

public class WanIp {
  private static readonly HttpClient httpClient = new();
  public static async Task<IPAddress> GetV4Async() => 
    await GetIpAsync(AddressFamily.InterNetwork);
  public static async Task<IPAddress> GetV6Async() => 
    await GetIpAsync(AddressFamily.InterNetworkV6);

  public static async Task<IPAddress> GetIpAsync(AddressFamily family = AddressFamily.Unspecified) {
    var uri = family switch {
      AddressFamily.InterNetwork => "https://api.ipify.org",
      AddressFamily.InterNetworkV6 => "https://api6.ipify.org",
      AddressFamily.Unspecified =>  "https://api64.ipify.org",
      _ => throw new ArgumentOutOfRangeException(nameof(family))
    };

    IPAddress ip;
    try {
      var ipString = await httpClient.GetStringAsync(uri);
      _ = IPAddress.TryParse(ipString, out ip);
    } catch (Exception ex) {  // If network down, etc.
      ip = IPAddress.None;
      // maybe throw an exception here if you like
    }

    // make sure we get family we asked for, or reply with none
    if (family != AddressFamily.Unspecified && ip.AddressFamily != family) ip = IPAddress.None;
    return ip;
  }
Rich K
  • 183
  • 2
  • 7
0

in the same direction as Lukas Šalkauskas, a friend of mine and I wrote this code:

   /* digged, built and (here and there) copied "as is" from web, without paying attention to style.
    Please, do not shot us for this. 
   */
public static void DisplayIPAddresses() 
    { 

        Console.WriteLine("\r\n****************************"); 
        Console.WriteLine("     IPAddresses"); 
        Console.WriteLine("****************************"); 


        StringBuilder sb = new StringBuilder(); 
        // Get a list of all network interfaces (usually one per network card, dialup, and VPN connection)      
        NetworkInterface[] networkInterfaces = NetworkInterface.GetAllNetworkInterfaces(); 

        foreach (NetworkInterface network in networkInterfaces) 
        { 

            if (network.OperationalStatus == OperationalStatus.Up ) 
            { 
                if (network.NetworkInterfaceType == NetworkInterfaceType.Tunnel) continue; 
                if (network.NetworkInterfaceType == NetworkInterfaceType.Tunnel) continue; 
                //GatewayIPAddressInformationCollection GATE = network.GetIPProperties().GatewayAddresses; 
                // Read the IP configuration for each network    

                IPInterfaceProperties properties = network.GetIPProperties(); 
                //discard those who do not have a real gateaway  
                if (properties.GatewayAddresses.Count > 0) 
                { 
                    bool good = false; 
                    foreach  (GatewayIPAddressInformation gInfo in properties.GatewayAddresses) 
                    { 
                        //not a true gateaway (VmWare Lan) 
                        if (!gInfo.Address.ToString().Equals("0.0.0.0")) 
                        { 
                            sb.AppendLine(" GATEAWAY "+ gInfo.Address.ToString()); 
                            good = true; 
                            break; 
                        } 
                    } 
                    if (!good) 
                    { 
                        continue; 
                    } 
                } 
                else { 
                    continue; 
                } 
                // Each network interface may have multiple IP addresses        
                foreach (IPAddressInformation address in properties.UnicastAddresses) 
                { 
                    // We're only interested in IPv4 addresses for now        
                    if (address.Address.AddressFamily != AddressFamily.InterNetwork) continue; 

                    // Ignore loopback addresses (e.g., 127.0.0.1)     
                    if (IPAddress.IsLoopback(address.Address)) continue; 

                    if (!address.IsDnsEligible) continue; 
                    if (address.IsTransient) continue;  

                    sb.AppendLine(address.Address.ToString() + " (" + network.Name + ") nType:" + network.NetworkInterfaceType.ToString()     ); 
                } 
            } 
        } 
        Console.WriteLine(sb.ToString()); 
    }
-1

Try to ping www.google.com on both interfaces.

mouviciel
  • 66,855
  • 13
  • 106
  • 140
-1

You could simply read http://myip.dnsomatic.com/

It's a reliable service by OpenDNS, and I use it to get the external IP all the time.

Can Berk Güder
  • 109,922
  • 25
  • 130
  • 137