Apache 拒絕在非預設虛擬主機上通過 SSL 進行 HTTP CONNECT
我有一個執行多個虛擬主機的 apache 2.4.18 伺服器。
/etc/apache2/sites-enabled/000-default.conf:
<VirtualHost *:80> DocumentRoot /var/www/html Redirect 400 / </VirtualHost>
/etc/apache2/sites-enabled/000-default-ssl.conf:
<VirtualHost _default_:443> DocumentRoot /var/www/html SSLEngine on SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key </VirtualHost>
/etc/apache2/sites-enabled/001-custom.conf:
<VirtualHost _default_:443> ServerName www.example.org Include /etc/apache2/letsencrypt/main.conf SSLCertificateFile /etc/letsencrypt/live/example.org/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/example.org/privkey.pem Include /etc/apache2/proxytunnel/main.conf </VirtualHost> <VirtualHost *:80> ServerName www.example.org Redirect permanent / https://www.example.org/ </VirtualHost>
/etc/apache2/proxytunnel/main.conf:
ProxyRequests On AllowConnect 2222 <Proxy *> Order deny,allow Deny from all </Proxy> <Proxy 127.0.0.1> Order deny,allow Allow from all </Proxy>
我還在同一台機器的 2222 埠上執行了一個正在執行的 SSH 伺服器。
如果我使用遠端機器上的 proxytunnel 通過 SSL 訪問 SSH 伺服器,使用 apache 作為代理伺服器:
proxytunnel -v -E -p www.example.org:443 -d 127.0.0.1:2222
我收到以下錯誤:
SSL client to proxy enabled Local proxy www.example.org resolves to xxx.xxx.xxx.xxx Connected to www.example.org:443 (local proxy) Tunneling to 127.0.0.1:2222 (destination) Communication with local proxy: -> CONNECT 127.0.0.1:2222 HTTP/1.1 -> Host: 127.0.0.1:2222 -> Proxy-Connection: Keep-Alive <- HTTP/1.1 405 Method Not Allowed HTTP return code: 405 Method Not Allowed <- Date: Thu, 14 Apr 2016 00:55:57 GMT <- Server: Apache/2.4.18 (Debian) <- Allow: GET,HEAD,POST,OPTIONS <- Content-Length: 309 <- Content-Type: text/html; charset=iso-8859-1
但是如果我將文件包含
/etc/apache2/proxytunnel/main.conf
在我的/etc/apache2/sites-enabled/000-default-ssl.conf
虛擬主機中,它就可以工作……SSL client to proxy enabled Local proxy www.example.org resolves to xxx.xxx.xxx.xxx Connected to www.example.org:443 (local proxy) Tunneling to 127.0.0.1:2222 (destination) Communication with local proxy: -> CONNECT 127.0.0.1:2222 HTTP/1.1 -> Host: 127.0.0.1:2222 -> Proxy-Connection: Keep-Alive <- HTTP/1.0 200 Connection Established <- Proxy-agent: Apache/2.4.18 (Debian) Tunnel established. SSH-2.0-OpenSSH_7.2p2 Debian-2
所以我的結論是,對於通過 SSL 上的 apache 伺服器工作的 CONNECT 請求,
AllowCONNECT
除了發出請求的實際 vhost 之外,該指令必須放置在 apache 代理埠的預設 vhost 中。請注意,當使用 CONNECT over HTTP(而不是 HTTPS)並且在 proxytunnel 中禁用加密時,不會重現該行為。此外,問題並非來自 proxytunnel,因為請求已正確轉發到 apache 並出現在伺服器日誌中:是 apache 主動拒絕它,因為它認為該伺服器上的 HTTP 方法 (CONNECT) 無效(儘管允許在相關的虛擬主機中)。
此外,問題並非來自 proxytunnel,因為請求已正確轉發到 apache 並且存在於伺服器日誌中
這是錯誤的,proxytunnel 在我使用的版本中不支持 SNI(截至本文發布之日,他們的儲存庫中的最新送出,所以如果我相信他們的發布標籤,那麼會比 1.9.1 稍早一些)。
結果是 apache 選擇的虛擬主機是預設虛擬主機,無論我嘗試連接到哪個主機。
我想通過提供關於我自己的經驗的回饋來補充這個問題。我還不能發表評論。
我在 Windows 7 上使用 Proxytunnel 1.9.9(大約 2018 年 4 月),我使用 Cygwin 32 位從原始碼編譯。
從我的測試中,我發現 Proxytunnel 沒有將 -p 參數中的主機名與 Apache2 虛擬主機中的 ServerName 正確匹配。除非包含 AllowCONNECT 方法的虛擬主機是預設虛擬主機,否則使用 Proxytunnel 隧道通過一個 http 或 https 本地代理會失敗。
列出在 Apache 中啟用的虛擬主機,看看哪個是預設的:
apachectl -S
在我的設置中,每個虛擬主機都在站點可用目錄中自己的文件中。執行此命令:
ls -1
在站點可用目錄中列出的第一個文件是 apache2 將使其成為預設虛擬主機的虛擬主機。通過這種方式,我將我的 http(或 https)轉發代理交換為預設和第二行虛擬主機……通過更改其名稱,使其不會首先出現在目錄列表中。
我發現這個命令用於 http 本地代理:
proxytunnel -v -p http-forward-proxy.com:80 -d 192.168.0.10:22
或者這個命令用於 https 本地代理:
proxytunnel -v -E -C root.pem https-forward-proxy.com:443 -d 192.168.0.10:22
如果 AllowCONNECT 方法在預設虛擬主機中,則給我 OpenSSH 橫幅,但如果不是,則給我一個 HTTP 405 錯誤……即使包含非預設埠 80 虛擬主機:
ServerName http-forward-proxy.com
或者在代理到 https 轉發代理的情況下,當非預設埠 443 虛擬主機包含:
ServerName https-forward-proxy.com
我查看了 Apache2 日誌並確認處理總是轉到預設虛擬主機。
我還在 Proxytunnel GitHub 頁面 https://github.com/proxytunnel/proxytunnel/issues/31上發布了關於 HTTP 案例的“問題”
然而
我將 Proxytunnel 客戶端與 sslh 和 stunnel 伺服器端一起使用。在這種情況下,我發現 Proxytunnel 命令中的主機名確實與 sslh 中的 sni_hostnames{} 功能匹配,因此在這種情況下,主機名似乎至少在加密和使用 SNI 時正確傳輸。