[英]Reasons for differing behavior between Apache reverse proxy with and without SSL
我一直在研究一個本地反向代理,它在兩個本地 Apache 安裝之間路由流量(每個都運行不同版本的 mod_wsgi,這是分叉的原因)。 我希望這個反向代理能夠工作,無論請求是 HTTP 還是 HTTPS。
但是,當使用 SSL 時,ProxyPassReverse 不會(正確地)修改位置響應 header。
下面分別是 HTTP 和 HTTPS 流量的 VirtualHost 定義:
<VirtualHost *:80>
# Proxy traffic for Version 6 with an alias of: 6x/
ProxyPass /6x/ http://localhost:10090/
ProxyPassReverse /6x/ http://localhost:10090/
# Proxy traffic for previous versions with aliases of: 5x/, 4x/, and /
ProxyPass /5x/ http://localhost:10080/
ProxyPassReverse /5x/ http://localhost:10080/
ProxyPass /4x/ http://localhost:10080/
ProxyPassReverse /4x/ http://localhost:10080/
ProxyPass / http://localhost:10080/
ProxyPassReverse / http://localhost:10080/
</VirtualHost>
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName snakeoil.us.com
ProxyPreserveHost on
ProxyRequests off
SSLEngine on
SSLProxyEngine on
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
SSLCertificateFile /etc/ssl/certs/snakeoil.crt
SSLCertificateKeyFile /etc/ssl/certs/snakeoil.key
SSLCertificateChainFile /etc/ssl/certs/bundle-client.crt
# Proxy traffic for Version 6 with an alias of: 6x/
ProxyPass /6x/ https://localhost:10453/
ProxyPassReverse /6x/ https://localhost:10453/
# Proxy traffic for previous versions with aliases of: 5x/, 4x/, and /
ProxyPass /5x/ https://localhost:10443/
ProxyPassReverse /5x/ https://localhost:10443/
ProxyPass /4x/ https://localhost:10443/
ProxyPassReverse /4x/ https://localhost:10443/
ProxyPass / https://localhost:10443/
ProxyPassReverse / https://localhost:10443/
</VirtualHost>
</IfModule>
When I access the url http://snakeoil.us.com/6x/snk610/index
, the location header comes back as: Location: http://snakeoil.us.com/6x/snk610/index
.
However, when I access the url https://snakeoil.us.com/6x/snk610/index
, the location header comes back as: Location: https://snakeoil.us.com/snk610/index
, which results in a 404,因為被代理的兩個本地 Apache 實例(與 6x 路由關聯的實例)中只有一個識別snk610
別名(在這種情況下,它不是路由到的實例)。
底線是 HTTP VirtualHost 定義代理兩個本地 Apache 實例之間的請求不會失敗。 但是,HTTPS VirtualHost 定義沒有,我不清楚導致這種差異的原因。
設法找到解決方案。 回想起來,它應該更明顯。
在代理到的 Apache 實例上,我將 access_log 格式更改為以下內容:
LogFormat "%h %l %u %t \"%r\" %>s %b --> ResponseLocation: '%{Location}o'" common
這會導致記錄傳出響應位置。
這是來自 Apache HTTP 實例(被代理)的 output:
[snake6x@test1 httpd6x]$ grep "ResponseLocation: 'http" logs/access_log
::1 - - [06/May/2020:15:43:25 -0400] "GET /snk610 HTTP/1.1" 301 233 --> ResponseLocation: 'http://localhost:10090/snk610/index'
::1 - - [06/May/2020:15:43:30 -0400] "GET /snk610/index HTTP/1.1" 302 247 --> ResponseLocation: 'http://localhost:10090/snk610/login?params=&message=&redirect_to=index'
::1 - - [06/May/2020:15:43:32 -0400] "POST /snk610/auth?redirect_to=index¶ms= HTTP/1.1" 302 204 --> ResponseLocation: 'http://localhost:10090/snk610/index'
從上面可以看出,響應位置 header 看起來和預期的一樣,即 ProxyPassReverse 應該可以成功替換它。
相反,這里是 output 來自 Apache HTTPS 實例(被代理到):
[snake6x@test1 httpd]$ grep "ResponseLocation: 'http" logs/ssl_request_log
[06/May/2020:19:53:38 +0000] ::1 "GET /snk610 HTTP/1.1" 240 2645788 --> ResponseLocation: 'https://snakeoil.us.com/snk610/index'
[06/May/2020:19:56:21 +0000] ::1 "GET /snk610/index HTTP/1.1" 254 2682899 --> ResponseLocation: 'https://snakeoil.us.com/snk610/login?params=&message=&redirect_to=index'
[06/May/2020:19:56:23 +0000] ::1 "POST /snk610/auth?redirect_to=index¶ms= HTTP/1.1" 240 752392 --> ResponseLocation: 'https://snakeoil.us.com/snk610/index'
從上面可以看出,在響應位置 header 中,服務器名稱已替換為傳入的主機名稱。 這就是導致 ProxyPassReverse 無法替換傳出主機名(在反向代理服務器上)的原因。
我通過顯式更新被代理到的服務器上的傳出位置 header 解決了這個問題:
# Since this server has a proxy immediately in front of it, we need the outgoing
# location to match the incoming location. However, the ServerName tag will
# cause the incoming location to be changed to include the ServerName, which will
# cause the upstream ProxyPassReverse to fail to update the outgoing location
# properly.
#
# This Header modification replaces the outgoing ServerName with the incoming
# name.
#
# FIXME: There is surely a better way to do this with a variable that contains
# the incoming host
Header edit Location ^https://snakeoil.us.com:443 https://localhost:10453
Header edit Location ^https://snakeoil.us.com https://localhost:10453
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.