Ssl

Apache 拒絕在非預設虛擬主機上通過 SSL 進行 HTTP CONNECT

  • June 7, 2018

我有一個執行多個虛擬主機的 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 時正確傳輸。

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