Apache-2.4

Apache ProxyPass + RewriteRule?

  • January 14, 2021

我已經設置了一個 apache 配置來嘗試重定向/login和 ProxyPass 所有其他請求:

RewriteEngine on
RewriteCond "%{REQUEST_URI}" "^/login$"
RewriteRule "^/login$" "https://sub.example.org/$1" [L,R]

SSLProxyEngine on
ProxyRequests off
ProxyPassMatch   ^/login ! # Prevent proxy on /login
ProxyPassReverse ^/login ! # Prevent proxy on /login
ProxyPassMatch   ^/      https://sub.example.org/
ProxyPassReverse ^/      https://sub.example.org/
ProxyPreserveHost off
RequestHeader set Host sub.example.org
Header set Host alt.example.org

我檢查的大多數結果都符合我的預期:

  • alt.example.org/login 重定向到 sub.example.org/login
  • alt.example.org/users 顯示 sub.example.org/users 的內容(沒有重定向)

…但是https://alt.example.org/(空路徑)會產生一個Location值為 的標頭https://alt.example.org^/login哇!是什麼導致^了域中的重定向,為什麼它引用alt而不是sub

在 apache 之上執行的 Rails 應用程序的日誌顯示 Rails 應用程序本身實際上正在重定向到https://sub.example.org/login,這更有意義,因為 ProxyPass 意味著 Rails 應該只看到 sub.example。 org 而不是 alt.example.org。那麼為什麼 apache 會給出 https://alt.example.org^/login 呢?

…但是https://alt.example.org/(空路徑)會產生一個Location值為 的標頭https://alt.example.org^/login。哇!是什麼導致^了域中的重定向,為什麼它引用 alt 而不是 sub?

ProxyPassReverse指令不採用正則表達式作為第一個參數,這似乎是發生衝突的地方。這也不能!作為第二個論點。如果指令與響應不匹配,子alt域將出現在標頭中。Location``ProxyPassReverse

您似乎不需要與ProxyPassReverse相關的第一個指令/login,因為該 URL 沒有被代理。

此外,這些ProxyPassMatch指令似乎將所有內容都代理到https://sub.example.org/- 您不想代理到目標域中的相應 URL 路徑嗎?雖然奇怪的是,這似乎是你觀察到的結果中發生的事情?如果您確實想代理到相同的 URL 路徑,那麼您可以使用更簡單的ProxyPass指令,並使用簡單的前綴匹配而不是正則表達式。

alt.example.org/login重定向到sub.example.org/login

雖然這不是由您在頂部發布的“重定向”執行的,它會重定向到文件根目錄,因為$1反向引用是空的,因為模式中沒有擷取子RewriteRule 模式。正如您稍後所說,“Rails 應用程序本身實際上正在重定向到https://sub.example.org/login”。

因此,為了重定向到sub.example.org/login(這似乎是意圖),您需要更改指令以改為閱讀以下內容:

RewriteRule ^/(login)$ https://sub.example.org/$1" [R,L]

RewriteCond此處不需要前面的指令,因為它只是重複您已經在RewriteRule 模式中執行的相同檢查。

RequestHeader set Host sub.example.org

該行是多餘的,因為這是前面ProxyPreserveHost off指令的目的。

Header set Host alt.example.org

這一行似乎也是多餘的,因為Host它是請求標頭,而不是響應標頭。

ProxyPassMatch   ^/login ! # Prevent proxy on /login

此外,Apache 不支持行尾註釋。只是因為處理 Apache 指令的方式有一個“怪癖”,才能防止這個特定的行尾註釋破壞你的伺服器!

因此,考慮到上述幾點,請嘗試以下操作:

RewriteEngine on

# Externally Redirect "/login" to other domain
RewriteRule ^/(login)$ https://sub.example.org/$1" [R,L]

SSLProxyEngine on

ProxyRequests off
ProxyPreserveHost off

# Prevent proxy on /login
ProxyPass /login !

# Proxy all other URLs
ProxyPass / https://sub.example.org/
ProxyPassReverse / https://sub.example.org/

引用自:https://serverfault.com/questions/1049834