Nginx反向代理获取真实IP问题

服务器
由于Nginx反向代理后,在应用中取得的IP都是反向代理服务器的IP,取得的域名也是反向代理配置的Url的域名。

 一、前言

前文 Nginx 解决WebApi跨域二次请求以及Vue单页面问题 当中虽然解决了跨域问题带来的二次请求,但也产生了一个新的问题,就是如果需要获取用户IP的时候,获取的IP地址总是本机地址。

回到顶部

二、原因

由于Nginx反向代理后,在应用中取得的IP都是反向代理服务器的IP,取得的域名也是反向代理配置的Url的域名。

回到顶部

三、解决方案

解决该问题,需要在Nginx反向代理配置中添加一些配置信息,目的将客户端的真实IP和域名传递到应用程序中。同时,也要修改获取IP地址的方法。

[[216611]]

但是需要注意的是,通过Nginx反向代理后,如果访问IP通过了几层代理,可能取得的IP地址是这种格式:clientIP,proxy1,proxy2。

如果需要将IP地址插入到数据库的话,需要做防止注入。因此要对上述的IP地址的格式进行截取。

3.1 Nginx 配置如下

server { 
        listen       9461; # 监听端口号 
        server_name  localhost 192.168.88.22; # 访问地址 
        location / { 
            root   项目路径; # 例如:E:/Publish/xxx/; 
            index  index.html; 
             
            # 此处用于处理 Vue、Angular、React 使用H5 的 History时 重写的问题 
            if (!-e $request_filename) { 
                rewrite ^(.*) /index.html last
                break; 
            } 
        } 
         
        # 代理服务端接口 
        location /api { 
            proxy_pass http://localhost:9460/api;# 代理接口地址 
            # Host配置以及域名传递 
            proxy_set_header Host $host; 
            proxy_set_header X-Real-IP $remote_addr; 
            proxy_set_header REMOTE-HOST $remote_addr; 
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
        } 
    } 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.

3.2 C#代码获取真实IP方法

#region Ip(客户端IP地址) 
 
/// <summary> 
/// 客户端IP地址 
/// </summary> 
public static string Ip 

    get 
    { 
        var result = string.Empty; 
        if (HttpContext.Current != null
        { 
            result = GetWebClientIp(); 
        } 
        if (string.IsNullOrWhiteSpace(result)) 
        { 
            result = GetLanIp(); 
        } 
        return result; 
    } 

 
/// <summary> 
/// 获取Web客户端的IP 
/// </summary> 
/// <returns></returns
private static string GetWebClientIp() 

    var ip = GetWebProxyRealIp() ?? GetWebRemoteIp(); 
    foreach (var hostAddress in Dns.GetHostAddresses(ip)) 
    { 
        if (hostAddress.AddressFamily == AddressFamily.InterNetwork) 
        { 
            return hostAddress.ToString(); 
        } 
    } 
    return string.Empty; 

 
/// <summary> 
/// 获取Web远程IP 
/// </summary> 
/// <returns></returns
private static string GetWebRemoteIp() 

    try 
    { 
        return HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] ?? 
               HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"] ?? ""
    } 
    catch (Exception e) 
    { 
        return string.Empty; 
    } 

 
