网关(Gateway)就是一个网络连接到另一个网络的“关口”,它实质上是一个网络通向其他网络的IP地址
。
举例:如果网络A中的主机发现数据包的目的主机不在本地网络中,就把数据包转发给它自己的网关,再由网关转发给网络B的网关,网络B的网关再转发给网络B的某个主机。
todo
伪首部的作用
伪首部既不向下传送也不向上递交,而仅仅是为了计算检验和
。
记住字段最多的那4字节:偏移、保留、控制、窗口(简记:偏保空窗
)
窗口
:用于告知对方自己的接收窗口大小!
选项
:这部分通常只填写了MSS(最大报文段长度),默认为536字节;
PSH
:这个字段为1时,则接收方尽快向上交付数据,而不用等待缓冲区满;
URG
:这个字段为1时,会将前面的数据紧急发送(这个时候会将紧急数据放在前面,紧急指针给出紧急数据的字节数)
…
过程概述
记住三条线上的信息,记住每段时间所处的状态
;
第一阶段:规定SYN报文段不能传递数据,但是要消耗一个序号
第二阶段:规定这个阶段的SYN报文段也不能传递数据,但是要消耗一个序号
;
第三阶段:这个阶段的ACK报文段可以携带数据,如果不携带则不消耗序号
(即SYN不能携带数据,但是消耗序号,面试时答出来应该是亮点)
为什么前两个阶段不能传递数据,但是第三个阶段可以传递数据?
1. 第一个阶段是A请求建立到B的连接,由于连接尚未建立,所以不应该发送数据(A->B);
2. 第二个阶段是B请求建立到A的连接(虽然同时也是在确认A的请求),所以也不应该从B发送数据到A;
3. 第三个阶段由于A->B的连接已经建立,虽然B尚未收到确认,但是A已经建立了到B的连接,所以A可以直接发送数据,这也就是可以捎带数据的原因; 即使这个确认阶段数据丢失,A也可以超时重传,不会导致数据少发
(个人的理解,不是很能确定是否正确)
可以改为四次握手吗
可以! 也就是说第二阶段B给A的报文段,可以拆成两个报文段:
1.先发送确认报文段(ACK=1,ack=x+1)建立A-->B的连接
;
2.再发送同步报文段(SYN=1,seq=y)请求建立B-->A的连接
;
但是效果与三次握手一样
可以改为两次握手吗(为什么要第三次握手)?
不可以;
三次握手的实质
:分两轮建立连接,一轮是A->B,一轮是B->A(按理说应该是四次连接,只是第二个阶段B同时发送了确认报文和同步报文,所以只剩三次)
改为两次握手的含义
:能否只用一轮就同时建立起A->B和B->A的连接 => 即第一阶段A发送请求同步,第二阶段B发送确认,B发送了确认它就认为建立了A->B的连接,只要A收到确认它就认为建立了B->A的连接
,从而一轮就建立了双向连接(从而没有第三阶段)
为什么不能只有两次握手?
:1.若A先发送了请求报文SYN1,但是SYN1在网络中长时间滞留;2.超时后A发送请求报文SYN2并与B建立连接然后释放连接; 3.之后SYN1才到达B,这时候B发送对SYN1的确认并认为建立了A->B的连接,并准备资源接收数据; 4.但是A收到B对SYN1的确认时知道它已经失效,并不会理睬(不会认为建立了B->A的连接); 5. 于是B就会空等,浪费了资源
为什么三次握手就不会受到SYN1超时的困扰?
:因为三次握手时只有在收到了确认报文后才认为建立了连接 => 有了第三次握手,即使SYN1超时,B发送对SYN1的确认并发起同步请求,但是A不会确认这个请求(因为SYN1超时),从而B无法收到A的确认,不会认为建立了连接,也就不会浪费资源
摘录自:DDoS攻击–Syn_Flood攻击防护详解(TCP)
SYN FLOOD攻击概述
攻击者首先伪造地址对服务器发起SYN请求(我可以建立连接吗?),服务器就会回应一个ACK+SYN(可以+请确认)。而真实的IP会认为,我没有发送请求,不作回应。服务器没有收到回应,会重试3-5次并且等待一个SYN Time(一般30秒-2分钟)后,丢弃这个连接。
如果攻击者大量发送这种伪造源地址的SYN请求,服务器端将会消耗非常多的资源来处理这种半连接,保存遍历会消耗非常多的CPU时间和内存,何况还要不断对这个列表中的IP进行SYN+ACK的重试。TCP是可靠协议,这时就会重传报文,默认重试次数为5次,重试的间隔时间从1s开始每次都番倍,分别为1s + 2s + 4s + 8s +16s = 31s,第5次发出后还要等32s才知道第5次也超时了,所以一共是31 + 32 = 63s。
也就是说一个假的syn报文,会占用TCP准备队列63s之久,而半连接队列默认为1024,系统默认不同,可 cat /proc/sys/net/ipv4/tcp_max_syn_backlog c查看。也就是说在没有任何防护的情况下,每秒发送200个伪造syn包,就足够撑爆半连接队列,从而使真正的连接无法建立,无法响应正常请求。 最后的结果是服务器无暇理睬正常的连接请求—拒绝服务。
SYN FLOOD防御
cookie源认证
:原理是syn报文首先由DDOS防护系统来响应syn_ack。带上特定的sequence number (记为cookie)。真实的客户端会返回一个ack 并且Acknowledgment number 为cookie+1。 而伪造的客户端,将不会作出响应。这样我们就可以知道那些IP对应的客户端是真实的,将真实客户端IP加入白名单。下次访问直接通过,而其他伪造的syn报文就被拦截。=> 简单说就是将正常响应的ip加入白名单
reset认证
:Reset认证利用的是TCP协议的可靠性,也是首先由DDOS防护系统来响应syn。防护设备收到syn后响应syn_ack,将Acknowledgement number (确认号)设为特定值(记为cookie)。当真实客户端收到这个报文时,发现确认号不正确,将发送reset报文,并且sequence number 为cookie + 1。 而伪造的源,将不会有任何回应。=> RST
……更多参考:DDoS攻击–Syn_Flood攻击防护详解(TCP)
记住三条线上的信息,记住每段时间所处的状态
(客户端状态简记:FFT
);即使FIN不携带数据也要消耗序号
需要通知高层应用进程A->B的连接已断开
必须发送ACK且ack为u+1
(为啥?)A不能立即释放连接
防止A最后一次发送的确认丢失
,这时候B收不到确认报文,就会超时重传第三阶段的报文,而A已经释放连接,B就无法正常结束…0.概述
可靠的含义
:无差错、不丢失、不重复、按序到达
教材上关于可靠传输的实现,主要强调的是连续ARQ+滑动窗口
,很多面经讲了许多杂七杂八的内容,像确认号、序列号、超时重传之类的,本质上都是连续ARQ+滑动窗口的一部分;而连续ARQ+滑动窗口这个方法也是逐步改进而来,本节主要阐述这个改进过程中涉及的方法。
注意,面试问道TCP可靠传输时,面试官多半还期望听到校验和
、拥塞控制
、流量控制
(这一小节我们暂且不讲这几个内容,仅专注于教材上的东西)
1.停止等待(即自动重传ARQ)
定义:发送方每发送完一个分组,就停止发送,等待接收方的确认;若一段时间后没有收到确认,则重新发送;
关键词:序列号
、确认号
、超时重传
存在的问题:效率不高,每次发送数后都需要等待
2.连续ARQ+滑动窗口
定义:在自动重传确认的基础上,增加了滑动窗口;对于窗口内的数据,发送方可采用流水线发送
,而不是每次只能发送一个分组;发送方每次收到确认,都需要将滑动窗口向前移动;接收方采用累积确认,可以在收到几个分组后,对按序到达的最后一个分组确认;累积确认可能导致重传部分已经收到的分组,这称为回退N帧
关键词:滑动窗口
、累积确认
、回退N帧
(当然也包括自动ARQ中的关键词)
3.具体实现细节
参考《计算机网络》谢希仁第七版,P221
补充
超时重传的时间选择:RTO=RTTs+4*RTTd
,RTO就是超时重传时间;RTTs是多次传输的加权平均往返时间;RTTd是RTTs的偏差的加权平均;
选择确认SACK:RFC2018的选项,可以只重传需要的,而不是回退N帧导致重复发送(但大多数情况并未使用SACK,实际仍然是重传所有未被确认的数据块)
0.概述
拥塞控制与流量控制的区别:拥塞控制是防止过多的数据注入到网络中,这是一个全局性的过程
; 流量控制是抑制发送端发生数据的速率,以便接受端来得及接受,这是一个点对点通信量的控制
。
拥塞控制主要涉及四个算法:慢开始、拥塞避免、快重传、快恢复
每个通信端点维护的三个窗口:发送窗口(swnd)、接收窗口(rwnd)、拥塞控制窗口(cwnd);
发送窗口大小:swnd的上限=min(rwnd,cwnd);拥塞控制主要是限制cwnd=> 简记:src
(s=rc)
慢开始门限ssthresh:cwnd
超时处理(图5-25 位置2):令ssthresh=cwnd/2; cwnd=1
,然后执行慢开始
通过cwnd进行拥塞控制示意图:
拥塞控制流程图
1.慢开始
开始时
(图5-25 坐标0处):通常将cwnd设置为1(单位是SMSS,即发送方最大报文段),在每收到一个对新的报文段的确认后,可以将拥塞控制窗口增加最多一个SMSS的数值 => 或者更常见的理解就是:每经过一个传输轮次,拥塞窗口cwnd就加倍
(发送方当前所有报文段都发送并收到确认为一个传输轮次)
"慢"
并不是指cwnd正常速率慢,而是指TCP开始发送报文段时先设置cwnd=1
2.拥塞避免
cwnd达到ssthresh时
(图5-25 位置1):每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加上1
(这里一个RTT也就对应一个传输轮次);
3.快重传
收到三个重复确认时
(图5-25 位置4)。但是快重传并非像慢开始、拥塞避免那样是从某个时刻开始的一个时间段。它只是在特定时刻发送方执行的一个算法。
实际上,快重传算法要求接收方不要等待自己发送数据时才进行捎带确认,而是要立即发送确认,即使收到了失序报文段也要立即发出对已收到的报文段的重复确认
。当接收方收到三个重复确认时,立即重传数据……注意快重传并不意味着超时,它是在超时之前发生的
!
4.快恢复
收到三个重复确认时
(图5-25 位置4)。同快重传,快恢复也不像慢开始、拥塞避免那样是从某个时刻开始的一个时间段。它也只是在特定时刻发送方执行的一个算法。
当接收方收到三个重复确认时,令ssthresh=cwnd/2; cwnd=ssthresh
,然后执行拥塞避免(注意对比超时处理
!)
概述
流量控制就是让发送方的发送速率不要太快,要让接收方来得及接收。 流量控制也是基于滑动窗口的。如图:
如上图,假设建立连接时,B将接收窗口设置为400;整个过程中接收方进行了三次流量控制……
接收方接收窗口更改的依据书上并未说明,待完善……
HTTP状态码
1xx:消息响应
这一类型的状态码,代表请求已被接受,需要继续处理
。
100 Continue:客户端应当继续发送请求的剩余部分
101 Switching Protocols:切换http协议到其他版本
102 Processing
2xx:成功响应
这一类型的状态码,代表请求已成功被服务器接收、理解、并接受
200 OK:请求已成功,请求所希望的响应头或数据体将随此响应返回;
201 Created:请求已经被实现,而且有一个新的资源已经依据请求的需要而建立,且其 URI 已经随Location 头信息返回
202 Accepted:服务器已接受请求,但尚未处理。最终该请求可能会也可能不会被执行 => 适用于异步
…
204 No Content:服务器成功处理了请求,但不需要返回任何实体内容
206 Partial Content:服务器已经成功处理了部分 GET 请求 => 实现断点续传或者将大文档分段下载
3xx:重定向
这类状态码代表需要客户端采取进一步的操作才能完成请求
304 Not Modified:自从上次这个请求返回后,请求的网页没有修改过;服务器返回304时不会返回网页内容
305 Use Proxy:被请求的资源必须通过指定的dl才能被访问。Location 域中将给出指定的dl所在的URI信息
307 Temporary Redirect:临时重定向
307 Permanent Redirect:永久重定向
4xx:请求错误
这类的状态码代表了客户端看起来可能发生了错误,妨碍了服务器的处理
400 Bad Request:语义有误,当前请求无法被服务器理解;
403 Forbidden:服务器已经理解请求,但是拒绝执行它;
404 Not Found:请求失败,请求所希望得到的资源未被在服务器上发现;
405 Method Not Allowed:请求行中指定的请求方法不能被用于请求相应的资源(比如该用POST而使用了GET);
406 Not Acceptable:请求的资源的内容特性无法满足请求头中的条件,因而无法生成响应实体(比如请求头accept指定json,而应用程序返回的数据不是json)
408 Request Timeout:请求超时
410 Gone:服务器上的某个资源被永久性删除
5xx:服务器错误
这类状态码代表了服务器在处理请求的过程中有错误或者异常状态发生
500 Internal Server Error:服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理;
501 Not Implemented:服务器不支持当前请求所需要的某个功能;
502 Bad Gateway:作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应;
504 Gateway Timeout:作为网关或者代理工作的服务器尝试执行请求时,未能及时从上游服务器或者辅助服务器收到响应
长、宽、缓、响
所谓长短连接说的是TCP连接保持时间,HTTP没有连接
支持流水线方式
If-Modify-Since
,Expires
来作为缓存判断的标准;Entity-tag
,If-Unmodify-Since
,If-Match
,If-None-Match
等更多可供选择的header字段来控制缓存地址是不可能不过期的,DHCP服务器在分配给用户IP地址后,当用户使用该IP地址时间过半还在使用的话,DHCP服务器会自动更新租用时间
。在默认状态下,局域网工作站从DHCP服务器中获得的IP地址,使用期限一般为8天时间.
对称密码体制
概念
:加密与解密使用相同的秘钥;
代表算法
:DES (简记:敌对 -> DES对称
)
公钥密码体制
概念
:加密秘钥与解密秘钥不同;加密秘钥PK向公众公开,解密秘钥SK保密;加密算法E和解密算法D也是公开的;
代表算法
:RSA => 公钥体制开销较大,通常需要先进行hash减少信息量,做hash常用的方法有MD5、SHA
公钥密码体制如图所示:
对比
对称秘钥是在通信信道上进行一对一的双向保密通信
;
非对称秘钥是在通信信道上进行多对一的单向保密通信
;
特别注意1:公钥、私钥运算本质上是可以互换的
也就是说最开始生成的一对秘钥(K1、K2):
情况1:明文 —> K1加密 —> 密文 —> K2解密 —> 明文
情况2:明文 —> K2加密 —> 密文 —> K1解密 —> 明文
哪个是公钥哪个是私钥仅仅取决于将哪个公开,将哪个保密
;
特别注意2:对报文X进行ED运算或DE运算结果都为X
即 E P K B ( D S K B ( X ) ) = D S K B ( E P K B ( X ) ) = X E_{PK_B}(D_{SK_B}(X))=D_{SK_B}(E_{PK_B}(X))=X EPKB(DSKB(X))=DSKB(EPKB(X))=X
加密数据
:公钥加密私钥解密,即 D S K B ( E P K B ( X ) ) = X D_{SK_B}(E_{PK_B}(X))=X DSKB(EPKB(X))=X
数字签名
:私钥加密公钥解密,即 E P K B ( D S K B ( X ) ) = X E_{PK_B}(D_{SK_B}(X))=X EPKB(DSKB(X))=X
参考资料:你知道,HTTPS用的是对称加密还是非对称加密?
SSL的位置
SSL增强了TCP的服务(更安全),本应该是传输层协议;然而实际上使用安全运输的应用程序(如HTTP)却把SSL驻留在了应用层,如图:
SSL的工作过程(必背)
上面共可以分为四个阶段:
协商加密算法:步骤1,2
服务器鉴别:步骤3、4
会话秘钥计算:步骤5、6
安全数据传输:步骤7(这时是对称加密
!!! 非对称仅仅是在CA验证时使用)
SSL与SSH相同点
如果按五层协议来划分的话,那SSH与SSL都可以算是应用层协议,他们都使用了非对称加密,将应用层进行了加密,另外,他们其实都是比较基础的应用层协议,即它们上面还可以再放其它应用层协议,如FTP协议等
以下几部分内容来自:SSH与SSL
SSL与SSH不同点
SSH不需要证书,即不需要公证机构
(从这点来说,SSH的安全性要比SSH弱一些,貌似SSH无法解决中间人攻击),SSH实现了主机用户名和密码的认证,这是SSH的SSH-TRANS部分完成的,而SSL没有这个功能。
SSL与SSH的适用场景
1. SSL一般用于私有访问,它提供了主机用户名和密码的验证功能,当然用户也可以通过在服务端保存自己的公钥来让服务端验证你,Github等就是通过这种方式;
2. 而对于Web等这种提供公共服务的访问呢?这种情况下,我并不想让用户登录主机的,这种情况下,也要求保证数据传输的安全,这时我们用SSL/TLS,我们会在自己设计的应用层(即应用程序中验证用户的身份。
3. 更通俗的说,SSH可以让用户以某个主机用户的身份登录主机,并对主机执行操作(即执行一些命令),目前用的最多的就是远程登录和SFTP(还有简易版的SCP);
而SSL和主机用户名登录没有任何关系,它本身并不实现主机登录的功能,它只的一个单纯的加密功能。为了方便理解,可以简单的认为SSH=SSL+主机用户登录功能等应用层协议
0. SSH是一种加密协议,不仅在登陆过程中对密码进行加密传送,而且对登陆后执行的命令的数据也进行加密,这样即使别人在网络上监听并截获了你的数据包,他也看不到其中的内容;
1. SSH登录安全性由非对称加密保证,一次产生两个密钥,一个公钥
,一个私钥
,一般命名为id_rsa.pub, id_rsa;
2. 私钥保存在本地主机,公钥保存在远程机器上(github);
3. SSH公钥免密登录原理
,就是用户将自己的公钥储存在远程主机上。
a. 登录时,本地主机向远程主机发送一个登录请求;
b. 远程收到消息后,随机生成一个字符串并用公钥加密,发回给本地;
c. 用户用自己的私钥加密收到的字符串后,再发回来;
d. 若收到的字符串与步骤b的源字符串等同,就证明用户是可信的,直接允许登录shell,不再要求密码
XSS
跨站脚本攻击(Cross Site Script):通过篡改网页,注入恶意的HTML,当用户浏览网页时,通过脚本控制用户进行恶意操作
跨站
的含义:不是直接攻击服务器,而是通过控制正常访问的用户进行攻击…
反射型XSS:攻击者诱使用户点击一个包含恶意脚本的链接…
持久型:攻击者将恶意脚本提交到被攻击的服务器数据库中
,用户正常访问网站时从数据库得到恶意脚本,从而被控制…
解决办法:消毒(即对用户提交的危险字符进行过滤);httpOnly
CSRF
跨站请求伪造(Cross Site RequestForgery):利用跨站请求,在用户不知情的情况下,以用户的身份伪造请求.
与XSS的区别:XSS含有脚本,通过脚本控制用户,当然脚本也能伪造请求实现CSRF;而CSRF只是单纯地诱导用户发出恶意请求(攻击者给的链接就是恶意请求),并没有使用恶意脚本在用户浏览器执行,CSRF举例如下:
解决办法:
表单token
(每个页面包含随机数,CSRF无法获取);
验证码
;
Referer Check
(它记录着请求来源,从而识别恶意请求不是来自用户 => 不过像上面例子中恶意请求链接就来自要攻击的服务器,Referer Check没有作用)
正:用户 -> dl-> csdn => 即为客户端dl(用户知道访问的结果来自哪里,比如这里的csdn
)
反:用户 -> nginx ->tomcat => 即为服务端dl(用户不知道访问的结果来自哪里,因为nginx背后有一堆tomcat服务器
,但是服务器知道请求来自哪个用户)
定义
假设当前页面为url1,且在当前页面发起一个请求url2。若url2与url1的协议、域名、端口三者中有任意一个不相同,则称为ky。
为什么要有ky限制
为了安全,浏览器限制了ky访问
,也就是不能ky请求资源。浏览器的ky限制(同源策略)体现在以下方面:
1. 无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB
2. 无法接触非同源网页的 DOM
3. 无法向非同源地址发送 AJAX 请求
可见有了ky限制,可以防止js脚本恶意读取用户在其他网站的信息;
但随之而来的问题是无法ky发起普通的ajax请求
jsonp通过script标签的src可以ky请求的特性,加载资源
(script标签可ky,ajax不可ky)参考:什么是ky?ky解决方法
cookie:cookie是浏览器端存储的一组数据,不同的网站对应的cookie分开存放(因而cookie不能ky
),访问某个网站时,浏览器会将该网站对应的cookie写入请求头的cookie字段(包括sessionID以及cookie中的其他k-v信息)
session:session是服务器端存储的数据,常用于存储用户信息(不管用户是否登录),一个session由一个sessionID标志它。用户首次访问网站(尚未登录)时,tomcat会生成一个session并将sessionID写入浏览器的cookie中,用户后续登录时可以将登录用户的信息写入session方便后续使用。
cookie+session:由上可知,cookie+session可用于跟踪会话,关键点就是sessionID。tomcat将sessionID写入浏览器端cookie中,服务端根据请求中的sessionID识别用户。由于tomcat中的session不能多个服务端共享,给单点登录造成麻烦 => 改用token
token:为了方便多个服务端共享用户信息,通常使用redis缓存登录用户的信息(而不再是tomcat生成session并存储在单个服务端),redis中一个用户的信息由一个token标志。由此可见token类似于sessionID,都是用于识别用户
token与sessionID的区别个人见解
1.sessionID由tomcat生成;token由后端程序员生成
2.sessionID由tomcat写入浏览器的cookie中;token可以由后端程序员写入浏览器cookie中,也可以直接返回给前端,由前端程序员选择保存策略(如存在localStorage中等)
3.即使没有登录的客户端也会生成并写入sessionID;token只针对登录用户
4.只要没有禁用cookie,每次请求都会通过cookie字段携带sessionID;如果token保存在cookie中,自然会出现在请求头的cookie字段。如果token不是保存在cookie中,用户的身份验证则需要通过将token写入请求url或者参数中
补充:登录流程如下
1.传统登录流程
2.单点登录流程
与传统的登陆方式相比本质上没有变化,标志信息都需要保存到cookie中,只是前者在浏览器端保存sessionId后者保存token;单点登录使用redis代替了tomcat保存用户信息
Set-Cookie
字段,它指明需要在浏览器的cookie中保存的信息,向浏览器cookie中写信息需满足一下规则:二级域名可以将cookie写入到主域名下。 A.taotao.com(响应从这里返回) => taotao.com(浏览器可以在这个主域名下写入cookie)
二级域名之间不能互相写入,a.taotao.com 不能写入到 b.taotao.com
默认情况下PUT、DELETE请求体中无法传递参数,因为tomcat对这两个请求不会解析表单 => 需在web.xml中配置过滤器
详见:解决Ajax中Restful风格PUT和DELETE请求传递参数无效