不断的学习,我们才能不断的前进
一个好的程序员是那种过单行线马路都要往两边看的人

计算机网络

OSI七层协议与TCP5层协议?

OSI七层协议从上到下是:应用层、表示层、会话层、运输层、网络层、链路层、物理层。
TCP五层协议从上到下是:应用层、运输层、网络层、链路层、物理层。( 没有表示层和会话层)。

  • 应用层:应用层是 OSI 标准模型的最顶层,是直接为应用进程提供服务的。其作用是在实现多个系统应用进程相互通信的同时,完成一系列业务处理所需的服务。包括文件传输FTP、电子邮件SMTP、远程登录Telnet和远端接口调用等协议。
  • 表示层: 表示层向上对应用进程服务,向下接收会话层提供的服务,表示层的主要作用就是将设备的固有数据格式转换为网络标准传输格式。
  • 会话层:会话层位于 OSI 标准模型的第五层,它是建立在传输层之上,利用传输层提供的服务建立和维持会话。
  • 传输层:传输层位于 OSI 标准模型的第四层,传输层涉及到两个节点之间的数据传输,向上层提供可靠的数据传输服务。传输层的协议有TCP、UDP协议。
  • 网络层:网络层位于 OSI 标准模型的第三层,它位于传输层和数据链路层的中间,将数据报的网络层分组从一台主机移动到另一台主机,从而向运输层提供最基本的端到端的数据传送服务。网络层的协议有IP协议。
  • 数据链路层:数据链路层位于物理层和网络层中间,数据链路层定义了在单个链路上如何传输数据。
  • 物理层:物理层是 OSI 标准模型中最低的一层,物理层是整个 OSI 协议的基础,物理层为设备之间的数据通信提供传输媒体及互连设备,为数据传输提供可靠的环境。

DNS 是应用层的协议,使用的是UDP协议

各种协议概述

IP协议
IP 位于网络层。IP是整个 TCP/IP 协议族的核心,也是构成互联网的基础。IP 能够为运输层提供数据分发,同时也能够组装数据供运输层使用。它将多个单个网络连接成为一个互联网,这样能够提高网络的可扩展性,实现大规模的网络互联。二是分割顶层网络和底层网络之间的耦合关系。
ICMP
ICMP 协议主要用于在 IP 主机、路由器之间传递控制消息。ICMP 属于网络层的协议,当遇到 IP 无法访问目标、IP 路由器无法按照当前传输速率转发数据包时,会自动发送 ICMP 消息
ARP
ARP 协议是 地址解析协议,它能够根据 IP 地址获取物理地址(MAC 地址)。主机发送信息时会将包含目标 IP 的 ARP 请求广播到局域网络上的所有主机,并接受返回消息,以此来确定物理地址。收到消息后的物理地址和 IP 地址会在 ARP 中缓存一段时间,下次查询的时候直接从 ARP 中查询即可
TCP
TCP 就是 传输控制协议,它是一种面向连接的、可靠的、基于字节流的传输协议,TCP 协议位于传输层,TCP 协议是 TCP/IP 协议簇中的核心协议,它最大的特点就是提供可靠的数据交付。
TCP 的主要特点有:3次握手、4次挥手、超时重传、快速重传、流量控制、慢启动、拥塞控制、快恢复。

TCP的每一端 都有接收缓冲区、发送缓冲区、滑动窗口(也叫接收窗口,用于保留接收方,最大可接收的数据大小)、拥塞窗口(在网络中发送一次数据报的最大可用大小)

UDP
UDP 协议就是 用户数据报协议,UDP 也是一种传输层的协议,与 TCP 相比,UDP 提供一种不可靠的数据交付,也就是说,UDP 协议不保证数据是否到达目标节点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。UDP 是一种无连接的协议,传输数据之前源端和终端无需建立连接,不对数据报进行检查与修改,无须等待对方的应答,会出现分组丢失、重复、乱序等现象。但是 UDP 具有较好的实时性,工作效率较 TCP 协议高
HTTP
HTTP是超文本传输协议,,基于请求与响应模式的,无状态的,应用层的协议,常基于TCP的连接方式。超文本指的是HTML,css,JavaScript和图片等,HTTP的出现是为了接收和发布HTML页面,经过不断的发展也可以用于接收一些音频,视频,文件等内容。

FTP
FTP 协议是 文件传输协议,应用层协议之一,是 TCP/IP 协议的重要组成之一,FTP 协议分为服务器和客户端两部分,FTP 服务器用来存储文件,FTP 客户端用来访问 FTP 服务器上的文件,FTP 的传输效率比较高,所以一般使用 FTP 来传输大文件。
DNS
DNS 协议是 域名系统协议,它也是应用层的协议之一,DNS 协议是一个将域名和 IP 相互映射的分布式数据库系统。DNS 缓存能够加快网络资源的访问。
SMTP
SMTP 协议是 简单邮件传输协议,应用层协议之一,SMTP 主要是用作邮件收发协议,SMTP 服务器是遵循 SMTP 协议的发送邮件服务器,用来发送或中转用户发出的电子邮件。

Http传输协议?HTTPS?

HTTP

HTTP是超文本传输协议,全英文名是HyperText Transfer Protocol,基于请求与响应模式的,无状态的,应用层的协议,常基于TCP的连接方式。超文本指的是HTML,css,JavaScript和图片等,HTTP的出现是为了接收和发布HTML页面,经过不断的发展也可以用于接收一些音频,视频,文件等内容。
HTTP协议是用于客户端和服务器端之间的通信,请求访问文本或图片等资源的一方,我们叫做客户端;负责接收,提供响应的一方称为服务器端。

HTTP是不会保留任何客户端的信息,所以HTTP是无状态协议,也就是浏览器对于事务的处理没有记忆能力。通过引入Cookile来保存之前的状态信息。Cookie会根据从服务端发送的响应报文的一个叫Set-Cookie的首部字段,通知客户端保存Cookie,当下次客户端再往该服务端发送请求时,客户端会自动在请求报文中加入Cookie值发送出去。
HTTP报文格式

  • 请求报文:
    • 第一行是:请求方法、请求资源目录、采用的协议
    • 第二行:请求的主机名
    • 第三行:Connection 表示是否使用持续连接,close表示不使用持续连接
    • 第四行:客户端浏览器的类型 User-Agent
    • 如果有的话,带上cookie信息
    • 第五行:得到该对象的法语版本
    • 第六行:请求体,当请求方法为GET时为空;当为POST时,为提交的表单内容。
  • 响应报文
    • 第一行:采用的协议、 状态码、
    • 第二行:是否使用持续连接
    • 第三行:请求时间
    • 第四行:服务器类型
    • 第五行:上一次修改的时间
    • 第六行:响应的实体对象类型
    • 第七行:响应的实体对象
