转载:原文链接http://zhiwei.li/text/2013/08/https%E6%B5%81%E9%87%8F%E5%88%86%E6%9E%90%E5%B7%A5%E5%85%B7mitmproxy/
原文应该有图片存在,但是由于网络原因无法显示,所以本文中没有这些图片,文章最后几个链接很重要
mitmproxy一个交互式,兼容https的中间人http代理,带控制台界面
mitmdump类似与tcpdump,是http版本的,哈哈,也就是mitmproxy的命令行版本
libmproxy,是mitmproxy依赖库
功能
窃听 http请求和响应,并可以修改他们
保存 完整的http会话,供以后回放或者分析
回放 客户端的http会话
回复 一个预先记录的服务端响应
反向代理模式:转发流量到指定的服务器
透明代理模式
用Python脚本化地改变http流量内容
动态生成 用来窃听的SSL证书
HTTPS窃听是如何实现的
子域名通配符SSL证书(wildcard SSL certificate,价格大约是每年125美元),能在一个IP地址上部署多个HTTPS子域名
UCC(统一通信证书,Unified Communications Certificate)支持一张证书同时匹配多个站点,可以是完全不同的域名。
SNI(服务器名称指示,Server Name Indication)允许一个IP地址上多个域名安装多张证书。
客户端 连接到代理,作出类似下面的请求:
CONNECT example.com:443 HTTP/1.1
传统上的代理,既不能查看也不能操作SSL加密的数据流,所以一个CONNECT请求,简单地要求代理在客户端和服务器之间打开一个管道.代理只是一个服务者—-它根本就看不到双向的转发数据的具体内容.SSL连接的协商发生在管道之中,请求与响应对代理来说,都是透明的(opaque)
MITM 代表Man-In-The-Middle,用这个过程我们可以截获理论上透明的数据流,基本的思想是:
假装成客户端想要的连接的服务器.对服务器又假扮成客户端.我们站在中间位置,解码双方的流量.最有技巧的部分是, CA(Certificate Authority )系统被设计成阻止这种中间人攻击.允许第3方机构对服务器的SSL证书进行签名,验证他们是否合法.如果签名不匹配,或者来自于不信任的第3方,那么安全的客户端就会丢弃这个链接,拒绝下一步的处理.
我们自己成为一个受信任的证书颁发机构是一个难点.mitmproxy包含了完整的CA实现,能够生成窃听证书.
(哈哈,我明白了,https的第1个过程就是去验证证书,但是mitm冒充了证书办法机构,让假的证书 也能通过客户端的校验)
为了让客户端行人这些证书,我们要在设备上手动地 注册 mitmproxy为一个可信的CA颁发结构.
难题1:远程的主机名是什么?
为了达到我们的阴谋,我们需要知道要假冒的证书的域名—客户端将要验证这个证书 是否属于它将要连接的域名,如果不是,就会中止.Mitmproxy用了一个狡猾的机制来探知域名—-upstream certificate sniffing.
一旦我们看到CONNECT请求,我们将暂停会话的客户端部分,初始化一个并发连接到服务器,我们完成同服务器的SSL握手,探测服务器所用的证书.现在,我们就用上游的SSL证书中的Common Name来为客户端生成一个假证书.瞧,我们现在有了正确的主机名,可以呈现给客户端端了,即使它没有被客户端指定过
难题2: SAN(可替换的名称)
有时候,证书的Common Name不是客户端要连接的主机名.这是因为在SSL证书有一个Subject Alternative Name字段,允许指定 任意数目的可选的域名.
如果客户端期望的域名,同可选域名的其中一个匹配,客户也会继续处理.尽管域名同证书的Common Name不匹配.
从上游的的证书中抽解出CN,我们也取出SAN, 并把它添加到生成的假证书里.
难题3: Server Name Indication
vanilla证书的一个最大限制就是,每个证书都要求它自己的IP地址.这意味着,你不能在很多域名共享一个IP的虚拟主机上使用 独立的证书.
SSL和TLS协议的服务器名称指示扩展,就是为了应对IP的缺乏.
客户端在SSL握手的开始,就指定远程服务器的名称,它让服务器可以选择一个正确的证书返回客户端.
SNI打破了我们的上游证书偷窥过程,因为当我们连接服务器时,不使用SNI,那么我们就得到服务的一个默认的证书.
解决方法是,当客户端连接过来,我们允许SSL握手继续,直到SNI从客户端发送过来,我们就暂停会话,用从客户端得到的SNI来初始化一个到服务器的连接,来获取正确的上游证书,然后从中抽解出CN和SANs
因为mitmproxy使用的SSL库的限制,我们不能检测一个连接 有没有发送一个SNI请求,以至于偷看上游证书太迟.
在实践中,我们做一个vanilla的SSL连接到服务器,先偷看到非SNI证书.如果客户端发送了一个SNI 提示,我们就丢掉这个连接.
如果你用tcpdump之类的东西查看流量,就会发现当 SNI请求发出时,有两个到服务器的连接.第1个连接在SSL握手完成后,就立即关闭.
好在,这对实际的使用 没有什么不利的影响.
透明的HTTP代理
使用透明代理时,HTTPS连接直接在网络层转给代理服务器.客户端什么都不需要配置.很多时候,你不能改变客户端的网络访问行为proxy-oblivious
Android应用是一个常见的例子
为了达到这个目的,我们需要介绍两个额外的组件.第1个就是重定向机制,它可以透明地重路由一个到互联网上的服务器的TCP 连接 到一个监听中的代理服务器.
这通常用跟代理服务器在同一个主机上的防火墙来实现,比如Linux下的iptables, 或者OSX中的pf,一旦客户端初始化了连接, 它将作出一个普通的HTTP请求(注意,这种请求就是客户端不知道代理存在)请求头中没有scheme(比如http://或者https://), 也没有主机名(比如example.com)我们如何知道上游的主机是哪个呢?路由机制执行了重定向,但保持了原始的目的地址.
不同的路由机制有不同的查看数据的方法,
mitmdump的使用
mitmdump -w outfile
证书默认保存在~/.mitmproxy目录
mitmproxy-ca.pem 私钥和证书
mitmproxy-ca-cert.pem 证书,这个用来分发到非windows平台
mitmproxy-ca-cert.p12 证书的PKCS12格式,用于windwos
mitmproxy-ca-cert.cer 同pem, Android设备需要这种格式的证书
CA用来动态生成假证书.因为你的浏览器不信任mitmproxy的CA,当你参观一个新的SSL域名时,你应该可以看到SSL证书警告.
当你测试单个站点是,手动选择接受bogus SSL证书,不是什么太麻烦的事情.但是很多环境,你需要配置你的测试系统或者浏览器,信任mitmproxy的CA证书 作为一个签名的root授权.
Firefox安装方法
复制 ~/.mitmproxy/mitmproxy-ca-cert.pem 到目标设备
Preference->Advanced->Encryption->View Certificates->Import
然后选择mitmproxy-ca-cert.pem 证书
勾选上 Trust this CS to identify web sites
Settings -> Security -> Credential Storage 然后选择 Install from storage
iptable设置
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080 iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j REDIRECT --to-port 8080
启用透明代理,
mitmproxy -T --host
Android上这样设置
http://blog.philippheckel.com/2013/07/05/how-to-sniff-the-whatsapp-password-from-your-android-phone-or-iphone/
Android上证书导入
上传到网站,用浏览器下载就可以了
http://blog.kylemanna.com/android/2013/06/02/android-ca-certificates/
http://renxifeng.is-programmer.com/posts/34205.html
http://blog.sina.com.cn/s/blog_6916fad10101bqh9.html
http://blog.csdn.net/haijun286972766/article/details/6247675
注意
net.bridge.bridge-nf-call-iptables
sysctl -w
net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-call-arptables = 0
对于tap接口iptables貌似起作用了