Tomcat捕获Nginx反向代理协议IP及端口配置

简介:

最近的技术调整,需要获取Nginx端请求方式是http还是https。我们当前的架构属于典型的互联网架构,Nginx+Tomcat+Mysql,启用了反向代理。当前并没有启用全站https,因此客户端发出的请求基于模块的方式使用http或者https协议。关于捕获这个请求的协议,我们需要使用到Nginx ngx_http_proxy_module这个模块中的proxy_set_header指令来进行配置。本文描述通过这个命令来实现捕获请求协议。

一、关于proxy_set_header指令

这个指令的使用上下文是http,server,location,它允许重新定义或附加字段到传递给代理服务器的请求头部 。简单的说,当客户端发出web请求后,这个指令可以把真实的客户端请求的如IP地址,端口号,协议等等追加或修改到代理服务器的请求头部。通过这个设置,我们可以获取最终客户的原始请求信息,而不是代理服务器作为客户端的信息。这个指令的值value可以包含文本,变量,以及它们的组合。当且仅当proxy_set_header 在当前级别上没有定义的指令时,这些指令才从前一级继承 。默认情况下,只有两个字段被重新定义,他们是,proxy_set_header Host $proxy_host; proxy_set_header Connection close。

proxy_set_header指令中几个常用的变量
$remote_addr  :客户端真实地址,非代理服务器地址
$remote_port  :客户端真实端口,非代理服务器端口
$proxy_host    :proxy_pass指令中指定的代理服务器的名称和端口 ;
$proxy_port      :proxy_pass指令中指定的代理服务器 的端口或协议的默认端口;
$proxy_add_x_forwarded_for  :带有$remote_addr变量的“X-Forwarded-For”客户机请求头字段,用逗号分隔。
如果客户请求头中不存在“X-Forwarded-For”字段,则$proxy_add_x_forwarded_for变量等于该$remote_addr变量。
它在多层代理时会包含真实客户端及中间每个代理服务器的IP。

二、环境描述

nginx服务器环境

[root@node132 ~]# more /etc/redhat-release 
CentOS release 6.7 (Final)
[root@node132 ~]# nginx -v
nginx version: nginx/1.10.2
[root@node132 ~]# ip addr|grep inet|grep global 
    inet 192.168.1.132/24 brd 192.168.1.255 scope global eth0
    inet 192.168.81.148/24 brd 192.168.81.255 scope global eth1

tomcat服务器环境

[root@datanode1 ~]# more /etc/redhat-release 
CentOS Linux release 7.2.1511 (Core)  ##,另外一台tomcat环境与此相同,仅仅是ip地址和主机名不同
[root@datanode1 ~]# /usr/local/tomcat/bin/catalina.sh version
erver version: Apache Tomcat/7.0.69
Server built:  Apr 11 2016 07:57:09 UTC
Server number:  7.0.69.0
root@datanode1 ~]# ip addr|grep inet|grep global
    inet 192.168.81.146/24 brd 192.168.81.255 scope global dynamic eno16777728

三、Nginx配置

nginx配置文件

[root@node132 ~]# more /etc/nginx/conf.d/tomcat.conf 
upstream app {
                server 192.168.81.146:8080;
                server 192.168.81.147:8080;
}

server {
    listen 80;
    server_name node132.ydq.com;
    location / {
        proxy_pass http://app;
    
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-scheme $scheme;
        proxy_set_header x-agent $http_user_agent;
        add_header backendIP $upstream_addr;
    }
}

server {
    listen      443 ssl;
    server_name  node132.ydq.com;
    ssl_certificate      /etc/nginx/conf.d/node132.ydq.com.crt;
    ssl_certificate_key  /etc/nginx/conf.d/node132.ydq.com.key;

    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;

    ssl_ciphers  HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers  on;

    location / {
        proxy_pass http://app;
      
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-Port $remote_port;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-scheme $scheme;
        proxy_set_header x-agent $http_user_agent;
        add_header backendIP $upstream_addr;
    }
} 

[root@node132 ~]# /etc/init.d/nginx reload
[root@node132 ~]# ss -nltp|grep nginx
LISTEN    0      128  *:80    *:*  users:(("nginx",13703,6),("nginx",13705,6))
LISTEN    0      128  *:443  *:*  users:(("nginx",13703,7),("nginx",13705,7))

四、Tomcat配置

TomcatA配置如下
[root@datanode1 ~]# more /usr/local/tomcat/conf/server.xml ##仅列出修改过的部分如下
<Engine name="Catalina" defaultHost="datanode1.example.com" jvmRoute="TomcatA">
<Host name="datanode1.example.com"  appBase="/website"
            unpackWARs="true" autoDeploy="true">
        <Context path="" docBase="webapps" reloadable="true" /> 
</Host>