/// <summary> 
/// 获取Web代理真实IP 
/// </summary> 
/// <returns></returns
private static string GetWebProxyRealIp() 

    var request = HttpContext.Current.Request; 
    string ip = request.Headers.Get("x-forwarded-for"); 
 
    if (string.IsNullOrEmpty(ip) || string.Equals("unknown", ip, StringComparison.OrdinalIgnoreCase)) 
    { 
        ip = request.Headers.Get("Proxy-Client-IP"); 
    } 
 
    if (string.IsNullOrEmpty(ip) || string.Equals("unknown", ip, StringComparison.OrdinalIgnoreCase)) 
    { 
        ip = request.Headers.Get("WL-Proxy-Client-IP"); 
    } 
 
    if (string.IsNullOrEmpty(ip) || string.Equals("unknown", ip, StringComparison.OrdinalIgnoreCase)) 
    { 
        ip = request.UserHostAddress; 
    } 
 
    if (string.IsNullOrEmpty(ip)) 
    { 
        return string.Empty; 
    } 
    // 可能存在如下格式:X-Forwarded-For: client, proxy1, proxy2 
    if (ip.Contains(", ")) 
    { 
        // 如果存在多个反向代理,获得的IP是一个用逗号分隔的IP集合,取***个 
        // X-Forwarded-For: client  ***个 
        string[] ips = ip.Split(new string[1] {", "}, StringSplitOptions.RemoveEmptyEntries); 
        var i = 0; 
        for (i = 0; i < ips.Length; i++) 
        { 
            if (ips[i] != ""
            { 
                // 判断是否为内网IP 
                if (false == IsInnerIp(ips[i])) 
                { 
                    IPAddress realIp; 
                    if (IPAddress.TryParse(ips[i], out realIp) && ips[i].Split('.').Length == 4) 
                    { 
                        //合法IP 
                        return ips[i]; 
                    } 
 
                    return ""
                } 
            } 
        } 
 
        ip = ips[0];// 默认获取***个IP地址 
    } 
 
    return ip; 
 

 
/// <summary> 
/// 判断IP地址是否为内网IP地址 
/// </summary> 
/// <param name="ip">IP地址</param> 
/// <returns></returns
private static bool IsInnerIp(string ip) 

    bool isInnerIp = false
    ulong ipNum = Ip2Ulong(ip); 
 
    /** 
     * 私有IP 
     * A类:10.0.0.0-10.255.255.255 
     * B类:172.16.0.0-172.31.255.255 
     * C类:192.168.0.0-192.168.255.255 
     * 当然,还有127这个网段是环回地址 
     */ 
 
    ulong aBegin = Ip2Ulong("10.0.0.0"); 
    ulong aEnd = Ip2Ulong("10.255.255.255"); 
    ulong bBegin = Ip2Ulong("172.16.0.0"); 
    ulong bEnd = Ip2Ulong("10.31.255.255"); 
    ulong cBegin = Ip2Ulong("192.168.0.0"); 
    ulong cEnd = Ip2Ulong("192.168.255.255"); 
 
    isInnerIp = IsInner(ipNum, aBegin, aEnd) || IsInner(ipNum, bBegin, bEnd) || IsInner(ipNum, cBegin, cEnd) || 
                ip.Equals("127.0.0.1"); 
    return isInnerIp; 

 
/// <summary> 
/// 将IP地址转换为Long型数字 
/// </summary> 
/// <param name="ip">IP地址</param> 
/// <returns></returns
private static ulong Ip2Ulong(string ip) 

    byte[] bytes = IPAddress.Parse(ip).GetAddressBytes(); 
    ulong ret = 0; 
    foreach (var b in bytes) 
    { 
        ret <<= 8; 
        ret |= b; 
    } 
 
    return ret; 

 
/// <summary> 
/// 判断用户IP地址转换为Long型后是否在内网IP地址所在范围 
/// </summary> 
/// <param name="userIp">用户IP</param> 
/// <param name="begin">开始范围</param> 
/// <param name="end">结束范围</param> 
/// <returns></returns
private static bool IsInner(ulong userIp, ulong begin, ulong end

    return (userIp >= begin) && (userIp <= end); 

 
/// <summary> 
/// 获取局域网IP 
/// </summary> 
/// <returns></returns
private static string GetLanIp() 

    foreach (var hostAddress in Dns.GetHostAddresses(Dns.GetHostName())) 
    { 
        if (hostAddress.AddressFamily == AddressFamily.InterNetwork) 
        { 
            return hostAddress.ToString(); 
        } 
    } 
    return string.Empty; 

#endregion 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
  • 154.
  • 155.
  • 156.
  • 157.
  • 158.
  • 159.
  • 160.
  • 161.
  • 162.
  • 163.
  • 164.
  • 165.
  • 166.
  • 167.
  • 168.
  • 169.
  • 170.
  • 171.
  • 172.
  • 173.
  • 174.
  • 175.
  • 176.
  • 177.
  • 178.
  • 179.
  • 180.
  • 181.
  • 182.
  • 183.
  • 184.
  • 185.
  • 186.
  • 187.
  • 188.
  • 189.
  • 190.
  • 191.
  • 192.
  • 193.
责任编辑:武晓燕 来源: 博客园
相关推荐

2022-07-01 07:33:24

nginx反向代理测试

2023-12-05 09:14:54

2020-10-22 08:05:46

Nginx

2019-02-11 12:00:33

2019-06-19 15:34:39

Nginx反向代理负载均衡

2018-11-12 12:17:00

2020-08-06 08:23:24

Nginx反向代理Web安全

2023-09-13 07:16:31

Ngnix代理服务器

2014-04-29 14:54:48

Nginx反向代理

2017-09-06 10:14:29

Nginx TCPmail邮件

2024-07-22 15:34:25

2023-07-10 09:48:30

Nginx反向代理

2019-09-18 10:39:08

负载均衡反向代理TCP

2017-12-18 12:04:02

Nginx代理均衡

2019-11-04 15:35:53

Nginx反向代理负载均衡

2020-07-28 15:10:34

Nginx反向代理负载均衡

2021-07-29 11:15:25

Nginx网络服务器

2024-04-02 12:36:01

2015-06-05 11:26:58

nginx运维

2024-02-01 08:32:03

Nginx服务器代理
点赞
收藏

51CTO技术栈公众号