简体   繁体   English

Apache反向代理将浏览器直接发送到后端

[英]Apache Reverse Proxy Sending Browser to Backend Directly Instead

( UPDATE at the bottom for the main question, below may be superfluous details) (主要问题的底部更新 ,下面可能是多余的细节)

I'm having an interesting problem with Apache not reverse proxying as expected. 我有一个有趣的问题,Apache没有按预期反向代理。

Basically, what's happening is when I click a link on my website that goes to the relative path /app1 , I am expecting it the URL to be external.company.ca/app1 with content coming from internal.company.ca/some_app . 基本上,当我点击我的网站上转到相对路径/app1的链接时,我发现它的URL是external.company.ca/app1 ,其内容来自internal.company.ca/some_app Instead, the browser is going directly to internal.company.ca/some_app . 相反,浏览器将直接转到internal.company.ca/some_app

No 302 or anything, just straight there. 没有302或任何东西,只是直接在那里。 This is odd to me, since internal.company.ca is not mentioned anywhere in the configuration except for the reverse proxy config, so I don't know how the browser is learning of the domain at all. 这对我来说很奇怪,因为除了反向代理配置之外,配置中的任何地方都没有提到internal.company.ca ,所以我不知道浏览器是如何学习域的。

Here is a Fiddler capture from the client (browser) point of view showing the behaviour right after I click the link that goes to /app1 (you'll have to trust me that the green names are external.company.ca and the black names are internal.company.com and the path is /some_app/blahblah ): 这是从客户端(浏览器)角度捕获的Fiddler,显示我点击进入/app1的链接后的行为(你必须相信我的绿色名称是external.company.ca和黑名字是internal.company.com ,路径是/some_app/blahblah ):

在此输入图像描述

Everything happening after this point is loading the page with internal.company.com . 在此之后发生的一切都是使用internal.company.com加载页面。 This won't work at all in production, of course. 当然,这在生产中根本不起作用。

The following is a (truncated) version of our Apache configuration files for consideration: 以下是我们的Apache配置文件的(截断的)版本供考虑:

<VirtualHost *:80>
    # rewrite rules to 443
</VirtualHost>

<VirtualHost *:443>
    ServerName external.company.ca
    ServerAlias external.company.com

    # Logging rules.........

    SSLEngine on
    SSLProxyEngine on
    SSLProxyVerify none

    # Most of this is off for testing purposes, adding in case it matters

    SSLProxyCheckPeerCN off
    SSLProxyCheckPeerName off
    SSLProxyCheckPeerExpire off

    # more SSL stuff.... Now on to the interesting part

    ProxyPreserveHost On
    ProxyPass /app1 https://internal.company.com/some_app
    ProxyPassReverse /app1 https://internal.company.com/some_app
</VirtualHost>

At one point, I thought that possibly the cookies were throwing things off since they were under different domains (.ca in front, .com in back), but I believe if the reverse proxying was working correctly, the browser would be none the wiser. 有一次,我认为可能是因为它们处于不同的域(前面的.ca,后面的.com)中,因此可能会丢弃cookie,但我相信如果反向代理工作正常,浏览器将不再是明智之举。 Anyone see anything wrong with the above? 有人看到上面有什么不对吗?

UPDATE UPDATE

I found the culprit: 我找到了罪魁祸首:

<script type="text/javascript">window.location.assign('https://internal.company.com/app1/login?redirectUrl=' + encodeURIComponent(window.location.pathname + window.location.hash));</script>

The problem is, how do I rewrite this absolute URL using Apache? 问题是,如何使用Apache重写这个绝对URL? I know mod_proxy_html modifies element attributes (such as href in the a element) but can it rewrite arbitrary data in an element itself? 我知道mod_proxy_html会修改元素属性(例如a元素中的href ),但是它可以重写元素本身的任意数据吗?

The internal application was provided by a vendor, and although it may be possible to make modifications to it to remove code like the above, I would prefer to stay away from that path for now to see if there are alternatives. 内部应用程序是由供应商提供的,虽然可以对其进行修改以删除上述代码,但我现在希望远离这条路径,看看是否有替代方案。

I've come up with a somewhat nasty work-around: 我想出了一个有点讨厌的解决方法:

ProxyHTMLEnable On
ProxyHTMLExtended On
ProxyHTMLLinks script src
ProxyHTMLURLMap https://internal.company.com

The problem is the use of absolute URL's throughout the HTML (and javascript) coming from the vendor's app. 问题是在整个来自供应商应用程序的HTML(和javascript)中使用绝对URL。 A search and removal of the domain solves the problem (but is incredibly slow). 搜索和删除域可以解决问题(但速度极慢)。

If anyone has this problem in the future, I do not recommend using this solution. 如果将来有人遇到此问题, 我建议不要使用此解决方案。 I'm guessing you're here because you can't modify the internal application. 我猜你在这里是因为你无法修改内部应用程序。 You should instead be sending in a ticket to whoever maintains the code to make their application more reverse-proxy friendly. 相反,您应该向维护代码的人发送票证,以使其应用程序更具反向代理友好性。

A potentially safer solution would be the use of mod_substitute . 一个可能更安全的解决方案是使用mod_substitute You could also consider ProxyHTMLExtended , but it can be quite brutal in its replacements, occasionally breaking JavaScript here and there. 您也可以考虑使用ProxyHTMLExtended ,但它的替代品可能非常残酷,偶尔会破坏JavaScript。

Edit: Just noticed you're currently using ProxyHTMLExtended. 编辑:刚刚注意到您目前正在使用ProxyHTMLExtended。 My bad. 我的错。 As you've highlighted it is a pretty brutal and dangerous solution to the problem. 正如您所强调的那样,这是一个非常残酷和危险的解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM