Files
caliverse_server/ServerCore/Network/NetworkHelper.cs
2025-05-01 07:20:41 +09:00

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
}
}