C#获取本机和客户端的IP地址

C#获取本机和客户端的IP地址

zeee 776 2021-01-20

获取本机内网地址

获取内网地址的方法主要有两种思路, 第一种比较简单: 检索所有网卡配置, 根据规则获取自己想要的网卡地址即可。

    using System.Net.NetworkInformation;
    public string GetInterIPAddress()
    {
        var localIps = NetworkInterface.GetAllNetworkInterfaces()
            .SelectMany(i => i.GetIPProperties().UnicastAddresses.Select(ip => ip.Address));

        var interIps = localIps.Where(ip => IsIntranet(ip)).ToList();
        if (!interIps.Any())
        {
            throw new InvalidOperationException("No network adapters with an IPv4 address in the system!");
        }

        var expectIp = interIps.FirstOrDefault(ip => ip.GetAddressBytes()[0] != 127) ?? interIps.First();
        return expectIp.ToString();
    }

    public static bool IsIntranet(IPAddress ip)
    {
        byte[] bytes = ip.GetAddressBytes();
        switch (bytes[0])
        {
            case 10:
                return true;
            case 127:
                return bytes[1] == 0 && bytes[2] == 0 && bytes[3] == 1;
            case 172:
                return bytes[1] < 32 && bytes[1] >= 16;
            case 192:
                return bytes[1] == 168;
            default:
                return false;
        }
    }

获取本机公网地址

由于公网IP是运营商申请分配的,所以单靠本机皮遏制无法获取到, 一个常见的办法是通过访问某个公网服务后, 被访问的服务根据地址查询(下面的客户端地址)可以确定请求者的地址(不一定是发出请求的机器, 所以存在一定不准确性), 目前有公共的服务提供此类功能, 如果担心安全问题,也可以自己搭建一个简单接口来实现, 示例代码如下:

示例代码:

public async Task<string> GetPublicIpAddress()
{
    var ipQueryUrls = new[]{
        "http://icanhazip.com",
        "https://ifconfig.me/ip"
    };
    foreach (var url in ipQueryUrls)
    {
        var response = await httpClient.GetStringAsync(url));

        if (!string.IsNullOrEmpty(response))
        {
            return response.Trim('\b', '\t', '\r', '\n');
        }
    }

    return null;
}

获取客户端地址

对于网站应用, 当客户端发生请求时, 可以通过HTTP请求头获取客户端的信息. 一般来说主要通过 X-Forwarded-ForX-Real-IP 来获取

这两个请求头不一定100%凑效, 这取决于客户端请求时是否按规范, 以及如果设置了反向代理, 反向代理服务器添加设置了相关的请求头设置

  • X-Forwarded-For 会在路由跳转的时候不断向后追加IP地址,格式为 : ip1,ip2,ip3 , 可以根据需要取, 比如去第一位即表示客户端的地址
  • X-Real-IP 一般取决于反向代理服务器是否设置, 例如nginx: proxy_set_header X-Real-IP $remote_addr; , 这个字段只有一个IP值, 直接获取即可

示例代码:

public static IPAddress GetClientIp(this HttpContext httpContext)
{
    string clientIp;
    if (httpContext.Request.Headers.ContainsKey("X-Forwarded-For"))
    {
        clientIp = httpContext.Request.Headers["X-Forwarded-For"].ToString().Split(',').FirstOrDefault();
        return IPAddress.Parse(clientIp);
    }
    else if (httpContext.Request.Headers.ContainsKey("X-Real-IP"))
    {
        clientIp = httpContext.Request.Headers["X-Real-IP"].ToString();
        return IPAddress.Parse(clientIp);
    }
    else
    {
        return httpContext.Connection.RemoteIpAddress;
    }
}

# dotnet