HTTP / HTTPS 的一些相关理解

OSI 模型

OSIOpen System Interconnection Reference Model 的缩写,意思是开放式系统互联通信参考模型

OSI 将计算机网络体系结构划分为7层,借用一下前人总结的模型图如下:

这里写图片描述

为方便快速理解,提取各层的关键字如下

应用层
HTTP、FTP、SMTP、POP3、DNS、DHCP、RPC 等
表示层
加密解密、转换翻译、压缩解压缩等
该层被弃用
会话层
该层被弃用
传输层
端口到端口、端口(16位二进制,0到1023被系统占用)、TCP (传输控制协议)、UDP(用户数据报协议)
SSL(安全套接字层协议)、TLS(传输层安全协议)
网络层
主机到主机、IP地址(32位二进制,4位十进制,网络部分+主机部分)、子网掩码、网关、路由协议
数据链路层
分为逻辑链路控制(logic link control,LLC)子层和介质访问控制(media access control,MAC)子层
PPTP(点对点隧道协议)、L2TP(第二层隧道协议)
以太网协议定义了帧、ARP(地址解析协议)、MAC地址(12位十六进制)、广播至本网络内所有计算机
物理层
传送0和1的电信号

通过 ARP,可以得到同一子网内目标 IPMAC 地址,例如:可以根据网关的 IP 得到网关的 MAC 地址

TCP/IP模型

OSI 是一种理论参考模型,而 TCP/IP 模型已被广泛使用,成为网络互联事实上的标准

TCP/IP 模型将计算机网络体系结构划分为4层,与 OSI 的对比如下:

这里写图片描述

上网4要素

  1. 本机IP
  2. 子网掩码
  3. DNS
  4. 网关

只有正确配置以上4要素,才能连接网络

配置的方式有两种:

  1. 设置静态IP
  2. 根据 DHCP 动态分配

域名解析

在浏览器中输入域名后,系统将进行域名解析,查询该域名对应的 IP 地址,查询步骤大致如下:

  1. 浏览器缓存,urlchrome://net-internals/#dns
  2. 系统缓存,命令 ipconfig /displaydns
  3. hosts 文件,路径 C:\Windows\System32\drivers\etc\hosts,如果更改了此文件,使用命令 ipconfig /flushdns 刷新 DNS 解析缓存
  4. DNS
  5. NetBIOS name Cache,电脑上的缓存,保存着近期和本机成功通信过的 IP
  6. WINS 服务器(是NETBIOS名称和IP地址对应的服务器)
  7. 广播查找
  8. LMHOSTS 文件,路径 C:\Windows\System32\drivers\etc\LMHOSTS.sam

TCP

3 次握手

建立TCP连接时需要进行3次握手

TCP 握手进行3次的原因: 这样通信双方知道自己和对方都能收发信息

4 次挥手

关闭TCP连接时需要进行4次挥手

TCP 挥手进行4次的原因:

  1. 一方关闭连接后,另一方仍可以发送数据
  2. 一方接收到另一方的关闭信号,要回传一个确认信号
  3. 两次来回总共4次挥手

Socket

Unix 系统把主机+端口,叫做"套接字"(Socket)。有了它,就可以进行网络应用程序开发了

这是系统封装了 TCP 连接,提供的上层接口,在执行 connect()accept() 方法时进行 TCP 的3次握手

HTTP

Hypertext Transfer Protocol 的缩写,全称是超文本传输协议

默认使用80端口

HTTP 的内容很多,这里只略介绍请求和响应的基本格式

Request 格式
请求方法 URL 协议版本号     //请求行
Header1: Value1      	 //请求头
Header2: Value2
Header3: Value3
			//空行
body         		//post请求有请求体
Response 格式
协议版本号 状态码 状态描述	 //状态行
Header1: Value1      		 //响应头
Header2: Value2
Header3: Value3
				//空行
body         			//响应体

当遇到连续两个 \r\n 时,Header部分结束,后面的数据全部是Body。

HTTPS

Http Over SSL 的缩写
默认使用443端口
非对称加密 (RSA) + 对称加密 ,可以防嗅探,但无法防范中间人攻击,这时候就需要CA证书
这也是抓包过程中如果想抓取 HTTPS 的数据就要安装并信任抓包工具的证书的原因

MITM (Man-In-The-Middle attack)—— 中间人攻击

CA(Certificate Authority)—— 数字证书认证机构

主流浏览器都内置了大部分可信的 CA 根证书,这些根证书中包含的公钥将用于服务端证书的检验

CA证书的主要内容

证书颁发机构的名称
证书本身的数字签名
证书持有者公钥
证书签名用到的Hash算法

SSL 握手

HTTPS 是在 SSL 握手阶段通过 “非对称加密” 协商出 “对称加密” 的秘钥,这个秘钥将用于后续的通信,这样同时兼顾了安全与效率