// 请求报文
GET /some/index.html HTTP/1.1
Host: www.baidu.com
Connection: close
User-agent: Mozilla/5.0
Accep-language: fr

// 响应报文
HTTP/1.1  200 ok 
Connection: close
Date: 时间
Server:centos
Last-Modified:上一次修改的时间
Content-Length:6821
Content-Type:text/html
data

非持续连接和持续连接
非持续连接:一个请求/响应,就是一个单独的TCP连接。
持续连接:所有的请求/响应,都是相同的TCP连接。

GET与POST的不同

  • GET在浏览器回退时是无害的,而POST会再次提交请求
  • GET请求会被浏览器主动cache,而POST不会,除非手动设置。
  • GET请求在URL中传送的参数是有长度限制的,而POST没有。
  • GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
    本质上GET和POST都是HTTP传输,底层都是TCP/IP链接,并没有差异,但是GET会产生一个TCP数据包;POST产生两个TCP数据包。
    对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);
    而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。

并不是所有浏览器都会在POST中发送两次包,Firefox就只发送一次。

WEB缓存/代理服务器
WEB缓存也叫代理服务器,能够代表服务器来满足客户端的HTTP请求,代理服务器有自己的磁盘存储空间,并保存最近的客户端请求的副本
代理服务器即是客户端也是服务器,当它接收客户端的请求,并做出响应时,它是服务器的角色;当它向初始服务器发出请求,并接收响应时,它是客户端的角色。
代理服务器,起缓存的作用,可以减少客户端请求的响应时间。那缓存过期了怎么办
使用条件GET方法,向初始服务器发送一个GET请求,请求中报文带上“If-Modified-Since”首部行,用于检查缓存是否在指定日期后被修改过,如果被修改过,则返回新的数据;否则返回空的数据

Http的缺点

  • 数据采用明文进行通信,内容可能被窃听
  • 通信双方的身份无法得到认证,身份可能遭遇伪装。
  • 无法验证报文的完整性。

HTTPS 分别通过加密、三方认证、MD5散列认证来进行内容检验 来解决上面的缺点

HTTPS

Https全称是Hypertext Transfer Protocol Secure,在HTTP的基础上对数据进行加密(SSL)。HTTP 是未经安全加密的协议,它的传输过程容易被攻击者监听、数据容易被窃取、发送方和接收方容易被伪造;而 HTTPS 是安全的协议,它通过 密钥交换算法 - 签名算法 - 对称加密算法 - 摘要算法 能够解决上面这些问题
基本流程如下:

  1. 浏览器向服务器发起HTTPS请求;
  2. HTTPS需要使用一套CA数字证书,证书内会附带一个公钥Pub,而与之对应的私钥Private保留在服务端不公开
  3. 服务端收到请求,返回配置好的包含公钥Pub的证书给客户端;
  4. 客户端收到证书,校验合法性,主要包括是否在有效期内、证书的域名与请求的域名是否匹配,上一级证书是否有效,如果不通过,则显示HTTPS警告信息,如果通过则继续;
  5. 客户端生成一个用于对称加密的随机Key,并用证书内的公钥Pub进行加密,发送给服务端;
  6. 服务端收到随机Key的密文,使用与公钥Pub配对的私钥Private进行解密,得到客户端真正想发送的随机Key;
  7. 服务端使用客户端发送过来的随机Key对要传输的HTTP数据进行对称加密,将密文返回客户端;
  8. 客户端使用随机Key对称解密密文,得到HTTP数据明文;
  9. 后续HTTPS请求使用之前交换好的随机Key进行对称加解密

https

非对称加解密耗时要远大于对称加解密
引入CA机构是为了保证了HTTPS证书的公信力,即为了保证公钥传输中不被篡改,也使用来数字签名。

对称加密、非对称加密
对称密钥加密,又称私钥加密,即信息的发送方和接收方用同一个密钥去加密和解密数据。优点:是加/解密速度快,适合于对大数据量进行加密,但密钥管理困难且较为不安全。
非对称密钥加密,又称公钥加密,它需要使用一对密钥来分别完成加密和解密操作,一个公开发布,即公开密钥,另一个由用户自己秘密保存,即私用密钥。信息发送者用公开密钥去加密,而信息接收者则用私用密钥去解密。非对称加密比对称加密功能强大且较为安全但加密和解密速度却比对称密钥加密慢得多
数字签名
数字签名有以下功能:

  • 报文鉴别。即接受者能够核实发送者对报文的签名
  • 报文的完整性。即接受者确信所收到的数据和发送者发送的完全一样而没有被篡改过
  • 不可否认。发送者事后不能抵赖对报文的签名。

TLS协议

TLS/SSL 是一个安全的通信协议框架,上面可以承载HTTP协议或者SMTP/POP3协议等。
TLS主要分为两层,底层的是TLS记录协议,主要负责使用对称密码对消息进行加密; 上层的是TLS握手协议,主要分为握手协议,密码规格变更协议和应用数据协议4个部分。

TLS握手协议

  • 握手协议负责在客户端和服务器端商定密码算法和共享密钥,包括证书认证,是4个协议中最最复杂的部分。
  • 密码规格变更协议负责向通信对象传达变更密码方式的信号
  • 警告协议负责在发生错误的时候将错误传达给对方
  • 应用数据协议负责将TLS承载的应用数据传达给通信对象的协议。

握手协议
握手协议是TLS协议中非常重要的协议,通过客户端和服务器端的交互,和共享一些必要信息,从而生成共享密钥和交互证书。

Http1.0 、Http1.1、Http2.0、Http 3.0的区别

Http1.1 和 Http1.0 的区别

1. 缓存策略
Http1.0 的缓存策略主要依赖头部的If-Modiified-Since,Expire
Http1.1 的缓存策略比1.0 要多,Entity tag(实体标签), If-Unmodified-Since, If-Match, If-None-Match等.
2. 宽带和网络连接优化
http1.0中会存在一些性能浪费,比如我们的只需要对象中的一部分,但是每次请求返回的却是整个对象,这无疑造成了性能的损害。
http1.1则不然,它可以通过在请求头处设置range头域,就可以返回请求资源的某一部分,也就是返回码为206(Partial Content)的时候,这对于性能优化很有必要。

比如断点续传, 设置range字段,来规定分割的byte数范围,服务端会给客户端返回一个包含着content-range的响应头,来对应相应的分割byte数范围。

