Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Helpful C# Network/IP functions. Parse IPs from any arbitrary block of text, retrieve private/public IP addresses and check if IP exists in any range defined by an address in CIDR notation.
namespace NetworkUtilitiesTest
{
using AaronLuna.Common.Network;
using AaronLuna.Common.Extensions;
using System.Threading.Tasks;
class Program
{
// async Main is a C# 7.1 feature, change your project settings to the
// new version if this is flagged as an error
static async Task Main()
{
// Usage examples for classes in this gist:
//
// NetworkUtilities
// bool IpAddressIsInRange(string checkIp, string cidrIp)
// bool IpAddressIsInRange(IPAddress checkIp, string cidrIp)
// List<IPAddress> ParseIPv4Addresses(string input)
// IPAddress GetLocalIPv4Address(string localNetworkCidrIp)
// List<IPAddress> GetLocalIPv4AddressList()
// Task<IPAddress> GetPublicIPv4AddressAsync()
//
// IpAddressExtensions
// bool IsInRange(this IPAddress ip, string cidrIp)
// bool IsPrivateAddress(this IPAddress ip)
// bool IsPublicAddress(this IPAddress ip)
var ip1 = "192.168.2.4";
var cidrIp1 = "192.168.2.0/24";
var isInRange1 = NetworkUtilities.IpAddressIsInRange(ip1, cidrIp1); // isInRange = true
var textToParse = "10.0.2.2 is a private (internal) address and 75.94.26.74 is a public (external) addresss";
var parse2Ips = NetworkUtilities.ParseIPv4Addresses(textToParse); // parse2Ips = {"10.0.2.2", "75.94.26.74"}
var isInRange2 = parse2Ips[1].IsPrivateAddress(); // isInRange2 = false
var myLocalIp = NetworkUtilities.GetLocalIPv4Address(cidrIp1); // myLocalIp = "192.168.3.5"
var myPublicIp = await NetworkUtilities.GetPublicIPv4AddressAsync(); // myPublicIp = "75.94.26.74"
var testLocalTrue = myLocalIp.IsPublicAddress(); // testLocalTrue = true
var testLocalFalse = myLocalIp.IsPrivateAddress(); // testLocalFalse = false'
var testPublic = myPublicIp.IsPublicAddress(); // testPublic = true;
}
}
}
namespace AaronLuna.Common.Network
{
using System;
using System.Linq;
using System.Net;
public static partial class NetworkUtilities
{
// This method is used multiple times by the other methods in this class.
// The input string must contain ONLY a single IPv4 address in a.b.c.d format.
// If the format of the input is unknown or you are attempting to parse
// an IP address from an arbitrary block of text, use ParseIPv4Addresses().
public static IPAddress ParseSingleIPv4Address(string input)
{
if (string.IsNullOrEmpty(input))
{
throw new ArgumentException("Input string must not be null", input);
}
var addressBytesSplit = input.Trim().Split('.').ToList();
if (addressBytesSplit.Count != 4)
{
throw new ArgumentException("Input string was not in valid IPV4 format \"a.b.c.d\"", input);
}
var addressBytes = new byte[4];
foreach (var i in Enumerable.Range(0, addressBytesSplit.Count))
{
if (!int.TryParse(addressBytesSplit[i], out var parsedInt))
{
throw new FormatException($"Unable to parse integer from {addressBytesSplit[i]}");
}
if (0 > parsedInt || parsedInt > 255)
{
throw new ArgumentOutOfRangeException($"{parsedInt} not within required IP address range [0,255]");
}
addressBytes[i] = (byte)parsedInt;
}
return new IPAddress(addressBytes);
}
}
}
namespace AaronLuna.Common.Network
{
using System;
using System.Collections.Generic;
using System.Net;
using System.Text.RegularExpressions;
public static partial class NetworkUtilities
{
// THis method can be used to parse all IP addresses from an arbitrary block of text, if you
// know that your input is a single IPv4 address in a.b.c.d format, use ParseSingleIPv4Address()
public static List<IPAddress> ParseIPv4Addresses(string input)
{
const string ipV4Pattern =
@"(?:(?:1\d\d|2[0-5][0-5]|2[0-4]\d|0?[1-9]\d|0?0?\d)\.){3}(?:1\d\d|2[0-5][0-5]|2[0-4]\d|0?[1-9]\d|0?0?\d)";
if (string.IsNullOrEmpty(input))
{
throw new ArgumentException("Input string must not be null", input);
}
var ips = new List<IPAddress>();
try
{
var regex = new Regex(ipV4Pattern);
foreach (Match match in regex.Matches(input))
{
var ip = ParseSingleIPv4Address(match.Value);
ips.Add(ip);
}
}
catch (RegexMatchTimeoutException ex)
{
// Handle exeption
}
return ips;
}
}
}
namespace AaronLuna.Common.Network
{
using System;
using System.Net;
public static partial class NetworkUtilities
{
// true if ipAddress falls inside the range defined by cidrIp, example:
// bool result = IsInCidrRange("192.168.2.3", "192.168.2.0/24"); // result = true
public static bool IpAddressIsInRange(string checkIp, string cidrIp)
{
if (string.IsNullOrEmpty(checkIp))
{
throw new ArgumentException("Input string must not be null", checkIp);
}
var ipAddress = ParseIPv4Addresses(checkIp)[0];
return IpAddressIsInRange(ipAddress, cidrIp);
}
public static bool IpAddressIsInRange(IPAddress checkIp, string cidrIp)
{
if (string.IsNullOrEmpty(cidrIp))
{
throw new ArgumentException("Input string must not be null", cidrIp);
}
var cidrAddress = ParseIPv4Addresses(cidrIp)[0];
var parts = cidrIp.Split('/');
if (parts.Length != 2)
{
throw new FormatException($"cidrMask was not in the correct format:\nExpected: a.b.c.d/n\nActual: {cidrIp}");
}
if (!Int32.TryParse(parts[1], out var netmaskBitCount))
{
throw new FormatException($"Unable to parse netmask bit count from {cidrIp}");
}
if (0 > netmaskBitCount || netmaskBitCount > 32)
{
throw new ArgumentOutOfRangeException($"Netmask bit count value of {netmaskBitCount} is invalid, must be in range 0-32");
}
var ipAddressBytes = BitConverter.ToInt32(checkIp.GetAddressBytes(), 0);
var cidrAddressBytes = BitConverter.ToInt32(cidrAddress.GetAddressBytes(), 0);
var cidrMaskBytes = IPAddress.HostToNetworkOrder(-1 << (32 - netmaskBitCount));
var ipIsInRange = (ipAddressBytes & cidrMaskBytes) == (cidrAddressBytes & cidrMaskBytes);
return ipIsInRange;
}
}
}
namespace AaronLuna.Common.Network
{
using System.Net;
public static partial class NetworkUtilities
{
public const string CidrPrivateAddressBlockA = "10.0.0.0/8";
public const string CidrPrivateAddressBlockB = "172.16.0.0/12";
public const string CidrPrivateAddressBlockC = "192.168.0.0/16";
public static bool IpAddressIsInPrivateAddressSpace(string ipv4string)
{
var checkIp = ParseIPv4Addresses(ipv4string)[0];
return IpAddressIsInPrivateAddressSpace(checkIp);
}
public static bool IpAddressIsInPrivateAddressSpace(IPAddress ipAddress)
{
var inPrivateBlockA = IpAddressIsInCidrRange(ipAddress, CidrPrivateAddressBlockA);
var inPrivateBlockB = IpAddressIsInCidrRange(ipAddress, CidrPrivateAddressBlockB);
var inPrivateBlockC = IpAddressIsInCidrRange(ipAddress, CidrPrivateAddressBlockC);
return inPrivateBlockA || inPrivateBlockB || inPrivateBlockC;
}
}
}
namespace AaronLuna.Common.Network
{
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
public static partial class NetworkUtilities
{
// This method first attempts to retrieve the local IP address by connecting
// to Google's Public DNS service. If there is no internet connection, the
// address range defined by localNetworkCidrIp is used to determine which
// IP is the correct local address. The CIDR IP must be in the correct
// format: a.b.c.d/n. For example, if your LAN is setup to allow 254 hosts
// and the router's address is 192.168.2.1, the correct value for
// localNetworkCidrIp would be "192.168.2.0/24"
public static IPAddress GetLocalIPv4Address(string localNetworkCidrIp)
{
var acquiredIp = true;
var localIp = IPAddress.None;
try
{
localIp = GetLocalIPv4AddressRequiresInternet();
}
catch (SocketException ex)
{
acquiredIp = false;
}
if (acquiredIp)
{
return localIp;
}
return GetLocalIPv4AddressWithoutInternet(localNetworkCidrIp);
}
static IPAddress GetLocalIPv4AddressRequiresInternet()
{
var localIp = IPAddress.None;
try
{
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0))
{
// Connect socket to Google's Public DNS service
if (!(socket.LocalEndPoint is IPEndPoint endPoint))
{
throw new InvalidOperationException($"Error occurred casting {socket.LocalEndPoint} to IPEndPoint");
}
localIp = endPoint.Address;
}
}
catch (SocketException ex)
{
// Handle exception
}
return localIp;
}
static IPAddress GetLocalIPv4AddressWithoutInternet(string localNetworkCidrIp)
{
var localIps = GetLocalIPv4AddressList();
if (localIps.Count == 1)
{
return localIps[0];
}
foreach (var ip in localIps)
{
if (IpAddressIsInRange(ip, localNetworkCidrIp))
{
return ip;
}
}
return IPAddress.None;
}
public static List<IPAddress> GetLocalIPv4AddressList()
{
var localIps = new List<IPAddress>();
foreach (var nic in NetworkInterface.GetAllNetworkInterfaces())
{
var ips =
nic.GetIPProperties().UnicastAddresses
.Select(uni => uni.Address)
.Where(ip => ip.AddressFamily == AddressFamily.InterNetwork).ToList();
localIps.AddRange(ips);
}
return localIps;
}
}
}
namespace AaronLuna.Common.Network
{
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
public static partial class NetworkUtilities
{
public static async Task<IPAddress> GetPublicIPv4AddressAsync()
{
var urlContent = await GetUrlContentAsStringAsync("http://ipv4.icanhazip.com/").ConfigureAwait(false);
return ParseSingleIPv4Address(urlContent);
}
static async Task<string> GetUrlContentAsStringAsync(string url)
{
var urlContent = string.Empty;
try
{
using (var httpClient = new HttpClient())
using (var httpResonse = await httpClient.GetAsync(url).ConfigureAwait(false))
{
urlContent = await httpResonse.Content.ReadAsStringAsync().ConfigureAwait(false);
}
}
catch (HttpRequestException ex)
{
// Handle exception
}
catch(InvalidOperationException ex)
{
// Handle exception
}
return urlContent;
}
}
}
namespace AaronLuna.Common.Extensions
{
using System.Net;
using Network;
public static class IpAddressExtensions
{
public static bool IsInRange(this IPAddress ip, string cidrIp)
{
return NetworkUtilities.IpAddressIsInRange(ip, cidrIp);
}
public static bool IsPrivateAddress(this IPAddress ip)
{
return NetworkUtilities.IpAddressIsInPrivateAddressSpace(ip);
}
public static bool IsPublicAddress(this IPAddress ip)
{
return !NetworkUtilities.IpAddressIsInPrivateAddressSpace(ip);
}
public static string ConvertToBinaryString(this IPAddress ip)
{
return NetworkUtilities.ConvertIpAddressToBinary(ip);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.