这个"握手阶段"涉及四次通信,"握手阶段"的所有通信都是明文的,流程大致如下:

  1. 客户端发起 HTTPS 请求,连接到服务端的 443 端口,发送的内容主要包括:支持的协议版本、支持的加密算法、压缩算法、一个随机数 k1
  2. 服务端返回的有:一个随机数 k2 、确认使用的加密通信协议版本(比如 TLS 1.0 版本)、确认使用的加密算法(比如RSA 算法)以及服务端证书
    如果服务器需要确认客户端的身份,就会再包含一项请求,要求客户端提供"客户端证书"
  3. 客户端检验服务端证书是否可信:用浏览器内置证书的公钥解密证书,如果没有证书能解密,则证书是不可信的,如果解密成功则证书是可信的
  4. 客户端检验服务端证书是否被篡改:如果证书是可信的,则用相应证书的公钥对数字签名进行解密得到摘要A,然后再根据签名的Hash算法计算出证书的摘要B,对比A与B,若相等则正常,若不相等则服务端证书是被篡改过的
  5. 如果服务端证书是可信的且没有被篡改,则客户端生成一个随机数 k3,然后取出证书中的公钥,用这个公钥加密 k3得到 k30并传给服务端,同时传送的还有:编码改变通知、客户端握手结束通知
  6. 服务端用自己的私钥解密 k30 得到 k3 ,回应客户端如下信息:编码改变通知、服务端握手结束通知

当客户端和服务端都有三个随机数 k1k2k3 时,双方就用商定的加密算法,各自生成本次会话所用的同一把"会话密钥"。

而使用3个随机数的原因是 一个伪随机可能完全不随机,可是三个伪随机就十分接近随机了,防止只使用一个伪随机被猜出秘钥

握手阶段结束后,客户端与服务器就进入加密通信,HTTP 内容在交给 TCP 之前都会被加密。

PSK (Pre-Shared Key) —— 预共享秘钥
在通信之前,通信双方部署若干共享的秘钥(通常是对称秘钥),每个秘钥一个ID。
客户端将自己选好的秘钥ID发送给服务端,服务端如果能在秘钥池中找到这个ID,就用对应的秘钥与客户端通信,否则报错并中断连接
Android中的https

当网络协议从 http 改为 https,服务端就需要提供证书给客户端,用于校验。

如果服务端没有提供证书,就会直接报错。

如果服务端提供了证书,客户端就要进行校验,校验方式有以下两种:

  1. 通过Android系统校验证书
    这是最简单的方式,客户端把 http 改为 https 就可以了,不用再做其他工作。

    只要是Android系统信任的证书,就可以通过校验,而系统会内置大部分可信的 CA 根证书。

    这种情况下的抓包非常简单,只需要在手机设备上安装抓包工具的证书即可,这样抓包工具就能通过Android系统校验,拿到 https 请求了。

    但从7.0版本开始,又没有这么简单了。

    官网的版本更新记录——默认受信任的证书颁发机构,写了以下限制:

默认情况下,面向 Android 7.0 的应用仅信任系统提供的证书,且不再信任用户添加的证书颁发机构 (CA)。如果面向 Android N 的应用希望信任用户添加的 CA,则应使用网络安全性配置以指定信任用户 CA 的方式。

根据官方的描述,这种情况下想要抓包 https 请求,可以通过这几种方法:

  • targetSdkVersion 设为23及以下

  • 在7.0以下系统抓包

  • 使用网络安全性配置,指定信任用户添加的 CA

  • 将用户添加的 CA 转变为系统 CA,这种方式一劳永逸,而且可以抓取设备上所有的 https 请求了。

    注意:抓包工具的 CA 证书,也可能因为有效期过长而不被信任(ERR_CERT_VALIDITY_TOO_LONG),因为为了安全,浏览器限制了证书的有效期时长。

Flutter中的https抓包
Flutter中的https抓包主要还需要解决两个问题:
1. Flutter中默认不使用手机设置好的网络代理,连不上抓包工具。
2. Flutter中默认不信任非可信根证书签发的证书,即使抓包工具的证书在系统证书中,也是不可信的。
如果自己有Flutter源码,解决方式直接看下面的代码:

    (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
        (client) {
      //代理设置
      client.findProxy = (uri) {
        return "PROXY host:port";
      };
      //抓Https包设置
      client.badCertificateCallback =
          (X509Certificate cert, String host, int port) => true;
    };

这样设置后,即使抓包工具的证书不在系统证书中,也是可信的。

当然,我们没有别人 Flutter app 的源码,所以想抓包别人 Flutter app 的 https 请求,暂时无解。
2. app自己校验证书
app自己校验证书有两种方式:

  • Android 7.0 中新引入的说明性 网络安全性配置, 无需任何代码修改。

  • 传统的易出错的编程 API(例如,X509TrustManager)。

    这种情况下想要抓包 https 请求,就需要去研究app内部校验证书的逻辑,修改app代码达到目的。

    xposed下有个可用的模块JustTrustMe

服务端和客户端双向认证

除了客户端对证书对单向认证,更安全严格的就是服务端和客户端双向认证了,但ta在实际中几乎很少用到,因为服务器端需要维护所有客户端的证书,这无疑增加了很多消耗,这里不再细述了。银行U盾就属于这种校验方式。

参考资料:
互联网协议入门(一)——阮一峰
互联网协议入门(二)——阮一峰
维基百科-OSI模型
维基百科-TCP/IP协议族
OSI 7层模型和TCP/IP 4层模型
编程随想——扫盲https系列
一次完整的HTTP事务是怎样一个过程?
SSL/TLS协议运行机制的概述——阮一峰
图解SSL/TLS协议——阮一峰
图解HTTPS
详解https是如何确保安全的?

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值