HTTP
https的通信流程简述
- 客户端像服务端发送hello server,内容包括协议版本,支持的对称加密算法和一个随机数a
- 服务端返回选择的一个对称加密算法,以及服务器证书,以及一个随机数b
- 客户端像CA验证证书,并生成随机数c然后使用证书中的公钥加密。
- 两方都知道随机数abc,两方生成对称秘钥然后用来加密会话进行通信。
session和cookies的区别
- session:
Session是服务器的会话技术,是存储在服务器的。 - cookie:
Cookie相当于服务器给浏览器的一个通行证,是一个唯一识别码,服务器发送的响应报文包含 Set-Cookie 首部字段,客户端得到响应报文后把 Cookie 内容保存到浏览器中。客户端之后对同一个服务器发送请求时,会从浏览器中取出 Cookie 信息并通过 Cookie 请求首部字段发送给服务器,服务器就可以识别是否是同一个客户。
区别
- s是存储在服务端,c存储在浏览器中
- s需要在c中传递的SESSIONID来寻找
- c只能存储ascII码,s可以存储任意
get和post
http报文字段
- 通用
- 请求
- 响应
实体是指请求和响应行中都有的,和内容有关的字段
http2特性
https://juejin.im/post/5b88a4f56fb9a01a0b31a67e
http1的问题
-
同一域名资源是公用连接还是分别连接 ?
对于同一个域名,浏览器最多只能同时创建 6~8 个 TCP 连接 (不同浏览器不一样)。为了解决数量限制,出现了 域名分片 技术,其实就是资源分域,将资源放在不同域名下 (比如二级子域名下),这样就可以针对不同域名创建连接并请求,以一种讨巧的方式突破限制,但是滥用此技术也会造成很多问题,比如每个 TCP 连接本身需要经过 DNS 查询、三步握手、慢启动等,还占用额外的 CPU 和内存,对于服务器来说过多连接也容易造成网络拥挤、交通阻塞等,对于移动端来说问题更明显 -
线头阻塞 (Head Of Line Blocking) 问题
每个 TCP 连接同时只能处理一个请求 - 响应,浏览器按 FIFO 原则处理请求,如果上一个响应没返回,后续请求 - 响应都会受阻。为了解决此问题,出现了 管线化 - pipelining 技术,但是管线化存在诸多问题,比如第一个响应慢还是会阻塞后续响应、服务器为了按序返回相应需要缓存多个响应占用更多资源、浏览器中途断连重试服务器可能得重新处理多个请求、还有必须客户端 - 代理 - 服务器都支持管线化 -
Header 内容多,而且每次请求 Header 不会变化太多,没有相应的压缩传输优化方案
-
为了尽可能减少请求数,需要做合并文件、雪碧图、资源内联等优化工作,但是这无疑造成了单个请求内容变大延迟变高的问题,且内嵌的资源不能有效地使用缓存机制
-
明文传输不安全
HTTP2 的优势:
- HTTP/2 采用二进制格式传输数据,而非 HTTP 1.x 的文本格式,二进制协议解析起来更高效。
抓个包(2进制解析过)
首部字段差不多,开头全小写的
strict-transport-security: max-age=63072000; includeSubdomains
字段是服务器开启 HSTS 策略,让浏览器强制使用 HTTPS 进行通信,可以减少重定向造成的额外请求和会话劫持的风险 服务器开启 HSTS的方法是: 以 nginx 为例,在相应站点的 server 模块中添加add_header Strict-Transport-Security "max-age=63072000; includeSubdomains" always;
即可 在 Chrome 中可以打开 chrome://net-internals/#hsts 进入浏览器的 HSTS
管理界面,可以增加 / 删除 / 查询 HSTS 记录
优势:
-
多路复用 (MultiPlexing)
在一个 TCP 连接上,我们可以向对方不断发送帧,每帧的 stream identifier 的标明这一帧属于哪个流,然后在对方接收时,根据 stream identifier 拼接每个流的所有帧组成一整块数据。
把 HTTP/1.1 每个请求都当作一个流,那么多个请求变成多个流,请求响应数据分成多个帧,不同流中的帧交错地发送给对方,这就是 HTTP/2 中的多路复用。
流的概念实现了单连接上多请求 - 响应并行,解决了线头阻塞的问题,减少了 TCP 连接数量和 TCP 连接慢启动造成的问题
所以 http2 对于同一域名只需要创建一个连接,而不是像 http/1.1 那样创建 6~8 个连接: -
服务端推送 (Server Push)
比如网页微信的实现 -
Header 压缩 (HPACK)
使用 HPACK 算法来压缩首部内容(因为首部经常传重复内容所以为压缩提供了条件) -
应用层的重置连接
对于 HTTP/1 来说,是通过设置 tcp segment 里的 reset flag 来通知对端关闭连接的。这种方式会直接断开连接,下次再发请求就必须重新建立连接。HTTP/2 引入 RST_STREAM 类型的 frame,可以在不断开连接的前提下取消某个 request 的 stream,表现更好。 -
流量控制
每个 http2 流都拥有自己的公示的流量窗口,它可以限制另一端发送数据。对于每个流来说,两端都必须告诉对方自己还有足够的空间来处理新的数据,而在该窗口被扩大前,另一端只被允许发送这么多数据。
请求方法们的区别
https://blog.youkuaiyun.com/qq_32575047/article/details/81298422
HTTP请求GET和POST的区别
GET提交,请求的数据会附在URL之后(就是把数据放置在HTTP协议头<request-line>中),以?分割URL和传输数据,多个参数用&连接;例如:login.action?name=hyddd&password=idontknow&verify=%E4%BD%A0 %E5%A5%BD。如果数据是英文字母/数字,原样发送,如果是空格,转换为+,如果是中文/其他字符,则直接把字符串用BASE64加密,得出如: %E4%BD%A0%E5%A5%BD,其中%XX中的XX为该符号以16进制表示的ASCII。
POST提交:把提交的数据放置在是HTTP包的包体<request-body>中。上文示例中红色字体标明的就是实际的传输数据
因此,GET提交的数据会在地址栏中显示出来,而POST提交,地址栏不会改变
2.传输数据的大小:
首先声明,HTTP协议没有对传输的数据大小进行限制,HTTP协议规范也没有对URL长度进行限制。 而在实际开发中存在的限制主要有:
GET:特定浏览器和服务器对URL长度有限制,例如IE对URL长度的限制是2083字节(2K+35)。对于其他浏览器,如Netscape、FireFox等,理论上没有长度限制,其限制取决于操作系统的支持。
因此对于GET提交时,传输数据就会受到URL长度的限制。
POST:由于不是通过URL传值,理论上数据不受限。但实际各个WEB服务器会规定对post提交数据大小进行限制,Apache、IIS6都有各自的配置。
3.安全性:
POST的安全性要比GET的安全性高。注意:这里所说的安全性和上面GET提到的“安全”不是同个概念。上面“安全”的含义仅仅是不作数据修改,而这里安全的含义是真正的Security的含义,比如:通过GET提交数据,用户名和密码将明文出现在URL上,因为(1)登录页面有可能被浏览器缓存, (2)其他人查看浏览器的历史纪录,那么别人就可以拿到你的账号和密码了,
4.应用场景
HTTP GET方法是幂等的,所以它适合作为查询操作,HTTP POST方法是非幂等的,所以用来表示新增操作。
HTTP POST方法 vs HTTP PUT方法
对于HTTP POST方法和HTTP PUT方法,我们一般的理解是POST表示创建资源,PUT表示更新资源。当然,这个是正确的理解。
但是,实际上,两个方法都用于创建资源,更为本质的差别是在幂等性。HTTP POST方法是非幂等,所以用来表示创建资源,HTTP PUT方法是幂等的,因此表示更新资源更加贴切。
HTTP PUT方法 vs HTTP PATCH方法
此时,你看会有另外一个问题。HTTP PUT方法和HTTP PATCH方法,都是用来表述更新资源,它们之间有什么区别呢?我们一般的理解是PUT表示更新全部资源,PATCH表示更新部分资源。首先,这个是我们遵守的第一准则。根据上面的描述,PATCH方法是非幂等的,因此我们在设计我们服务端的RESTful API的时候,也需要考虑。如果,我们想要明确的告诉调用者我们的资源是幂等的,我的设计更倾向于使用HTTP PUT方法。
DHCP
- 应用层协议,传输层使用udp
- 作用是分配动态ip。
- 步骤
- 客户机运行dhcp客户端进程,端口号是68,一开始广播dhcp 发现报文(给67端口发送),里面包含事务id。
- 局域网中的dhcp服务机监听67号进程,接受dhcp 发现报文,并向68端口广播ip以及事务id
- 每个客户端接收服务机的广播,根据自己的事务id进行匹配出自己的ip。
RPC协议
Http和RPC区别
RPC(即Remote Procedure Call,远程过程调用)和HTTP(HyperText Transfer Protocol,超文本传输协议)他们最本质的区别,就是RPC主要工作在TCP协议之上,而HTTP服务主要是工作在HTTP协议之上,我们都知道HTTP协议是在传输层协议TCP之上的,所以效率来看的话,RPC当然是要更胜一筹。
(1)RPC架构
先说说RPC服务的基本架构吧。一个完整的RPC架构里面包含了四个核心的组件,分别是Client ,Server,Client Stub以及Server Stub,这个Stub大家可以理解为存根。分别说说这几个组件:
1)客户端(Client),服务的调用方。
2)服务端(Server),真正的服务提供者。
3)客户端存根,存放服务端的地址消息,再将客户端的请求参数打包成网络消息,然后通过网络远程发送给服务方。
4)服务端存根,接收客户端发送过来的消息,将消息解包,并调用本地的方法。
TCP
简介:
下面这句话如果记不住建议文身上。
TCP是面向连接的、可靠的、基于字节流的传输层通信协议。
TCP中一切举措基本都围绕上面这句话展开的
虽然是字节流协议,但是会有报文段:
上层的http报文交给tcp,tcp是先将其看成流的,然后打包整体交给ip层(有时ip层也会将包继续分片,但很少)
所以tcp的报文段只是为了发出去更方便,就像将鸡蛋用车厢装走,一个包没有也不需要有具体的含义的。
延迟确认,和选择性确认(SACK)
延迟确认
- 当有响应数据要发送时,ack 会随着响应数 据立即发送给对方.
- 如果没有响应数据,ack 的发 送将会有一个 延迟,以等待看是否有响应数据可以一起发 送
- 如果在等待发送 ack 期间,对方的第二个数 据段又到达了,这时要立即发送 ack
也就是说,默认情况:
应答时机 = 俩包没答 或 超过200ms
关闭 delayed ACK:TCP_QUICKACK
接收方在收到数据后,并不会立即回复ACK,而是延迟一定时间。一般ACK延迟发送的时间为200ms,但这个200ms并非收到数据后需要延迟的时间。系统有一个固定的定时器每隔200ms会来检查是否需要发送ACK包。这样做有两个目的。
1、这样做的目的是ACK是可以合并的,也就是指如果连续收到两个TCP包,并不一定需要ACK两次,只要回复最终的ACK就可以了,可以降低网络流量。
2、如果接收方有数据要发送,那么就会在发送数据的TCP数据包里,带上ACK信息。这样做,可以避免大量的ACK以一个单独的TCP包发送,减少了网络流量。
选择性确认:
SACK,Selective Acknowledgement,选择性确认。
- 告诉发送方我缺失了哪个包,避免它重新发送后面我已经收到的包。
TCP收到乱序数据后,会将其放入乱序队列中,然后发送重复ACK给对端。对端如果收到多个重复的ACK,认为发生丢包,TCP会重传最后确认的包开始的后续包。这样原先已经正确传输的包可能会重复发送,降低了TCP性能。为改善这种情况,发展出SACK技术,使用SACK选项可以告知发包方收到了哪些数据,发包方收到这些信息后就会知道哪些数据丢失,然后立即重传丢失的部分。
需要注意的是只有收到失序的分组时才会可能会发送SACK,TCP的ACK还是建立在累积确认的基础上的。也就是说如果收到的报文段与期望收到的报文段的序号相同就会发送累积的ACK,SACK只是针对失序到达的报文段的。
关于timewait
为什么要有timewait
可以重传ack以及防止上一个重复分节的信息在新的分节中出现,即
- 实现TCP全双工连接的终止。当客户主动中断连接时,根据TCP协议,客户必须接收服务器的FIN信息并给予ACK应答。因此客户需要维护状态信息,以便能回复ACK。如果过程中ACK丢失,它必须能够重传,否则将会产生错误。而处于TIME_WAIT状态没有关闭可以实现重传ACK。
- 允许老的重复分节在网络中消失。如果一个TCP连接关闭,过了一会又在相同的IP和端口建立新的连接。TCP需要防止之前连接没有传完的数据在新的连接出现。而如果连接处于TIME_WAIT状态,就不会给这个相同IP和端口建立新的连接。之前没有传完的数据将会在TIME_WAIT结束前在网络中消失,因为TIME_WAIT的持续时间是数据的生存时间MSL的两倍。
怎样实现流量控制(拥塞控制)
https://blog.youkuaiyun.com/sinat_21112393/article/details/50810053
拥塞避免的实现方式是维护一个拥塞窗口。
使用算法来控制拥塞窗口的增长从而实现流量控制和拥塞控制
采用的算法有
- 慢开始:窗口指数增长直到门限
- 拥塞避免:窗口超过门限每次加1增长;若发生超时,门限降半,窗口置1
- 快重传:接收端收到失序包发送ack,发送端收到3个ack重传下一包。
- 快恢复:发生快重传,门限窗口降半
详细版:
- 发送方维护拥塞窗口cwnd,其值动态变化,维护拥塞窗口的cwnd的原则,有拥塞窗口就小点。没有拥塞就大点。怎样判断是否有拥塞呢?有没有发生超时重传。ssthresh是慢开始门限,当cwnd<ssthresh时,窗口2次幂增长,即为慢开始
- cwnd >ssthresh 使用拥塞避免算法。 拥塞避免算法让拥塞窗口缓慢增长,即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1,而不是加倍。这样拥塞窗口按线性规律缓慢增长。
- 无论是在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞(其根据就是没有收到确认,虽然没有收到确认可能是其他原因的分组丢失,但是因为无法判定,所以都当做拥塞来处理),就把慢开始门限设置为出现拥塞时的发送窗口大小的一半。然后把拥塞窗口设置为1,执行慢开始算法。
- 快重传: 快重传要求接收方在收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方)而不要等到自己发送数据时捎带确认。快重传算法规定,发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器时间到期。
TCP报文
几个不熟悉的:
- PSH :Push标志(接收方应尽快将报文段提交至应用层)
TCP粘包/拆包
TCP分片
1、SO_BACKLOG:是否阻塞
ChannelOption.SO_BACKLOG对应的是tcp/ip协议listen函数中的backlog参数,函数listen(int socketfd,int backlog)用来初始化服务端可连接队列,服务端处理客户端连接请求是顺序处理的,所以同一时间只能处理一个客户端连接,多个客户端来的时候,服务端将不能处理的客户端连接请求放在队列中等待处理,backlog参数指定了队列的大小
2、SO_KEEPALIVE
是否启用心跳保活机制。在双方TCP套接字建立连接后(即都进入ESTABLISHED状态)并且在两个小时左右上层没有任何数据传输的情况下,这套机制才会被激活。
3、SO_SNDBUF,SO_RCVBUF
这两个参数用于操作接收缓冲区和发送缓冲区的大小,接收缓冲区用于保存网络协议站内收到的数据,直到应用程序读取成功,发送缓冲区用于保存发送数据,直到发送成功。
4、TCP_NODELAY
在TCP/IP协议中,无论发送多少数据,总是要在数据前面加上协议头,同时,对方接收到数据,也需要发送ACK表示确认。为了尽可能的利用网络带宽,TCP总是希望尽可能的发送足够大的数据。这里就涉及到一个名为Nagle的算法,该算法的目的就是为了尽可能发送大块数据,避免网络中充斥着许多小数据块。
TCP_NODELAY就是用于启用或关于Nagle算法。如果要求高实时性,有数据发送时就马上发送,就将该选项设置为true关闭Nagle算法;如果要减少发送次数减少网络交互,就设置为false等累积一定大小后再发送。默认为false。
5、SO_REUSEADDR,这个参数表示允许重复使用本地地址和端口,比如,某个服务器进程占用了TCP的80端口进行监听,此时再次监听该端口就会返回错误,使用该参数就可以解决问题,该参数允许共用该端口,这个在服务器程序中比较常使用。
比如某个进程非正常退出,该程序占用的端口可能要被占用一段时间才能允许其他进程使用,而且程序死掉以后,内核一需要一定的时间才能够释放此端口,不设置SO_REUSEADDR
TCP层分片
- udp不分片,tcp分片
以太网和802.3对数据帧的长度都有一个限制,其最大 值分别是1500和1492个字节。链路层的这个特性称作MTU,如果IP层有一个数据要传,且数据的长度比链路层的 MTU还大,那么IP层就要进行分片(fragmentation)
ip层分不分传输层都不知道,透明的。IP首部中有足够的信息让接收端能正确组装这些数据报片。
ip分片效率太低!因为超时重传校验等只有在tcp层才有,假如一个ip包的分片丢了,整个ip包都要重传
SWS(Silly Window syndrome)糊涂窗口综合症
Nagle 算法
(TCP_NODELAY 用于关闭 Nagle 算法)
- 没有已发送未确认报文段时,立刻发送数据
- 存在未确认报文段时,直到:1-没有已发送未确认报文段,或者 2-数据 长度达到 MSS 时再发送
在 UDP 中,UDP 是直接把应用层的数据往对方的端口上 “扔” ,他基本没有任何的处理。所以说他发给网络层的数据如果大于1500字节,也就是大于MTU。这个时候发送方 IP 层就需要分片。把数据报分成若干片,使每一片都小于MTU.而接收方IP层则需要进行数据报的重组。这样就会多做许多事情,而更严重的是 ,由于UDP的特性,当某一片数据传送中丢失时 , 接收方便无法重组数据报,将导致丢弃整个UDP数据报。
而在 TCP 中会按MTU合理分片,也就是在 TCP 中有一个概念叫做最大报文段长度(MSS)它规定了 TCP 的报文段的最大长度,注意这个不包括 TCP 的头,典型值就是 1460 个字节(TCP 和 IP 的头各占用了 20 字节)。并且由于 TCP 是有序号和确认号的,接收方会缓存未按序到达的数据,根据序号重新排序报文段后再交给应用层。
IP层
IP报文
-
版本:IP协议的版本,目前的IP协议版本号为4,下一代IP协议版本号为6。
-
首部长度:IP报头的长度。固定部分的长度(20字节)和可变部分的长度之和。共占4位。最大为1111,即10进制的15,代表IP报头的最大长度可以为15个32bits(4字节),也就是最长可为15*4=60字节,除去固定部分的长度20字节,可变部分的长度最大为40字节。
-
服务类型:Type Of Service。
-
总长度: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的协议号为6,UDP的协议号为17。ICMP的协议号为1,IGMP的协议号为2.
-
首部校验和:计算IP头部的校验和,检查IP报头的完整性。
-
源IP地址:标识IP数据报的源端设备。
-
目的IP地址:标识IP数据报的目的地址。
ping工作在哪一层
ping工作在应用层,直接使用网络层的icmp协议。
介绍下icmp协议
所谓ICMP协议,全称是Internet Control Message Protocol,中文意思是Internet控制消息协议。它是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用。
icmp的报文?
ICMP它是一个3层网络协议,工作在网络层。由于数据包的传输是需要源地址和目的地址,所以被封装在IP中。它的数据包结构非常简单,因为一个“侦察兵”要“轻装上阵”,不能携带太多的包袱。
-
查询报文
-
回显请求
-
回显应答
ping就是查询报文,数据包在icmp的基础上增加了自己的东西:任务标识符和序号。ping还会存放发生请求的时间,用来计算往返的时间。
-
-
差错报文
icmp协议有什么用?(ping和trace out)
ICMP协议主要用来检测网络通信故障和实现链路追踪,最典型的应用就是PING和tracerooute。
-
PING:通过发送回送请求报文和回送回答报文来检测源主机到目的主机的链路是否有问题,目的地是否可达,以及通信的延迟情况。
Ping 的原理是通过向目的主机发送 ICMP Echo 请求报文,目的主机收到之后会发送 Echo 回答报文。Ping 会根据时间和成功响应的次数估算出数据包往返时间以及丢包率。 -
traceout:
Traceroute是一个“大骗子”,它使用ICMP的差错报文的规则,去制造一些错误场景,已获得想到的答案。接下来我将一一说明:
第一个作用:获得到达目的地的路径
第一场景:故意设置特殊的TTL(Time to Live),来追踪去往目的地时沿途经过的路由器。比如,他会发生一个TTL为1的UDP数据包,一旦到达下一个路由器,就会由于数据包“死亡”返回一个时间超时的ICMP数据包。这样它就知道了下一条路由器的IP地址了。接着,又把TTL设置为2,有获得了下一条路由器的地址了。以此类推,就获得了到达目的地的整条路的IP地址了。
但是,第一个场景里面存在一个缺陷,比如,最后一个UDP数据包已经可以到目的地了,他就不会返回ICMP差错报文,那么我怎么知道最后一个UDP数据包到底到目的地了吗?这样就有了第二个场景。
第二个场景:故意选择一个不可能的值作为 UDP 端口号(大于 30000)。当该数据报到达时,将使目的主机的 UDP 模块 产生一份“端口不可达”错误 ICMP 报文。
这就相当于故意派人去西天如来那里去请一本《道德经》,结果人家信佛不信道,消息就会被打出来。 被打的消息传回来,你就知道西天是能够到达的。为什么不去取《心经》呢?因为 UDP 是无连接的。也就是说这人一派出去,你就得不到任何音信。你无法区别到底是半路走丢了,还是真的信佛遁入空门了,只有让人家打出来,你才会得到消息。
第二个作用:确定路径的MTU
Traceroute 还有一个作用是**故意设置不分片,从而确定路径的 MTU。**要做的工作首先是发送分组,并设置“不分片”标志。发送的第一个分组的长度正好与出口 MTU 相等。如果中间遇到窄的关口会被卡 住,会发送 ICMP 网络差错包,类型为“需要进行分片但设置了不分片位”。其实,这是人家故意的好吧,每次收到 ICMP“不能分片”差错时就减小分组的长度,直到到达目标主机。
你知道icmp的攻击吗?
ICMP协议对于网络安全具有极其重要的意义。ICMP协议本身的特点决定了它非常容易被用于攻击网络上的路由器和主机。比如,可以利用操作系统规定的ICMP数据包最大尺寸不超过64KB这一规定,向主机发起“Ping of Death”(死亡之Ping)攻击。“Ping of Death” 攻击的原理是:如果ICMP数据包的尺寸超过64KB上限时,主机就会出现内存分配错误,导致TCP/IP堆栈崩溃,致使主机死机。 此外,向目标主机长时间、连续、大量地发送ICMP数据包,也会最终使系统瘫痪。大量的ICMP数据包会形成“ICMP风暴”,使得目标主机耗费大量的CPU资源处理,疲于奔命。
- ICMP 相当于网络世界的侦察兵。我讲了两种类型的 ICMP 报文,一种是主动探查的查询报文,一种异常报告的差错报文。
- Ping 使用查询报文,Traceroute 使用差错报文。
参考:
https://mannuan.github.io/post/20190707153102/
vpn
虚拟局域网
部门A和B之间想要进行加密通信,可以利用公网传输,效果是和在局域网中一样。
步骤
- 先配置A和B的子网ip
- A的机器封装数据包发给A的路由,A的路由将其加密,然后封装自己的ip头部发给B的路由
- B的路由解出包内容,根据子网的ip传给相应的目的主机。
vpn使用nat技术进行ip转换
NAT
nat转换的路由器叫nat路由器
使用大量内部局域网的ip共享外部全球ip
nat关键在于nat路由器有外部ip和内部ip的网络转换表
边界协议网关bgp
你 抓 过 包 吗
工具
tcpdump 和 Wireshark 就是最常用的网络抓包和分析工具,更是分析网络性能必不可少的利器。
tcpdump 仅支持命令行格式使用,常用在 Linux 服务器中抓取和分析网络包。
Wireshark 除了可以抓包外,还提供了可视化分析网络包的图形页面。
所以,这两者实际上是搭配使用的,先用 tcpdump 命令在 Linux 服务器上抓包,接着把抓包的文件拖出到 Windows 电脑后,用 Wireshark 可视化分析。
当然,如果你是在 Windows 上抓包,只需要用 Wireshark 工具就可以。
- tcpdump
抓包分析TCP 三次握手和四次挥手
网络攻击
https://www.jianshu.com/p/1c3db5585ba1
https://developer.aliyun.com/article/463023
你了解哪些网络攻击?
- XSS攻击(关键是脚本,利用恶意脚本发起攻击),
- SQL注入(关键是通过用SQL语句伪造参数发出攻击),
- DDOS攻击(关键是发出大量请求,最后令服务器崩溃),
- CSRF攻击(关键是借助本地cookie进行认证,伪造发送请求)。
DDOS
DDOS:分布式拒绝服务攻击(Distributed Denial of Service),简单说就是发送大量请求是使服务器瘫痪。DDos攻击是在DOS攻击基础上的,可以通俗理解,dos是单挑,而ddos是群殴,因为现代技术的发展,dos攻击的杀伤力降低,所以出现了DDOS,攻击者借助公共网络,将大数量的计算机设备联合起来,向一个或多个目标进行攻击。
在技术角度上,DDoS攻击可以针对网络通讯协议的各层,手段大致有:TCP类的SYN Flood、ACK Flood,UDP类的Fraggle、Trinoo,DNS Query Flood,ICMP Flood,Slowloris类等等。一般会根据攻击目标的情况,针对性的把技术手法混合,以达到最低的成本最难防御的目的,并且可以进行合理的节奏控制,以及隐藏保护攻击资源。
一般解决办法:
- syn缓存增大
- 减小tcp_fin_timeout
- 设置
具体的:
- 设置方法1
vim编辑/proc/sys/net/ipv4/tcp_max_syn_backlog
8000
默认500,建议改为8000以上
- 设置方法2
vim编辑/proc/sys/net/ipv4/tcp_fin_timeout
默认值60,建议改为15
- syncooies
sysctl -w net.ipv4.icmp_echo_ignore_all=1 ``echo` `1 > ``/proc/sys/net/ipv4/tcp_syncookies` `sysctl -w net.ipv4.tcp_max_syn_backlog=``"2048"` `sysctl -w net.ipv4.tcp_synack_retries=``"3"` `iptables -A INPUT -i eth0 -p tcp --syn -j syn-flood ``# Limit 12 connections per second (burst to 24) ``iptables -A syn-flood -m limit --limit 12``/s` `--limit-burst 24 -j RETURN
- limit
iptbales -A FORWARD -p tcp --syn -m limit --limit 1``/s` `-j ACCEPT
下面介绍一下TCP协议中的SYN攻击。
SYN-洪水攻击
假设一个用户向服务器发送了SYN报文后突然死机或掉线,那么服务器在发出SYN+ACK应答报文后是无法收到客户端的ACK报文的(第三次握手无法完成),这种情况下服务器端一般会重试(再次发送SYN+ACK给客户端)并等待一段时间后丢弃这个未完成的连接。 这段时间的长度我们称为SYN Timeout,一般来说这个时间是分钟的数量级(大约为30秒-2分钟)。
但如果有一个恶意的攻击者大量模拟这种情况,服务器端将为了维护一个非常大的半连接列表而消耗非常多的资源-—数以万计的半连接,即使是简单的保存并遍历也会消耗非常多的CPU时间和内存,何况还要不断对这个列表中的IP进行SYN+ACK的重试。
如何应对 SYN 攻击?
攻击者短时间伪造不同 IP 地址的 SYN 报文,快速占满 backlog 队列,使 服务器不能为正常用户服务
- 启用syncookies
sysctl -w net.ipv4.tcp_syncookies=1
syncookies: 服务端不必维持
syncookie基本原理
1)仔细处理连接的初始序列号而不是随机选择一个序列号。
2)一旦server接收到SYN报文,将关键信息仔细编码并作为state存储在SYN队列中。
3)这种经过编码的信息是用一个秘钥进行加密hash,形成SYN-ACK报文中的序列号并发送给client。
在合法握手的第三个报文中,即从client返回给server的ACK报文中,在acknowledgment number字段中包含该序列号(加1)。这样,open双向连接所必须的所有信息又返回给server,而server在三次握手完成之前不必维护state。syn-cookies解决了SYN的基本问题,但是随之带来一个新的问题,就是服务器需要对收到的ACK报文进行计算,提高了三次握手需要的系统资源。一种新的攻击方式随之而来,即ACK攻击,发送大量的ACK数据报,导致服务器忙于计算最终导致服务器停止相应。Linux上的实际应用中,有等待数被占满的时候才会启用 syncookies的方式
- net.core.netdev_max_backlog 接收自网卡、但未被内核协议栈处理的报文队列长度 •
- net.ipv4.tcp_max_syn_backlog SYN_RCVD 状态连接的最大个数
- net.ipv4.tcp_abort_on_overflow 超出处理能 力时,对新来的 SYN 直接回包 RST,丢弃连接
######################## cat /proc/sys/net/ipv4/tcp_syncookies
# 默认值:1
# 作用:是否打开SYN Cookie功能,该功能可以防止部分SYN攻击
net.ipv4.tcp_syncookies = 1
- 如何预防DDOS
DDoS 防御产品的核心是检测技术和清洗技术。
icmp攻击
- 利用操作系统规定的ICMP数据包最大尺寸不超过64KB这一规定
ICMP协议对于网络安全具有极其重要的意义。ICMP协议本身的特点决定了它非常容易被用于攻击网络上的路由器和主机。比如,可以利用操作系统规定的ICMP数据包最大尺寸不超过64KB这一规定,向主机发起**“Ping of Death”(死亡之Ping)攻击**。“Ping of Death” 攻击的原理是:如果ICMP数据包的尺寸超过64KB上限时,主机就会出现内存分配错误,导致TCP/IP堆栈崩溃,致使主机死机。 此外,向目标主机长时间、连续、大量地发送ICMP数据包,也会最终使系统瘫痪。大量的ICMP数据包会形成“ICMP风暴”,使得目标主机耗费大量的CPU资源处理,疲于奔命。
XSS
-
XSS攻击:跨站脚本攻击(Cross-Site Scripting)
攻击者将恶意代码植入到提供给其它用户使用的页面中。不同于大多数攻击(一般只涉及攻击者和受害者),XSS涉及到三方,即攻击者、客户端与Web应用。XSS的攻击目标是为了盗取存储在客户端的cookie或者其他网站用于识别客户端身份的敏感信息。一旦获取到合法用户的信息后,攻击者甚至可以假冒合法用户与网站进行交互。
-
XSS通常可以分为两大类:
- 存储型XSS,主要出现在让用户输入数据,供其他浏览此页的用户进行查看的地方,包括留言、评论、博客日志和各类表单等。应用程序从数据库中查询数据,在页面中显示出来,攻击者在相关页面输入恶意的脚本数据后,用户浏览此类页面时就可能受到攻击。这个流程简单可以描述为:恶意用户的Html输入Web程序->进入数据库->Web程序->用户浏览器。
- 反射型XSS,主要做法是将脚本代码加入URL地址的请求参数里,请求参数进入程序后在页面直接输出,用户点击类似的恶意链接就可能受到攻击。
-
比如说我写了一个网站,然后攻击者在上面发布了一个文章,内容是这样的 ,如果我没有对他的内容进行处理,直接存储到数据库,那么下一次当其他用户访问他的这篇文章的时候,服务器从数据库读取后然后响应给客户端,浏览器执行了这段脚本,就会将cookie展现出来,这就是典型的存储型XSS。
-
如何预防XSS
答案很简单,坚决不要相信用户的任何输入,并过滤掉输入中的所有特殊字符。这样就能消灭绝大部分的XSS攻击。目前防御XSS主要有如下几种方式:
- 过滤特殊字符
避免XSS的方法之一主要是将用户所提供的内容进行过滤(如上面的script标签)。 - 使用HTTP头指定类型
w.Header().Set("Content-Type","text/javascript")
这样就可以让浏览器解析javascript代码,而不会解析html输出。
- 过滤特殊字符
CSRF
- 攻击者盗用了你的身份,以你的名义发送恶意请求。
CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。
你这可以这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账…造成的问题包括:个人隐私泄露以及财产安全。
要完成一次CSRF攻击,受害者必须依次完成两个步骤:
- 登录受信任网站A,并在本地生成Cookie。
- 在不登出A的情况下,访问危险网站B。
受害者 Bob 在银行有一笔存款,通过对银行的网站发送请求 http://bank.example/withdraw?account=bob&amount=1000000&for=bob2 可以使 Bob 把 1000000 的存款转到 bob2 的账号下。通常情况下,该请求发送到网站后,服务器会先验证该请求是否来自一个合法的 session,并且该 session 的用户 Bob 已经成功登陆。
黑客 Mallory 自己在该银行也有账户,他知道上文中的 URL 可以把钱进行转帐操作。Mallory 可以自己发送一个请求给银行:http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory。但是这个请求来自 Mallory 而非 Bob,他不能通过安全认证,因此该请求不会起作用。
这时,Mallory 想到使用 CSRF 的攻击方式,他先自己做一个网站,在网站中放入如下代码: src=”http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory ”,并且通过广告等诱使 Bob 来访问他的网站。当 Bob 访问该网站时,上述 url 就会从 Bob 的浏览器发向银行,而这个请求会附带 Bob 浏览器中的 cookie 一起发向银行服务器。大多数情况下,该请求会失败,因为他要求 Bob 的认证信息。但是,如果 Bob 当时恰巧刚访问他的银行后不久,他的浏览器与银行网站之间的 session 尚未过期,浏览器的 cookie 之中含有 Bob 的认证信息。这时,悲剧发生了,这个 url 请求就会得到响应,钱将从 Bob 的账号转移到 Mallory 的账号,而 Bob 当时毫不知情。等以后 Bob 发现账户钱少了,即使他去银行查询日志,他也只能发现确实有一个来自于他本人的合法请求转移了资金,没有任何被攻击的痕迹。而 Mallory 则可以拿到钱后逍遥法外。
防御方法
- 验证 HTTP Referer 字段
- 在请求地址中添加 token 并验证(黑客并不知道token)
Linux网络篇
查看我的另一篇 操作系统面试
网络配置文件里都有啥?
首先在这里:
/proc/sys/net/ipv4
【net】
######################## cat /proc/sys/net/ipv4/tcp_syncookies
# 默认值:1
# 作用:是否打开SYN Cookie功能,该功能可以防止部分SYN攻击
net.ipv4.tcp_syncookies = 1
######################## cat /proc/sys/net/ipv4/ip_local_port_range
# 默认值:32768 61000
# 作用:可用端口的范围
net.ipv4.ip_local_port_range = 1024 65535
######################## cat /proc/sys/net/ipv4/tcp_fin_timeout
# 默认值:60
# 作用:TCP时间戳
net.ipv4.tcp_fin_timeout = 30
######################## cat /proc/sys/net/ipv4/tcp_timestamps
# 默认值:1
# 作用:TCP时间戳
net.ipv4.tcp_timestamps = 1
######################## cat /proc/sys/net/ipv4/tcp_tw_recycle
# 默认值:0
# 作用:针对TIME-WAIT,不要开启。不少文章提到同时开启tcp_tw_recycle和tcp_tw_reuse,会带来C/S在NAT方面的异常
# 个人接受的做法是,开启tcp_tw_reuse,增加ip_local_port_range的范围,减小tcp_max_tw_buckets和tcp_fin_timeout的值
# 参考:http://ju.outofmemory.cn/entry/91121, http://www.cnblogs.com/lulu/p/4149312.html
net.ipv4.tcp_tw_recycle = 0
######################## cat /proc/sys/net/ipv4/tcp_tw_reuse
# 默认值:0
# 作用:针对TIME-WAIT,做为客户端可以启用(例如,作为nginx-proxy前端代理,要访问后端的服务)
net.ipv4.tcp_tw_reuse = 1
######################## cat /proc/sys/net/ipv4/tcp_max_tw_buckets
# 默认值:262144
# 作用:针对TIME-WAIT,配置其上限。如果降低这个值,可以显著的发现time-wait的数量减少,但系统日志中可能出现如下记录:
# kernel: TCP: time wait bucket table overflow
# 对应的,如果升高这个值,可以显著的发现time-wait的数量增加。
# 综合考虑,保持默认值。
net.ipv4.tcp_max_tw_buckets = 262144
######################## cat /proc/sys/net/ipv4/tcp_max_orphans
# 默认值:16384
# 作用:orphans的最大值
net.ipv4.tcp_max_orphans = 3276800
######################## cat /proc/sys/net/ipv4/tcp_max_syn_backlog
# 默认值:128
# 作用:增大SYN队列的长度,容纳更多连接
net.ipv4.tcp_max_syn_backlog = 819200
######################## cat /proc/sys/net/ipv4/tcp_keepalive_intvl
# 默认值:75
# 作用:探测失败后,间隔几秒后重新探测
net.ipv4.tcp_keepalive_intvl = 30
######################## cat /proc/sys/net/ipv4/tcp_keepalive_probes
# 默认值:9
# 作用:探测失败后,最多尝试探测几次
net.ipv4.tcp_keepalive_probes = 3
######################## cat /proc/sys/net/ipv4/tcp_keepalive_time
# 默认值:7200
# 作用:间隔多久发送1次keepalive探测包
net.ipv4.tcp_keepalive_time = 1200
######################## cat /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established
# 默认值:432000
# 作用:设置 conntrack tcp 状态的超时时间,如果系统出现下述异常时要考虑调整:
# ping: sendmsg: Operation not permitted
# kernel: nf_conntrack: table full, dropping packet.
# 参考:http://www.linuxidc.com/Linux/2012-11/75151.htm, http://blog.youkuaiyun.com/dog250/article/details/9318843
net.netfilter.nf_conntrack_tcp_timeout_established = 600
######################## cat /proc/sys/net/netfilter/nf_conntrack_max
# 默认值:65535
# 作用:设置 conntrack 的上限,如果系统出现下述异常时要考虑调整:
# ping: sendmsg: Operation not permitted
# kernel: nf_conntrack: table full, dropping packet.
# 参考:https://blog.yorkgu.me/2012/02/09/kernel-nf_conntrack-table-full-dropping-packet/, http://www.cnblogs.com/mydomain/archive/2013/05/19/3087153.html
net.netfilter.nf_conntrack_max = 655350
##########################################################################################
######################## cat /proc/sys/net/core/netdev_max_backlog
# 默认值:1000
# 作用:网卡设备将请求放入队列的长度
net.core.netdev_max_backlog = 500000
######################## cat /proc/sys/net/core/somaxconn
# 默认值:128
# 作用:已经成功建立连接的套接字将要进入队列的长度
net.core.somaxconn = 65536
######################## cat /proc/sys/net/core/rmem_default
# 默认值:212992
# 作用:默认的TCP数据接收窗口大小(字节)
net.core.rmem_default = 8388608
######################## cat /proc/sys/net/core/wmem_default
# 默认值:212992
# 作用:默认的TCP数据发送窗口大小(字节)
net.core.wmem_default = 8388608
######################## cat /proc/sys/net/core/rmem_max
# 默认值:212992
# 作用:最大的TCP数据接收窗口大小(字节)
net.core.rmem_max = 16777216
######################## cat /proc/sys/net/core/wmem_max
# 默认值:212992
# 作用:最大的TCP数据发送窗口大小(字节)
net.core.wmem_max = 16777216
######################## cat /proc/sys/net/ipv4/tcp_mem
# 默认值:94389 125854 188778
# 作用:内存使用的下限 警戒值 上限
net.ipv4.tcp_mem = 94500000 915000000 927000000
######################## cat /proc/sys/net/ipv4/tcp_rmem
# 默认值:4096 87380 6291456
# 作用:socket接收缓冲区内存使用的下限 警戒值 上限
net.ipv4.tcp_rmem = 4096 87380 16777216
######################## cat /proc/sys/net/ipv4/tcp_wmem
# 默认值:4096 16384 4194304
# 作用:socket发送缓冲区内存使用的下限 警戒值 上限
net.ipv4.tcp_wmem = 4096 16384 16777216
##########################################################################################
######################## cat /proc/sys/net/ipv4/tcp_thin_dupack
# 默认值:0
# 作用:收到dupACK时要去检查tcp stream是不是 thin ( less than 4 packets in flight)
net.ipv4.tcp_thin_dupack = 1
######################## cat /proc/sys/net/ipv4/tcp_thin_linear_timeouts
# 默认值:0
# 作用:重传超时后要去检查tcp stream是不是 thin ( less than 4 packets in flight)
net.ipv4.tcp_thin_linear_timeouts = 1
######################## cat /proc/sys/net/unix/max_dgram_qlen
# 默认值:10
# 作用:UDP队列里数据报的最大个数
net.unix.max_dgram_qlen = 30000
##########################################################################################
######################## 针对lvs,关闭网卡LRO/GRO功能
# 现在大多数网卡都具有LRO/GRO功能,即网卡收包时将同一流的小包合并成大包 (tcpdump抓包可以看到>MTU 1500bytes的数据包)交给 内核协议栈;LVS内核模块在处理>MTU的数据包时,会丢弃;
# 因此,如果我们用LVS来传输大文件,很容易出现丢包,传输速度慢;
# 解决方法,关闭LRO/GRO功能,命令:
# ethtool -k eth0 查看LRO/GRO当前是否打开
# ethtool -K eth0 lro off 关闭GRO
# ethtool -K eth0 gro off 关闭GRO