网站接入Web应用防火墙(Web Application Firewall,简称WAF)后,访问请求在到达源站服务器之前,需要经过WAF的代理转发。这种情况下,源站服务器可以通过解析回源请求中的X-Forwarded-For记录,获取客户端的真实IP。本文介绍如何配置不同类型的Web应用服务器(包括Nginx、IIS 6、IIS 7、Apache、Tomcat)以及容器K8s,以获取客户端的真实IP。
背景信息
WAF在将客户端的访问请求转发到下一环节的服务器时,会在HTTP的请求头中添加一条X-Forwarded-For记录,用于记录客户端的IP,格式为X-Forwarded-For:客户端IP
。如果客户端和源站服务器之间有多个代理服务器(例如WAF、DDoS高防、CDN等),则X-Forwarded-For记录使用以下格式记录客户端IP和依次经过的代理服务器IP:X-Forwarded-For:客户端IP, 代理服务器1的IP, 代理服务器2的IP, 代理服务器3的IP, ……
。
因此,常见的Web应用服务器(包括Nginx、IIS 6、IIS 7、Apache、Tomcat)以及容器K8s可以通过解析X-Forwarded-For记录获取客户端真实IP。
下文分别介绍如何配置Nginx、IIS 6、IIS 7、Apache和Tomcat服务器以及容器K8s,解析X-Forwarded-For记录,获取客户端的真实IP。
开始配置之前,请务必备份现有环境,包括ECS快照备份和Web应用服务器配置文件备份。
Nginx配置方案
Nginx服务器使用http_realip_module模块解析X-Forwarded-For记录。您可以参考如下步骤,安装http_realip_module模块,修改Nginx配置。
安装http_realip_module模块。
在Nginx服务器上执行
# nginx -V | grep http_realip_module
命令,查看是否已安装http_realip_module模块。如果已在Nginx服务器上安装该模块,请跳过安装步骤。
如果没有在Nginx服务器上安装该模块,请重新编译Nginx服务并参考如下方法安装该模块。
说明一般情况下,通过一键安装包安装的Nginx服务器默认不安装http_realip_module模块。
wget http://nginx.org/download/nginx-1.12.2.tar.gz tar zxvf nginx-1.12.2.tar.gz cd nginx-1.12.2 ./configure --user=www --group=www --prefix=/alidata/server/nginx --with-http_stub_status_module --without-http-cache --with-http_ssl_module --with-http_realip_module make make install kill -USR2 `cat /alidata/server/nginx/logs/nginx.pid` kill -QUIT `cat /alidata/server/nginx/logs/nginx.pid.oldbin`
修改Nginx服务器配置文件。
打开
nginx.conf
配置文件。在
http {}
中添加以下内容:http { # 定义可从哪些IP地址接收真实客户端IP set_real_ip_from <ip_range1>; set_real_ip_from <ip_range2>; ... set_real_ip_from <ip_rangex>; # 定义客户端IP地址的HTTP头 real_ip_header X-Forwarded-For; }
其中,
<ip_range1>
、<ip_range2>
、<ip_rangex>
需要设置为代理服务器(即WAF)的回源IP段。您需要登录Web应用防火墙控制台,在顶部菜单栏,选择WAF实例的资源组和地域(中国内地、非中国内地),单击 即可获取所有的WAF回源IP段。多个回源IP段必须分行添加,且需要添加所有回源IP段。假设WAF回源IP段包括10.10.10.0/24、11.11.XX.X/25、2.13.XX.XX/27,则使用如下格式:
set_real_ip_from 10.10.10.0/24; set_real_ip_from 11.11.XX.X/25; set_real_ip_from 2.13.XX.XX/27; real_ip_header X-Forwarded-For;
这里提供一个脚本将复制到的WAF回源IP段字符串(仅IPv4地址)转换成
set_real_ip_from <ip_rangeX>
格式import re def format_ip_ranges(ip_ranges_str): # 使用正则表达式匹配所有的IP段 ip_pattern = re.compile(r'\d+\.\d+\.\d+\.\d+/\d\d') ip_list = ip_pattern.findall(ip_ranges_str) formatted_ips = [f" set_real_ip_from {ip};" for ip in ip_list] output = "\n".join(formatted_ips) return output ip_ranges_str = "WAF回源ip段字符串" formatted_output = format_ip_ranges(ip_ranges_str) print(formatted_output)
修改log_format日志记录格式。
打开
nginx.conf
配置文件,定位到http
配置部分的log_format
。在
log_format
中添加x-forwarded-for
字段,替换默认的remote-address
字段。修改后的log_format内容如下:
log_format main '$http_x_forwarded_for - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" ';
执行
nginx -s reload
命令,重启Nginx服务器,使配置生效。测试配置是否生效。
使用curl命令模拟请求:
curl -H "X-Forwarded-For: 1.2.3.4" http://example.com
检查Nginx访问日志,确认客户端IP已成功提取:
tail -f access.log
IIS 6配置方案
IIS 6服务器使用F5XForwardedFor模块解析X-Forwarded-For记录。您可以参考如下步骤,安装F5XForwardedFor模块。
将
x86\Release
或x64\Release
目录下的F5XForwardedFor.dll
文件拷贝到某个自定义目录(例如C:\ISAPIFilters\x86
、C:\ISAPIFilters\x64
)。说明请确保IIS进程拥有自定义目录的读写权限。
如果该目录下,没有
F5XForwardedFor.dll
文件,请手动下载该文件,并将该文件放到自定义目录。下载路径,请参见F5XForwardedFor.dll。
打开IIS管理器,定位到目标站点,右键单击属性。
在ISAPI筛选器页签,单击添加。完成如下配置后,单击确定。
以32位操作系统为例:
筛选器名称:
x_forwarded_for_x86
。可执行文件:
F5XForwardedFor.dll
文件所在的完整路径(例如C:\ISAPIFilters\x86\F5XForwardedFor.dll
)。
重启IIS 6服务器,使配置生效。
IIS 7配置方案
IIS 7服务器使用F5XForwardedFor模块解析X-Forwarded-For记录。您可以参考如下步骤,安装F5XForwardedFor模块。
将
x86\Release
或x64\Release
目录下的F5XFFHttpModule.dll
和F5XFFHttpModule.ini
文件拷贝到某个自定义目录(例如C:\x_forwarded_for\x86
、C:\x_forwarded_for\x64
)。说明请确保IIS进程拥有自定义目录的读写权限。
如果该目录下,没有
F5XForwardedFor.dll
和F5XFFHttpModule.ini
文件,请手动下载文件,并将文件放到自定义目录。下载路径,请参见F5XForwardedFor模块。
打开IIS管理器,在IIS区域,双击模块。
在模块页面右侧操作区域,单击配置本机模块。
在配置本机模块对话框,单击注册。填写注册信息后,单击确定。
以32位操作系统为例:
名称:
x_forwarded_for_x86
。路径:
F5XFFHttpModule.dll
文件所在的完整路径(例如C:\x_forwarded_for\x86\F5XFFHttpModule.dll
)。
在配置本机模块对话框,选中新注册的模块,单击确定。
在ISAPI 和CGI限制页面,添加已注册的DLL,并将限制设置为允许。
重启IIS 7服务器,使配置生效。
Apache配置方案
Windows操作系统
Apache 2.4及以上版本的安装包中自带remoteip_module模块文件(mod_remoteip.so
),Apache服务器使用该模块获取客户端IP地址。
进入Apache服务器的extra配置文件夹(
conf/extra/
),新建httpd-remoteip.conf
配置文件。说明通过引入
remoteip.conf
配置文件的方式加载相关配置,减少直接修改httpd.conf
配置文件的次数,避免因操作失误导致业务异常。编辑
httpd-remoteip.conf
配置文件,在文件中添加以下内容:# 加载mod_remoteip.so模块 LoadModule remoteip_module modules/mod_remoteip.so # 设置RemoteIPHeader头部 RemoteIPHeader X-Forwarded-For # 设置回源IP段 RemoteIPInternalProxy <ip_range1> <ip_range2> …… <ip_rangex>
其中,
<ip_range1>
、<ip_range2>
、<ip_rangex>
需要设置为代理服务器(即WAF)的回源IP段。您需要登录Web应用防火墙控制台,在顶部菜单栏,选择WAF实例的资源组和地域(中国内地、非中国内地),单击 即可获取所有的WAF回源IP段。多个回源IP段之前使用空格分隔。假设代理服务器的回源IP段包含10.0.0.1、10.0.0.2、10.0.0.3,则使用以下格式:
RemoteIPInternalProxy 10.0.0.1 10.0.0.2 10.0.0.3
编辑conf/httpd.conf配置文件,在文件中添加以下内容:
Include conf/extra/httpd-remoteip.conf
以上命令表示在conf/httpd.conf中插入
httpd-remoteip.conf
配置文件。在
httpd.conf
配置文件中修改日志格式。LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined LogFormat "%a %l %u %t \"%r\" %>s %b" common
重启Apache服务,使配置生效。
Linux操作系统
您可以参考上述Windows操作系统服务器的配置方式,添加Apache 2.4及以上版本自带的remoteip_module模块(mod_remoteip.so
)并配置日志格式,获取客户端IP地址。
如果Linux服务器使用的Apache版本低于2.4,请参照以下步骤,通过设置Apache的第三方模块(mod_rpaf)来获取客户端IP地址。
安装mod_rpaf模块。
wget https://github.com/gnif/mod_rpaf/archive/v0.6.0.tar.gz tar zxvf mod_rpaf-0.6.tar.gz cd mod_rpaf-0.6 /alidata/server/httpd/bin/apxs -i -c -n mod_rpaf-2.0.so mod_rpaf-2.0.c
编辑Apache配置文件
/alidata/server/httpd/conf/httpd.conf
,在文件最后添加以下内容:LoadModule rpaf_module modules/mod_rpaf-2.0.so RPAFenable On RPAFsethostname On RPAFproxy_ips <rpaf ip地址> RPAFheader X-Forwarded-For
其中,
<rpaf ip地址>
不是代理服务器的公网IP地址,具体IP请通过Apache日志查询。通常包含两个IP地址,示例如下:LoadModule rpaf_module modules/mod_rpaf-2.0.so RPAFenable On RPAFsethostname On RPAFproxy_ips 10.XX.XX.65 10.XX.XX.131 RPAFheader X-Forwarded-For
重启Apache服务,使配置生效。
/alidata/server/httpd/bin/apachectl restart
更多Apache相关模块的信息,请参见Apache帮助文档。
Tomcat配置方案
Tomcat服务器通过启用X-Forwarded-For功能,获取客户端IP地址。
打开
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"/>
容器K8s配置方案
如果您的服务部署在K8s上,K8s会将真实的客户端IP记录在X-Original-Forwarded-For字段中,并将WAF回源地址记录在X-Forwarded-For字段中。您需要修改容器的配置文件,使Ingress将真实的IP添加到X-Forwarded-For字段中,以便您正常获取真实的客户端IP地址。
您可以参考以下步骤,对容器配置文件进行修改。
执行以下命令修改配置文件
kube-system/nginx-configuration
。kubectl -n kube-system edit cm nginx-configuration
在配置文件中添加以下内容:
compute-full-forwarded-for: "true" forwarded-for-header: "X-Forwarded-For" use-forwarded-headers: "true"
保存配置文件。
保存后配置即刻生效,Ingress会将真实的客户端IP添加到X-Forwarded-For字段中。
将业务程序获取客户端真实IP的字段修改为X-Original-Forwarded-For。