nginx反向代理取得IP地址

nginx反向代理后,在应用中取得的ip都是反向代理服务器的ip,取得的域名也是反向代理配置的url的域名,解决该问题,需要在nginx反向代理配置中添加一些配置信息,目的将客户端的真实ip和域名传递到应用程序中。

nginx反向代理配置时,一般会添加下面的配置:

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;

其中第一行关于host的配置,是关于域名传递的配置,余下跟IP相关。

先看下C#代码的处理:

#region 获取反向代理时的客户端的IP地址 getClientIP
 /// <summary>
/// 获取反向代理时的客户端的IP地址
 /// </summary>
 /// <returns>返回客户端真实IP</returns>
private string getClientIP()
{
    HttpRequestBase request = HttpContext.Request;

    string ip = request.Headers.Get("x-forwarded-for");

    if (ip == null || ip.Length == 0 || string.Equals("unknown", ip, StringComparison.OrdinalIgnoreCase))
    {
       ip = request.Headers.Get("Proxy-Client-IP");
    }
    if (ip == null || ip.Length == 0 || string.Equals("unknown", ip, StringComparison.OrdinalIgnoreCase))
    {
       ip = request.Headers.Get("WL-Proxy-Client-IP");

    }
     if (ip == null || ip.Length == 0 || string.Equals("unknown", ip, StringComparison.OrdinalIgnoreCase))
     {
           ip = request.UserHostAddress;
     }
       return ip;
   } 

但是需要注意的是,通过nginx反向代理后,如果访问IP通过了几层代理,可能取得的IP地址是这种格式:clientIP, proxy1, proxy2 .又可能需要进行插入数据库的话,防止数据库恶意注入。所以要针对上述IP地址的格式进行截取。

        #region 获取反向代理时的客户端的IP地址 getClientIP
        /// <summary>
        /// 获取反向代理时的客户端的IP地址
        /// </summary>
        /// <returns>返回客户端真实IP</returns>
        private string getClientIP()
        {
            HttpRequestBase request = HttpContext.Request;

            string ip = request.Headers.Get("x-forwarded-for");

            if (ip == null || ip.Length == 0 || string.Equals("unknown", ip, StringComparison.OrdinalIgnoreCase))
            {
                ip = request.Headers.Get("Proxy-Client-IP");
            }
            if (ip == null || ip.Length == 0 || string.Equals("unknown", ip, StringComparison.OrdinalIgnoreCase))
            {
                ip = request.Headers.Get("WL-Proxy-Client-IP");

            }
            if (ip == null || ip.Length == 0 || string.Equals("unknown", ip, StringComparison.OrdinalIgnoreCase))
            {
                ip = request.UserHostAddress;
            }
            //可能存在如下格式:X-Forwarded-For: client, proxy1, proxy2
            int i = 0;
            if(ip.Contains(", "))
            {
                //如果存在多个反向代理,获得的IP是一个用逗号分隔的IP集合,取第一个
                //X-Forwarded-For: client  第一个
                string[] ipaddrs = ip.Split(new string[1] { ", " },StringSplitOptions.RemoveEmptyEntries);

                for(i=0;i<ipaddrs.Length;i++)
                {
                    if(ipaddrs[i]!="")
                    {
                        if (false == IsInnerIP(ipaddrs[i]))//判断是否为内网IP
                        {
                            IPAddress realip;
                            if (IPAddress.TryParse(ipaddrs[i], out realip) && ipaddrs[i].Split(‘.‘).Length == 4)
                            {//合法IP
                                return ipaddrs[i];
                            }
                            else
                            {//非法IP
                                //IP地址不符合规范
                            }
                        }
                    }
                }
                ip = ipaddrs[0];//默认取第一个ip地址
            }

            return ip;
        }
        #endregion

