`
benni82
  • 浏览: 123138 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

多层代理下jetty forwarded功能

阅读更多

最近在实施apache2.2+mod_proxy+jetty7.2.0时遇到的一个诡异的问题

 

现象:

直接访问应用(A)能正常显示页面;但是通过应用(B)再代理访问A,则页面显示出错。

A的域名benni82.a.com
===============
B的域名www.b.com

apache rewrite配置如下:
RewriteRule ^/proxy/(.*)$ $1 [P,L]

用户通过访问  http://www.b.com/proxy/http://benni82.a.com 来访问应用A,就显示错误页面。

而用户直接访问  http://benni.a.com 正常显示页面。


A应用的逻辑上依赖request.getServerName()

 

分析:

当通过mod_proxy代理访问时,http请求头会带上一些额外的信息

X-Forwarded-For:  10.20.156.2, 10.20.156.3  
X-Forwarded-Host: www.b.com, benni82.a.com
X-Forwarded-Server: www.b.com, www.a.com

X-Forwarded-For的内容从左到右依次是,用户的ip,第一个代理ip

X-Forwarded-Host依次是,第一次代理时请求头的Host值,第二次代理时请求头的Host值

X-Forwarded-Server依次是:第一个代理的ServerName,第二个代理的ServerName(取自apache ServerName指令的设值)

    而为了解决获取客户端原始ip地址,我们开启了jetty的forwarded功能。
开启该功能后,jetty在解析请求头时会优先使用X-Forwarded的内容。

  1. 会拿X-Forwarded-For最左边的ip地址(10.20.156.2)作为客户端原始ip,设置request.remoteAddr
  2. 会拿X-Forwarded-Host的最左边的值(www.b.com),设置request.serverName,
  3. 如果X-Forwarded-Host没有内容,会拿X-Forwarded-Server的最左边的值(crm.cn.alibaba-inc.com),设置request.serverName。

所以最后应用获取的ServerName时第一次代理时的Host,即www.b.com,页面返回错误。

 

        而直接访问http://benni82.a.com时,
相应的值如下:
X-Forwarded-Host:  benni82.a.com
X-Forwarded-Server:  www.a.com
最后应用获取的serverName是benni82.a.com,和请求头的host一致,页面能正常返回。

 

 

解决方案:

connector配置中添加两行

<Call name="addConnector">
      <Arg>
          <New class="org.eclipse.jetty.server.nio.SelectChannelConnector">
                        <Set name="port"><Property name="jetty.port" default="7001"/></Set>
                        <Set name="forwarded">true</Set>
                        <Set name="forwardedServerHeader">ignore</Set>
                        <Set name="forwardedHostHeader">ignore</Set>
                        <Set name="maxIdleTime">600000</Set>
          </New>
      </Arg>
</Call>

forwardedServerHeader默认是: X-Forwarded-Server
forwardedHostHeader默认值: X-Forwarded-Host
目的阻止jetty用 X-Forwarded-Host或 X-Forwarded-Server的内容复写ServerName .

 

 

    protected void checkForwardedHeaders(EndPoint endpoint, Request request) throws IOException
    {
        HttpFields httpFields = request.getConnection().getRequestFields();

        // Retrieving headers from the request
        String forwardedHost = getLeftMostValue(httpFields.getStringField(getForwardedHostHeader()));
        String forwardedServer = getLeftMostValue(httpFields.getStringField(getForwardedServerHeader()));
        String forwardedFor = getLeftMostValue(httpFields.getStringField(getForwardedForHeader()));
        String forwardedProto = getLeftMostValue(httpFields.getStringField(getForwardedProtoHeader()));

        if (_hostHeader != null)
        {
            // Update host header
            httpFields.put(HttpHeaders.HOST_BUFFER,_hostHeader);
            request.setServerName(null);
            request.setServerPort(-1);
            request.getServerName();
        }
        else if (forwardedHost != null)
        {
            // Update host header
            httpFields.put(HttpHeaders.HOST_BUFFER,forwardedHost);
            request.setServerName(null);
            request.setServerPort(-1);
            request.getServerName();
        }
        else if (forwardedServer != null)
        {
            // Use provided server name
            request.setServerName(forwardedServer);
        }

        if (forwardedFor != null)
        {
            request.setRemoteAddr(forwardedFor);
            InetAddress inetAddress = null;

            if (_useDNS)
            {
                try
                {
                    inetAddress = InetAddress.getByName(forwardedFor);
                }
                catch (UnknownHostException e)
                {
                    Log.ignore(e);
                }
            }

            request.setRemoteHost(inetAddress == null?forwardedFor:inetAddress.getHostName());
        }
        
        if (forwardedProto != null)
        {
            request.setScheme(forwardedProto);
        }
    }
 

 

分享到:
评论

相关推荐

    jetty反相代理配置

    在Jetty 9.4.6这个版本中,反向代理功能可以通过Jetty的ProxyServlet来实现。 首先,让我们理解反向代理的基本概念。反向代理是一种网络代理服务,它接收来自客户端的请求,然后将这些请求转发给内部网络上的一个或...

    jetty实现websocket功能

    Jetty是一个轻量级、高性能的Java Web服务器和Servlet容器,它也支持WebSocket协议,并且集成了一系列WebSocket的API,使得开发者可以轻松地在Java应用中实现WebSocket功能。 在Jetty中实现WebSocket功能,首先你...

    jetty hot deploy.zip

    Jetty Hot Deploy是一个针对Java应用程序的特性,特别适用于Web应用服务器Jetty,它允许开发者在不中断服务的情况下更新或部署新的应用。这个压缩包“jetty hot deploy.zip”可能包含了实现这一功能的相关配置、库...

    jetty各个版本下载

    此外,Jetty还支持热部署,这意味着你可以在不重启服务器的情况下更新Web应用。 6. **Jetty与其他服务器的比较** 相比Apache Tomcat或其他服务器,Jetty在轻量级特性、内存使用效率和响应速度上有优势。特别是对于...

    jetty-all.jar

    这个Uber JAR包含了该版本下所有必要的Jetty组件,使得用户只需引用这一个JAR文件就能使用Jetty的全部功能,简化了构建过程。 接下来,jetty-server-9.4.14.v20181114.jar是Jetty的核心组件之一,提供了基础的HTTP...

    jetty相关的全部jar包

    jetty-security-9.4.8.v20171121.jar,jetty-io-9.4.8.v20171121.jar,jetty-continuation-9.4.8.v20171121.jar,jetty-client-9.4.8.v20171121.jar,jetty-jmx-9.4.8.v20171121.jar,jetty-plus-9.4.8.v20171121....

    maven项目下用 jetty 启动热部署

    当我们使用Maven构建Java Web项目时,结合Jetty服务器,可以实现项目的热部署功能,即在开发环境中修改代码后无需重新启动服务器,改动就能实时生效,极大地提高了开发效率。 在Maven项目中启用Jetty热部署,主要...

    jetty 6 指南书

    - **下载与安装**:提供Jetty的下载地址和简单安装步骤,包括Windows和Linux下的操作。 - **启动与停止**:通过java命令快速启动和停止Jetty服务,以及使用start.jar的深入解析。 - **Windows和Linux的启动关闭...

    jetty所需jar包

    11. **jetty-proxy.jar**:如果你需要使用Jetty作为反向代理或负载均衡器,这个jar包包含了相关实现。 12. **jetty-client.jar**:如果你的应用需要作为HTTP客户端发送请求,这个jar包提供了客户端API。 13. **...

    jetty 事例

    在`webapps`目录下创建`WEB-INF/web.xml`,在其中定义Servlet。 - 部署Web应用:只需将WAR文件放入`webapps`目录,Jetty会自动解压并部署应用。 4. **Jetty实用特性** - 嵌入式使用:Jetty可以轻松地嵌入到你的...

    jetty 8及依赖包

    在Jetty 8中,Servlet容器是其核心功能之一,它负责管理和调度Servlet实例。Servlet是一种Java API,用于生成动态Web内容。在Jetty中,Servlet容器负责解析HTTP请求,将请求路由到对应的Servlet,并将Servlet的响应...

    jetty 适合jdk1.8用的服务器

    为了部署Web应用程序,可以将WAR文件放置在`webapps`目录下,Jetty会自动检测并部署它们。 总的来说,Jetty 9.4.22.v20191022是适用于JDK 1.8的稳定版本,适合那些寻求轻量级、高性能服务器解决方案的开发者。其...

    jetty 9.4.9

    - **模块化设计**:Jetty的模块化架构允许用户只加载需要的功能,减少不必要的依赖,进一步提高性能。 - **直接支持WebSocket**:Jetty 9.4.9 支持WebSocket协议,使得实时双向通信成为可能,这对于开发实时应用...

    jetty-6.1.26.zip

    Jetty 6.1.26是该服务器的一个旧版本,尽管如此,它仍包含了许多关键特性和功能。以下是一些关于Jetty 6.1.26及其核心知识点的详细介绍: 1. **Servlet容器**:Jetty作为Servlet容器,能够解析HTTP请求并将其转发给...

    eclipse-jetty-plugin-master_源码.rar

    7. **测试框架**:源码通常包含了单元测试和集成测试,这对于理解插件或Jetty本身的功能和行为至关重要,同时也能为自己的项目提供测试思路。 总的来说,这份源码不仅对于Eclipse插件开发者,也对于任何对Jetty或者...

    jetty9.4.11+jetty在idea上的配置教程

    创建一个名为`start.ini`的文件,放入Jetty的解压目录下的`etc`子目录中。在此文件中,指定Jetty的端口、Web应用的上下文路径等配置,例如: ``` --module=webapp jetty.port=8080 webapp.contextPath=/myapp ...

    jetty6 指南书

    1. **Jetty的功能介绍**: Jetty提供了HTTP服务和Servlet容器的基本功能,支持WebSocket、Continuations(用于异步处理)和JMX管理。此外,它还能够嵌入到其他Java应用中,成为应用程序的一部分,使得快速开发和...

    eclipse_jetty9离线插件

    通过离线插件,开发者可以在没有互联网连接的情况下方便地安装和管理Jetty服务器,避免了在线查找和下载的繁琐步骤。 首先,让我们了解一下Eclipse IDE。Eclipse是一款开源的Java集成开发环境,支持多种语言和框架...

    Jetty Servlet+ HttpClient 制作的 Java HttpProxy

    总结,通过结合Jetty Servlet容器和Apache HttpClient,我们可以快速搭建一个功能完备的Java HTTP代理服务器。这种方式不仅灵活,还可以根据需要扩展实现更复杂的功能,如支持HTTPS、缓存、日志记录等。了解并掌握...

    Maven下使用Jetty进行Debug

    本文将详细介绍如何在Maven环境下利用Jetty插件进行调试。 **1. 环境和条件** 首先确保你已经安装了以下软件: - Maven:这里以Maven 3.0.3为例。 - Eclipse:作为IDE,用于编写和调试代码。 此外,对Maven的基本...

Global site tag (gtag.js) - Google Analytics