CNAME 接入 Web应用防火墙(Web Application Firewall,简称WAF) 时,源站收到的请求源 IP 为最后一跳代理地址而非客户端真实 IP。WAF 通过在 HTTP 请求头中插入 X-Forwarded-For 字段传递真实 IP。本文介绍如何在各后端 Web 服务器配置,从该字段提取客户端真实 IP,以确保日志记录和安全审计正常工作。
工作原理
CNAME 接入 WAF 后,客户端请求先经过 WAF 及可能存在的其他中间代理(如 CDN、DDoS 高防等),再转发至源站。此时源站接收到的 TCP 连接源 IP 为最后一跳代理的 IP,而非客户端真实 IP。
WAF 转发 HTTP 请求时会自动添加 X-Forwarded-For 头部字段。该字段初始值为客户端 IP;每经过一个代理节点,该节点的 IP 会被追加至末尾,格式如下:
X-Forwarded-For: 客户端IP, 代理1IP, 代理2IP, …
因此,需要在后端 Web 服务器配置从 X-Forwarded-For 头部提取最左侧的 IP 地址(即原始客户端 IP)。以下分别介绍各平台的配置方法。
步骤一:获取 WAF 回源 IP 段
登录Web应用防火墙控制台,在顶部菜单栏选择 WAF 实例的资源组和地域(中国内地、非中国内地),单击,记录所有 WAF 回源 IP 段,供后续配置使用。
步骤二:配置源站服务器
配置前请通过 ECS 快照或配置文件备份等方式完成环境备份,避免配置丢失。
Nginx 配置方案
Nginx 使用 http_realip_module 模块解析 X-Forwarded-For。按以下步骤修改 Nginx 配置。
检查是否已安装 http_realip_module
登录服务器并执行以下命令:
nginx -V 2>&1 | grep -o with-http_realip_module
-
若输出
with-http_realip_module,说明模块已安装,跳至配置 Nginx 信任 WAF 回源 IP 段。 -
若无输出,说明当前 Nginx 未编译该模块,请继续执行添加 realip 模块。
通过 yum install nginx 或 apt install nginx 安装的版本通常包含该模块。自定义编译版本或极简镜像可能缺失。
添加 realip 模块(仅缺失时适用)
方式一:通过系统包管理器重新安装
# Alibaba Cloud Linux / CentOS / RHEL
sudo yum reinstall nginx -y
# Ubuntu / Debian
sudo apt install --reinstall nginx-core nginx-full
方式二:源码编译
-
安装依赖。
# Alibaba Cloud Linux / CentOS / RHEL sudo yum install -y gcc pcre-devel zlib-devel openssl-devel # Ubuntu / Debian sudo apt update sudo apt install -y build-essential libpcre3-dev zlib1g-dev libssl-dev -
查看已安装的 Nginx 版本。
# 查看版本(用于下载对应源码) nginx -v # 查看完整编译参数 nginx -V 2>&1 | grep 'configure arguments' | sed 's/configure arguments: //'记录输出内容,例如
--prefix=/usr/local/nginx --with-http_ssl_module --with-http_v2_module。 -
下载对应版本的 Nginx 源码,请替换为实际版本号。
cd /tmp wget http://nginx.org/download/nginx-1.26.0.tar.gz tar zxvf nginx-1.26.0.tar.gz cd nginx-1.26.0 -
配置编译选项,将步骤 2 中的原始参数复制,并在末尾追加
--with-http_realip_module。./configure \ --prefix=/usr/local/nginx \ --with-http_ssl_module \ --with-http_v2_module \ --with-http_realip_module -
编译并升级服务。
make # make后会在 objs/ 目录下生成新的 nginx 二进制文件。 # 重命名旧二进制(保留备份) sudo mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old # 替换为新编译的版本 sudo cp objs/nginx /usr/local/nginx/sbin/nginx # 获取当前主进程 PID OLD_PID=$(pgrep -f 'nginx: master' | head -1) # 启动新主进程 sudo kill -USR2 $OLD_PID # 等待新进程启动 sleep 2 # 关闭旧进程 sudo kill -QUIT $OLD_PID
配置 Nginx 信任 WAF 回源 IP 段
-
编辑
nginx.conf主配置文件(默认位于/etc/nginx/nginx.conf),在http {}块中添加以下内容。http { # 信任来自 WAF 回源 IP 的 X-Forwarded-For 头 # 请替换为实际从控制台获取的 WAF 回源 IP 段,每个网段单独一行 # 必须包含全部 WAF 回源网段,若有遗漏,则可能导致日志仍显示 WAF 的回源IP,而非客户端真实 IP。 set_real_ip_from <ip_range1>; set_real_ip_from <ip_range2>; ... set_real_ip_from <ip_rangex>; # 指定从X-Forwarded-For请求头提取真实 IP real_ip_header X-Forwarded-For; } -
重载 Nginx 配置:
nginx -t && nginx -s reload
验证
-
访问网站,将
http://your-domain.com/替换为已接入 WAF 的域名。curl http://your-domain.com/ -
查看 Nginx 访问日志,应显示客户端真实 IP 地址。
tail -f /var/log/nginx/access.log
IIS 7 配置方案(IIS 7 及以上版本适用)
WAF 作为反向代理时,IIS 默认日志中的 c-ip 字段记录的是 WAF 回源 IP 而非真实用户 IP。通过 IIS 的 W3C 自定义日志字段功能,可将 X-Forwarded-For 请求头写入日志,便于审计和排查。
-
打开 IIS 管理器,在左侧连接树中展开服务器节点,选择目标网站(例如
Default Web Site)。 -
双击右侧功能视图中的日志图标。
-
在日志文件区域,确认日志格式为 W3C(默认值)。若为其他格式,请切换为 W3C。
-
在日志文件区域,单击选择字段… 。
-
在弹出窗口底部,单击添加字段… 。
-
在添加自定义字段对话框中填写以下信息,单击确定。
配置项
配置说明
字段名称
填写
X-FORWARDED-FOR源类型
选择
请求标头源
填写
X-Forwarded-For -
单击确定保存自定义字段。
-
再次单击确定关闭日志记录字段窗口,然后单击右侧应用保存更改。
-
重启 IIS 服务器使配置生效。
-
访问网站进行验证,并查看访问日志(默认路径
C:\inetpub\logs\LogFiles\W3SVC1\),应显示真实客户端 IP 地址。
Apache 配置方案
Apache 2.4 及以上版本自带 remoteip_module 模块(mod_remoteip.so),使用该模块可获取客户端真实 IP。
Alibaba Cloud Linux / CentOS / RHEL
-
编辑 Apache 主配置文件。
sudo vim /etc/httpd/conf/httpd.conf -
在文件末尾添加以下内容。
# 启用 mod_remoteip LoadModule remoteip_module modules/mod_remoteip.so # 指定 WAF 传递真实 IP 的请求头(WAF 使用 X-Forwarded-For) RemoteIPHeader X-Forwarded-For # 设置WAF回源IP段 请务必替换为阿里云 WAF 的回源 IP 段 RemoteIPTrustedProxy 100.xx.xx.0/10 RemoteIPTrustedProxy 11.xx.xx.0/13 RemoteIPTrustedProxy 112.xx.xx.0/16 -
定位至配置文件的日志格式部分,将
%h改为%a。%a表示连接的远程 IP(经mod_remoteip修正后的真实客户端 IP),%h为原始连接 IP(即 WAF 节点 IP)。修改后的示例如下所示。<IfModule log_config_module> # # The following directives define some format nicknames for use with # a CustomLog directive (see below). # LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined LogFormat "%a %l %u %t \"%r\" %>s %b" common <IfModule logio_module> # You need to enable mod_logio.c to use %I and %O LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio </IfModule> # # The location and format of the access logfile (Common Logfile Format). # If you do not define any access logfiles within a <VirtualHost> # container, they will be logged here. Contrariwise, if you *do* # define per-<VirtualHost> access logfiles, transactions will be # logged therein and *not* in this file. # #CustomLog "logs/access_log" common # # If you prefer a logfile with access, agent, and referer information # (Combined Logfile Format) you can use the following directive. # CustomLog "logs/access_log" combined </IfModule> -
重启 Apache 服务使配置生效。
sudo systemctl restart httpd -
访问网站进行验证,并查看访问日志,应显示真实客户端 IP 地址。
tail -f /var/log/httpd/access_log
Ubuntu / Debian
-
启用
remoteip模块。sudo a2enmod remoteip -
编辑 Apache 主配置文件。
sudo vim /etc/apache2/apache2.conf -
在文件末尾添加以下内容。
# 指定 WAF 传递真实 IP 的请求头(WAF 使用 X-Forwarded-For) RemoteIPHeader X-Forwarded-For # 设置WAF回源IP段 请务必替换为阿里云 WAF 的回源 IP 段 RemoteIPTrustedProxy 100.xx.xx.0/10 RemoteIPTrustedProxy 11.xx.xx.0/13 RemoteIPTrustedProxy 112.xx.xx.0/16 -
定位至配置文件的日志格式部分,将
%h改为%a。%a表示连接的远程 IP(经mod_remoteip修正后的真实客户端 IP),%h为原始连接 IP(即 WAF 节点 IP)。修改后的示例如下所示。# LogFormat "%v:%p %a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined LogFormat "%a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined LogFormat "%a %l %u %t \"%r\" %>s %O" common LogFormat "%{Referer}i -> %U" referer LogFormat "%{User-agent}i" agent -
重启 Apache 服务使配置生效。
sudo systemctl restart apache2 -
访问网站进行验证,并查看访问日志,应显示真实客户端 IP 地址。
tail -f /var/log/apache2/access.log
Tomcat 配置方案
Tomcat 通过启用 X-Forwarded-For 功能获取客户端真实 IP。
-
前往 Tomcat 安装目录,打开
tomcat/conf/server.xml配置文件。 -
将 AccessLogValve 日志配置修改为以下内容:
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix=".txt" pattern="%{X-FORWARDED-FOR}i %l %u %t %r %s %b %D %q %{User-Agent}i %T" resolveHosts="false"/> -
重启 Tomcat。
sudo systemctl restart tomcat -
访问网站进行验证,并查看访问日志,应显示真实客户端 IP 地址。
# 请将以下命令替换为实际的Tomcat安装目录路径,并替换为实际的日志文件 tail -f /opt/tomcat/logs/localhost_access_log.2026-01-01.txt
Kubernetes 集群配置方案
使用 Nginx Ingress Controller 的 Kubernetes 集群接入 WAF 时,客户端真实 IP 会被 WAF 添加至 X-Forwarded-For 请求头。默认情况下 Nginx Ingress Controller 不信任该字段,业务容器无法获取真实客户端 IP。
按以下步骤配置 Nginx Ingress Controller。
-
编辑 Ingress Controller 的 ConfigMap:
kubectl -n kube-system edit cm nginx-configuration -
在
data字段中添加以下配置项:compute-full-forwarded-for: "true" forwarded-for-header: "X-Forwarded-For" use-forwarded-headers: "true" -
保存并退出。配置将自动生效,无需重启 Pod。
配置完成后,Ingress Controller 会将
X-Forwarded-For中的第一个 IP 识别为客户端真实 IP,并在转发请求时保留该值。
进阶优化:通过自定义 Header 透传真实 IP
复杂网络架构中,依赖标准 X-Forwarded-For(XFF)头存在被伪造、多层代理 IP 混淆等风险。可通过自定义 HTTP Header 透传真实客户端 IP,提升安全性和可控性。
以下示例演示通过自定义 Header 获取真实客户端 IP。
-
CDN 配置
CDN 默认在回源请求中携带
Ali-Cdn-Real-IpHTTP 请求头,表示客户端与 CDN 节点连接时的真实 IP。通过增加自定义出站请求头,可将该 IP 传递至 WAF。CDN 控制台配置示例如下。配置项
示例
请求头操作
增加
自定义请求头参数
自定义回源请求头
自定义请求头名称
填写自定义名称,例如
TrueIP请求头值
$http_Ali_Cdn_Real_Ip是否允许重复
不允许
规则条件
不使用
-
WAF 配置
在 WAF 控制台完成以下两项配置:
-
WAF前是否有七层代理(高防/CDN等):使 WAF 正确识别真实客户端 IP。
-
启用流量标记:使源站服务器获取真实客户端 IP。
具体配置方法,请参见获取真实客户端信息。
配置项
示例
WAF前是否有七层代理(高防/CDN等)
选择是,继续选择 【推荐】取指定Header字段中的第一个IP作为客户端源IP,避免XFF伪造,填写上一步 CDN 配置中的 自定义请求头名称,例如
TrueIP。启用流量标记
选择 客户端真实源IP,并填写上一步 CDN 配置中的 自定义请求头名称,例如
TrueIP。 -
-
源站服务器配置
以 Nginx 为例,编辑
nginx.conf主配置文件,在http {}块中添加以下内容。详情请参见Nginx 配置方案。http { # 信任来自 WAF 回源 IP 的请求头 # 请替换为实际从控制台获取的 WAF 回源 IP 段,每个网段单独一行 # 必须包含全部 WAF 回源网段,若有遗漏,则可能导致日志仍显示 WAF 的回源IP,而非客户端真实 IP。 set_real_ip_from <ip_range1>; set_real_ip_from <ip_range2>; ... set_real_ip_from <ip_rangex>; # 指定从自定义的请求头提取真实 IP,本示例使用TrueIP real_ip_header TrueIP; }建议在源站服务器安全组配置仅放行 WAF 回源 IP 段,确保仅有 WAF 能与源站通信,避免攻击者绕过 WAF 直接访问源站公网 IP。
常见问题
源站服务器的真实 IP 获取配置与 WAF 控制台中的“WAF前是否有七层代理(高防/CDN等)”配置项有什么区别?
-
源站服务器的真实 IP 获取配置(本文内容)
-
作用:CNAME 接入 WAF 后,使源站服务器(如 Nginx)的访问日志(如
access.log)记录真实客户端 IP,而非 WAF 回源 IP。 -
是否必需:仅在需要在源站侧查看或处理真实客户端 IP 时才需配置。
-
-
WAF 控制台的WAF前是否有七层代理(高防/CDN等)配置项
-
适用场景:WAF 前方部署了其他七层代理(如 CDN、高防等)。
-
作用:告知 WAF 从指定 HTTP 请求头(如
Ali-Cdn-Real-Ip或X-Forwarded-For)中提取真实客户端 IP,确保安全报表和攻击识别基于真实来源 IP。 -
是否必需:仅在 WAF 前存在七层代理时才需启用;若无前置代理,保持默认值否。
-
X-Forwarded-For 伪造是什么,如何避免?
X-Forwarded-For(XFF)伪造指攻击者在 HTTP 请求中构造或篡改 X-Forwarded-For 请求头,注入虚假客户端 IP,以绕过基于 IP 的访问控制、日志审计或安全策略。X-Forwarded-For 是非标准请求头,客户端可任意设置,若后端服务未经验证直接信任该字段,将带来安全风险。
示例:XFF 伪造攻击命令
攻击者可使用 curl 命令伪造 X-Forwarded-For 头,伪装 IP 为 1.2.3.4:
curl -H "X-Forwarded-For: 1.2.3.4" https://example.com/
防范 XFF 伪造的方法是使用自定义可信请求头传递真实 IP:
配置 CDN 或 WAF 在回源时使用预定义的自定义 HTTP 请求头传递真实客户端 IP,源站侧仅解析该自定义头。该请求头由可信中间件(如 WAF)注入,客户端无法直接控制,可有效避免伪造。