3. Host头处理:
http1.0中默认每台服务器都绑定唯一的一个IP地址,所以请求消息中url并没有传递主机名,也就是hostname.

http1.1中请求消息和响应消息都支持Host头域,而且,如果我们不传这个字段还会报一个400(bad request)的状态码

4. 长连接
http1.1支持长连接和请求的流水线(pipelining),在一个TCP链接上可以传送多个http请求和响应.这样就不用多次建立和关闭TCP连接了

Http2.0 和 Http1.x 的区别

1. 解析协议不同
http1.x 的解析是基于文本协议的各式解析,
http2.0的协议解析是二进制格式,
2. 支持多路复用(Mutiplexing)
一个连接上可以有多个request,且可以随机的混在一起,每个不同的request都有对应的id,服务端可以通过request_id来辨别,大大加快了传输速率header压缩。
3. 头部压缩
http1.x中的header需要携带大量信息,而且每次都要重复发送。
http2.0使用encode来减少传输的header大小,而且客户端和服务端可以各自缓存(cache)一份header filed表,避免了header的重复传输,还可以减少传输的大小.
4. 服务器依赖解析
服务端推送(server push): 可以通过解析html中的依赖,只能的返回所需的其他文件(css或者js等),而不用再发起一次请求.

Http3.0 和2.0的区别?

Http 2.0的不足

  • 如果使用Https的话,在Http2.0里面有两次三次握手,一次是TLS/SSL协议的三次握手,一次是TCP的三次握手,等待的延迟时间比较长
  • 因为Http2.0支持I/O多路复用,就是一个管道里面有多个请求,但是如果出现丢包,就会出发超时重传,整个TCP都要开始等待重传,就会阻塞整个TCP中的请求,也就是队头阻塞问题。

Http 3.0的改变

  • Http 3.0 放弃了TCP协议,而使用了一个基于 UDP 协议的“QUIC”协议,因为UDP是无连接的,所以不需要握手和挥手;
  • 另外也基于UDP实现了可靠的传输,保证了数据不会丢失,TCP的可靠性传输是在内核态完成的,而QUIC 是在用户态,应用层实现的;
  • 也集成了TLS加密功能;
  • 并且基于UDP的流传输,一个连接上可以有多个流,每个流之间互不影响,也就避免了Http2.0的队头阻塞的问题。

QUIC

QUIC 连接分为首次连接和非首次连接, 可以不进行三次握手,在第一次连接就发送数据。

首次连接
首次连接时客户端和服务端需要进行密钥协商和数据传输过程:

  • 客户端对于首次连接的服务端先发送连接请求
  • 服务器会生成一对私钥和公钥,公钥发送给客户端
  • 客户端随机生成一个key作为自己的私钥,然后用服务器返回的公钥进行加密,并把加密后的密钥发送给服务器
  • 服务器用自己的私钥进行解密,获取加密数据的密钥
  • 为了保证数据安全,上述生成的密钥K只会生成使用1次,后续服务端会按照相同的规则生成一套全新的公钥和私钥,并使用这组公私钥生成新的密钥M。
  • 服务端将新公钥和新密钥M加密的数据发给客户端,客户端根据新的服务端公钥和自己原来的私钥计算出本次的密钥M,进行解密。

非首次连接
客户端会将服务器返回的配置存储下来,后续再连接时可以直接使用,从而跳过密钥协商阶段。

TCP?

TCP(传输控制协议)是一个面向连接的、可靠的、基于字节流的传输层协议。TCP是全双工服务。面向连接是因为一个进程向另一个进程发送数据之前,必须先进行握手。Tcp通过超时重传、快速重传、流量控制、慢启动、拥塞控制、快恢复来实现可靠性。

TCP的每一端 都有接收缓冲区、发送缓冲区、滑动窗口(也叫接收窗口,用于保留接收方,最大可接收的数据大小)拥塞窗口(在网络中发送一次数据报的最大可用大小)

TCP的头部有20字节固定大小的信息:源端口号、目的端口号、seq序列号、ack应答信号、滑动窗口、标志位(FIN、SYN、RST、ACK...)、检验和

TCP的三次握手

过程:

  • 最开始客户端和服务器都处于CLOSED 状态,然后服务端先主动监听某个端口,此时服务器端就变成了 LISTEN(监听)状态;
  • 然后客户端主动发起连接,发送 SYN(同步序列编号),此时客户端就变成了 SYN-SENT 状态;
  • 服务端接收到信息之后返回 SYN 和 ACK 至客户端,此时服务器端就变成了 SYN-REVD 状态;
  • 客户端接收到消息之后,再发送 ACK 至服务器端,此时客户端就变成了 ESTABLISHED(已确认)状态,服务端收到 ACK 之后,也变成了 ESTABLISHED 状态,此时连接工作就执行完了。
    tcp3

TCP的标志位SYN 表示建立连接,FIN表示释放连接
在前两次握手,连接不包含任何数据报文信息,只有在第三次握手,才开始带上报文信息。

backlog参数的意义?
backlog是一个建议值,用于指定内部的队列大小,以控制同时建立的两种状态的连接请求数量之和。

全连接队列、半连接队列
在 TCP 三次握手的时候,Linux 内核会维护两个队列,分别是:

  • 半连接队列,也称 SYN 队列;
  • 全连接队列,也称 accepet 队列;
    服务端收到客户端发起的 SYN 请求后,内核会把该连接存储到半连接队列,并向客户端响应 SYN+ACK,接着客户端会返回 ACK,服务端收到第三次握手的 ACK 后,内核会把连接从半连接队列移除,然后创建新的完全的连接,并将其添加到 accept 队列,等待进程调用 accept 函数时把连接取出来。

主要的目的是为了防止被攻击,即大量的连接都是半连接状态,如果分配资源则会导致服务器资源被占满,所以使用半连接队列。

如何应对 SYN Flood 攻击?
SYN Flood 攻击属于典型的 DoS/DDoS 攻击。其攻击的原理很简单,就是用客户端在短时间内伪造大量不存在的 IP地址,并向服务端疯狂发送SYN连接请求,服务器端会造成两个严重的后果:

  • 处理大量的SYN包并返回对应ACK, 势必有大量连接处于SYN_RCVD状态,从而占满整个半连接队列,无法处理正常的请求
  • 由于是不存在的 IP,服务端长时间收不到客户端的ACK,会导致服务端不断重发数据,直到耗尽服务端的资源

