我正在编写一个HTTP代理,但是在了解如何通过TLS进行CONNECT请求时遇到了一些问题。为了更好地了解情况,我正在使用Apache进行实验,以观察它如何与客户端交互。这是来自我的默认虚拟主机。
NameVirtualHost *:443
<VirtualHost>
ServerName example.com
DocumentRoot htdocs/example.com
ProxyRequests On
AllowConnect 22
SSLEngine on
SSLCertificateFile /root/ssl/example.com-startssl.pem
SSLCertificateKeyFile /root/ssl/example.com-startssl.key
SSLCertificateChainFile /root/ssl/sub.class1.server.ca.pem
SSLStrictSNIVHostCheck off
</VirtualHost>
Apache和我的客户端之间的对话如下所示。
a. 客户端连接到 example.com:443
,并在TLS握手中发送example.com
。
b. 客户端发送HTTP请求。
CONNECT 192.168.1.1:22 HTTP/1.1
Host: example.com
Proxy-Connection: Keep-Alive
c. Apache报告 HTTP/1.1 400 Bad Request
。Apache错误日志显示:
Hostname example.com provided via SNI and hostname 192.168.1.1
provided via HTTP are different.
看起来Apache除了检查是否存在Host头部外,不会对其进行进一步的检查。即使客户端发送Host: foo
,我也会得到相同的失败行为。如果我在没有TLS的情况下向example.com:80发出HTTP请求,那么Apache将连接我到192.168.1.1:22。
我不完全理解这种行为。 CONNECT请求有什么问题吗?我似乎找不到相关的RFC部分来解释所有这些。
SSLStrictSNIVHostCheck off
。 - eckes