Tomcat获取Nginx代理后的真实客户端IP地址

可访问
• 阅读 450
在传统的架构中,中小型企业采用Nginx+Tomcat这种架构时,客户端请求将由Nginx转发至后端Tomcat,当有需求在Tomcat日志中也能看到客户端真实IP地址的情况下,我们就需要使用到Nginx的 proxy_set_header指令来进行协助,而且还需要修改Tomcat对于 localhost_access 的日志格式,要不然tomcat记录的访客IP全都是Nginx的, 这是因为所有的请求都是由Nginx前端服务器转发而来的。

Nginx配置日志格式

Nginx需要先获取到客户端的真实IP地址后才能将客户端真实IP地址发送到后端Tomcat,所以也需要配置Nginx的日志格式,在Nginx代理Tomcat的日志格式中最为重要的配置为 $remote_addr 来获取到真实客户端IP地址,我这里的Nginx日志格式如下:

   log_format  main  '$remote_addr" "$remote_user" "[$time_local]" "$request"'
                     ' "$status" "$body_bytes_sent" "$http_referer"'
                     ' "$http_user_agent" "$http_x_forwarded_for" "$gzip_ratio"'
                     ' "$upstream_addr" "$request_time" "$upstream_response_time" "$http_host"';

有关更多Nginx日志格式请见:https://k8sops.cn/nginx_log_m...

Nginx配置转发IP头

proxy_set_header指令可以配置到 http, server, location 三个配置段当中,我这里配置到 location 字段中。

location ^~ /crm-newm {
         proxy_pass  http://172.26.3.55:8086;
         proxy_http_version 1.1;
         proxy_set_header Host $host;
         proxy_set_header Port $proxy_port;
         proxy_set_header X-Real-IP $remote_addr;
      }

proxy_http_version指令解析:
proxy_http_version指令用于设置代理的HTTP协议版本。默认情况下,使用的是1.0版。建议将版本1.1用于keepalive连接和NTLM身份验证

Syntax:    proxy_http_version 1.0 | 1.1;
Default:    proxy_http_version 1.0;
Context:    http, server, location

proxy_set_header
proxy_set_header指令用于重新定义header或将字段附加到代理服务器的请求头中。该值可以包含文本、变量、或者文本变量的组合。

proxy_set_header Host $host;
Host为自定义文本,$host变量为Nginx中的内置变量,用于获取当前主机名

proxy_set_header Port $proxy_port;
Port为自定义文本,$proxy_port变量也是为Nginx中的内置变量,用于获取nginx代理的主机端口

proxy_set_header X-Real-IP $remote_addr;
X-Real-IP为自定义文本,$remote_addr变量也是Nginx中的内置变量,用于获取真实客户端IP地址,与Nginx中的$remote_addr一致

以上配置对于HTTP头部内容,这些变量是不区分大小写的

Tomcat日志格式讲解

在tomcat家目录下的 conf/server.xml 文件中,定位到 logs 字段来修改tomcat日志格式

vim conf/server.xml
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />

prefix
prefix用于指定tomcat 访问日志的前缀

suffix
suffix用于指定tomcat 访问日志的后缀

pattern
pattern用于指定tomcat 访问日志的输出格式

访问日志支持的格式如下:

