通过ALB获取客户端真实IP

当使用ALB监听转发流量时,您可通过HTTP头部的X-Forwarded-For字段获取客户端真实IP地址。

获取方法介绍

七层负载均衡(HTTP或HTTPS协议)支持在HTTP头部的X-Forwarded-For字段保留客户端真实IP信息,服务器进行相应配置后即可获取到客户端真实IP地址。

X-Forwarded-For字段格式如下:

X-Forwarded-For: <客户端真实IP, 代理服务器1-IP, 代理服务器2-IP,...>

当使用此方式获取客户端真实IP时,获取的第一个地址就是客户端真实IP。

操作步骤

步骤一:检查监听已开启通过X-Forwarded-For获取功能

  1. 登录应用型负载均衡ALB控制台

  2. 在顶部菜单栏,选择实例所属的地域。

  3. 实例页面,找到目标实例,单击实例ID。

  4. 在实例详情页面,单击监听页签,找到目标监听,单击监听ID。

  5. 在监听详情页面,查看到附加HTTP头字段包括开启通过X-Forwarded-For头字段获取来访者客户端IP

    说明

    ALB默认开启通过X-Forwarded-For头字段获取客户端真实IP功能,不支持关闭。

步骤二:配置后端服务器

请根据您所使用的服务器类型,选择对应的操作步骤。

配置Nginx服务器

此处以CentOS 7.9操作系统、Nginx 1.20.1 版本配置为例介绍。具体请以您实际使用的环境为准。

  1. 在服务器执行nginx -V | grep http_realip_module命令,检查Nginx服务器是否安装了http_realip_module模块。Nginx使用http_realip_module模块解析X-Forwarded-For记录。

    如果返回信息中包括--with-http_realip_module,表示已安装http_realip_module模块,可进行下一步。

    已安装http_realip_module模块返回信息示例

    nginx version: nginx/1.20.1
    built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) 
    built with OpenSSL 1.1.1k  FIPS 25 Mar 2021
    TLS SNI support enabled
    configure arguments: --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx --with-compat --with-debug --with-file-aio --with-google_perftools_module --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_degradation_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_mp4_module --with-http_perl_module=dynamic --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-http_xslt_module=dynamic --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-stream_ssl_preread_module --with-threads --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -m64 -mtune=generic' --with-ld-opt='-Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,-E'
    
    说明
    • Nginx 1.0.4 版本(2011年)开始支持http_realip_module 模块。如果您使用的Nginx版本过老,建议您备份配置数据并升级Nginx版本。

    • 如果未安装http_realip_module模块,需要重新编译安装Nginx并安装http_realip_module 模块。操作较为繁琐,建议您使用类似yum的包管理器安装Nginx。

  2. 修改Nginx服务配置文件并保存,修改点可参考下方说明。执行nginx -t命令查看配置文件所在路径,默认通常为 /etc/nginx/nginx.conf,具体请以实际环境为准。

    http {
      # 确保设置$http_x_forwarded_for,该变量用于记录X-Forwarded-For的值
      log_format  main  '$remote_addr- $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
      
      # ...
    }
    

  3. 执行sudo nginx -s reload命令,重新加载Nginx配置文件。

配置Apache服务器

此处以CentOS 7.9操作系统、Apache 2.4.6 版本配置为例介绍。具体请以您实际使用的环境为准。

  1. 在服务器执行httpd -M | grep remoteip_module命令,检查Apache服务器是否安装了remoteip_module模块。Apache使用remoteip_module模块解析X-Forwarded-For记录。

    如果返回信息中包括remoteip_module (shared),表示已安装该模块,可进行下一步。

    说明
    • Apache 2.4.0 版本(2012年)开始支持remoteip_module 模块。如果您使用的Apache版本过老,建议您备份配置数据并升级Apache版本。

    • 如果未安装remoteip_module 模块,需要重新编译安装Apache并安装remoteip_module 模块。操作较为繁琐,建议您使用类似yum的包管理器安装Apache。

  2. 修改Apache服务配置文件并保存,修改点可参考下方说明。默认通常为/etc/httpd/conf/httpd.conf,具体请以实际环境为准。

    # ...
    <IfModule log_config_module>
    	# 增加%{X-Forwarded-For}i ,用于记录X-Forwarded-For信息
      LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
      LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %b" common
    	#...
    </IfModule>
    # ...

  3. 执行sudo systemctl restart httpd命令,重启apache服务。

配置IIS服务器