解决方案

  • 增加 SYN 连接,也就是增加半连接队列的容量。
  • 减少 SYN + ACK 重试次数,避免大量的超时重发。
  • 利用 SYN Cookie技术,在服务端接收到SYN后不立即分配连接资源,而是根据这个SYN计算出一个Cookie,连同第二次握手回复给客户端,在客户端回复ACK的时候带上这个Cookie值,服务端验证Cookie 合法之后才分配连接资源。

为什么要三次握手?

  1. 防止重复的连接
    三次握手的主要原因是为了防止旧的重复连接引起连接混乱问题。如果 TCP 握手的次数只有两次,那么接收方只能选择接受请求或者拒绝接受请求,但它并不清楚这次的请求是正常的请求,还是由于网络环境问题而导致的过期请求,如果是过期请求的话就会造成错误的连接。
    所以如果 TCP 是三次握手的话,那么客户端在接收到服务器端 SEQ+1 的消息之后,就可以判断当前的连接是否为历史连接。
  2. 同步初始化序列化
    首先客户端发送一个携带了初始序列号的 SYN 报文给服务器端;服务端接收到消息之后会回复一个 ACK 的应答报文,表示客户端的 SYN 报文已被服务端成功接收了;而客户端收到消息之后也会发送一个 ACK 给服务端,服务器端拿到这个消息之后,我们就可以得到一个可靠的初始化序列号了。
    而如果是两次握手的话,就无法进行序列号的确认工作了,因此也就无法得到一个可靠的序列号了,所以 TCP 连接至少需要三次握手。

TCP的四次挥手

基本过程:

  1. 客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。
  2. 服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
  3. 客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
  4. 服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
  5. 客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
  6. 服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。
    tcp4_1

为什么是四次挥手?
因为在建立连接时当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。
但是在关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,只有等Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

为什么等待时间是2MSL?
虽然在四个报文都发送完毕后我们可以直接进入CLOSE状态了,但是网络是不可靠的,有可能最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文
在Client发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。
所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。

如果服务端在二次挥手、三次挥手之间发的数据包,因为网络阻塞导致比第三次挥手的Fin包后到客服端,那么主动关闭的一方就会先收到Fin包,然后在收到延迟的数据包,这个时候怎么处理?
客户端接收到Fin包后,发现seq序列号不连续(因为有延迟的数据包后到达),就会把乱序的Fin报文加入到乱序队列里面,不会进入到time_wait状态。等接收到延迟的数据包之后,会判断乱序队列里面有没有数据,如果发现乱序队列里面有与当前报文序列号保持一致的报文,并且是Fin报文,则才会进入到time_wait 状态。

尽管维护了TIME-WAIT,但是双方也不一定能正确关闭连接
question1:若被动关闭连接的一方没有收到对方的最后一条ACK,而重发FIN+ACK,而FIN+ACK也丢失了,并且在TIME_WAIT等待时间内,一直丢包,导致等待时间过后一方关闭连接,而被动关闭的一方因始终没有收到最后一个ACK而无法关闭连接

question2:两台主机建立连接成功后,一方因故障断网/断电,而另一方并不知情会一直白白等下去,显然这并不合理。

当发生以上两种情况时,就会用到保活计时器。服务器每收到一次客户的数据,就会重新设置保活计时器,若直到计时器时间内没有收到客户端的数据,服务器就发送一个探测报文段,以后每隔一段时间发送一次,如连续发送n个探测报文让没有收到客户的响应,服务器就认为客户端出现了故障,会主动关闭该连接

进程退出时,进程所拥有的文件描述符(包含socket)都会被释放,文件会被关闭,也就是会执行close,对于TCP连接来说就是进程会主动关闭连接。机器关机相同(OS会先关闭所有服务再关机)。

TIME_WAIT状态造成的危害
question3: 在高并发短连接的TCP服务器上,当服务器处理完请求后主动请求关闭连接,这样服务器上会有大量的连接处于TIME_WAIT状态,服务器维护每一个连接需要一个socket,也就是每个连接会占用一个文件描述符,而文件描述符的使用是有上限的,如果持续高并发,会导致一些连接失败。

question4: 假设高并发的情况,比如双十一,因为一些原因,服务器进程挂掉了,退出了,由于是服务器主动关闭连接,因此会有TIME_WAIT状态存在,也就意味着服务器进程想立即重启,但是起不来,因为端口(可能是80)还被之前处于TIME_WAIT的连接占用着,如果TIME_WAIT状态维持60秒,这60秒服务器都起不来,在双十一高并发情况下,是很影响用户体验的。

解决方案:可设置套接字选项为SO_REUSEADDR,该选项的意思是,告诉操作系统,如果端口忙,但占用该端口TCP连接处于TIME_WAIT状态,并且套接字选项为SO_REUSEADDR,则该端口可被重用。如果TCP连接处于其他状态,依然返回端口被占用。该选项对服务程序重启非常有用。

TCP的滑动窗口/拥塞窗口?

滑动窗口是为了避免,TCP发送端和接收端速率不一致导致丢包的问题。滑动窗口也成为接收窗口,为接收方缓冲区里面可用的数据大小(rwnd=接收方缓冲区大小-缓存中TCP数据包的大小),主要目的是控制发送方已经发送出去的数据包但还没收到确认回复的数据包小于滑动窗口的大小
拥塞窗口是因为网络的拥塞而导致的丢包,比如路由器的缓冲区满了,就会丢包。拥塞窗口的大小是动态变化的,当发送拥塞时(丢包时),窗口大小进行乘法减小;当没有发送拥塞时,窗口大小成加法增加。

每次发送的数据包都要小于 滑动窗口和拥塞窗口的最小值

超时重传、快重传?

超时重传是指对于每一个TCP发送的报文,都设置一个定时器,定时器的时间为超时时间,一般比 发送一个报文到接收到回复的时间大一点点。如果超时还没收到回复,则立即进行重传报文,并设置超时时间为之前的两倍。
超时重传每次设置的超时时间为之前的两倍,可能会等待大量的时间,所以进行快重传,如果客户端连续收到三次重复的ACK应答,则立即重传对应的丢失的报文。

TCP的拥塞控制?

双方在通信的时候,发送方的速率与接收方的速率是不一定相等,如果发送方的发送速率太快,会导致接收方处理不过来,这时候接收方只能把处理不过来的数据存在缓存区里,如果缓存区满了发送方还在疯狂着发送数据,接收方只能把收到的数据包丢掉,大量的丢包会极大着浪费网络资源,因此需要拥塞控制。
采用的是慢开始、拥塞避免、快恢复:
最开始是慢开始从1开始指数增长,当达到阈值后,进行拥塞避免,也就是变成线性增加,然后达到最大值后,如果是块重传拥塞窗口变成最大值的一半,然后进行快恢复,从最大值的一半开始进行线性增长。 如果是超时重传,则从1开始指数增长,达到阈值再进行快恢复。