TomcatB配置如下
[root@datanode2 ~]# more /usr/local/tomcat/conf/server.xml ##仅列出修改过的部分如下
<Engine name="Catalina" defaultHost="datanode2.example.com" jvmRoute="TomcatB">
<Host name="datanode2.example.com"  appBase="/website"
            unpackWARs="true" autoDeploy="true">
        <Context path="" docBase="webapps" reloadable="true" /> 
</Host>

两台tomcat均创建如下目录,第二台演示略
[root@datanode1 ~]# mkdir -pv /website/webapps
[root@datanode1 ~]# vi /website/webapps/reverse_proxy.jsp 
<%@page contentType="text/html; charset=UTF-8" trimDirectiveWhitespaces="true"%>
<%

String proto=request.getHeader("X-Forwarded-scheme");
String serverName = request.getServerName();
String remoteName = request.getRemoteAddr();
String get_method = request.getMethod().toString();
int serverPort = request.getServerPort();
int clientPort = request.getRemotePort();

String xforwardedip = request.getHeader("X-Forwarded-For");
String xrealip = request.getHeader("X-Real-IP");
String Host = request.getHeader("Host");

String client_ip_port = proto+"://"+xforwardedip+":"+clientPort;
String reverse_proxy_ip_port = proto+"://"+remoteName+":"+serverPort;

String request_url=request.getRequestURL().toString();
String request_uri=request.getRequestURI().toString();
String usr_agent = request.getHeader("x-agent");
%>

<h1>Client Information</h1>
ClientPort:<%=clientPort%><br>
Client IP and Port : <%=client_ip_port%> <br>
Client Request method : <%=get_method%> <br>
Full Request Link : <%=request_url%> <br>
user_agent:<%=usr_agent%> <br>

<h1>Reverse Proxy Server Information</h1>
Server Name : <%=serverName%> <br>
Reverse Hostname : <%=Host%> <br>

Reverse Proxy Server IP and Port : <%=reverse_proxy_ip_port%> <br>
Request URL : <%=reverse_proxy_ip_port%>  <br>
Request URI : <%=request_uri%>  <br>

五、测试

在Windows客户端测试
浏览器http请求:http://node132.ydq.com/reverse_proxy.jsp
Client Information
ClientPort:58906
Client IP and Port : http://192.168.1.242:58906  //正确捕获到了客户端的ip地址及端口
Client Request method : GET
Full Request Link : http://node132.ydq.com/reverse_proxy.jsp  //完整的请求链接
user_agent:Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0

Reverse Proxy Server Information
Server Name : node132.ydq.com
Reverse Hostname : node132.ydq.com
Reverse Proxy Server IP and Port : http://192.168.81.148:80  //服务器端对应的ip地址及端口
Request URL : http://192.168.81.148:80
Request URI : /reverse_proxy.jsp                                                 

浏览器https请求:https://node132.ydq.com/reverse_proxy.jsp
Client Information  ## Author : Leshami
ClientPort:58908   ## Blog : http://blog.csdn.net/leshami
Client IP and Port : https://192.168.1.242:58908
Client Request method : GET
Full Request Link : http://node132.ydq.com/reverse_proxy.jsp
user_agent:Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0

Reverse Proxy Server Information
Server Name : node132.ydq.com
Reverse Hostname : node132.ydq.com
Reverse Proxy Server IP and Port : https://192.168.81.148:80
Request URL : https://192.168.81.148:80  //此处与上一行端口应当为443才对
Request URI : /reverse_proxy.jsp

Google了N多,需要修改tomcat的配置,修改如下(修改后重启tomcat):
<Valve className="org.apache.catalina.valves.RemoteIpValve"  
remoteIpHeader="X-Forwarded-For"  
requestAttributesEnabled="true"
protocolHeader="X-Forwarded-scheme"  
protocolHeaderHttpsValue="https"/> 

Client Information
ClientPort:41168
Client IP and Port : https://null:41168  //这个地方显示为Null值了
Client Request method : GET
Full Request Link : https://node132.ydq.com/reverse_proxy.jsp
user_agent:Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0

Reverse Proxy Server Information
Server Name : node132.ydq.com
Reverse Hostname : node132.ydq.com
Reverse Proxy Server IP and Port : https://192.168.1.242:443
Request URL : https://192.168.1.242:443  //此行同上行IP地址应该为反向代理服务器IP才对,端口现在OK
Request URI : /reverse_proxy.jsp

上述的这个问题被遗留,暂时没有找到明确的答案。有知道的专家们请指点。

六、更多参考

http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_set_header
http://tomcat.apache.org/tomcat-7.0-doc/servletapi/javax/servlet/http/HttpServletRequest.html

DBA牛鹏社(SQL/NOSQL/LINUX)

