225 lines
7.1 KiB
C#
225 lines
7.1 KiB
C#
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<NetworkInterfaceType> 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<NetworkInterfaceType> 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
|
|
}
|
|
}
|
|
|