如何查看TCP连接成功

  • 通过TCP KeepAlive字段进行判断
  • TCP_INFO 套接字查看TCP连接状态
  • netstat -t 查看连接情况

TCP 报文

TCP 首部长度20字节
tcpbao-wen

UDP?

UDP 协议就是 用户数据报协议,UDP 也是一种传输层的协议,与 TCP 相比,UDP 提供一种不可靠的数据交付,也就是说,UDP 协议不保证数据是否到达目标节点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。UDP 是一种无连接的协议,传输数据之前源端和终端无需建立连接,不对数据报进行检查与修改,无须等待对方的应答,会出现分组丢失、重复、乱序等现象。但是 UDP 具有较好的实时性,工作效率较 TCP 协议高。

UDP 报文

UDP相比较于TCP,比TCP的报文首部少了12字节。(TCP20字节,UDP8字节),包括:源端口号、目的端口号、检验和、UDP的长度。

UDP 最大可传输的报文长度=1500-8-20=1472字节,当传入报文长度大于1472字节时,就会对报文进行分片。

PS : 链路层的最大传输单元MTU是 1500 字节,可以通过netstat -i查看。

UDP、TCP的区别

  • TCP是面向字节流的,即把应用层传来的报文看成字节流,将字节流拆分成大小不等的数据块,并添加TCP首部;UDP是面向报文的,对应用层传下来的报文不拆分也不合并,仅添加UDP首部
  • TCP是面向有连接型,UDP是面向无连接型;
  • TCP是一对一传输,UDP支持一对一、一对多、多对一、多对多。
  • TCP支持传输可靠性的多种措施,包括保证包的传输顺序、重发机制、流量控制和拥塞控制;UDP仅提供最基本的数据传输能力。
  • TCP首部20字节,UDP只有8字节。
  • TCP不会出现丢包,UDP会出现丢包的情况。
  • TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道

UDP如何实现TCP
实现TCP保证可靠性的连接即可,即三次握手、四次挥手、序列号、确认好、流量控制、拥塞避免、快重传、超时重传、添加发送缓冲区和接收缓冲区。

IP协议

IP报文格式

版本:IP协议的版本,目前的IP协议版本号为4,下一代IP协议版本号为6。

首部长度:IP报头的长度。固定部分的长度(20字节)和可变部分的长度之和。共占4位。最大为1111,即10进制的15,代表IP报头的最大长度可以为15个32bits(4字节),也就是最长可为15* 4=60字节,除去固定部分的长度20字节,可变部分的长度最大为40字节。

总长度:IP报文的总长度。报头的长度和数据部分的长度之和。

标识:唯一的标识主机发送的每一分数据报。通常每发送一个报文,它的值加一。当IP报文长度超过传输网络的MTU(最大传输单元)时必须分片,这个标识字段的值被复制到所有数据分片的标识字段中,使得这些分片在达到最终目的地时可以依照标识字段的内容重新组成原先的数据。

标志:共3位。R、DF、MF三位。目前只有后两位有效,DF位:为1表示不分片,为0表示分片。MF:为1表示“更多的片”,为0表示这是最后一片。

片位移:本分片在原先数据报文中相对首位的偏移位。(需要再乘以8)

生存时间:IP报文所允许通过的路由器的最大数量。每经过一个路由器,TTL减1,当为0时,路由器将该数据报丢弃。TTL 字段是由发送端初始设置一个 8 bit字段.推荐的初始值由分配数字 RFC 指定,当前值为 64。发送 ICMP 回显应答时经常把 TTL 设为最大值 255。

协议:指出IP报文携带的数据使用的是那种协议,以便目的主机的IP层能知道要将数据报上交到哪个进程(不同的协议有专门不同的进程处理)。和端口号类似,此处采用协议号,TCP的协议号为6UDP的协议号为17。ICMP的协议号为1,IGMP的协议号为2.

首部校验和:计算IP头部的校验和,检查IP报头的完整性。

源IP地址:标识IP数据报的源端设备。

目的IP地址:标识IP数据报的目的地址。
ipxie-yi

DNS 协议?

DNS是域名解析协议,即将域名解析成对应的IP地址,是应用层的协议。DNS是采用的分层系统,最顶层是根DNS服务器,第二层是顶级域DNS服务器、第三层是权威DNS服务器;除此之外还有本地DNS服务器。
DNS查询使用的是递归加迭代的方式:

  • 递归:是指请求的接收者不知道所请求的内容,然后自己扮演请求者向其他接收者发送请求,直到获得答案。
  • 迭代:是指请求的接收者,直到请求的内容,直接返回给请求者。

DNS缓存是指,当某个DNS服务器接收到一个DNS回答时,能够将映射缓存在本地存储器中。一般有浏览器缓存和操作系统缓存,浏览器缓存存放在浏览器里面,有过期时间;操作系统缓存存放在hosts文件里面。
域名解析的过程:

  1. 首先搜索浏览器的 DNS 缓存,有结果就直接返回;
  2. 搜索操作系统的 DNS 缓存,有结果就返回;
  3. 没有命中,则访问本地DNS服务器,本地DNS服务器查询自己的 DNS 缓存,查找成功则返回结果。
  4. 本地DNS服务器向根DNS服务器进行查询,根DNS服务器是最高层次的,它并不会直接指明这个域名对应的 IP 地址,而是返回顶级DNS服务器的地址。
  5. 本地DNS服务器拿到这个顶级DNS服务器的地址后,就向其发起请求,获取权限域名服务器的地址
  6. 本地DNS服务器根据权限域名服务器的地址向其发起请求,获得IP地址
  7. 将IP地址缓存到操作系统缓存和浏览器缓存里面。

DNS解析采用的的协议?

DNS同时占用UDP和TCP的53端口,进行区域传送时使用TCP协议域名解析时使用UDP协议
DNS在进行域名解析的时候,如果DNS服务器没有冷门网站的解析缓存,需要到域名根服务器、一级域名服务器、二级域名服务器迭代查询,直到查询到冷门网站的权威服务器,这中间可能涉及到多次的查询。如果使用TCP传输,多几次查询,就多几次TCP连接时间,每次查询都需要三次握手四次挥手,时间消费就非常大。

UDP协议传输内容不能超过512字节

