这篇文章用来复习前端所接触到的网络协议的基本内容和常见网络安全的攻击手段,后续有更新的内容将会补充。
TCP
TCP是传输控制协议,它是用于端对端传输数据包的传输层协议,同属于传输层的协议还有UDP(用户数据报协议)。
TCP与UDP的区别?
TCP是面向链接,也就是TCP需要三次握手建立连接。而UDP没有建立连接的过程。
TCP有状态:记录哪些数据发送,哪些数据被接收,哪些数据没有被接收,保证数据包按序到达。
可控制:当网络不佳或丢包时,TCP会根据情况调整发送速度或重发。而UDP是无状态和不可控。
TCP是面向字节流,将IP包变为字节流。而UDP是基于数据报。
TCP的三次握手
TCP的三次握手就是要确认客户端和服务端双方都具有发送和接收的能力。
1. 客户端向服务端发送SYN(表示建立连接)报文。
2. 服务端收到,返回SYN和ACK(表示响应)报文。
3. 客户端再次发送ACK报文给服务端。
4. 数据传输
通俗一点讲三次握手像打电话一样,就是要两个人都知道对方是谁和对方能否听到自己说话的声音
1. 客户端向服务端打电话说:“你好,服务端,我是客户端,你能听见我说话吗?”
2. 服务端接到电话说:“你好,客户端,我能听到。你能听到我说话吗?”
3. 客户端:“我能听到。...”
4. 两个人具体通话
为什么不是两次握手?
因为两次握手无法确认客户端的接收能力。
为什么不是四次握手?
三次握手已经足够确认双发都有发送和接收的能力了,所以只要大于等于三次都可以。
三次握手可以携带数据吗?
第三次握手可以,前两次不可以。
TCP四次挥手
四次挥手断开连接
1. 客服端向服务端发送FIN(表示关闭连接)报文。
2. 服务端接收后返回ACK报文。
3. 服务点向客户端发送FIN报文。
4. 客户端收到后向服务端返回ACK报文。
为什么次四次挥手
因为服务端在收到FIN后并不会立即返回FIN,必须等到服务端所有的报文发送完毕才能返回FIN。
所以先发一个ACK表示收到了客户端的FIN,等待一段时间后再发送FIN。
为什么要等待2MSL
MSL(Maximum Segment Lifetime)报文最大生存时间。
因为在2个MSL后如果没有收到服务端的重发请求,表明ACK已经成功到达,挥手结束,否则客户端重新发送ACK
1个MSL确认四次挥手中ACK能够到达对端
1个MSL确认对端没有收到ACK重传的FIN可以到达
HTTP
HTTP是建立在TCP之间的协议,超文本传输协议,是一种允许浏览器向服务器获取资源的协议。
HTTP报文结构
起始行 + 头部 + 空行 + 实体
请求报文的起始行,由 方法 + 路径 + http版本 组成
GET /home HTTP/1.1
响应报文的起始行,也叫状态行,由 http版本 + 状态码 + 原因 组成
HTTP/1.1 200 OK
HTTP请求方法
GET:通常用来获取资源
HEAD:获取资源的元信息
POST:提交数据
PUT:修改数据
DELETE:删除资源
CONNECT:建立连接隧道,用于代理服务器
OPTIONS:列出可对资源实行的请求方法,用来跨区请求
TRACE:追踪请求-响应的传输路径
GET和POST的区别
GET的参数一般放在URL中,不是很安全,POST的参数放在请求体中。
GET请求会被浏览器缓存,而POST默认不会。
GET请求会把请求报文一次性发完,而POST会分为两个TCP数据包,先发header,当服务器响应100,再发body部分。
GET请求是URL编码的,只能接收ASCII字符,而POST没有限制。
HTTP状态码
1xx:表示目前是协议处理的中间状态,还需要后续操作。
2xx:表示成功状态。
3xx:重定向状态,资源位置发生变动,需要重新请求。
4xx:请求报文有误。
5xx:服务器端发生错误。
1xx
101 Switching Protocols:在HTTP升级为WebSocket的时候,如果服务器同意变更,就会发送状态码101。
2xx
200 OK:成功状态码。通常在响应体中放有数据。
204 NO Content:含义与200一致,但响应头后没有body数据。
206 Partial Content:表示部分内容,它的使用场景为HTTP分块下载和断点续传,当然也会带上相应的响应头字段Content-Range。
3xx
301 Moved Permanently:即永久重定向,对应着302 Found,即临时重定向。
304 Not Modified:当协商缓存命中时会返回这个状态码。
4xx
400 Bad Request:笼统地提示了一下错误,并不知道哪里出错了。
403 Forbidden:服务器禁止访问,原因有很多,比如法律禁止,信息敏感。
404 Not Found:资源未找到,表示在服务器上没有找到相应的资源。
405 Method Not Allowed:请求方法不被服务器端允许。
406 Not Acceptable:资源无法满足客户端的条件。
408 Request Timeout:服务器等待了太长时间。
409 Conflict:多个请求发生了冲突。
413 Request Entity Too Large:请求体的数据过大。
414 Request-URI Too Long:请求行里的 URI 太大。
429 Too Many Request:客户端发送的请求过多。
431 Request Header Fields Too Large:请求头的字段内容太大。
5xx
500 Internal Server Error:仅仅告诉你服务器出错了,出了啥错咱也不知道。
501 Not Implemented:表示客户端请求的功能还不支持。
502 Bad Gateway:服务器自身是正常的,但访问的时候出错了,啥错误咱也不知道。
503 Service Unavailable:表示服务器当前很忙,暂时无法响应服务。
HTTP1.0
HTTP/1.0支持多种类型下载,并引入了请求头和响应头,还提供了cache机制、用户代理、状态码。
HTTP/1.1加入了持久连接,还引入了Cookie。
队头阻塞:由于HTTP共用一个TCP管道,前面的请求没有结束,其他的请求只能处于阻塞状态。
HTTP/1.1对于对头阻塞采用
并发连接:允许一个域名分配多个长连接,在Chrome中是6个。
域名分片:对同一个域名分多个二级域名,这样并发的长连接就更多了。
HTTP2.0
对于对头阻塞,HTTP/2采用 一个域名只使用一个TCP长连接,也就是多路复用。
HTTP/2.0引入了二进制分帧层,实现HTTP的多路复用。
数据进入二进制分帧层后,转换为一个个带有ID的帧。服务器接收到帧后,将相同ID的帧合并为一条完整的请求信息。服务器响应原理同上。
HTTP/2.0同时还增加了
请求优先级:对于一些优先级高的请求标记优先级。
服务器推送:将请求的HTML所需要的js文件和css文件一并返回。
头部压缩:对请求头和响应头压缩
HTTP代理
HTTP在请求-响应的过程中,作为代理的服务器会起到一个中间人的作用,对客户端而言,表现为服务器进行响应;对于服务器而言,表现为客户端发起请求。
功能
1. 负载均衡。客户端的请求到达代理服务器,代理服务器可以根据算法分发给不同的源服务器,让各台源服务器的负载尽量平均。
2. 保障安全。将故障服务器提出服务器集群。并且对于上下行的数据进行过滤,对非法 IP 限流,这些都是代理服务器的工作。
3. 缓存代理。将内容缓存到代理服务器,客户端不必从源服务器请求数据。
相关字段
Via
用来表明代理服务器的身份。例如一段请求-响应:
客户端 -> 代理1 -> 代理2 -> 源服务器
源服务器在请求头中拿到这个字段:
Via: proxy_server1, proxy_server2
源服务器响应后,在客户端拿到的响应头中:
Via: proxy_server2, proxy_server1
X-Forwarded-For
它记录请求方的IP地址。每经过一个代理,它的名字就会改变。
X-Real-IP
获取用户真实IP字段,不管经过多少代理,它始终记录最初的客户端IP。
Cookie
HTTP是一个无状态的协议,每次请求都是独立的,但是想要保存状态,就引入了Cookie。Cookie是浏览器里面存储很小的一个文本文件,以键值对的方式存储。向同一个域名下发送请求,都会携带上相同的cookie,服务器拿到cookie进行解析,就能拿到客户端的状态。服务端可以通过响应头的Set-Cookie字段来对客户端写入Cookie。
session也是经常和cookie被一起问到的。
session是一种用来解决会话跟踪的机制,session是基于cookie实现的,服务器根据请求信息创建session,并将sessionID返回,下次请求时在cookie中携带sessionID。再根据 sessionID 查找对应的 session 信息,验证用户是否登录。
Cookie字段
作用域
domain:指定cookie所属域名
path:指定cookie在哪个路径下生效。 “/”表示域名下的任意路径都可以使用cookie
生存周期
max-age:cookie的失效时间,单位为秒。如果为负数,该cookie为临时cookie。如果为0,表示删除cookie。
expires:过期时间,指在具体的某个时间点后cookie失效。
(max-age和expires同时存在,max-age优先级更高)
安全
Secure:说明只能通过HTTPS传输cookie
HTTPOnly:说明只能通过HTTP传输cookie,不能通过JavaScript访问。预防XSS攻击重要手段。
SameSite:预防CSRF攻击。它有三个值,Strict、Lax和None。
Strict:浏览器完全禁止第三方亲求携带cookie。
Lax:只能在 get方法提交表单 和 a标签发送get请求 的情况下可以携带cookie。
None:默认模式,请求会自动携带上cookie。
Cookie的缺点
1. 容量小。cookie的体积只有4KB,只能存储少量信息。
2. 性能。 cookie会紧跟域名,当域名下的某个地址不需要这个cookie,请求也会携带cookie,造成性能浪费。
(可以通过Domain和path来解决)
3. 安全。cookie是以纯文本形式传递,容易被截取。
(可以通过HTTPOnly为false来禁止通过JavaScript脚本读取cookie)
HTTP缓存和代理缓存
HTTP缓存
关于HTTP的缓存具体写在 强缓存和协商缓存中。
通过Cache-Control来验证强缓存是否可用?
a. 可用,直接使用
b. 不可用,进入协商缓存,发送HTTP请求,服务器对请求的中
If-Modified-Since 或 If-None-Match 字段来检查资源是否需要更新?
a. 需要更新,返回资源和状态码200
b. 不需要更新,返回状态码304,告诉浏览器直接从缓存获取资源
代理缓存
如果每次客户端缓存失效都要去源服务器获取,对源服务器的压力很大,所以引入代理缓存机制,让一部分代理服务器缓存一部分资源,客户端资源过期后就近到代理服务器缓存中获取。
源服务器缓存控制字段
private 和 public
在源服务器的响应头中的Cache-Control字段中加入这个两个值来表示是否允许代理服务器缓存
private表示不允许;public表示允许
must-revalidata 和 proxy-revalidata
must-revalidata表示客户端资源过期就去源服务器获取
proxy-revalidata表示代理服务器资源过期就去源服务器获取
s-max-age
限定缓存在代理服务器中可以存放多久,单位为秒,与max-age并不冲突
客户端缓存控制字段
max-stale:n
表示客户端到代理服务器拿缓存的时候,只要过期时间不超过n秒,还是可以获取的
min-fresh: n
表示客户端到代理服务器拿缓存的时候,一定要在过期之前n秒内获取
only-if-cached
表示客户端只会接收代理缓存,不会接收源服务器的响应。如果代理缓存失效,返回504
跨域
浏览器遵循同源策略(协议、主机和端口相同 为同源)。非同源站点存在限制
- 不能读取修改对方DOM
- 不可访问Cookie、localStorage和indexDB
- 限制XMLHttpRequset请求
浏览器发起请求是在渲染进程中,但是为了防止黑客攻击系统资源,给渲染进程增加了沙箱机制,所以请求只能通过进程之间通信(IPC)发给网络进程,网络进程请求返回数据响应传递给主进程,主进程会检查跨域,且没有CORS响应头,如果没有匹配,响应就会被主进程拦截。
所以,跨域请求的响应可以成功到达客户端,但是会被浏览器拦截
跨域请求的解决方式
1. CORS
CORS(跨域资源共享)是W3C的标准。COSR是需要双方支持的,实现CORS的关键是服务器,在浏览器端CORS都是自动完成的,当浏览器发现ajax跨域请求资源,会自动添加一些头部信息,或者附加一次请求。
浏览器将请求分为简单请求和非简单请求
满足以下条件的为简单请求:
1. 请求方法为 GET/POST/PUT
2. 请求头范围:Accept、Accept-Language、Content-Language、
Content-Type(application/x-www-form-urlencoded、multipart/form-data、text/plain)
不满足简单请求条件的为非简单请求
简单请求
简单请求目的是为了兼容表单。 对于简单请求的跨域,浏览器在请求头中会携带Origin字段来表示请求的源,服务器验证这个源。
如果在允许范围内,服务器在返回的响应头中加上Access-Control-Allow-Origin等字段
如果Origin不在这个字段范围内,浏览器就会将响应拦截,否则放行
非简单请求
非简单请求的跨域,首先浏览器会发送预检请求OPTIONS,来询问服务器当前网页所在的域名是否在服务器的允许名单内。
预检请求加上
- Origin 表示请求来自哪个源
- Access-Control-Request-Method 表明用到的请求方法
- Access-Control-Request-Headers 表明自己要发送的头部信息
预检请求响应
当检查了预检请求的如上字段后,确认其允许跨域,会在响应中加入如下字段
- Access-Control-Allow-Origin 表示允许该源发送跨域请求,如果值为
*,表示允许任意源 - Access-Control-Allow-Methods 表明服务器支持的所有跨域请求的方法
- Access-Control-Allow-Headers 表明服务器支持的所有头信息字段
- Access-Control-Max-Age 用来指定本次预检请求的有效期,单位为秒
一旦服务器通过了预检请求,剩下的和简单请求一样。
2. JSONP
script标签的src向目标地址发送get请求,并且服务端触发响应函数,返回给客户端
3. Nginx
正向代理是代理帮助客户端访问到它访问不到的服务器
反向代理是代理帮其它的服务器拿到请求,然后选择一个合适的服务器,将请求转交给它。
Nginx反向代理实现跨域
客户端先访问设置为同域名的代理服务器
然后Nginx作为反向代理,将请求转给目标服务器,当响应时,将响应给客户端。
HTTPS
由于HTTP是明文传输,为了防止传输数据的环节中被中间人攻击,引入了HTTPS协议。
HTTPS是在HTTP和TCP之间加入了一个安全层,安全层的核心就是对数据的加解密。
对称加密
加密和解密都使用相同的密钥
1. 浏览器发送给服务器随机数client_random和加密方法列表。
2. 服务器选择一个加密方法,生成一个随机数server_random,并将其两个返回给浏览器。
3. 这样双方有具有了加密方法和两个随机数client_random和server_random,然后用加密方法将两个随机混合生成密钥,进行加密传输。
缺点:传输的随机数是明文的,可以被窃取。
非对称加密
两个密钥,A钥加密,只能B钥解密,B钥加密,只能A钥解密。
1. 浏览器发送加密方法列表给服务器。
2. 服务器选择一个加密方法,将加密方法和公钥一起返回给浏览器。
3. 浏览器用公钥对数据进行加密,服务器使用自己的私钥对加密数据进行解密。
缺点:效率低。无法包真正服务器发送给浏览器的数据是安全的。
传统RAS
使用对称加密和非对称加密组合。
1. 浏览器发送加密方法列表和随机数client_random给服务器。
2. 服务器选择加密方法,生成随机数server_random,并将加密方法、随机数和公钥返回给浏览器
3. 浏览器用两个随机数计算出pre_master,并用公钥匙对其加密发送给服务器。
4. 私钥解密数据拿到pre_master。
5. 这样双方都有了随机数和pre_master,用加密方法将这三者混合生成对称密钥,然后加密传输数据
缺点:如果服务器地址被恶意篡改为恶意服务器地址,那么恶意服务器也可以和浏览器进行这总加密方式传输数据。
数据证书:为了解决组合加密带来的缺点,让服务器证明自己,引入了数字证书。数字证书中有服务器的明文信息,数字证书签名,和公钥。
数字证书申请:服务器运用者向CA(数字证书颁发机构)申请数字证书,准备自己的信息,和一套公钥私钥,向CA提供公钥和信息,审核通过后向其颁发数字证书同时包含一个数字签名。
数字签名是CA用hash函数对提供的明文信息计算得到信息摘要,并用CA的私钥加密,密文就是数字签名。
数字证书认证:浏览器用CA认证时的hash函数对证书上的明文计算得到信息摘要A,然后再用CA的公钥解密得到信息摘要B,两者进行对比,如果一致则证明证书合法。
XSS
XSS 全称是 Cross Site Scripting(即跨站脚本),为了和 CSS 区分,故叫它XSS。XSS 攻击是指浏览器中执行恶意脚本(无论是跨域还是同域),从而拿到用户的信息并进行操作。
如果页面被注入了恶意脚本,它都能做哪些事情?
- 窃取
cookie信息 - 监听用户行为。如获取输入的银行卡等信息发送至黑客服务器
- 修改DOM伪造假的登录窗口
- 在页面内生成浮窗广告
通常情况下,实现 XSS 攻击的方式主要有三种
- 存储型
- 反射型
- 文档型
存储型
存储型 的XSS将脚本存在服务器,用户请求包含恶意脚本的页面,恶意脚本就会将用户的信息窃取上传的黑客服务器。
常见的场景是留言评论区提交一段脚本代码,如果前后端没有做好转义的工作,那评论内容存到了数据库,在页面渲染过程中直接执行, 相当于执行一段未知逻辑的 JS 代码,是非常恐怖的。这就是存储型的 XSS 攻击。
反射型
反射型 的XSS指的是恶意脚本作为网络请求的一部分。
比如一段URL:
http://sanyuan.com?q=<script>alert("你被攻击了")</script>
这样,在服务端就会拿到q参数,然后将内容返回给浏览器,浏览器将这戏内容作为HTML的一部分解析,发现这是个脚本,直接执行,这样就被攻击了。
在现实生活中,黑客经常通过QQ群或者邮件等渠道诱导用户去点击这些恶意链接,所以对一些链接我们一定要谨慎对待。
文档型
文档型的XSS攻击并不会经过服务器,而是作为中间人,在数据传输过程中劫持网络数据包,然后修改里面的HTML文档。
这种劫持类型很多,有通过WiFi路由器,有通过本地恶意软件。
防范措施
无论哪一种XSS攻击,它们的共同特点就是在浏览器中注入恶意脚本。 要防范XSS攻击,就要阻止这些脚本执行。
服务器对输入的脚本进行过滤或转码
我们可以在服务端对一些关键字符进行过滤
code:<script>alert('你被攻击了')</script>
经过过滤后
code:
除了过滤,还可以对这些内容进行转码
code:<script>alert('你被攻击了')</script>
经过转码之后。<script>标签被转为了<script>,因此即使这段脚本返回给页面,页面也不会执行这段脚本。
利用CSP
CSP,即浏览器中的内容安全策略,它的核心思想就是服务器决定浏览器加载哪些资源,具体来说可以完成以下功能:
- 限制加载其他域下的资源。
- 禁止向其他域提交数据
- 提供上报机制,能够帮助我们及时发现XSS攻击
利用HttpOnly
很多XSS攻击脚本都是用来窃取Cookie,而设置Cookie的HttpOnly属性后,JavaScript便无法读取Cookie的值,这样也可以有效防范XSS攻击。
总结
XSS攻击是浏览器中执行了恶意脚本,然后拿到用户信息进行恶意操作。
主要分为存储型、反射型和文档型
防范措施:
- 对输入内容进行过滤或转码
- 利用CSP
- 利用cookie的HttpOnly属性
CSRF
CSRF(Cross-site request forgery),即跨站请求伪造,指的是黑客诱导用户点击链接,打开黑客的网站,然后黑客利用用户目前登录的状态发起跨站请求。
当你点击了黑客的一个链接,打开了黑客的页面后,黑客有三种方式去实施CSRF攻击。
1.自动发起GET请求
黑客网页里可能有这样一段代码:
<img src="https://xxx.com/info?user=hhh&count=100"></img>
进入这个页面后自动发送get请求,值得注意的是,这个请求会自动带上关于xxx.com的cookie信息(假设你已经在xxx.com中登录过)。
假如服务端没有相应的验证机制,它可能认为这是一个正常的用户发起的请求,因为携带了相应的cookie,然后进行相应的各种操作,转账汇款等恶意操作。
2.自动发起POST请求
黑客可能自己填了一个表单,写了一段自动提交的脚本。
<form id='hacker-form' action="https://xxx.com/info" method="POST">
<input type="hidden" name="user" value="hhh" />
<input type="hidden" name="count" value="100" />
</form>
<script>document.getElementById('hacker-form').submit();</script>
同样也会携带相应的用户信息,让服务器误以为是一个正常的用户在操作。当用户打开改站点时,这个表单就会自动执行提交。当表单被提交后,服务器就会执行转账操作。
3.诱导用户点击链接
在黑客网站上,可能会放上一个链接,诱导你去点击。
<a href="https://xxx/info?user=hhh&count=100" taget="_blank">点击进入修仙世界</a>
点击后,自动发送 get 请求,接下来和自动发 GET 请求部分同理。
这就是CSRF攻击的原理。和XSS攻击不同的是,CSRF攻击并不需要将恶意脚本注入用户当前的html文档中,而是跳转到新的页面,利用服务器的验证漏洞和用户当前登录状态来模拟用户操作。
防范措施
1.利用Cookie的SameSite属性
CSRF攻击的最重要一环就是自动发送目标站点的Cookie,然后利用这一份Cookie 模拟用户的身份。
而在Cookie的字段中有这么一个关键字段,可以对请求中的Cookie的携带做一些限制,这个字段就是SameSite。
SameSite可以设置三个值,Strict、Lax和None。
a. 在Strict模式下,浏览器完全禁止第三方请求携带的Cookie。比如xxx.com网站只能在xxx.com域名当中请求才能携带Cookie,在其他网站都不行。
b. 在Lax模式下,就宽松一点,但是只能在get方法提交表单或者a标签发送get请求的情况下可以携带Cookie,其他情况均不能。
c. 在None模式下,也就是默认模式,请求会自动携带上Cookie。
2.验证来源站点
这就需要用到请求头中的两个字段Referer和Origin。
其中,Origin只包含域名信息,而Referer包含了具体的URL路径。
当然,这两者都是可以伪造的,通过 Ajax 中自定义请求头即可,安全性略差。
3.CSRF Token
浏览器向服务器发送请求时,服务器会生成一个字段,将其植入到返回的页面中。
然后浏览器如果要发送请求,就必须带上这个字符串,然后服务器验证是否合法,如果不合法则不予相应,这个字符串就是CSRF token,通常第三方站点无法拿到这个token,因此也就会被服务器拒绝。
总结
CSRF,跨站请求伪造,指的是黑客诱导用户点击链接,打开黑客的网站,然后黑客利用用户目前登录的状态发起跨站请求。
CSRF攻击一般会有三种形式:
- 自动发送get请求
- 自动发送post请求
- 诱导点击发送get请求
防范措施:
- 利用Cookie的
SameSite属性 - 验证来源站点
- CSRF token