之前发现,虽然说截取了上述IP地址的第一个clientip,但是发现有时候读出来的这个ip地址为内网IP。所以要加上内网IP的判断。

        #region 判断IP地址是否为局域网内网地址
        /// <summary>
        /// 判断IP地址是否为内网IP地址
        /// </summary>
        /// <param name="ipAddress">IP地址字符串</param>
        /// <returns></returns>
        private  bool IsInnerIP(String ipAddress)
        {
            bool isInnerIp = false;
            ulong ipNum = ip2ulong(ipAddress);
            /**
               私有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("172.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) || ipAddress.Equals("127.0.0.1");
            return isInnerIp;
        }
        /// <summary>
        /// 把IP地址转换为Long型数字
        /// </summary>
        /// <param name="ipAddress">IP地址字符串</param>
        /// <returns></returns>
        private ulong ip2ulong(string ipAddress)
        {
            byte[] bytes = IPAddress.Parse(ipAddress).GetAddressBytes();
            ulong ret = 0;

            foreach (byte b in bytes)
            {
                ret <<= 8;
                ret |= b;
            }
            return ret;
        }
        /// <summary>
        /// 判断用户IP地址转换为Long型后是否在内网IP地址所在范围
        /// </summary>
        /// <param name="userIp"></param>
        /// <param name="begin"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        private bool IsInner(ulong userIp, ulong begin, ulong end)
        {
            return (userIp >= begin) && (userIp <= end);
        }
        #endregion

后面又发现,nginx反向代理,得到的IP地址格式是unknown, 86.15.56.29。然后继续做处理。

 if (ip.Contains(", "))
 {
    //如果存在多个反向代理,获得的IP是一个用逗号分隔的IP集合,取第一个
     //X-Forwarded-For: client  第一个
     string[] ipaddrs = ip.Split(new string[1] { ", " }, StringSplitOptions.RemoveEmptyEntries);
    ip = ipaddrs[0];//先默认取第一个IP地址
    foreach(string ipaddr in ipaddrs)
    {
     if (ipaddr != "" && ipaddr.Split(‘.‘).Length == 4 && string.Equals("unknown",ipaddr,StringComparison.OrdinalIgnoreCase) == false)
     {//对应一些特殊的获取的特殊IP地址结构 unknown, 86.15.56.29
          if (false == IsInnerIP(ipaddr))
          {
              IPAddress realip;
              if (IPAddress.TryParse(ipaddr, out realip))
              {//合法IP
                   ip = ipaddr;
                       break;//只要找到一个非内网的IP地址,则跳出循环
              }
              else
              {//非法IP
                   LogHelper.writeLog(LogHelper.IP_THREAD_LOG + "_" + mApp, string.Format("非法IP地址为:\n{0}",ipaddr));
              }
          }
       }
       }
       }

综合上述的得到IP地址,可以发现,其实并不能完全的到真实的IP地址。因为IP地址是可以伪造的。所以大家可以通过这种方式取得。但是一定要做一些特殊的判断及其处理,防止插入到数据库中,引起异常现象。

时间: 2024-11-10 11:27:52

nginx反向代理取得IP地址的相关文章

ASP.NET Core 2.1发布/部署到Ubuntu并配置Nginx反向代理实现ip访问

一.准备 我用的是Ubuntu服务器器 [Ubuntu 18.04 x64] 和终端管理工具[Xshell] 二.安装 在服务器上安装.NET Core 三.部署程序 1.创建实例程序 可以直接使用.NET Core 的命令创建一个ASP.NET Core 示例网站应用程序,创建目录 /home/myuser/firstapp,执行命令: dotnet new mvc 接着,发布刚才创建的ASP.NET Core 网站发网站目录,所以,我们先创建一个网站发布目录:/var/www/firstap

使用nginx反向代理一个ip下的多个tomcat

问题:使用阿里云主机和域名后,默认只能解析到ip的80端口,如果配置二级域名指向同一个ip的话是不成立的 解决方案:使用nginx反向代理服务器进行反向代理 原理:利用 nginx upstream机制使得nginx可以成为一个反向代理服务器,没画图软件后期补上 配置文件如下 1 worker_processes 1; 2 error_log logs/error.log; 3 pid logs/nginx.pid; 4 worker_rlimit_nofile 65535; 5 events

在centos 7中安装nginx并配置nginx反向代理

Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行.其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度.京东.新浪.网易.腾讯.淘宝等. 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,

nginx 反向代理实现负载均衡*配置实战

(接理论篇) 查看lb01的配置文件如下: cat /usr/local/nginx/conf/nginx.conf worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; upstream www_server_pools { #默认调度算

Linux系统——Nginx反向代理与负载均衡

集群集群是指一组(若干个)相互独立的计算机,利用高速通信网路组成的一个较大的计算机服务系统,每个集群节点(即集群中的每台计算机)都是运用各自服务的独立服务器.这些服务器之间可以彼此通信,协同向用户提供应用程序,系统资源和数据,并以单一系统的模式加以管理.当用户客户机请求集群系统时,集群给用户的感觉就是一个单一独立的服务器,而实际上用户请求的是一组集群服务器. 特点:(1)高性能用户通过Internet到公司的网关,网关通过防火墙,调载到前端的主负载均衡服务器上(有主有备,预防单点问题),主负载均

nginx反向代理简介

简介 服务器根据客户端的请求,从其关联的一组或多组后端服务器(如Web服务器)上获取资源,然后再将这些资源返回给客户端,客户端只会得知反向代理的IP地址,而不知道在代理服务器后面的服务器的存在. 模块 ngx_http_proxy_module 示例 location / { proxy_pass http://localhost:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } 1.设置缓

Nginx反向代理Tomcat静态资源无法加载以及请求链接错误

 在使用Nginx实现Tomcat的负载均衡的时候,项目发布到了Tomcat,Nginx也配置好了, 当访问的时候发现了与预期不符 表现为: 静态资源加载失败 链接跳转地址错误 下面是我错误的配置文件 #user nobody; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; e

nginx反向代理到后端tomcat,并将IP地址发送到后端的配置

nginx反向代理到后端,并将IP地址发送到后端的tomcat上. 假设我们的网站叫demo.demo.com 前端Nginx配置如下: /usr/local/nginx/conf/nginx.conf 在http段加上下面4行:     proxy_set_header X-Forwarded-For $remote_addr;     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;     proxy_set_head

让nginx反向代理能够记录来自客户端的真实IP地址

上一节,我们说到了让Nginx能够正确识别用户到底访问的是哪个虚拟主机的域名,本章,我们讨论一下,如何让Nginx能够记录来自客户端的真实IP地址. 1.首先,我们看一下httpd的访问日志,看看客户端的IP地址是哪一个? 192.168.1.6 - - [29/Apr/2015:07:51:07 +0800] "GET / HTTP/1.0" 200 13 192.168.1.6 - - [29/Apr/2015:07:51:07 +0800] "GET / HTTP/1.