目录
相关文章
|
8月前
|
编解码 应用服务中间件 Linux
centos配置nginx-rtmp实现ffmpeg转码rtsp为rtmp视频流
centos配置nginx-rtmp实现ffmpeg转码rtsp为rtmp视频流
684 1
|
8月前
|
Ubuntu 安全 应用服务中间件
详细指南:配置Nginx服务器在Ubuntu平台上
以上步骤涵盖了基本流程:从软件包管理器获取 Ngnix, 设置系统服务, 调整UFW规则, 创建并激活服务器块(也称作虚拟主机), 并进行了初步优化与加固措施。这些操作都是建立在命令行界面上,并假设用户具有必要权限(通常是root用户)来执行这些命令。每个操作都有其特定原因:例如,设置开机启动确保了即使重启后也能自动运行 Ngnix;而编辑server block则定义了如何处理进入特定域名请求等等。
480 18
|
8月前
|
Ubuntu 安全 应用服务中间件
详细指南:配置Nginx服务器在Ubuntu平台上
以上步骤涵盖了基本流程:从软件包管理器获取 Ngnix, 设置系统服务, 调整UFW规则, 创建并激活服务器块(也称作虚拟主机), 并进行了初步优化与加固措施。这些操作都是建立在命令行界面上,并假设用户具有必要权限(通常是root用户)来执行这些命令。每个操作都有其特定原因:例如,设置开机启动确保了即使重启后也能自动运行 Ngnix;而编辑server block则定义了如何处理进入特定域名请求等等。
795 17
|
9月前
|
数据建模 应用服务中间件 PHP
配置nginx容器和php容器协同工作成功,使用ip加端口的方式进行通信
本示例演示如何通过Docker挂载同一宿主目录至Nginx与PHP容器,实现PHP项目运行环境配置。需注意PHP容器中监听地址修改为0.0.0.0:9000,并调整Nginx配置中fastcgi_pass指向正确的IP与端口。同时确保Nginx容器中/var/www/html权限正确,以避免访问问题。
配置nginx容器和php容器协同工作成功,使用ip加端口的方式进行通信
|
9月前
|
Ubuntu 应用服务中间件 Linux
在Ubuntu上配置Nginx实现开机自启功能
至此,Nginx应该已经被正确地设置为开机自启。在Ubuntu中利用 `systemd`对服务进行管理是一种高效的方式,为系统管理员提供了强大的服务管理能力,包括但不限于启动、停止、重启服务,以及配置服务的开机自启动。通过这些简洁的命令,即使是对Linux不太熟悉的用户也能轻松地进行配置。
440 0
|
10月前
|
SQL Apache Windows
Windows服务器80端口被占用的全面解决方案
在服务管理器中启动apache2服务,即可正常使用80端口。若系统中还安装了其他微软产品如sql等,也可尝试停止其服务进行测试,但请注意,SQL通常不会使用80端口,因此一般不会受到影响。以上就是关于80端口被system占用的详细解决方法,希望对你有所帮助。
|
网络协议 安全 应用服务中间件
云服务器怎么开启被关闭的端口?手把手教你开启端口
在使用云服务器时,若发现某些服务无法访问,可能是端口被关闭。本文介绍了端口关闭的原因、检查方法及开启步骤。原因包括初始设置限制、防火墙规则和外部网络策略;可通过netstat或ss命令检查端口状态,用ufw、iptables或firewalld调整防火墙规则。最后提供了解决常见问题的建议,确保端口正常开放并可供外网访问。
2363 9
|
8月前
|
网络协议
端口最多只有65535个,为什么服务器能承受百万并发
服务器通过四元组(源IP、源端口、目标IP、目标端口)识别不同TCP连接,每条连接对应独立socket。数据包携带四元组信息,服务端据此查找对应socket进行通信。只要四元组任一元素不同,即视为新连接,可创建独立socket。资源充足时,单进程可支持百万级并发连接,socket与端口非一一对应。
569 10
端口最多只有65535个,为什么服务器能承受百万并发
|
10月前
|
弹性计算 网络协议 安全
【转】如何配置服务器的端口映射?
本文详解端口映射原理及配置方法,涵盖家庭、企业与云环境,包含静态、动态与双向映射类型,并提供常见问题解决方案。
2283 6
|
弹性计算 应用服务中间件 Linux
阿里云服务器开放端口完整图文教程
笔者近期开发完成的服务端程序部署在阿里云的ECS云服务器上面,一些应用程序配置文件需要设置监听的端口(如Tomcat的8080、443端口等),虽然通过CentOs 7系统的的「防火墙」开放了对应的端口号,任然无法访问端口号对应的应用程序,后面了解到原来还需要设置云服务器的「安全组规则」,开放相应的端口权限,服务端的接口才能真正开放。
4702 1
阿里云服务器开放端口完整图文教程