OSI七层模型非常复杂,且部分功能冗余,因此完全实现OSI参考模型的系统不多。而TCP/IP直接面向市场需求,实现容易,他们分别是:1. 应用层;2. 传输层;3. 网际层;4. 网络接口层
各层 | 协议 |
---|---|
应用层 | DNS(域名系统)、FTP(文件传输)、HTTP(超文本)、SMTP(电子邮件)、RIP(路由信息协议)、DHCP(动态主机配置) |
传输层 | TCP、UDP |
网络层 | IP、ARP(地址解析)、RARP、ICMP(网际控制报文协议)、NAT(网络地址转换) |
当然分层也有一些缺点,例如,有些功能会在不同的层次中重复出现,因而产生了额外开销。
局域网是指在一个较小的地理范围内,将各种设备通过双绞线等介质互相连接起来,组成信息共享的计算机互联网络。它是一种典型的广播信道,主要特点是网络为一个单位所拥有,且地理范围和站点数目均有限。
以太网是一种星型拓扑结构局域网,信息以广播形式发送。
CSMA/CD表示载波监听多点接入/碰撞检测,适用于总线形网络或半双工网络环境。工作流程可简单概况为:“先听先发,边听边发,冲突停发,随即重发”。
交换机具有自学习能力,学习的是交换表的内容,交换表中存储着MAC地址到接口的映射。
虚拟局域网可以建立与物理位置无关的逻辑组,只有在同一个虚拟局域网中的成员才会收到链路层广播信息。
网络层向上只提供简单灵活的、无连接的、尽最大努力交互的数据报服务。
IP协议又称互联网协议,是支持网间互联的数据包协议。IP协议是不可靠、尽力交付的数据包传输服务,作用有如下:
RARP是反向地址转换协议,是网络层协议,RARP与ARP工作方式相反。ARP是IP地址->MAC地址,RARP是MAC->IP。
原理
IP在一个网络中是唯一的,一个域名只能对应一个IP,而一个IP可以对应多个域名。
从数据报的首部提取目的主机的 IP 地址 D,得到目的网络地址 N。
ICMP是网际控制报文协议,主要是实现IP协议中为实现的部分功能,用来传输控制信息来辅助网络层通信。其主要功能是验证网络是否畅通(确认接收方是否受到IP数据包)以及辅助IP协议实现可靠传输(若发生IP丢包,ICMP会通知发送方IP数据包被丢弃的原因)
ARP是地址解析协议的缩写,该协议将IP地址转换为物理地址,工作在数据链路层。
NAT是网络地址转换,他是将内部私有网络翻译成共有网络IP地址的技术。该协议可以将IP地址不足的问题,而且能隐藏和保护网络内部主机,从而避免来自外部网络的攻击。
网络层协议负责提供网络主机间(点对点)的逻辑通信;运输层协议负责提供进程间(端到端)的逻辑通信。
三次握手
三次握手是TCP连接的建立过程。在握手前,客户端处于CLOSED阶段,服务器处于监听LISTEN阶段。然后进行三次握手:
四次挥手
双方都处于ESTABLISHED阶段,假设客户端先主动释放连接。
三次握手是为了保证双方的发送和接收都正常。若采用两次握手,服务器不知道自己的发送是否正常。
两次握手会发生这样的情况:若客户端发起连接请求,这个请求长时间滞留,于是客户端重新发起新的请求,这一次双方建立连接了;当双方断开连接后,这个滞留的请求来了,服务器向该客户端发送报文建立连接(两次握手),但客户端不发送数据,服务器一直等待,造成了资源的浪费。反之若采用三次握手,服务器没收到第三次握手,就会建立连接失败。
ACK 是为了告诉客户端发来的数据已经接收无误,传回SYN是表示服务器要连接客户端。
因为FIN释放连接报文和ACK确认报文分别在两次握手中传输的。被动方可能还有数据要处理,所以会先返回ACK,过后再发送FIN。
举个例子:A 和 B 打电话,通话即将结束后,A 说“我没啥要说的了”,B回答“我知道了”,但是 B 可能还会有要说的话,A 不能要求 B 跟着自己的节奏结束通话,于是 B 可能又巴拉巴拉说了一通,最后 B 说“我说完了”,A 回答“知道了”,这样通话才算结束。
CLOSE-WAIT发生在第二次挥手后,服务器进入CLOSE-WAIT,处理一些未完成传输的数据。
TIME-WAIT发生在第三次挥手后,客户端会等待2MSL,以确保这个ACK包已经顺利被服务器接收到并处理完毕;如不等待,客户端返回的最后确认报文丢失,服务器不能进入正常关闭状态。
总之,等待2MSL时间可以保证数据传输的可靠性和安全性。同时,在日常网络应用环境中,由于整个过程较长,通常不会对网络性能产生影响。
在高并发的场景中,会有大量连接处于TIME_WAIT状态,而文件描述符的使用有上限,若持续高并发,会导致一些正常的连接失败。
当客户端发出最后的 ACK 确认报文时,并不能确定服务器端能够收到该段报文。所以客户端在发送完 ACK 确认报文之后,会设置一个时长为 2 MSL 的计时器。
若服务器在 1 MSL 内没有收到客户端发出的 ACK 确认报文,再次向客户端发出 FIN 报文。如果客户端在 2 MSL 内收到了服务器再次发来的 FIN 报文,说明服务器由于一些原因并没有收到客户端发出的 ACK 确认报文。客户端将再次向服务器发出 ACK 确认报文,并重新开始 2 MSL 的计时。若2MSL没收到服务器的FIN,则说明服务器确认收到了,则进入CLOSED。
设置SO_REUSEADDR套接字通知内核,若端口被占用,但TCP处于TIME_WAIT可以重用端口。(特别好用,WebServer项目中就用到了)
可以采用长连接减少TCP的连接和断开,但并发量会降低。
首先检查是不是自己的代码问题(看是否服务端程序忘记关闭连接),如果是,则修改代码。
调整系统参数,包括句柄相关参数和 TCP/IP 的参数,一般一个 CLOSE_WAIT 会维持至少 2 个小时的时间,我们可以通过调整参数来缩短这个时间。
类型 | 是否面向连接 | 传输可靠性 | 传输形式 | 所需资源 | 传输效率 | 应用场景 | 首部字节 |
---|---|---|---|---|---|---|---|
TCP | 是 | 可靠 | 字节流 | 多 | 慢 | 文件传输、邮件传输 | 20~60 |
UDP | 否 | 不可靠 | 数据报 | 少 | 快 | 即使传输、域名转换 | 8个字节 |
为了让发送方的发送速率不要太快,让接收方来得及接收。如果接收方来不及接收,会有分组丢失。在TCP利用滑动窗口机制实现。主要是的方式是接收方返回的包中会包含自己的接收窗口大小,以及控制发送方的发送窗口大小。
在实际的网络通信系统中,除了发送方和接收方外,还有路由器,交换机等复杂的网络传输线路,此时就需要拥塞控制。拥塞控制是作用于网络的,它是防止过多的数据注入到网络中,避免出现网络负载过大的情况。常用的解决方法有:慢开始和拥塞避免、快重传和快恢复。
拥塞控制是全局的,防止过多数据注入网络;流量控制往往针对点对点通信量的控制,是端到端的问题。
UDP只有接收缓冲区,只要有数据就发送,尽最大能力交付。且UDP没有流量控制和拥塞避免机制,因此UDP的传输是不可靠的。
bind: UDP 的发送端调用 bind 函数时,就会将这个套接字指定一个端口,若不调用 bind 函数,系统内核会随机分配一个端口给该套接字。当手动绑定时,能够避免内核来执行这一操作,从而在一定程度上提高性能。
connect:UDP 中调用 connect 只是把对端的 IP 和 端口号记录下来没有三次握手过程。
发送方在发送一次数据后开启一个定时器,在一定时间内如果没收到数据报的ACK报文,就重发数据,若达到一定次数后还没有成功的话,就放弃重传并发送一个复位信号。定时时间的确定需要权衡,过长会使网络利用率不高,过短会造成多次重传,使得网络阻塞。
停止等待协议是为了实现 TCP 可靠传输而提出的一种相对简单的协议,该协议指的是发送方每发完一组数据后,直到收到接收方的确认信号才继续发送下一组数据。
滑动窗口:每个TCP/IP主机支持全双工数据传输,因此TCP有两个滑动窗口:一个用于接收数据,另一个用于发送数据。
作用
接收方会返回给发送方的ACK包中的接收窗口大小为0,此时发送方会等待接收方的发送窗口大小直到变为非0为止。
SYN Flood是典型的DoS(拒绝服务)攻击,其目的是通过消耗服务器所有可用资源使服务器无法用于处理合法请求。通过重复发送初始链接请求(SYN)数据报,攻击者能够压倒目标服务器上所有可用端口,导致目标设备不响应合法请求。
SYN泛洪攻击,其实这个攻击主要利用的就是TCP三次握手机制的缺陷。
A(攻击者)发送TCP SYN,SYN是TCP三次握手中的第一个数据包,而当这个服务器返回ACK以后,A不再进行确认,那这个连接就处在了一个挂起的状态,也就是半连接的意思,那么服务器收不到再确认的一个消息,还会重复发送ACK给A。这样就造成了服务器的大量资源浪费,导致服务器崩溃。
优化方式:
HTTP头部本质上是一个传递额外重要信息的键值对。主要分为:通用头部,请求头部,响应头部和实体头部。
DNS是域名系统,因特网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便地访问互联网,而不用去记很复杂的IP数字串。
通过主机名,最终得到该主机名对应的IP地址的过程叫做域名解析。
将主机域名转换为IP地址,属于应用层协议,使用UDP传输。
域名解析有两种方式:递归查询和递归与迭代相结合的查询。
一、主机向本地域名服务器的查询一般都采用递归查询。
二、本地域名服务器向根域名服务器、顶级域名服务器、权限域名服务器的查询为迭代查询。
具体解析过程
因为UDP快,UDP的DNS协议只要一个请求、一个应答就好了。
而如果使用TCP,需要三次握手、发送数据以及应答、四次挥手,很耗时,且DNS只发送IP地址,数据较短,一半都不超过512字节(UDP的限制),所以用UDP传输即可。
因为TCP可靠性好,若用UDP容易丢失。而且传输的内容较多,UDP有512字节的限制,所以用TCP比较好。
在HTTP/1.0中默认使用短连接。也就是说,客户端和服务器没进行一个HTTP操作,就建立一次连接,任务结束就断开连接。
而从HTTP/1.1开始,默认使用长连接,用以保持连接特性。
get把请求的数据放在url上,用?分割url和传输数据,参数之间用&连接,所以get不太安全,而post把数据放在HTTP实体主体里面,相对安全一点。
get提交的数据最大是2K(限制实际上取决于服务器),post理论上没有限制。
GET产生一个TCP数据报,浏览器会把http header和data一起发出去,服务器响应200;POST产生两个TCP数据报,浏览器先发送header实体头,服务器响应100 continue,浏览器再发送data实体主体,服务器响应200 OK
GET请求会被浏览器主动缓存,而POST不会,因为每一次POST请求都不同
本质区别:GET是幂等的,而POST不是幂等的(幂等性是指一次和多次请求某一个资源应该具有同样的副作用。简单来说意味着对同一URL的多个请求应该返回同样的结果。)
正因为它们有这样的区别,所以不应该且不能用get请求做数据的增删改这些有副作用的操作。因为get请求是幂等的,在网络不好的隧道中会尝试重试。如果用get请求增数据,会有重复操作的风险,而这种重复操作可能会导致副作用(浏览器和操作系统并不知道你会用get请求去做增操作)。
如果采用长连接,一个TCP连接可以发送多个HTTP请求。
就是DNS步骤+浏览器渲染,具体可以看上面。
大致就是查浏览器->查本地->用ARP查同一个子网->查本地DNS服务器…获取到IP后,进行TCP连接,开始通信,之后浏览器渲染。
如果不是http协议,服务器会返回一个5开头的的重定向消息,告诉我们用的是https,那就是说IP没变,但是端口号从80变成443了,好了,再四次挥手,完事;再来一遍,这次除了上述的端口号从80变成443之外,还会采用SSL的加密技术来保证传输数据的安全性,保证数据传输过程中不被修改或者替换之类的,这次依然是三次握手,沟通好双方使用的认证算法,加密和检验算法,在此过程中也会检验对方的CA安全证书。
SSL代表安全套接字层。它是一种用于加密和验证应用程序(如浏览器)和Web服务器之间发送的数据的协议。 身份验证 , 加密Https的加密机制是一种共享密钥加密和公开密钥加密并用的混合加密机制。
SSL/TLS协议作用:认证用户和服务,加密数据,维护数据的完整性的应用层协议加密和解密需要两个不同的密钥,故被称为非对称加密;加密和解密都使用同一个密钥的
对称加密:优点在于加密、解密效率通常比较高 ,HTTPS 是基于非对称加密的, 公钥是公开的
(1)客户端向服务器端发起SSL连接请求;(2) 服务器把公钥发送给客户端,并且服务器端保存着唯一的私钥 (3)客户端用公钥对双方通信的对称秘钥进行加密,并发送给服务器端 (4)服务器利用自己唯一的私钥对客户端发来的对称秘钥进行解密, (5)进行数据传输,服务器和客户端双方用公有的相同的对称秘钥对数据进行加密解密,可以保证在数据收发过程中的安全,即是第三方获得数据包,也无法对其进行加密,解密和篡改。
因为数字签名、摘要是证书防伪非常关键的武器。 “摘要”就是对传输的内容,通过hash算法计算出一段固定长度的串。然后,通过发送方的私钥对这段摘要进行加密,加密后得到的结果就是“数字签名”
SSL/TLS协议的基本思路是采用公钥加密法,也就是说,客户端先向服务器端索要公钥,然后用公钥加密信息,服务器收到密文后,用自己的私钥解密。
补充:SSL/TLS的四次握手,目前网上的主流答案都在重复阮一峰老师的博客,属于TLS 1.0版本的答案,使用RSA密钥交换算法。但是现在TLS 1.2已经成为主流,使用ECDHE算法,如果面试可以说出这个版本的答案,应该会更好。
请求报文
响应报文
HTTP是无状态的,主要是为了让HTTP协议尽可能简单,使得它能够处理大量事务,HTTP/1.1引入Cookie来保存状态信息。
Cookie 是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器之后向同一服务器再次发起请求时被携带上,用于告知服务端两个请求是否来自同一浏览器。由于之后每次请求都会需要携带 Cookie 数据,因此会带来额外的性能开销(尤其是在移动环境下)。
cookie 的出现是因为 HTTP 是无状态的一种协议,换句话说,服务器记不住你,可能你每刷新一次网页,就要重新输入一次账号密码进行登录。这显然是让人无法接受的,cookie 的作用就好比服务器给你贴个标签,然后你每次向服务器再发请求时,服务器就能够 cookie 认出你。
抽象地概括一下:一个 cookie 可以认为是一个「变量」,形如 name=value,存储在浏览器;一个 session 可以理解为一种数据结构,多数情况是「映射」(键值对),存储在服务器上。
客户端登陆完成之后,服务器会创建对应的session,session创建完毕后,会把session的id发送给客户端,存储到浏览器。这也客户端每次访问服务器,都会带着sessionid,服务器拿到sessionid后,在内存找到与之对应的session这样就可以正常工作了。
Session是服务器保持状态的方法。
Session保存在服务器上。我们可以理解为每个用户有一个独一无二的Session,用户在客户端上记录用户的操作。 ID作为Session文件的Hash键,通过这个值可以锁定具体的Session结构的数据,这个Session结构中存储了用户操作行为。
Cookie是客户端保持状态的方法。Cookie简单的理解就是存储由服务器发至客户端并由客户端保存的一段字符串。为了保持会话,服务器可以在响应客户端请求时将Cookie字符串放在Set-Cookie下,客户机收到Cookie之后保存这段字符串,之后再请求时候带上Cookie就可以被识别。
当服务器需要识别客户端时就需要结合Cookie了。第一次创建Session的时候,服务端会在HTTP协议中告诉客户端,需要在Cookie里面记录一个Session ID,以后每次请求把这个会话ID发送给服务器,这样我就知道你是什么。
攻击者在HTTP请求中注入恶意的SQL代码,例如在最后加入1 = 1
,就会出现 select * from user where name = ‘lianggzone’ and password = ‘’ or ‘1’=‘1’
不管用户名和密码是什么内容,使查询出来的用户列表不为空。
防治措施:
Web端
1)有效性检验。 2)限制字符串输入的长度。
服务端
不用拼接SQL字符串。
使用预编译的PrepareStatement。
有效性检验。(为什么服务端还要做有效性检验?第一准则,外部都是不可信的,防止攻击者绕过Web端请求)
过滤SQL需要的参数中的特殊字符。比如单引号、双引号。
客户端向服务器发送请求连接数据报,服务端回复确认数据包,但客户端不向服务器发送确认数据包,服务器一直等待客户端的确认,耗费资源,使服务器崩溃。
预防:
MTU:最大传输单元,由硬件决定,如以太网的MTU为1500字节。
MSS:最大分节大小,为TCP数据包每次传输的最大数据分段大小,一般由发送端向对端TCP通知对端在每个分节中能发送的最大TCP数据。MSS值为MTU值减去IPv4 Header(20 Byte)和TCP header(20 Byte)得到。
max-age 指令出现在请求报文,并且缓存资源的缓存时间小于该指令指定的时间,那么就能接受该缓存。
max-age 指令出现在响应报文,表示缓存资源在缓存服务器中保存的时间。
Cache-Control: max-age=31536000
服务器第一次收到客户端的 SYN 之后,就会处于 SYN_RCVD 状态,此时双方还没有完全建立其连接,服务器会把此种状态下请求连接放在一个队列里,我们把这种队列称之为半连接队列。
当然还有一个全连接队列,就是已经完成三次握手,建立起连接的就会放在全连接队列中。如果队列满了就有可能会出现丢包现象。
只有第三次可以携带数据。
如果第一次握手可以携带数据,那么攻击者在第一次握手中的SYN报文放入大量数据,会让服务器花费很多时间、内存空间来接收这些报文。而对于第三次的话,此时客户端已经处于 ESTABLISHED 状态。对于客户端来说,他已经建立起连接了,并且也已经知道服务器的接收、发送能力是正常的了,所以能携带数据也没啥毛病。
服务器端的资源分配是在二次握手时分配的,而客户端的资源是在完成三次握手时分配的,所以服务器容易受到SYN洪泛攻击。SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server则回复确认包,并等待Client确认,由于源地址不存在,因此Server需要不断重发直至超时,这些伪造的SYN包将长时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络拥塞甚至系统瘫痪。SYN 攻击是一种典型的 DoS/DDoS 攻击。
如果一个服务器上有大量的半连接状态,那么就说明该服务器遭到了SYN攻击。
防御方法
TCP粘包:是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。
TCP拆包:假如发送方发送了2个TCP报文段,接收方也接收到了2个报文段,但是收到的第一个TCP报文段中粘上了发送方发送的第2个报文段的一部分,这其实就是对第2个TCP报文段的拆包,同样接收方应用程序也无法处理和区分
粘包和拆包问题的解决方法
2字节或4字节
的长度标识,接收方程序每次先读取该长度,然后再读取相应数目的数据'\n'
'\t'
等