Android中HTTPS之一(一)HTTP和TCP/IP基础

一.背景

1.1 遇到的问题

最近公司的云采编app为了加强数据安全,决定将现有的http协议改为使用https协议。目前此app使用的网络请求还是非常古老的HttpClient,并且,其中有关于https的设置,但是这个设置是骗人的因为里面写的是相信所有的服务端(不校验域名)。那么问题来了怎么使我的https协议真正的起作用呢?下面就是解决问题的过程和过程中关于https的思考和总结。由于涉及的点很多这里打算分几篇记录。

Android中HTTPS之一(一)HTTP和TCP/IP基础
Android中HTTPS之一(二)SSL/TLS协议运行原理
Android中HTTPS之一(三)具体操作(代码实现)

1.2 解决过程中的问题

1.2.1 网上大多数的解决方案都是抄的,而且没有真正用到生产中就瞎写,我感觉这是极度不负责任的表现;

1.2.2 真正要解决问题,要“知其然,知其所以然”,原理比较重要(知道原理才能用的放心);同时怎么写也是很重要的(好多的网上的解决方案都是给了个原理,写到代码里的时候完全不对,例如校验服务端压根就没有写,因为它们压根就没用过,只是瞎写);

1.3真正的问题

1.3.1 https是什么,它比http安全在哪里(涉及https和http概念)?

1.3.2 CA证书是什么?

1.3.3 使用CA机构颁发(购买的)的证书和使用自签名的证书配置时候的区别?更进一步使用CA机构的证书的时候客户端要不要自己写验证过程?

1.3.4 app客户端验证服务端的时候具体要验证什么?

1.3.5 各个网络框架中具体代码怎么写?

1.4着重强调的点

同时注意无论我们使用的公钥证书是否由CA机构颁发,我们都应在客户端配置的时候对服务端的合法性进行校验。
解释:虽然当使用可信CA签发的证书的时候,Android系统会为我们进行合法性校验(表现为只需要调用相应网络框架中的Https相应sdk方法,不用自己动手校验)可以正常访问服务端,但是这里面存在安全漏洞(我公司在实际生产中就遇到过类似的事情,当时请第三方安全公司检验说要做“手动”服务端安全校验)。私有CA签发的数字证书不在Android系统信任证书列表内,所以服务端无法访问,必然需要自己配置了(服务端和客户端都要配置)。

二.涉及的点

根据上面1.3中提出的问题很好总结出我们要的知识点,如下:

2.1 https比http安全的原理

2.2 http概念以及Tcp的握手挥手过程

2.3 https加密过程原理

2.4 CA机构和证书

2.5 https在代码中具体怎么写(这里主要是Httpclient,并且是我自己调通了的;至于HttpsUrlConnection,Okhttp,WebView中的配置和HttpClient原理是一样的,网上有比较完善可用的代码,这里不做拷贝)

2.6 自己如何生成服务端和客户端需要的私钥证书和公钥证书

作为第一篇,本篇主要介绍点如下:

1.https比http安全的原理

2.http和https等各种基本概念的链接

3.Tcp的三次握手和四次挥手

三.Https协议的原理(原理很乏味但很有用,知其然,知其所以然)

3.1 为什么使用https

相对Http来说就是安全。HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。由于在Http(应用层协议)和Tcp(传输层协议)中间增加了SSL(安全套接字层:加密/身份验证作用),在建立连接的时候先Tcp的三次握手然后加入了SSL握手,而后者的握手过程就是安全检测的过程(后面Tcp三次握手和四次挥手;SSL的握手过程都有详细分析),从而带来了安全的链接。
下图可以简单的表示Http和Https的不同

这里写图片描述

3.2 各种相关概念

下面罗列一些用到的基础概念,具体用来干什么,为什么产生的以及各自的演进过程大家可以点击下面的概念的链接或者自己搜索。
3.2.1 HTTP:超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。
3.2.2 HTTPS:(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。
3.2.3 TCP:(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义
3.2.4 TCP/IP协议:不是TCP和IP这两个协议的合称,而是指因特网整个TCP/IP协议族。
3.2.5 OSI参考模型OSI参考模型:网络参考模型,是ISO的建议,它是为了使各层上的协议国际标准化而发展起来的。
3.2.6 CA认证,第三方权威机构,中间人的角色保障信息安全。

3.3Tcp的三次握手和四次挥手

3.3.1 链接的时候的三次握手

先来了解一下TCP详解,这里面有Tcp的报文结构,SYN,ACK标记是什么意思有什么作用等。如果想仔细研究一下Tcp的报文的话可以参考Tcp报文的英文文档
3.3.1.1这里简单介绍我们用到的Tcp报文头的部分知识,首先是Tcp的报文头部结构如下图:

这里写图片描述

这里介绍比较重要的序号和确认号
序号(Sequence Number):32 bits.
The sequence number of the first data byte in this segment. If the SYN bit is set, the sequence number is the initial sequence number and the first data byte is initial sequence number + 1.这是英文注释。
确认序号(Acknowledgment Number). 32 bits.
If the ACK bit is set, this field contains the value of the next sequence number the sender of the segment is expecting to receive. Once a connection is established this is always sent.这是英文注释。
解释一下分段的意义和两个序号的意义:TCP是将应用层交给的数据分段(package)后发送的。为了支持数据出错重发和数据段组装,TCP程序为每个数据段封装的报头中设计了两个数据报序号字段,分别称为发送序号和确认序号。出错重发是指一旦发现有丢失的数据段,可以重发丢失的数据,以保证数据传输的完整性。如果数据没有分段,出错后源主机就不得不重发整个数据。为了确认丢失的是哪个数据段,报文就需要安装序号。另一方面,数据分段可以使报文在网络中的传输非常灵活。一个数据的各个分段,可以选择不同的路径到达目标主机。由于网络中个条路径在传输速度上不一致性,有可能前面发出的数据段后到达,而后发出的数据段先到达。为了使目标主机能够按照正确的次序重新装配数据,也需要在数据段的报头中安装序号。TCP报头中的第三、四字段(seq和ack)是两个基本点序号字段。发送序号是指本数据段是第几号报文包。接收序号是指对方该发来的下一个数据段是第几号段。确认序号实际上是已经接收到的最后一个数据段加1。
3.3.1.2下面是三次握手的过程示意图

这里写图片描述

下面对上图解释一下:
首先,四个名词的作用:
SYN: SYN置1就表示这是一个连接请求或连接接受报文。ACK : TCP协议规定,只有ACK=1时有效,也规定连接建立后所有发送的报文的ACK必须为1。
seq是序列号,这是为了连接以后传送数据用的,ack是对收到的数据包的确认,值是等待接收的数据包的序列号。(seq是数据包本身的序列号;ack是期望对方继续发送的那个数据包的序列号。

其次,分析三次握手(客户点设为A,服务端设为B):
1.第一次握手:A随机选取一个序列号作为自己的初始序号发送给B;
2.第二次握手:B使用ACK对A的数据包进行确认,因为已经收到了序列号为x的数据包,准备接收序列号为x+1的包,所以ack=x+1,同时B告诉A自己的初始序列号,就是seq=y;
3.第三次握手:A告诉B收到了B的确认包并准备建立连接,A自己此数据包的序列号是x+1,所以seq=x+1,而ack=y+1是表示A正准备接收B序列号为y+1的数据包。

3.3.2四次挥手

先上示意图

这里写图片描述

然后是对上图的解释
1.第一次:客户端主动发送断开连接的包,标明本包序号为u。这时客户端进入FIN_WAIT_1状态。
2.第二次:服务端收到客户端的结束包,此时自己只先回复一个确认收到包,标明本包序号为v,并希望接收的下个包序号为u+1。服务端进入CLOSE_WAIT状态。
3.第三次:服务端等所有要发送的数据包发送完毕,此时发送确认断开数据包,标明本包序号为w,并希望下个收到的包序号为u+1。服务端进入LAST_ACK状态,等待最后的断开包。
4.第四次:客户端经过1MSL之后进入关闭状态。

3.3.3为什么建立连接是三次握手断开时候是四次挥手

这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的连接请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可能未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。

3.3.4为什么TIME_WAIT状态还需要等2MSL后才能返回到CLOSED状态?

主动关闭的Socket端会进入TIME_WAIT状态,并且持续2MSL时间长度,MSL就是maximum segment lifetime(最大分节生命期);这是一个IP数据包能在互联网上生存的最长时间,超过这个时间将在网络中消失。
MSL在RFC 1122上建议是2分钟,而源自berkeley的TCP实现传统上使用30秒,因而,TIME_WAIT状态一般维持在1-4分钟。

TIME_WAIT状态两个存在的理由。

第一:可靠的关闭TCP连接(预防最后ACK丢包)
在进行关闭连接四路握手协议时,最后的ACK是由主动关闭端发出的,如果这个最终的ACK丢失,服务器将重发最终的FIN,因此客户端必须维护状态信息允 许它重发最终的ACK。如果不维持这个状态信息,那么客户端将响应RST分节,服务器将此分节解释成一个错误(在java中会抛出connection reset的SocketException)。因而,要实现TCP全双工连接的正常终止,必须处理终止序列四个分节中任何一个分节的丢失情况,主动关闭 的客户端必须维持状态信息进入TIME_WAIT状态。
第二:防止上一次连接中的包,迷路后重新出现,影响新连接。
上一次老连接中即使有数据包也会在2MSL时间长度后消失,不会影响本次链接的正常断开。

3.4 补充,Tcp状态转换图及其解释(图是偷得别人的):

这里写图片描述

CLOSED: 这个没什么好说的了,表示初始状态。
LISTEN: 这个也是非常容易理解的一个状态,表示服务器端的某个SOCKET处于监听状态,可以接受连接了。
SYN_RCVD: 这个状态表示接受到了SYN报文,在正常情况下,这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂,基本 上用netstat你是很难看到这种状态的,除非你特意写了一个客户端测试程序,故意将三次TCP握手过程中最后一个ACK报文不予发送。因此这种状态 时,当收到客户端的ACK报文后,它会进入到ESTABLISHED状态。
SYN_SENT: 这个状态与SYN_RCVD遥想呼应,当客户端SOCKET执行CONNECT连接时,它首先发送SYN报文,因此也随即它会进入到了SYN_SENT状 态,并等待服务端的发送三次握手中的第2个报文。SYN_SENT状态表示客户端已发送SYN报文。
ESTABLISHED:这个容易理解了,表示连接已经建立了。
FIN_WAIT_1: 这个状态要好好解释一下,其实FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别 是:FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET即 进入到FIN_WAIT_1状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2状态,当然在实际的正常情况下,无论对方何种情况下,都应该马 上回应ACK报文,所以FIN_WAIT_1状态一般是比较难见到的,而FIN_WAIT_2状态还有时常常可以用netstat看到。
FIN_WAIT_2:上面已经详细解释了这种状态,实际上FIN_WAIT_2状态下的SOCKET,表示半连接,也即有一方要求close连接,但另外还告诉对方,我暂时还有点数据需要传送给你,稍后再关闭连接。
TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带 FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。
CLOSING: 这种状态比较特殊,实际情况中应该是很少见,属于一种比较罕见的例外状态。正常情况下,当你发送FIN报文后,按理来说是应该先收到(或同时收到)对方的 ACK报文,再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文。什 么情况下会出现此种情况呢?其实细想一下,也不难得出结论:那就是如果双方几乎在同时close一个SOCKET的话,那么就出现了双方同时发送FIN报 文的情况,也即会出现CLOSING状态,表示双方都正在关闭SOCKET连接。
CLOSE_WAIT: 这种状态的含义其实是表示在等待关闭。怎么理解呢?当对方close一个SOCKET后发送FIN报文给自己,你系统毫无疑问地会回应一个ACK报文给对 方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正需要考虑的事情是察看你是否还有数据发送给对方,如果没有的话,那么你也就可以 close这个SOCKET,发送FIN报文给对方,也即关闭连接。所以你在CLOSE_WAIT状态下,需要完成的事情是等待你去关闭连接。
LAST_ACK: 这个状态还是比较容易好理解的,它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到CLOSED可用状态了。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值