using System; using System.Collections.Generic; using System.Linq; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Net; using System.Text; using System.Threading.Tasks; namespace ServerCore; //============================================================================================= // 네트워크 관련 각종 지원 함수 // // author : kangms // //============================================================================================= public static class NetworkHelper { private static string m_ip_address_ipv4 = string.Empty; public static bool parseIPnPort(this string _this, UInt16 defaultPort, out string host, out UInt16 port) { host = string.Empty; port = 0; var splitted_value = _this.Split(":"); if (2 == splitted_value.Length) { host = splitted_value[0]; port = Convert.ToUInt16(splitted_value[1].Trim()); } else if (1 == splitted_value.Length) { host = splitted_value[0]; port = defaultPort; } else { return false; } return true; } public static string getEthernetLocalIPv4() { if(true == m_ip_address_ipv4.isNullOrWhiteSpace()) { m_ip_address_ipv4 = NetworkHelper.getLocalIPAddress(new[] { NetworkInterfaceType.Ethernet }, AddressFamily.InterNetwork); } return m_ip_address_ipv4; } public static string getLocalIPAddress(IEnumerable networkTypes, AddressFamily addressFamiltyType) { string return_address = string.Empty; // Get a list of all network interfaces (including Ethernet, Wi-Fi, etc.) NetworkInterface[] networkInterfaces = NetworkInterface.GetAllNetworkInterfaces(); foreach (NetworkInterface network in networkInterfaces) { // Check if the network type matches the given types if (false == networkTypes.Contains(network.NetworkInterfaceType)) continue; // Read the IP configuration for each network IPInterfaceProperties properties = network.GetIPProperties(); // Check if the network interface is up and is not a virtual/pseudo interface if ( network.OperationalStatus != OperationalStatus.Up || true == network.Description.ToLower().Contains("virtual") || true == network.Description.ToLower().Contains("pseudo")) { continue; } // Each network interface may have multiple IP addresses foreach (IPAddressInformation address in properties.UnicastAddresses) { if ( address.Address.AddressFamily == addressFamiltyType) { if (false == IPAddress.IsLoopback(address.Address)) { return_address = address.Address.ToString(); break; // Exit after first non-loopback address found } } } if (false == string.IsNullOrEmpty(return_address)) { break; } } if (string.IsNullOrEmpty(return_address)) { // If no address is found, return appropriate loopback address based on the available version if (true == isIPv6Available(networkTypes)) { return_address = "::1"; // Fallback to IPv6 loopback address if no address found } else { return_address = "127.0.0.1"; // Fallback to IPv4 loopback address if no address found } } return return_address; } // Private IP 범위 체크 (네트워크 범위도 아규먼트로 받기) public static bool isPrivateIP(string ipAddress, string[] privateRanges) { if (IPAddress.TryParse(ipAddress, out IPAddress? ip)) { if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) { // IPv4 처리 var octets = ip.GetAddressBytes(); foreach (var range in privateRanges) { if(false == range.Contains(":")) { // IPv4 체크 if (isInRangeIPv4(octets, range)) { return true; } } } } else if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6) { // IPv6 처리 var octets = ip.GetAddressBytes(); foreach (var range in privateRanges) { if (range.Contains(":")) { if (isInRangeIPv6(octets, range)) { return true; } } } } } return false; // Public IP } // IPv4 주소가 특정 대역에 포함되는가 public static bool isInRangeIPv4(byte[] ipAddress, string range) { var parts = range.Split('/'); var network = IPAddress.Parse(parts[0]); int prefixLength = int.Parse(parts[1]); var networkBytes = network.GetAddressBytes(); int mask = 32 - prefixLength; for (int i = 0; i < 4; i++) { if ((networkBytes[i] & (255 << mask)) != (ipAddress[i] & (255 << mask))) { return false; } } return true; } // IPv6 주소가 특정 대역에 포함되는가 public static bool isInRangeIPv6(byte[] ipAddress, string range) { var parts = range.Split('/'); var network = IPAddress.Parse(parts[0]); int prefixLength = int.Parse(parts[1]); var networkBytes = network.GetAddressBytes(); int mask = 128 - prefixLength; for (int i = 0; i < 16; i++) { if ((networkBytes[i] & (255 << mask)) != (ipAddress[i] & (255 << mask))) { return false; } } return true; } private static bool isIPv6Available(IEnumerable networkTypes) { // Check if any network interface of the specified types has an IPv6 address NetworkInterface[] networkInterfaces = NetworkInterface.GetAllNetworkInterfaces(); foreach (var network in networkInterfaces) { // Check if the network type matches the given types if (!networkTypes.Contains(network.NetworkInterfaceType)) continue; IPInterfaceProperties properties = network.GetIPProperties(); // Check if this network interface has any IPv6 address foreach (var address in properties.UnicastAddresses) { if (address.Address.AddressFamily == AddressFamily.InterNetworkV6) { return true; // Found an IPv6 address } } } return false; // No IPv6 address found } }