%a - 远程IP地址
%A - 本地IP地址
%b - 发送的字节数,不包括HTTP头,或“ - ”如果没有发送字节
%B - 发送的字节数,不包括HTTP头
%h - 远程主机名
%H - 请求协议
%l - (小写的L)- 远程逻辑从identd的用户名(总是返回' - ')
%m - 请求方法
%p - 本地端口
%q - 查询字符串(在前面加上一个“?”如果它存在,否则是一个空字符串
%r - 第一行的要求
%s - 响应的HTTP状态代码
%S - 用户会话ID
%t - 日期和时间,在通用日志格式
%u - 远程用户身份验证
%U - 请求的URL路径
%v - 本地服务器名(访问域名)
%D - 处理请求的时间(以毫秒为单位)
%T - 处理请求的时间(以秒为单位)
%I -(大写的i) - 当前请求的线程名称

另外,还可以将request请求的查询参数、session会话变量值、cookie值或HTTP请求/响应头内容的变量值等内容写入到日志文件。
它仿照了apache的语法:

%{XXX}i  xxx代表传入的头(HTTP Request)
%{XXX}o  xxx代表传出​​的响应头(Http Resonse)
%{XXX}c  xxx代表特定的Cookie名
%{XXX}r  xxx代表ServletRequest属性名
%{XXX}s  xxx代表HttpSession中的属性名

配置Tomcat日志记录客户真实IP

此配置需要修改Tomcat的日志格式来支持记录客户端的真实IP地址,默认是不可以的。
在Nginx+Tomcat架构中使用日志格式中的 %a 是获取不到真实客户端IP地址的,如果直接访问Tomcat那么 %a 可以获取到真实客户端IP地址。
如果要在Nginx+Tomcat架构中记录真实客户端IP地址需要在日志格式中添加 %{X-Real-IP}i 配置来获取,
%{X-Real-IP}i 是我们在Nginx location 配置段中指定的文本来获取 $remote_addr 变量值的,在这里将此值传送给 Tomcat。
%{Port}i 也是我们在Nginx中定义的文本来获取后端的转发端口,这里也将值转发至Tomcat。

        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log" suffix=".txt"
               pattern="%t %{X-Real-IP}i %h:%p %A:%{Port}i %m %s %S %u %H %v %U %b %T %I" />

以上日志输出格式默认以空格做为分割的,以上格式我已经做了排版,tomcat输出访问日志如下:

1. %t 日期和时间 
2. %{X-Real-IP}i 客户端真实IP地址
3. %h:%p 远程IP(Nginx代理IP),远程端口(客户端访问Nginx的端口)
4. %A:%{Port}i 本地IP地址及访问的本地端口
5. %m HTTP请求方法
6. %s 请求状态码
7. %S 用户会话ID
8. %u 远程用户身份验证
9. %H HTTP请求协议
10. %v 访问的域名
11. %U 访问的URL
12. %b 发送的字节数,不包括HTTP头,或“ - ”如果没有发送字节
13. %T Tomcat处理请求的时间(以秒为单位)
14. %I (大写的i)当前请求的线程名称
※更多文章和资料|点击后方文字直达 ↓↓↓
100GPython自学资料包
阿里云K8s实战手册
[阿里云CDN排坑指南]CDN
ECS运维指南
DevOps实践手册
Hadoop大数据实战手册
Knative云原生应用开发指南
OSS 运维实战手册
云原生架构白皮书
Zabbix企业级分布式监控系统源码文档
云原生基础入门手册
10G大厂面试题戳领
点赞
收藏
评论区
推荐文章
Stella981 Stella981
3年前
Nginx多层代理获取真实客户端IP
一般的应用都是通过Nginx来做为反向代理,并且Nginx还可能是多层的。如果想在内部服务里面获取最原始的客户端IP地址。则需要做一些配置最外层Nginx为了防止XForwardedFor头的伪造,可在最外层Nginx将XForwardedFor设置为真实IP$remote\_addr。$remote\_addr是获取的是
Stella981 Stella981
3年前
Docker Compose 一键部署Nginx代理Tomcat集群
DockerCompose一键部署Nginx代理Tomcat集群目录结构root@localhost~treecompose_nginx_tomcat/compose_nginx_tomcat/├──dockercompose.yml├──mysql│  ├──
Stella981 Stella981
3年前
Nginx proxy_set_header 理解
用户认证接口:根据客户端IP和port,进行IP反查和端口范围确认,如符合则用户认证通过。当前使用的是Nginx负载均衡,从客户端到Nginx端ip和port都对,从Nginx到应有服务器上port端口变成很奇怪的端口号。真是遇到的问题,登录页的ip和port在登录验证没有问题,但在登录完成后跳转的时候,端口号发生了变化。跟nginx服务器
Wesley13 Wesley13
3年前
Java获取HttpServletRequest真实的调用ip
有时候我们需要获取Http请求的源IP,但由于有着各种代理,与反向代理,还有代理请求头标准的缺失,导致我们想拿到真正的ip变得更加困难。这篇文章来总结下一个目前可行的比较全面的通用方法。首先,真实调用的ip,应该不是内网ip,并且考虑到客户端多样性,我们从通用的Header出发,并也考虑各种常见客户端的自定义Header。验证IP有效
Stella981 Stella981
3年前
Docker实战——分布式Websocket服务
一、项目介绍我们很容易可以使用Springboot来搭建一个支持websocket的应用,用来实现基于HTML5的客户端之间进行消息的接收和推送。但是在实际应用的部署时,客户端和应用服务器之间总会用到Nginx或者Apache来做反向代理,来实现负载均衡。用Nginx举个例子来说,我们使用轮询的方式,将客户端的请求分发到后端3台w
Stella981 Stella981
3年前
Nginx配置实验反向代理
l 实验要求浏览器访问8083.mine.com:8081地址,(Nginx端口是8081)通过Nginx服务器反向代理监听请求,将请求转发到tomcat服务器上,实现真正内容的访问。l 实验环境一台已安装Nginx(port:8081),tomcat8.5.39(port:8083)的CentOS服务
Stella981 Stella981
3年前
Nginx 简单配置域名跳转
暂时用到这么多,简单记录下首先要买个域名去买域名的网站后台管理配置域名解析,设置跳转到服务器公网ip直接访问公网ip的结果是访问80端口,一般web应用并不是,如tomcat默认8080服务器安装Nginx修改Nginx配置文件,转发80端口收到的请求到web应用的真实地址使生效
Stella981 Stella981
3年前
Nginx反向代理Tomcat配置
Nginx代理Tomcat为什么要为Tomcat配置反向代理?1)如果同一台机器既有nginx又有Tomcat,则会产生端口冲突2)我们需要把8080端口变成80端口3)nginx对于静态的请求速度上要优于Tomcat,Tomcat不擅长做静态的处理。如何配置?cd/etc/ngin
Wesley13 Wesley13
3年前
7个获取访问者真实IP的方法,速学!!!
通常情况下,网站访问并不是简单地从用户的浏览器直达服务器,中间可能部署有CDN、WAF、高防。例如,采用这样的架构:“用户CDN/WAF/高防源站服务器”。那么,在经过多层代理之后,服务器如何获取发起请求的真实客户端IP呢?一个透明的代理服务器在把用户的HTTP请求转到下一环节的服务器时,会在HTTP的头部中加入一条“XForwarded
Easter79 Easter79
3年前
Tomcat集群方案
一、需求多个tomcat要一起协同工作有几种办法,可以考虑的方案有以下几个:1\.使用tomcat自带的cluster方式,多个tomcat间自动实时复制session信息,配置起来很简单。但这个方案的效率比较低,在大并发下表现并不好。2\.利用nginx的基于访问ip的hash路由策略,保证访问的ip始终被路由到同一个tomcat上,
Stella981 Stella981
3年前
Nginx负载均衡
前面我们说了反向代理,例子中用的是,两个请求请求同一个ip地址和端口,然后Nginx来根据域名调用不同的tomcat来进行请求处理及响应。反向代理主要说的是:不同的请求请求同一个Nginx服务器,Nginx服务器来决定由那个真正的业务服务器(eg:tomcat)处理某个请求。下面说负载均衡负载均衡一般是指,针对同一个(域名的)请求发送很多次,同