Http/https代理和抓包分析

前言

最近工作需要部署http/https的代理,所以用squid部署了一下,重新回顾了一下http和https的代理知识。

HTTP代理

根据《HTTP 权威指南》如图:

这种情况下,对访问服务器而言,它会把代理当做客户端,完全察觉不到真正客户端的存在,完全隐藏了客户端的IP,当然代理也可以修改Http头部,X-Forwarded-IP头部告诉服务器真正的客户端IP。

代理可以用两种方式,一种是代码实现,一种用现成的代理软件如squid,本文是用squid,配置文件如下(这里不详细介绍squid的使用,有需要单独另开来讲squid)。然后启动squid起来

代码实现

javascript 复制代码
var http = require('http');
var net = require('net');
var url = require('url');

function request(cReq, cRes) {
    var u = url.parse(cReq.url);

    var options = {
        hostname : u.hostname, 
        port     : u.port || 80,
        path     : u.path,       
        method     : cReq.method,
        headers     : cReq.headers
    };

    var pReq = http.request(options, function(pRes) {
        cRes.writeHead(pRes.statusCode, pRes.headers);
        pRes.pipe(cRes);
    }).on('error', function(e) {
        cRes.end();
    });

    cReq.pipe(pReq);
}

http.createServer().on('request', request).listen(3128, '0.0.0.0');

squid配置

# Squid normally listens to port 3128
http_port 3128

然后客户端使用curl命令通过代理访问百度(注意这里访问百度用的http协议而非https)

curl -x http://43.129.198.37:3128 http://www.baidu.com

可以看到这时候访问成功了, 分析报文(报文分别是在客户端和服务端这边抓取的)由于是http,所以报文都是明文发送的,分别可以看到客户端和代理TCP的三次握手,代理和服务器TCP三次握手,以及http报文。

但是上述的过程能不能代理https的流量呢,答案是代码形式的不行,squid的可以,这就涉及到第二个内容http的隧道代理

HTTP隧道代理-代理https流量

也就是上述squid配置不变,把命令改成:

curl -x http://43.129.198.37:3128 https://www.baidu.com 把百度协议改成https它依然能够成功,因为squid是有http的隧道代理的。

还是抄《HTTP 权威指南》图,首先客户端会发送connect请求将需要访问域名发送给proxy,proxy会回应http connect established就绪报文,并且proxy和server建立了TCP通道,后续proxy会进行盲转发client和server之间报文

客户端到proxy之间报文:

proxy和server之间的报文:

直接上报文讲解,可以 看到在客户端和proxy之间发送connect请求,然后proxy回了connection established,后续就是TLS的通信过程。proxy和server会创建一个TCP通道,然后后续client发送给server的TLS通信过程,proxy只是进行盲转发,如何验证这点?请看如图:

把TLS第一个Client hello报文拿出来分别对比,可以看到客户端到proxy,proxy到server的client hello的随机值Random都是一样的,证明proxy只是进行盲转发。

https代理

很多时候在讨论代理,因为发现很多人都混淆了https代理和代理https流量。如上面http隧道代理,它能支持客户端访问服务器,也就是说它能代理https流量,但它是http代理,因为站在客户端角度,它配置的就是http代理,如上述curl命令就是客户端:

-x http://43.129.198.37:3128,填的协议就是http

再比如switchyOmega配置也是配置http,因为本质上客户端和proxy之间是http connect明文交互的。

所以https代理本质上指的就是,客户端和proxy之间交互是加密的,也就是上述的http connect是加密的,客户端配置的代理协议是https。

squid配置文件修改:

javascript 复制代码
https_port 443 cert=./myCA.pem

那么curl命令就变为:

javascript 复制代码
SSLKEYLOGFILE=./ssl-key.log curl -x https://43.129.198.37:443 https://www.baidu.com --proxy-cacert ./test2.pem

其中myCA.pem里面包含公私钥,curl命令的test.pem只包含公钥,这里加上了一个环境变量SSLKEYLOGFILE是用于wireshark进行解密的。

还是一样抓取client-proxy的流量,以及proxy到server的流量

第一份报文是解密后的数据,可以看到客户端和proxy之间先进行了TLSv1.3协商,协商完成后,加密了http connect数据,以及返回connection established

第二份报文是proxy和服务器的协商是TLSv1.2进行协商的,但是其实这时候proxy依然只是和server进行tcp连接进行盲转发,还是客户端和服务器的tls协商,也就是说客户端和proxy先进行TLSv1.3协商,然后客户端再和服务器再进行TLS1.2协商,这中间TLSv1.3 加密了客户端与服务器的TLSv1.2协商过程。

要验证也很简单跟上述一样找client hello报文的随机数:

Squid-SSL-Bump模式

这种模式下,proxy是一种中间人的角色Man-in-middle,能够对客户端到服务器的加密信息进行解密。

squid的配置

javascript 复制代码
http_port 3128 ssl-bump \
  cert=/etc/squid/ssl_cert/myCA.pem \
  generate-host-certificates=on dynamic_cert_mem_cache_size=4MB

# For squid 3.5.x
sslcrtd_program /usr/local/squid/libexec/ssl_crtd -s /var/lib/ssl_db -M 4MB

# For squid 4.x
# sslcrtd_program /usr/local/squid/libexec/security_file_certgen -s /var/lib/ssl_db -M 4MB

acl step1 at_step SslBump1

ssl_bump peek step1
ssl_bump bump all

未完待续

参考文献:

Intercept HTTPS CONNECT messages with SSL-Bump | Squid Web Cache wiki (squid-cache.org)

相关推荐
千天夜1 小时前
使用UDP协议传输视频流!(分片、缓存)
python·网络协议·udp·视频流
长弓三石2 小时前
鸿蒙网络编程系列44-仓颉版HttpRequest上传文件示例
前端·网络·华为·harmonyos·鸿蒙
xianwu5432 小时前
反向代理模块
linux·开发语言·网络·git
follycat2 小时前
[极客大挑战 2019]HTTP 1
网络·网络协议·http·网络安全
earthzhang20213 小时前
《深入浅出HTTPS》读书笔记(5):随机数
网络协议·http·https
xiaoxiongip6663 小时前
HTTP 和 HTTPS
网络·爬虫·网络协议·tcp/ip·http·https·ip
JaneJiazhao3 小时前
HTTPSOK:SSL/TLS证书自动续期工具
服务器·网络协议·ssl
JaneJiazhao3 小时前
HTTPSOK:智能SSL证书管理的新选择
网络·网络协议·ssl
CXDNW3 小时前
【网络面试篇】HTTP(2)(笔记)——http、https、http1.1、http2.0
网络·笔记·http·面试·https·http2.0
无所谓จุ๊บ3 小时前
树莓派开发相关知识十 -小试服务器
服务器·网络·树莓派