区域传送

DNS的规范规定了2种类型的DNS服务器,一个叫主DNS服务器,一个叫辅助DNS服务器。在一个区中主DNS服务器从自己本机的数据文件中读取该区的DNS数据信息,而辅助DNS服务器则从区的主DNS服务器中读取该区的DNS数据信息。当一个辅助DNS服务器启动时,它需要与主DNS服务器通信,并加载数据信息,这就叫做区传送

区域传送的目的

DNS的区域传输目的是为了DNS的备份,当DNS服务器坏了,它的数据不会丢失。注意在配置区域传输是一定要注意辅助服务器上建立的区域是辅助区域且与主服务器的域名相同,而且区域传输是双向的,不但需要在辅助服务器上配置还要在主服务器上进行相应的配置。

输入URL后,期间发生了什么?

首先浏览器做的第一步工作就是要对 URL 进行解析,从而获取发送给 Web 服务器的请求信息。对 URL 进行解析之后,浏览器确定了 Web 服务器和文件名,接下来就是根据这些信息来生成 HTTP 请求消息了。
通过浏览器解析 URL 并生成 HTTP 消息后,需要委托操作系统将消息发送给 Web服务器。但在发送之前,需要进行DNS解析,那就是查询服务器域名对于的 IP 地址,因为委托操作系统发送消息时,必须提供通信对象的 IP 地址。
DNS解析
首先会检查是否在浏览器缓存或者本地缓存中,有的话就直接返回IP地址,没有的话浏览器会发出一个 DNS请求到本地DNS(域名分布系统)服务器 。本地DNS服务器一般都是你的网络接入服务器商提供,比如中国电信,中国移动。本地DNS服务器会首先查询它的缓存记录,如果缓存中有此条记录,就可以直接返回结果,此过程是递归的方式进行查询。如果没有,本地DNS服务器还要向DNS根服务器进行查询,根DNS服务器没有记录具体的域名和IP地址的对应关系,而是告诉本地DNS服务器,你可以到具体域服务器上去继续查询,并给出域服务器的地址。最后,本地DNS服务器向域名的解析服务器发出请求,这时就能收到一个域名和IP地址对应关系。

在通过DNS得到IP地址后,向WEB服务器程序80端口发起TCP的连接请求。然后需要和目的服务器进行三次握手建立连接,如果采用的是HTTPS的话,还需要进行SSL安全认证。
在HTTP进行请求的时候,会把请求封装成HTTP报文;然后交给运输层,TCP需要在报文头部增加TCP头部信息;然后将报文传递给下一层的网络层,网络层进行IP数据包的封装,增加IP头部信息,包括源IP地址、目的IP地址;然后报文进入链路层,进行ARP地址解析,增加IP地址对应的MAC地址信息。最后通过物理层,网卡进行数据传输。

HTTP报文包括:请求的方法、请求的URL、采用的协议、请求的主机名、User-Agent、Connection表示是否持续连接
TCP头部有源端口号、目的端口号、SEQ、ACK、标志位、窗口大小、检验和
IP头部有源IP地址、目的IP地址、检验和、标志位

然后浏览器客户端接收到响应的Http报文,里面有响应状态码,数据类型(text/html)、数据。然后获取到html、CSS、JS格式的数据,进行DOM树渲染,渲染结果显示给用户,然后对于Html文件里面的图片、超链接又进行Http请求获取结果。

DOM渲染流程
1、浏览器解析html源码,然后创建一个DOM树。在DOM树中,每一个HTML标签都有一个对应的节点(元素节点),并且每一个文本也都有一个对应的节点(文本节点)。DOM树的根节点就是documentElement,对应的是html标签。

2、浏览器解析CSS代码,计算出最终的样式数据。对CSS代码中非法的语法它会直接忽略掉。解析CSS的时候会按照如下顺序来定义优先级:浏览器默认设置,用户设置,外联样式,内联样式,html中的style(嵌在标签中的行间样式)。

3、创建完DOM树并得到最终的样式数据之后,构建一个渲染树。渲染树和DOM树有点像,但是有区别。DOM树完全和html标签一一对应,而渲染树会忽略不需要渲染的元素(head、display:none的元素)。渲染树中每一个节点都存储着对应的CSS属性。

4、当渲染树创建完成之后,浏览器就可以根据渲染树直接把页面绘制到屏幕上。

一个TCP连接发送多少个Http连接请求

linux的ping命令?

ping 是基于 ICMP 协议工作的, ICMP也称为互联网控制报文协议,可以用来确认 IP 包是否成功送达目标地址、报告发送过程中 IP 包被废弃的原因和改善网络设置等。
ICMP 报文是封装在 IP 包里面,它工作在网络层,是 IP 协议的助手。
比如 ping www.baidu.com ,首先进行dns解析获取到www.baidu.com 对应的IP地址,然后构建一个数据包,包含序列号、检验和、源ip地址、目的ip地址、源mac地址、目的mac地址,还会计算数据包往返的时间。可以通过wireshark来获取并查看数据包。

ICMP协议采用的是UDP

ARQ协议?

ARQ协议,即自动重传请求,意思是如果发送方在发送后一段时间之内没有收到确认回执,它通常会重新发送。ARQ协议包括停止等待ARQ协议和连续ARQ协议:
停止等待ARQ协议
停止等待ARQ协议是指,如果接收端没有收到发送端发来的分组,接收端就不会给发送端发送确认回执,此时发送端会重新发送之前的报文分组。发送端会维护一个超时计时器,超时时间会设置的比数据在传输往返过程的时间要长一些。
连续ARQ协议
连续ARQ协议是指,发送端维护一个“窗口”,“窗口”内可以有多个分组,窗口的大小就是窗口中分组的个数,凡是位于“窗口”内的分组可以连续发送出去而不必等待接收端返回的确认回执,对按序到达的最后一个分组,接收端会向发送端发送确认回执,如果有分组没有正确到达,会返回最后一个正确达到的分组序号,该序号后面的分组会重新发送给接收端。
在连续ARQ协议中,发送端会维护一块发送端的数据缓存,“窗口”里的分组都会在这个缓存中,当需要重新发送“窗口”中的分组报文时,便会从缓存里读取分组并发送。

TCP 拆包、粘包?

TCP是个可靠的、面向字节流的传输协议,TCP会根据缓冲区的实际情况进行包的划分,所以在业务上 一个完整的包可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题。

