02-常见的面试题目-TCP
TCP是在IP网络层之上的传输层协议,用于提供port到port面向连接的可靠的字节流传输。
port到port:IP层只管数据包从一个IP到另一个IP的传输,IP层之上的TCP层加上端口后,就是面向进程了,每个port都可以对应到用户进程。
1. TCP和UDP的区别和优缺点及应用场景
https://www.cnblogs.com/GuoXinxin/p/11657676.html
①TCP协议是有连接的,有连接的意思是开始传输实际数据之前TCP的客户端和服务器端必须通过三次握手建立连接,会话结束之后通过四次挥手结束连接。而UDP是无连接的
②TCP协议保证数据按序发送,按序到达,提供超时重传来保证可靠性,但是UDP不保证按序到达,甚至不保证到达,只是努力交付,即便是按序发送的序列,也不保证按序送到。
③TCP有流量控制和拥塞控制,而UDP没有,所以UDP即使网络拥堵客户端的发送速率也不会有影响
④TCP协议所需资源多,TCP首部需20个字节(不算可选项),UDP首部字段只需8个字节。
⑤TCP只支持一对一通信,而UDP支持一对一,一对多,多对多通信
⑥TCP是面向字节流,可靠的服务,,发送的是一个流数据。UDP是面向报文,不可靠的服务,一个一个的发,一个一个的收。
⑦TCP注重数据安全性,UDP数据传输快,因为不需要连接等待,少了许多操作,但是其安全性却一般
采用TCP传输协议的MSN比采用UDP的QQ传输文件慢
但并不能说QQ的通信是不安全的,因为程序员可以手动对UDP的数据收发进行验证, 比如发送方对每个数据包进行编号然后由接收方进行验证什么的。
2. TCP三次握手及原因
为什么不能进行两次握手?
现在把三次握手改成仅需要两次握手,死锁是可能发生的。作为例子,考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,S收到了这个分组,并发 送了确认应答分组。按照两次握手的协定,S认为连接已经成功地建立了,可以开始发送数据分组。可是,C在S的应答分组在传输中被丢失的情况下,将不知道S 是否已准备好,不知道S建立什么样的序列号,C甚至怀疑S是否收到自己的连接请求分组。在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分组,只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。这样就形成了死锁。
3. 三次握手过程中有哪些不安全性
1)伪装的IP向服务器发送一个SYN请求建立连接,然后服务器向该IP回复SYN和ACK,但是找不到该IP对应的主机,当超时时服务器收不到ACK会重复发送。当大量的攻击者请求建立连接时,服务器就会存在大量未完成三次握手的连接,服务器主机backlog被耗尽而不能响应其它连接。即SYN泛洪攻击 ,(属于DOS的一种,发送大量的半连接请求,耗费CPU和内存资源,引起网络堵塞甚至系统瘫痪)
当你服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN攻击。在Linux下可以如下命令检测是否被Syn攻击
netstat -n -p TCP | grep SYN_RECV
防范措施:
1、降低SYN timeout时间,使得主机尽快释放半连接的占用
2、采用SYN cookie设置,如果短时间内连续收到某个IP的重复SYN请求,则认为受到了该IP的攻击,丢弃来自该IP的后续请求报文
3、在网关处设置过滤,拒绝将一个源IP地址不属于其来源子网的包进行更远的路由
2)当一个主机向服务器发送SYN请求连接,服务器回复ACK和SYN后,攻击者截获ACK和SYN。然后伪装成原始主机继续与服务器进行通信
4. TCP四次挥手及原因
5. 为什么TCP可以可靠传输
拥塞控制,流量窗口,慢启动,快重传,快恢复。。。。
6. TIME_WAIT状态持续时间及原因
- 为了可靠的断开TCP连接,假设最后客户端回复的ACK丢失,服务器端会在超时时间到来时,重传最后一个FIN包。ACK和FIN在网络中的最长生存时间就为2MSL,这样就可以可靠的断开TCP的双向连接。
- 一个数据包在网络中的最长生存时间为MSL,持续2MSL时间,可以让上一次连接的数据包在网络中消失,以防影响下一次连接。
所谓的2MSL是两倍的MSL(Maximum Segment Lifetime最大 报文段存活时间(往返时间))。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。
7. 超时重传和快速重传
- 超时重传:当超时时间到达时,发送方还未收到对端的ACK确认,就重传该数据包
- 快速重传:当后面的序号先到达,如接收方接收到了1、 3、 4,而2没有收到,就会立即向发送方重复发送三次ACK=2的确认请求重传。如果发送方连续收到3个相同序号的ACK,就重传该数据包。而不用等待超时
8. TCP首部长度,有哪些字段(画出TCP报文)?及TCP选项有哪些?
最少20字节,因为TCP的头部中20字节的首部是固定的
TCP首部选项字段多达40B,一些常用的字段有:
1)选项结束字段(EOP,0x00),占1B,一个报文段仅用一次。放在末尾用于填充,用途是说明:首部已经没有更多的消息,应用数据在下一个32位字开始处
2)无操作字段(NOP, 0x01),占1B,也用于填充,放在选项的开头
3)MSS(最大报文段长度),格式如下:种类(1B,值为2),长度(1B,值为4),数值(2B)
用于在连接开始时确定MSS的大小,如果没有确定,就用默认的(一般实现是536B)
4)窗口扩大因子,格式如下:种类(1B,值为3),长度(1B,值为3),数值(1B)
新窗口值 = 首部窗口值 * 2的(扩大因子)次方
当通信双方认为首部的窗口值还不够大的时候,在连接开始时用这个来定义更大的窗口。仅在连接开始时有效。一经定义,通信过程中无法更改。
5)时间戳(应用测试RTT和防止序号绕回)
6)允许SACK和SACK选项
9. TCP在listen时的参数backlog的意义
linux内核中会维护两个队列:
1)未完成队列:接收到一个SYN建立连接请求,处于SYN_RCVD状态
2)已完成队列:已完成TCP三次握手过程,处于ESTABLISHED状态
当有一个SYN到来请求建立连接时,就在未完成队列中新建一项。当三次握手过程完成后,就将套接口从未完成队列移动到已完成队列。
backlog曾被定义为两个队列的总和的最大值,也曾将backlog的1.5倍作为未完成队列的最大长度,一般将backlog指定为5 。
10. accept发生在三次握手的哪一步
accept会监听已完成队列是否非空,当队列为空时,accept就会阻塞。当队列非空时,就从已完成队列中取出一项并返回。
而已完成队列中的都是三次握手过程已经完成的,因此accept发生在三次握手之后。
三次握手是发生在connect函数中,connect函数执行成功就相当于已经建立三次握手
11. 有哪些应用层协议是基于TCP的,哪些是基于UDP的
- TCP: FTP、HTTP、Telnet、SMTP、POP3、HTTPS
- UDP:DNS、SNMP、NFS
12. TCP报文长度是在TCP三次握手中哪一次确定的(第三次)
这个是关于TCP报文的最大报文段长度mss的相关问题。在TCP连接的前两次握手中(SYN报文中),通信双方都会在选项字段中告知对方自己期待收到最大报文长度(mss值),以双方两个SYN报文中最小的mss最为本次数据传输的mss值。通信双方以“协商”的方式来确定报文长度的,前两次握手是告诉对方自己的mss值,在第三次握手确定mss值。
13. TCP报文长度是由什么确定的
这个跟具体传输网络有关,以太网的MTU为1500字节,Internet的MTU为576字节。
MTU是网络层的传输单元,那么MSS = MTU - 20字节(IP首部) - 20字节(TCP首部)。所以以太网的MSS为1460字节,而Internet的MSS为536字节。
14. 如果TCP连接过程中,第三次握手失败怎么办
server端发送了SYN+ACK报文后就会启动一个定时器,等待client返回的ACK报文。如果第三次握手失败的话client给server返回了ACK报文,server并不能收到这个ACK报文。那么server端就会启动超时重传机制,超过规定时间后重新发送SYN+ACK,重传次数根据/proc/sys/net/ipv4/tcp_synack_retries来指定,默认是5次。如果重传指定次数到了后,仍然未收到ACK应答,那么一段时间后,server自动关闭这个连接。但是client认为这个连接已经建立,如果client端向server写数据,server端将以RST包响应,方能感知到server的错误。
15. DOS攻击 拒绝服务攻击
DoS(分布式拒绝服务攻击) DOS攻击利用合理的服务请求占用过多的服务资源,使正常用户的请求无法得到响应。
常见的DOS攻击有计算机网络带宽攻击和连通性攻击。
- 带宽攻击指以极大的通信量冲击网络,使得所有可用网络资源都被消耗殆尽,最后导致合法的用户请求无法通过。
- 连通性攻击指用大量的连接请求冲击计算机,使得所有可用的操作系统资源都被消耗殆尽,最终计算机无法再处理合法用户的请求。
16. 死亡值ping ???
许多操作系统的TCP/IP协议栈规定ICMP包大小为64KB(网间控制报文),且在对包的标题头进行读取之后,要根据该标题头里包含的信息来为有效载荷生成缓冲区。 ”死亡值ping”就是故意产生畸形的测试ping包,声称自己的尺寸超过ICMP上限,也就是加载的尺寸超过64KB上限,使未采取保护措施的网络系统出现内存分配错误,导致TCP/IP协议栈崩溃,最终接收方宕机。 图
17. 画一下TCP的状态转移图
18. 如果已经建立了连接,但是客户端突然出现故障了怎么办?
TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。
服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。
19. 为什么连接的时候是三次握手,关闭的时候却是四次握手
因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。
21. 通过TCP协议建立连接的两方,如果一方突然发生故障(比如断电)断开了连接,那么一下说法错误的是()?
-
A: TCP协议会自动检测连接是否断开,经过一段时间后另外一段会收到TCP连接断开的通知
-
B: 如果设置了TCP_KEEPALIVE,那么对端能够马上收到断开的信息
-
C: 可以自己实现心跳检测的方法来确定对方是不是已经断开连接
-
D: 另外一方能够马上知道连接已经断开
正确答案:A B D
TCP连接不能自动检查断连的现象; 所以A选项错误
20. TCP中出现RST包的几种情况
在TCP协议中RST表示复位,用来异常的关闭连接,在TCP的设计中它是不可或缺的。发送RST包关闭连接时,不必等缓冲区的包都发出去,直接就丢弃缓存区的包发送RST包。而接收端收到RST包后,也不必发送ACK包来确认。
共有四种情况:
1 端口未打开
服务器程序端口未打开而客户端来连接。这种情况是最为常见和好理解的一种了。去telnet一个未打开的TCP的端口可能会出现这种错误。这个和操作系统的实现有关。在某些情况下,操作系统也会完全不理会这些发到未打开端口请求。
比如在下面这种情况下,主机241向主机114发送一个SYN请求,表示想要连接主机114的40000端口,但是主机114上根本没有打开40000这个端口,于是就向主机241发送了一个RST。这种情况很常见。特别是服务器程序core dump之后重启之前连续出现RST的情况会经常发生。
当然在某些操作系统的主机上,未必是这样的表现。比如向一台WINDOWS7的主机发送一个连接不存在的端口的请求,这台主机就不会回应。
2 请求超时
曾经遇到过这样一个情况:一个客户端连接服务器,connect返回-1并且error=EINPROGRESS。 直接telnet发现网络连接没有问题。ping没有出现丢包。用抓包工具查看,客户端是在收到服务器发出的SYN之后就莫名其妙的发送了RST。
比如像下面这样:
有89、27两台主机。主机89向主机27发送了一个SYN,表示希望连接8888端口,主机27回应了主机89一个SYN表示可以连接。但是主机27却很不友好,莫名其妙的发送了一个RST表示我不想连接你了。
后来经过排查发现,在主机89上的程序在建立了socket之后,用setsockopt的SO_RCVTIMEO选项设置了recv的超时时间为100ms。而我们看上面的抓包结果表示,从主机89发出SYN到接收SYN的时间多达110ms。(从15:01:27.799961到15:01:27.961886, 小数点之后的单位是微秒)。因此主机89上的程序认为接收超时,所以发送了RST拒绝进一步发送数据。
3 提前关闭
关于TCP,我想我们在教科书里都读到过一句话,'TCP是一种可靠的连接'。 而这可靠有这样一种含义,那就是操作系统接收到的来自TCP连接中的每一个字节,我都会让应用程序接收到。如果应用程序不接收怎么办?你猜对了,RST。
例子:
server:监听一个TCP端口然后当有客户端来连接的时候fork一个子进程来处理。每次只是读socket的前4096个字节,然后就关闭掉连接。
client:打开一个socket然后连接一个服务器并发送5000个字节。刚才我们看服务器的代码,每次只接收4096个字节。
那么就是说客户端发送的剩下的4个字节服务端的应用程序没有接收到,服务器端的socket就被关闭掉。
这种情况下会发生什么状况呢,还是抓包看一看。
前三行就是TCP的3次握手,从第四行开始看,客户端的49660端口向服务器的9877端口发送了5000个字节的数据,然后服务器端发送了一个ACK进行了确认,紧接着服务器向客户端发送了一个RST断开了连接。和我们的预期一致。
4 在一个已关闭的socket上收到数据
如果某个socket已经关闭,但依然收到数据也会产生RST。
客户端在服务端已经关闭掉socket之后,仍然在发送数据。这时服务端会产生RST。
21. 服务端几种情况下的操作:
如果客户端已经接受到一个RST数据报的时候,这个时候在向服务器端发送数据的时候,内核会向客户端进程发送一个SIGPIPE信号,是客户端进程结束。
服务器主机崩溃的状态:
如果,客户端和服务器已经建立了连接的时候,此时服务器崩溃(达到这一标准可以把服务器的网线拔掉,这个时候,服务器就不能发送FIN数据报了,和关机不一样的)
此时如果客户端向服务器发送数据的时候,因为服务器已经不存在了,那么客户端就不能接受到服务器给客户端的ack信息,这个时候,客户端建立的是TCP连接,就会重发数据报,发送多少次之后就会返回超时,前面所说的ETIMEOUT。
服务器主机崩溃后重启:
当客户端和服务器已经建立连接的时候,服务器发生崩溃,重新启动的时候,丢失了原来和客户端的连接信息,这个时候,当客户端向服务器发送数据的时候(客户端并不知道,服务器已经忘记三次握手了),此时服务器发送RST数据报,就结束了客户端的发送。
服务器关机:
会断开tcp连接,会发送FIN数据报
22. 从TCP协议的原理来谈谈rst复位攻击
TCP是在IP网络层之上的传输层协议,用于提供port到port面向连接的可靠的字节流传输。
port到port:IP层只管数据包从一个IP到另一个IP的传输,IP层之上的TCP层加上端口后,就是面向进程了,每个port都可以对应到用户进程。
1、为了能够说清楚下面的RST攻击,需要结合上图说说:SYN标志位、序号、滑动窗口大小。
建立连接的请求中,标志位SYN都要置为1,在这种请求中会告知MSS段大小,就是本机希望接收TCP包的最大大小。
发送的数据TCP包都有一个序号。它是这么得来的:最初发送SYN时,有一个初始序号,根据RFC的定义,各个操作系统的实现都是与系统时间相关的。之后,序号的值会不断的增加,比如原来的序号是100,如果这个TCP包的数据有10个字节,那么下次的TCP包序号会变成110。
滑动窗口用于加速传输,比如发了一个seq=100的包,理应收到这个包的确认ack=101后再继续发下一个包,但有了滑动窗口,只要新包的seq与没有得到确认的最小seq之差小于滑动窗口大小,就可以继续发。
2、滑动窗口
滑动窗口毫无疑问是用来加速数据传输的。TCP要保证“可靠”,就需要对一个数据包进行ack确认表示接收端收到。
- 有了滑动窗口,接收端就可以等收到许多包后只发一个ack包,确认之前已经收到过的多个数据包。
- 有了滑动窗口,发送端在发送完一个数据包后不用等待它的ack,在滑动窗口大小内可以继续发送其他数据包。
举个例子来看吧。
标志位为.表示所有的flag都为0。标志位P表示flag为PSH的TCP包,用于快速传输数据。
前三个包是三次握手,客户端表示自己的滑动窗口大小是65535(我的XP机器),服务器端表示滑动窗口是5840(屏幕宽了,没截出来)。从第四个包开始,客户端向服务器发送PSH包,数据长度是520字节,服务器发了ack确认包。注意此时win窗口大小发生了改变哈。以此类推。
倒数第二、三包,服务器在滑动窗口内连续向客户端发包,客户端发送的ack 124同时确认了之前的两个包。这就是滑动窗口的功能了。
3、RST攻击
A和服务器B之间建立了TCP连接,此时C伪造了一个TCP包发给B,使B异常的断开了与A之间的TCP连接,就是RST攻击。
那么伪造什么样的TCP包可以达成目的呢?我们至顶向下的看。
假定C伪装成A发过去的包,这个包如果是RST包的话,毫无疑问,B将会丢弃与A的缓冲区上所有数据,强制关掉连接。
如果发过去的包是SYN包,那么,B会表示A已经发疯了(与OS的实现有关),正常连接时又来建新连接,B主动向A发个RST包,并在自己这端强制关掉连接。
这两种方式都能够达到复位攻击的效果。似乎挺恐怖,然而关键是,如何能伪造成A发给B的包呢?这里有两个关键因素,源端口和序列号。
一个TCP连接都是四元组,由源IP、源端口、目标IP、目标端口唯一确定一个连接。所以,如果C要伪造A发给B的包,要在上面提到的IP头和TCP头,把源IP、源端口、目标IP、目标端口都填对。这里B作为服务器,IP和端口是公开的,A是我们要下手的目标,IP当然知道,但A的源端口就不清楚了,因为这可能是A随机生成的。当然,如果能够对常见的OS如windows和linux找出生成source port规律的话,还是可以搞定的。
序列号问题是与滑动窗口对应的,伪造的TCP包里需要填序列号,如果序列号的值不在A之前向B发送时B的滑动窗口内,B是会主动丢弃的。所以我们要找到能落到当时的AB间滑动窗口的序列号。这个可以暴力解决,因为一个sequence长度是32位,取值范围0-4294967296,如果窗口大小像上图中我抓到的windows下的65535的话,只需要相除,就知道最多只需要发65537(4294967296/65535=65537)个包就能有一个序列号落到滑动窗口内。RST包是很小的,IP头+TCP头也才40字节,算算我们的带宽就知道这实在只需要几秒钟就能搞定。
那么,序列号不是问题,源端口会麻烦点,如果各个操作系统不能完全随机的生成源端口,或者黑客们能通过其他方式获取到source port,RST攻击易如反掌,后果很严重。
23. OSI与TCP/IP各层的结构和功能,协议和作用
OSI七层模型对应TCP/IP四层模型,只是分法不同而已。
应用层:提供应用层服务,文件传输(FTP),电子邮件(SMTP), 主要的协议还有HTTP(超文本传输协议),DNS,和telnet
表示层:用于数据格式化,代码转换,数据加密,没有协议
会话层:解除或建立与别的接点的联系,没有协议
传输层:TCP UDP
网络层: IP ICMP(ping主要实现), OSPF(全局泛洪,主要用于IP选路)
数据链路层 ARP(地址解析协议,根据IP地址获得MAC地址)
物理层:
按照TCP/IP分的话,就四层:应用层,传输层,网络层还有不知道叫什么名字,主机到网络层?(包含物理层和数据链路层)
宿舍用的是路由器还是交换机?
22. TCP拥塞控制
拥塞控制就是防止过多的数据注入到网络中,这样使得网络中的路由器或者链路不至于过载。TCP拥塞控制方法主要包括:慢开始,拥塞避免,快重传和快恢复。
慢开始是指发送方先设置cwnd=1,一次发送一个报文段,随后每经过一个传输轮次,拥塞串口cwnd就加倍,其实增长并不慢,以指数形式增长。还要设定一个慢开始门限,当cwnd>门限值,改用拥塞避免算法。拥塞避免算法使cwnd按线性规律缓慢增长。当网络发生延时,门限值减半,拥塞窗口执行慢开始算法。
之后又提出了快重传和快恢复,见下一题
23. TCP快速重传与快速恢复原理
24. 滑动窗口协议
25. 回退n针协议
26. 选择重传协议
27. 超时重传
28. tcp/ip 端口范围
29. TCP/IP中MSL详解及MSL 字段类型范围大小字节大小
30. MSL、TTL和RTT
28. 以太网与Internet的区别
29. 找UDP编程的项目
以上收集于:
http://www.pianshen.com/article/3633335616/
https://msd.misuland.com/pd/3094725972029606300
https://blog.csdn.net/wendy_keeping/article/details/76098504
https://www.cnblogs.com/huajiezh/p/7492416.html