通过SSL连接将转发请求连接到转发HTTP代理?

sig*_*ice 14 apache ssl proxy http

我正在编写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>
Run Code Online (Sandbox Code Playgroud)

Apache和我的客户之间的对话是这样的.

一个.客户端连接example.com:443并发送example.comTLS握手.

湾 客户端发送HTTP请求.

CONNECT 192.168.1.1:22 HTTP/1.1
Host: example.com
Proxy-Connection: Keep-Alive
Run Code Online (Sandbox Code Playgroud)

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. 
Run Code Online (Sandbox Code Playgroud)

似乎Apache没有查看Host头,除了看到它存在,因为HTTP/1.1需要它.如果客户端发送,我会得到相同的失败行为Host: foo.如果我在不使用TLS的情况下向example.com:80发出HTTP请求,那么Apache会将我连接到192.168.1.1:22.

我不完全理解这种行为.CONNECT请求有问题吗?我似乎无法找到解释所有这些的RFC的相关部分.

Bru*_*uno 37

目前尚不清楚您是否尝试将Apache Httpd用作代理服务器,这可以解释您获得的400状态代码. CONNECT客户端使用,并发送到代理服务器(可能是Apache Httpd,但通常不是),而不是发送到目标Web服务器.

CONNECT在客户端和终端服务器之间建立TLS连接之前,在客户端和代理服务器之间使用.客户端(C)连接到代理(P)proxy.example.com并发送此请求(包括空行):

C->P: CONNECT www.example.com:443 HTTP/1.1
C->P: Host: www.example.com:443
C->P:
Run Code Online (Sandbox Code Playgroud)

代理打开到www.example.com:443(PS)的TCP连接,并使用200状态代码响应客户端,接受请求:

P->C: 200 OK
P->C: 
Run Code Online (Sandbox Code Playgroud)

此后,客户端和代理(CP)之间的连接保持打开状态.代理服务器中继与CP之间的CP连接上的所有内容.客户端通过在该通道上启动TLS握手,将其活动(PS)连接升级为SSL/TLS连接.由于现在所有内容都被中继到服务器,就好像TLS交换是直接完成的www.example.com:443.

代理在握手中没有任何作用(因此与SNI有关).TLS握手有效地直接在客户端和终端服务器之间发生.

如果您正在编写代理服务器,则在CONNECT请求中读取允许客户端连接到HTTPS服务器所需的所有操作,建立从代理到终端服务器的连接(在CONNECT请求中给出),发送客户端一个200 OK答复,您从客户端读取到服务器,反之亦然再往前一切.

RFC 2616将其CONNECT视为建立简单隧道(​​即它)的一种方式.RFC 2817中有更多关于它的内容,尽管很少使用RFC 2817的其余部分(在非代理HTTP连接中升级到TLS).

看起来你要做的是通过TLS在客户端(C)和代理(P)之间建立连接.这没关系,但客户端不会CONNECT用来连接外部Web服务器(除非它也是连接到HTTPS服务器).