此处以Windows Server 2016操作系统配置为例介绍。具体请以您实际使用的环境为准。

  1. 下载并解压F5XForwardedFor文件

  2. 根据自己的服务器操作系统版本将x86\x64\目录下的F5XFFHttpModule.dllF5XFFHttpModule.ini拷贝到某个目录,确保IIS进程对该目录有读取权限。

  3. 服务器管理器中,打开IIS管理器

  4. 选中服务器,双击模块功能。

  5. 单击配置本机模块,然后在弹出的对话框中,单击注册

  6. 添加下载的.dll文件。

    1. 输入文件名称,选择路径之后,单击确定

    2. 此时系统会自动选中新注册的模块,请单击确定注册模块

  7. 回到服务器主页,双击日志模块,配置日志格式,在日志中记录X-Forwarded-For字段信息。

    1. 单击选择字段

      image.png

    2. 单击左下角添加字段,添加如下日志字段并确认。

      image.png

    3. 单击右上角应用,完成修改。

  8. 重启IIS服务器,等待配置生效。

步骤三:验证后端服务器已获取客户端真实IP

请根据您所使用的服务器类型,选择对应的操作步骤。

Nginx服务器

当Nginx作为后端服务器时,您可以通过检查Nginx日志来判断是否成功获取到了客户端的真实IP地址。

Nginx日志文件默认路径为:/var/log/nginx/access.log

每行日志中,$http_x_forwarded_for变量对应的字段中,第一个IP地址即为客户端真实IP地址。

image.png

Apache服务器

当Apache作为后端服务器时,您可以通过检查Apache日志来判断是否成功获取到了客户端的真实IP地址。

Apache日志文件默认路径为:/var/log/httpd/access_log

每行日志中,%{X-Forwarded-For}i 对应的字段中,第一个IP地址即为客户端真实IP地址。

image.png

IIS服务器

当IIS作为后端服务器时,您可以通过检查IIS日志来判断是否成功获取到了客户端的真实IP地址。

IIS日志文件路径,可在日志模块查看。

image.png

每行日志中,X-Forwarded-For对应的字段中,第一个IP地址即为客户端真实IP地址。

image.png

常见问题

为什么有100开头的IP在频繁访问ECS实例

负载均衡系统除了会通过系统服务器的内网IP将来自外部的访问请求转到后端ECS实例之外,还会对ECS实例进行健康检查和可用性监控,这些访问的来源都是由负载均衡系统发起的。

负载均衡系统的地址段为100.64.0.0/10(100.64.0.0/10是阿里云保留地址,其他用户无法分配到该网段内,不会存在安全风险),所以会有很多100开头的IP地址访问ECS实例。

为了确保您对外服务的可用性,请确保您的所有服务器均对上述地址的访问配置了安全组放行规则。

与WAF/CDN/GA等配合使用时,如何获取客户端真实IP

流量在经过负载均衡前,如果经过WAF、CDN、GA等转发,也可以通过X-Forwarded-For字段获取客户端真实IP地址,这些产品默认透传X-Forwarded-For字段,无需进行其他配置。

如果您业务安全性要求较高,想避免X-Forwarded-For伪造,您可通过在其他产品中指定header字段记录客户端真实IP。假如您采用客户端 > CDN > WAF > 负载均衡 > ECS架构时,CDN透传HTTP头部的Ali-Cdn-Real-Ip字段,在WAF中接入时客户端IP判定方式选择指定header字段为Ali-Cdn-Real-Ip,后端Nginx服务器配置日志变量为$http_Ali_Cdn_Real_Ip,日志中获取的亦为客户端真实IP。

您也可以通过其他多种手段加固系统安全性,例如:

  • 验证和过滤XFF头部:在后端服务器中,对XFF头部进行验证和过滤,以确保它是合法且可信的。您可以检查XFF头部的格式和IP地址,拒绝非法或可疑的值。

  • 使用防火墙和访问控制列表:在负载均衡器和后端服务器之间,使用防火墙和访问控制列表来限制和过滤针对XFF头部的恶意请求。

  • SSL/TLS加密:使用SSL/TLS加密来保护通信,包括XFF头部的传输。这样可以减少中间人攻击和数据篡改的风险。

ACK场景下使用负载均衡时如何获取客户端真实IP

当您在ACK集群中使用负载均衡时,获取方式相同,具体操作有部分差异,具体操作请参考ACK容器集群Pod如何获取客户端真实IP?

相关文档

不同负载均衡类型获取客户端真实IP方式有所不同: