首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

多层代理上jetty forwarded功能

2012-09-04 
多层代理下jetty forwarded功能最近在实施apache2.2+mod_proxy+jetty7.2.0时遇到的一个诡异的问题?现象:直

多层代理下jetty forwarded功能

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

?

现象:

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

A的域名benni82.a.com===============B的域名www.b.comapache 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.comX-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的内容。

    会拿X-Forwarded-For最左边的ip地址(10.20.156.2)作为客户端原始ip,设置request.remoteAddr会拿X-Forwarded-Host的最左边的值(www.b.com),设置request.serverName,如果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 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);        }    }
?

?

热点排行