TCP进行网络通信的流程分为;1. 数据发送到客户端的TCP 发送缓冲区; 2. TCP发送缓冲区发送数据到服务器端的接收缓冲区;3. 服务器从接收缓冲区里面接收数据;4. 服务器从发送缓冲区向客户端发送数据。
TCP发送数据
如果数据包太大,在第一阶段在客户端的TCP发送缓冲区里面,就会对数据进行拆分,分为多个TCP数据包
如果数据包太小,为了减少网络通信次数,会进行多个数据包的合并,在发送出去
TCP 接收数据
TCP 从接收好缓冲区里面读取数据,只能一次读取指定大小的数据,这个数据里面可能来自多个包

TCP 拆包

TCP 粘包

如果客户端连续不断的向服务端发送数据包时,服务端接收的数据会出现两个数据包粘在一起的情况,也就是一个数据包中包含了发送端发送的两个数据包的信息,这种现象即为粘包。
发送方粘包
采用 TCP 协议传输数据的客户端与服务器经常是保持一个长连接的状态(一次连接发一次数据不存在粘包),双方在连接不断开的情况下,可以一直传输数据。但当发送的数据包过于的小时,那么 TCP 协议默认的会启用 Nagle 算法,将这些较小的数据包在发送缓冲区进行合并发送,也就是说数据发送出来它已经是粘包的状态了。
接收方粘包
接收方采用 TCP 协议接收数据时的过程是这样的:数据会发送到接收方的接收缓冲区,然后由应用层来主动获取(C 语言用 recv、read 等函数);这时会出现一个问题,就是我们在程序中调用的读取数据函数不能及时的把缓冲区中的数据拿出来,而下一个数据又到来并有一部分放入的缓冲区末尾,等我们读取数据时就是一个粘包。(存放缓冲区的速度 > 应用层读取数据的速度)。

解决方案

  • 在每个包的末尾加上特殊字符,用以区分连续的两个包;比如加上&符号,则接收端可以根据&来分割包。
  • 在报文首部添加包的开始信息和长度信息

UDP 丢包问题?

UDP丢包的主要原因是:

  1. 接受端处理的时间过长:开启多线程处理
  2. 发送的包太大:增加缓存区大小
  3. 发送的频率太快:增加应答机制
  4. 最安全的方式:增加序列号、应答机制、重传机制、超时机制

IP地址与子网掩码?

IP地址是一个32位的二进制数,通常被分割为4个 8位二进制数。IP 地址通常用点分十进制表示成(A.B.C.D)的形式,其中A,B,C,D的取值为0-255(2的8次方),但是第一个0和最后一个255 分别为保留地址和广播地址,实际上只使用1-254的范围。

  • A类地址:10.0.0.0--10.255.255.255
  • B类地址:172.16.0.0--172.31.255.255
  • C类地址:192.168.0.0--192.168.255.255

子网掩码又叫网络掩码、 地址掩码、子网络遮罩,它是一种用来指明一个IP地址的哪些位标识的是主机所在的子网,以及哪些位标识的是主机的位掩码。子网掩码不能单独存在,它必须结合IP地址一起使用。子网掩码只有一个作用,就是将某个IP地址划分成网络地址和主机地址两部分,方便路由器进行快速转发使用的。 子网掩码是一个32位地址,用于屏蔽IP地址的一部分以区别网络标识和主机标识,通过网络标识就可以确定ip地址所在的网断,并说明该IP地址是在局域网上,还是在远程网上。进行ping的时候如果是同一个网段,则去查找有没有对应的主机;如果不是同一个网段,则去查找网关。

同网络位的IP地址进行通信不需要通过网关,不同网络位的IP地址进行通信就需要网关进行路由转发

网关实质上是一个网络通向其他网络的IP地址。比如有网络A和网络B,网络A的IP地址范围为“192.168.1.1~192.168.1.254”,子网掩码为255.255.255.0;网络B的IP地址范围为“192.168.2.1~192.168.2.254”,子网掩码为255.255.255.0。在没有路由器的情况下,两个网络之间是不能进行TCP/IP通信的,即使是两个网络连接在同一台交换机(或集线器)上,TCP/IP协议也会根据子网掩码(255.255.255.0)判定两个网络中的主机处在不同的网络里。而要实现这两个网络之间的通信,则必须通过网关。如果网络A中的主机发现数据包的目标主机不在本地网络中,就把数据包转发给它自己的网关,再由网关转发给网络B的网关,网络B的网关再转发给网络B的某个主机。网络B向网络A转发数据包的过程也是如此 所以说,只有设置好网关的IP地址,TCP/IP协议才能实现不同网络之间的相互通信。那么这个IP地址是哪台机器的IP地址呢?网关的IP地址是具有路由功能的设备的IP地址,具有路由功能的设备有路由器、启用了路由协议的服务器(实质上相当于一台路由器)、代理服务器(也相当于一台路由器)。

子网掩码二进制位对应的是0,那么对应的IP地址数就是主机位;如果子网掩码二进制位对应的是1,那么对应的IP地址数就是网络位。主机地址的数量等于 = $ 2 ^{子网掩码0的个数}-2$。 掩码位24的意思就是遮住24个网络码,其余的都是主机码,也就是前24个1,后面全是0.

ARP 攻击

ARP 是位于TCP/IP协议栈中的链路层协议,根据IP地址解析成对应的MAC地址。主机将包含目标IP地址信息的ARP请求广播到网络中的所有主机,并接收返回消息,以此确定目标IP地址的物理地址;收到返回消息后将该IP地址和物理地址存入本机ARP缓存中并保留一定时间,以便下次请求时直接查询ARP缓存以节约资源。
这个协议是建立在局域网上主机相互信任的基础上的(缺乏安全验证),局域网中的主机可以自主发送ARP应答消息,其他主机收到应答报文时不会检测该报文的真实性并直接将其记入本机ARP缓存。ARP的缓存表是可以被更改的。表中的IP地址和MAC地址也是随时可以修改,这样在局域网中很容易被ARP欺骗。通常此类攻击的手段有两种:路由欺骗和网关欺骗。

攻击原理

ARP攻击主要是通过伪造IP地址和MAC地址进行欺骗。使以太网数据包的源地址、目标地址和ARP通信数量剧增导致网络中断或中间人攻击。

1、ARP欺骗主机的攻击

