簡體   English   中英

帶和不帶 SSL 的 Apache 反向代理之間行為不同的原因

[英]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&params= 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&params= 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM