| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 网络协议 -> TCP、TLS |SSL、JSSE、HTTPS杂烩笔记 -> 正文阅读 |
|
[网络协议]TCP、TLS |SSL、JSSE、HTTPS杂烩笔记 |
目录 以目前我的理解以及这两天的各种百度写个总结笔记,有不对的请指正 TCP简介全名Transmission Control Protocol,传输控制协议,是网络层IP协议和链路层Ethernet协议之上,Ethernet协议实现链路层的数据传输和地址封装(源方和目标方的MAC地址),解决局域网的点对点通信,而不同局域网之间的两台机子则需要IP协议进行地址的路由中转,TCP则面向的是端口到端口,保证数据传输的完整和可靠,包括数据包的确认、失败重发、流量控制,数据量大的情况TCP会将数据拆分为有序的多个数据包传输,TCP需要能将数据包重组为完整的数据 一个数据包的旅程????????本机浏览器写个url准备回车,此时本机都有什么信息,本机的mac、ip、浏览器应用的端口自然是知道的,url里只有对方的域名,浏览器形成了HTTP报文数据之后,委托给操作系统进行处理并发送,但是操作系统只认IP,不认域名,所以在委托之前还需要查询对方域名的IP地址,也就是DNS服务器(url是ip+port也就不需要解析了),浏览器向DNS询问出IP之后,交给操作系统。 ????????操作系统收到委托,首先TCP处理,数据太多切割成多份,为每份增加一些 保证数据传输的完整和可靠所必要的信息头,例如源端口和目标端口,数据包的序号,本机当前可接收的最大数据量等等。 ????????其次IP协议为每份TCP处理过的包再加上ip包头,例如本机IP地址和对方IP地址,最后需要为数据包加上目标的物理mac地址。 ????????此时判断对方IP地址是不是同一个局域网,如果是,那么使用ARP(地址解析协议)在局域网广播,IP是XXXX.XXX.XX.X是谁的,局域网其他主机收到包,其中一个主机发现说的是自己,回复我在这,mac地址是YYYY,这样就可以为数据包加上mac头交给网卡转换成电信号由网线传输给目标主机,每次都广播显然不合理,所以主机会维护一个arp表记录ip和mac的对应关系。如果不是一个局域网,那么就需要网关来转发数据包,所以mac地址就需要写网关的mac地址,也是一样ARP广播的是网关的IP。 ? ? ? ? 此时数据包已经完成组装发出,网关收到以后拆开最外层的包头,发现确实是发给自己的,在拆开第二层,目的IP不是自己,从自己的路由表查找目的IP对应的MAC地址,有就直接写目的mac,没有则写下一个网关的mac地址,重新封上两层数据包头,发出去。一次一次的接力最终把数据包发送给目标主机。 ? ? ? ? 目标主机再一层层解析,解析TCP报头,了解了目标端口,查下本机发现这个端口是一个Tomcat服务器在监听,则把按数据包序号重新组织好的数据发送给Tomcat进程,Tomcat处理完毕,再将响应返回给操作系统,操作系统重新一层层组织好数据包头,由网卡再发送回去。 TCP如何保证数据的可靠和完整确认应答和序列号TCP给发送的每一个包添加报文头时,会进行编号seq,这样接收方接收到被拆分后的数据后,按照序号seq对数据包进行排序,数据重组后把有序数据传送给应用层 并且接收方会对收到的报文回复确认ack,确认时会带有确认序号,表示此确认序号之前的所有数据我已收到,下次请给我发这个序号之后的数据。 确认并不是每收到一个数据包就返回一次ack,如果是这样,那么网络中就会存在一半数据,一半确认,而且确认大多都是没有必要的。发送方可以一次性发送多个数据包,接收方若接受正常,只需要发送一次ack 超时重传发送数据包之后,若一定时间没有收到接收放的ack确认消息,则会重新发送数据包,那么有两种可能没有收到ack,1接收方没有收到数据,2接收方的ack传输中丢失了,在第一种情况,重新发送接收方若收到,发ack,发送方收到继续下一批数据的发送,若第二种情况,接收方接收到相同序号seq的数据,直接丢弃不处理,仍发送ack。所以序号既排序也作为去重的依据。 流量控制发送端和接收端处理数据的速度不一致,发送端发送的太快,接收端处理不过来导致丢包,那么发送端长时间等不到ack,超时重传形成一个恶性循环。根据接收端对数据的处理能力,决定发送端的发送速度,这个机制就是流量控制。 在确认报文中,接收方会回复给发送方一个窗口大小,表示我最多接收这么点数据,接收方处理不过来时,窗口缩小,发送方根据这个大小控制自己发送的频率和数据量 滑动窗口 即上边流量控制中的说的窗口,用于网络数据传输时的流量控制,以避免拥塞的发生 分为四段,已发送并已被确认的数据, 已发送未收到确认的数据,还未发送但可以发送的数据,不可发送的数据。其中第二段和第三段就是当前窗口的大小,当前大小为51 - 32 + 1 = 20。此时如果发送方接收到ack回复ack=34?win=21,其中win就是接收方窗口大小,接收方条件好些了比上次可以多接收一个字节,此时窗口向右滑动,即就是28--34为第一段,35--55就是新的窗口大小,带下为21。 TCP报文格式两个端口,代表了两台主机的两个进程; 两个序号,第一个代表发送端本次数据包的序号,确认序号表示发送端希望下次收到接收端的报文序号; 4位首部长度,表示tcp头多少个字节 6位标志位,常见的就是ACK,SYN,FIN,RST
16位窗口大小,滑动窗口最大65535字节 16位检验和,由发送端填充,校验数据包中数据是否正确 16位紧急指针,?标记紧急数据在数据字段中的位置 ?选项,对tcp的扩展,例如最大报文长度、窗口扩大比例等。窗口扩大比例是指,当前65535的窗口大小已经不满足通信需要,如果存在窗口扩大比例选项,那么窗口大小就是16位窗口大小乘以这个选项中的比例。 三次握手建立连接建立了什么样的连接TCP是面向连接的通信,上述的数据包路径来看,TCP建立的并不是两台主机间什么直接的物理上实际的连接,只能算有链接特性的、互相维持的一个状态。 双方都存有此次连接的相关数据,例如需要保证数据传输的完整和可靠,需要一些数据结构来支持数据包的确认、失败重发、重组等。 而完整和可靠的连接保证,需要复杂的连接建立交互过程,在交互过程中协商、初始化各种信息来让双方达到一个共识,确保后续数据的正常处理。 三次握手服务器端状态当前为LISTEN监听端口,客户端先发送请求建立连接报文,SYN标志为1,附带客户端初始序列号seq=x,并进入?SYN-SENT(同步已发送状态) 服务端收到连接报文,若同意建立连接,同样回复建立连接报文,SYN标志为1,附带确认信息,ACK标志为1,服务端初始序列号seq=y,希望下次收到客户端序列号ack=x+1,进入SYN-RCVD(同步收到)状态 客户端收到回复确认ACK标志为1,客户端序号为上次发送的x+1,希望下次收到服务端包序号为y+1,进入ESTABLISHED(已建立连接)状态,服务端收到后也进入ESTABLISHED(已建立连接)状态,开始发送数据。 序列号不是都从0开始,只是示例。为什么都是序列号+1,因为三次握手是建立共识的过程,不允许携带数据但消耗一个序列号,如果是建立连接之后,包中有数据,例如客户端发送seq=6, ack=20,数据大小为30,那么服务端接收到后回复确认就是seq=20,ack=36,客户端下次发送的序号就是36 为什么是三次握手TCP是可靠的,精髓在于序列号,A向B建立连接,告诉B我的序列号是从5000开始的,那么B在后续接收处理时,就知道5000之前的数据是错误该丢弃的,同时回复A确认以及B的初始序列号,A就知道我的初始序号已经成功传输,同时回复B确认,此刻AB双方才都对初始序列号达成共识,后续才能开展可靠传输。 因此,建立连接需要四个步骤,A发送A的初始序列号,B收到并回复确认,B发送B的初始序列号,A收到并回复确认,建立共识。第二和第三可以合并,因此是三次握手。 假设两次握手,也就是说A请求,B响应,此连接就算建立,此时B对A的初始序列号已经知晓,但并不知道A是否收到自己的初始序列号,连接是不可靠的。 四次挥手A,B双方都可以发起连接的关闭 1、A向B发送FIN报文,表示A已经没有数据要发送了,准备关闭连接 2、B收到后回复确认ACK,表示知道了,此时可能B中还存在部分未发送完的数据,此时B继续发送,A仍需要接收 3、B向A发送FIN报文,表示B也没有数据了,准备关闭连接,等待最后的确认 4、A收到FIN,回复确认并关闭连接,B收到确认也关闭连接 三次握手是因为第二第三阶段可以合并发送,所以减少了一次交互,而四次挥手因为接收到对方的FIN时,只表示了对方不再发送数据给自己,还可以接收,而且自己的数据也可能没有发送完毕,从而导致多发生了一次挥手。 WireShark抓包三次握手、两次传输数据、四次挥手的示例 下方为一次SYN请求的数据报文,两个16进制数为一个字节,按照报文头结构,前两字节为源端口,也就是d7 1c 即55068,24 2a 为9258 SYN标志位1,滑动窗口大小fa f0 即64240 ? 在选项中,定义了窗口缩放比例为2^8=256, 即握手之后传输数据,窗口大小为WIN * 256 ?再来看序号的增加,第一次HTTP请求中seq==1,ack==1,报文中携带数据长度320 ?那么对应HTTP响应的TCP头的ack中的确认序号就是ack==321,表示320的数据已收到,下次来321,此次ack中seq==1,数据长度444 ?那么下次的回复可以推断出seq==321,ack=445,看报文确实 序列号是从0开始这只是相对序列号,如果想看真实序列号,wireshark-》编辑-》首选项-》协议-》TCP,不勾选下边这个选项,即可看见眼花缭乱的序号 TLS????????SSL(Secure Socket Layer 安全套接层)是属于应用层下,TCP传输层之上的一个协议加密层,最初是由网景公司(Netscape)研发,在SSL更新到3.0时,IETF(The Internet Engineering Task Force - 互联网工程任务组)对SSL3.0进行了标准化,并添加了少数机制(但是几乎和SSL3.0无差异),标准化后的IETF更名为TLS1.0(Transport Layer Security 安全传输层协议),可以说TLS就是SSL的新版本 ? ? 没有使用SSL加密的消息通讯因为都是明文传输,通讯过程容易被监听、修改或者身份冒充遭到中间人攻击等。TLS就是解决安全传输问题的解决方案,核心思想是非对称加密,通讯双方都使用对方公钥加密消息,私钥签名,接受到消息后使用私钥解密,公钥验证签名,并辅以CA签发证书来验证双方身份,这样即解决了上述安全问题。 ????????但是非对称加密算法计算量太大,每一次的消息都使用公钥私钥加密对性能损耗极大,因此解决方法就变成了 : 双方协商生成一个对称密钥,对称密钥运算速度块,由公私密钥加密传输这个对称密钥,这样双方之后的交互就是用这个对称密钥进行加密通讯。 在JSSE节,会wireShark抓包来分析真正交互的各个阶段,下边只是描述大概 单向认证也即只是客户端验证服务端身份,大致一次的通讯过程为: 1、TCP三次握手建立连接 2、客户端向服务端发送建立SSL请求,表明自己支持的所有加密方式,并请求获取服务端证书 3、服务端接收请求,选择一种加密方式以及附带证书响应给客户端 4、客户端验证服务端证书可信,生成对称密钥,加密后发送给服务端 5、服务端接收到加密的对称密钥,解密后得到对称密钥 6、开始使用对称密钥加密通信 双向认证双向认证即服务端也需要验证客户端身份,加粗为与单向区别 1、TCP三次握手建立连接 2、客户端向服务端发送建立SSL请求,表明自己支持的所有加密方式,并请求获取服务端证书 3、服务端接收请求,选择一种加密方式以及附带证书响应给客户端,并请求获取客户端证书 4、客户端验证服务端证书可信,生成对称密钥,加密后附带客户端证书发送给服务端 5、服务端接收到加密的对称密钥和客户端证书,验证证书可信,解密后得到对称密钥 6、开始使用对称密钥加密通信 ALPNApplication Layer Protocol Negotiation,应用层协议协商,双方协商在安全连接之上的应用层协议,TLS的扩展,类似TCP对滑动窗口大小的扩展,在TLS握手中,客户端会会发送给服务端客户端所支持的协议列表,服务端从中选择自己支持的协议类型响应给客户端 下图是抓包截图,客户端在请求安全连接之时,附带自己支持的应用层协议列表,下图为http2和http/1.1 ??服务端响应时从中选择支持的协议 JSSEJava Secure Socket Extension (Java安全套接字扩展) 它包含了实现Internet安全通信的一系列包的集合,是SSL和TLS的Java实现 JSSE API 类图如下,SSLServerSocket/SSLSocket继承ServerSocket/Socket,表示实现了SSL协议的Socket,负责安全会话握手等,封装了底层复杂的安全通信细节 代码示例见博文: 测试代码,首先需要产生两对keystore client.keystore? 客户端密钥对所在的密钥库 client_trust.keystore? 客户端所信任的证书库 server.keystore? 服务端密钥对所在库 server_trust.keystore 服务端所信任的证书库 产生客户端密钥对
导出客户端证书,只包含客户端公钥
将客户端证书导入到 服务端信任库中server_trust.keystore
产生服务端密钥对
导出服务端证书,只包含服务端公钥
将服务端证书导入到 客户端信任库中client_trust.keystore
单向认证代码服务端代码
客户端代码
双向认证代码服务端代码,与单向认证区别,在于需要加载服务端信任库,由此去验证客户端身份,以及设置setNeedClientAuth(true),表明需要验证客户端身份
客户端代码,与单向区别在于需要加载客户端的密钥库,因为需要给服务端发送客户端证书
WireShark分析单向认证上边测试代码中服务端有一行注释代码,目的是为了指定服务端选择的加密套件 选择了TLS_RSA_WITH_AES_256_CBC_SHA,即对称密钥交换算法使用RSA,身份认证算法使用RSA,对称加密算法使用AES_256_CBC,摘要算法使用SHA。 再比如TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,密钥交换算法使用ECDHE,身份认证算法使用RSA,对称加密算法使用AES_256_CBC,摘要算法使用SHA384。 不同的加密套件,有不同的算法,交互流程也会有些微的不同,不过基本差不多,下面截图的加密套件是TLS_RSA_WITH_AES_256_CBC_SHA ?1、Client Hello 发送给服务端一个随机数,稍后用于产生对称密钥,还有自己支持的所有加密套件(图例43个) 2、Server Hello / Certificate / Server Hello Done ? ?1)server hello? ? ? 服务端生成session保存握手信息,返回客户端一个随机数,SessionID和选中的加密套件 ? ? 随机数稍后用于产生对称密钥,sessionID用于会话复用 ? ?2) certificate ? ? ?服务端公钥证书返回给客户端 ? ??3) server hello done ? ? ?只是个标识,告诉客户端,首次握手事完了 3、Client Key Exchange ? ? ?客户端验证证书后,再次生成一个随机数,使用服务端公钥加密后发送给服务端,此时客户端已经知道三个随机数了, 根据协商的算法计算出对称密钥 ? ? 为什么需要计算对称密钥需要三个随机数,百度说是为了增加随机性 4、(C --> S) Change Cipher Spec 编码改变通知,标识我要使用对称密钥加密传输数据了 5、(C --> S) Encrypted Handshake Message 客户端握手结束通知,表示客户端的握手阶段已经结束。对前面发送的所有内容的进行hash,用来供服务器校验 6、(S --> C) Change Cipher Spec 服务端接收到第三个随机数后,计算出相同的对称密钥,通知客户端可以使用对称密钥加密传输数据了 7、(S --> C) Encrypted Handshake Message 同5 双向认证?比单向认证中,server hello阶段多了几步 Server Key Exchange? 这是因为server hello选择的加密套件为TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 , ECDHE椭圆曲线算法特有步骤,具体啥未详细了解,告诉客户端一个数用来计算对称密钥 Certificate Request 服务端请求客户端证书,并告诉客户端签名和摘要算法使用下边列举的 Certificate Verify 客户端发送证书后,选择一种算法,发送一个签名信息向服务端表明证书属于自己 ?其他交互和单向一致 Tomcat配置HTTPS访问使用上一节jsse生成的证书, Tomcat8.5 配置Tomcat的server.xml 配置连接器Connector的证书为server.keystore
启动项目,访问controller,发现http已经不能使用了 https可以正常访问,但是会提示不安全,这是因为浏览器不信任服务端证书 证书如下,因为我上述证书是随意生成的,证书颁发给谁随意填写的,所以如下双击安装了证书后依旧不安全,现重新keytool生成一个 如下新创建一个,在姓名姓氏那里填写浏览器要访问的地址或域名,再导出证书,安装证书,修改server.xml中证书信息 再次访问路径,发现不是非安全了 ?额,ie是好了,但是谷歌依旧不安全,暂时不知道为啥 |
|
网络协议 最新文章 |
使用Easyswoole 搭建简单的Websoket服务 |
常见的数据通信方式有哪些? |
Openssl 1024bit RSA算法---公私钥获取和处 |
HTTPS协议的密钥交换流程 |
《小白WEB安全入门》03. 漏洞篇 |
HttpRunner4.x 安装与使用 |
2021-07-04 |
手写RPC学习笔记 |
K8S高可用版本部署 |
mySQL计算IP地址范围 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 | -2024/12/29 10:51:21- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |
数据统计 |