攻击者通过ARP欺骗使得局域网内被攻击主机发送给网关的流量信息实际上都发送给攻击者。通过替换其他主机的MAC地址为攻击者的MAC地址。
假设有台主机A,B,C位于同一个交换式局域网中,监听者主机为A,而主机B、c正在进行通信,A希望能嗅探到B与c之间的通信数据,于是A就可以伪装成c对B做ARP欺骗,向B发送伪造的ARP应答包,在这个伪造的应答包中,IP地址为c的IP地址,而MAC地址为A的MAC地址:B在接收到这个应答包后,会刷新它的ARP缓存,这样在B的ARP缓存表中就出现了c的IP地址对应的是A的MAC地址,这样,B想要发送给C的数据实际上却发送给了A,这样就达到了嗅探的目的。黑客就可以利用这种手段盗取网络上的重要信息.

2、IP地址冲突攻击

当网络内部有计算机中了ARP病毒,网络内其他计算机就会经常弹出IP地址冲突的警告:这是怎么产生的呢?
比如某主机B规定IP地址为192.168.1.18,如果它处于开机状态,那么其他主机D也把它的IP地址改为192.168.1.18就会造成IP地址冲突。其原理就是:主机D在连接网络(或更改IP地址)的时候它就会向网络内部发送ARP广播包,告诉其他计算机自己的IP地址。如果网络内部存在相同IP地址的主机B,那么B就会通过ARP来作出应答,当D接收到这个应答数据包后,D就会跳出IP地址冲突的警告,B也会弹出IP地址冲突警告:因此用ARP欺骗可以来伪造这个ARPReply,使目标主机一直受到IP地址冲突警告的困扰.

3、阻止目标的数据包通过网关

比如在一个局域网内通过网关上网,那么局域网内部的计算机上的ARP缓存中就存在网关IP-MAC对应记录。如果该记录被ARP病毒更改,那么该计算机向外发送的数据包就会发送到了错误的网关硬件地址上。这样,该计算机就无法上网了.

避免攻击

设置静态路由关系;
通过查看其中的源地址是否是通过dhcp服务器分配的ip,是的话就接受,不是的话就拒绝;

DHCP: 动态主机配置协议,自动分配IP地址

NAT 网络地址转换协议

NAT 网络地址转换协议, 在私有地址和全局地址之间进行转换的协议。
私有地址是指不能在公网上面使用的IP地址,只能用在局域网的内部使用。与之相反的是公网IP地址,私有地址和公网IP地址是不能直接通信的,需要在专用网(私网IP)连接到因特网(公网IP)的路由器上安装NAT软件。装有NAT软件的路由器叫做NAT路由器,它至少有一个有效的外部全球IP地址(公网IP地址)。
使用私网IP地址的主机在和外界通信时,都要在NAT路由器上将其私有地址转换成全球IP地址,才能和因特网连接。另外,这种通过使用少量的全球IP地址(公网IP地址)代表较多的私有IP地址的方式,将有助于减缓可用的IP地址空间枯竭的问题。 而且也可以用来避免来自网络的外部攻击。

NAT实现方式

静态转换

指将内部网络的私有IP地址转换为公有IP地址,私有地址和公网地址转换是一对一配置的,配置后是不能更改的。借助于静态转换,可以实现外部网络对内部网络中某些特定设备(如服务器)的访问。

动态转换

为私网分配多个公网 IP 地址, 组成一个公网 IP 地址池。私网内部地址需要转换时, NAT 路由器从公网 IP 地址池中取出一个 IP 地址,分配给私网机器用于网络通信。 当私网机器数据传输结束后, NAT 路由器收回公网 IP 地址,返回 IP 地址池中。 分配后的 IP 地址是不能再用于其他数据传输。 在公网 IP 地址数量略少于私网机器数量的时候,可以采用动态转换

端口多路复用

改变私网内机器发送到公网的数据包的源端口并进行端口转换,即端口地址转换(PAT)。采用端口多路复用方式,内部网络的所有主机均可共享一个合法外部IP地址实现对Internet的访问,从而可以最大限度地节约IP地址资源。同时,又可隐藏网络内部的所有主机,有效避免来自internet的攻击。目前 NAT 路由器应用最广的就是端口地址映射。

CRC循环冗余检验算法

CRC循环冗余检验是一种根据网上数据包或计算机文件等数据产生简短固定位数校验码的一种散列函数,主要用来检测校验数据传输或者保存后可能出现的错误。生成的数字在传输或者存储之前计算出来并且附加到数据后面,然后接收方进行检验确定数据是否发生变化。一般来说,循环冗余校验的值都是32位的整数。

CRC 算法的基本思想是将传输的数据当做一个位数很长的数。将这个数除以(这里的除,用二进制的异或运算替换)另一个数(生成多项式)。得到的余数作为校验数据附加到原数据后面。

常用的生成多项式:
CRC8=X8+X5+X4+X0

CRC-CCITT=X16+X12+X5+X0

CRC16=X16+X15+X2+X0

CRC12=X12+X11+X3+X2+X0

CRC32=X32+X26+X23+X22+X16+X12+X11+X10+X8+X7+X5+X4+X2+X1+X0

尽管在错误检测中非常有用,但 CRC并不能可靠地校验数据完整性(即数据没有发生任何变化),这是因为CRC多项式是线性结构,可以非常容易地故意改变量据而维持CRC不变。

CSRF 攻击与防御

跨站请求伪造(CSRF), 是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去运行。CSRF 利用的是网站对用户网页浏览器的信任。

CSRF攻击与防御

防御措施

检查Referer字段

HTTP头中有一个Referer字段,这个字段用以标明请求来源于哪个地址。在处理敏感数据请求时,通常来说,Referer字段应和请求的地址位于同一域名下。
这种办法简单易行,工作量低,仅需要在关键访问处增加一步校验。但这种办法也有其局限性,因其完全依赖浏览器发送正确的Referer字段。虽然http协议对此字段的内容有明确的规定,但并无法保证来访的浏览器的具体实现,亦无法保证浏览器没有安全漏洞影响到此字段。并且也存在攻击者攻击某些浏览器,篡改其Referer字段的可能。

添加校验token

CSRF 攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于 cookie 中,因此黑客可以在不知道这些验证信息的情况下直接利用用户自己的 cookie 来通过安全验证。要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。

在 HTTP 头中自定义属性并验证

这种方法也是使用 token 并进行验证,和上一种方法不同的是,这里并不是把 token 以参数的形式置于 HTTP 请求之中,而是把它放到 HTTP 头中自定义的属性里。通过 XMLHttpRequest 这个类,可以一次性给所有该类请求加上 csrftoken 这个 HTTP 头属性,并把 token 值放入其中。这样解决了上种方法在请求中加入 token 的不便,同时,通过 XMLHttpRequest 请求的地址不会被记录到浏览器的地址栏,也不用担心 token 会透过 Referer 泄露到其他网站中去.


目录