计算机网络-自顶向下方法 读书笔记

运输层

一 为何有些应用依然适用udp而不是可靠的tcp

*1 udp没有拥塞控制,而tcp的可靠传输/拥塞控制会不停重试/等待 确认数据发送成功,对于一些延迟容忍度低的应用比如电话会议音视频会议不可接受,另外如果需要处于重压状态下依然能够正常运行,这时候会选择udp而不是受拥塞控制的tcp【难以实现】

2 udp不用握手建立链接 ,而tcp需要三次握手在大多数场景下加剧了延迟。如dns运行在udp上就是因为udp没有握手引入的延迟。而web/http建立在tcp上因为他需要非常可靠至关重要。

3 udp链接不需要维护状态,而每条tcp链接需要维护包括发送缓存/接受缓存/拥塞控制参数/序号确认号的参数,udp不需要这些,他能支持更多的活跃客户

4 udp开销小,udp报文之需要8个首部字节,而tcp报文需要20个

二 当分组丢包率低时 并且为了安全原因,某些机构阻塞udp流量 这句话怎么理机?

这里我猜测一个原因,由于udp没有拥塞机制,他可能会把某个带宽挤占满从而导致一些正常的tcp流量得不到服务/服务质量下降,为了安全/质量考虑,就把udp流量给禁掉了。

三 udp

udp机制显得很简单,从应用成收到数据后,即加上目的端口和源端口,标记长度与校验和(用于错误检测)后,直接发送给ip层了,所以他没有任何可靠性与拥塞控制性。

这样的特征也使得udp像是网络上的流氓协议[没有任何自我约束,抢占带宽】,

另外报文也不进行分割,应用层一次传多少数据下来就当作一个报文。

此外,由于udp传输之前不需要建立连接,他可以用于多播,而面向连接的点到点的tcp是不能的。

四 可靠传输原理

这部分是为了介绍tcp的可靠传输铺垫的,tcp总的来说有三大特征

可靠传输(差错恢复),流量控制(注意这里值得是端到端的流量控制),拥塞控制(对网络状态负责的流量控制),【尽管后面两个的控制的实现方式一致,但解决的问题不一样需要注意。】

可靠传输需要借用的技术

注意:这里指考虑单工,即A向B发送数据,其实双工也是类似,只不过为了简化描述。

1 通过接收端的确认机制

发送端发送一个数据报文,接收端收到后回复ack,尔后发送端再次发送。这种叫做停等协议。

考虑一种情况,如果回复的ack丢失了or出错了怎么办?

解决办法是引入序号机制+超时重传机制,即ack需要带上对确认报文的序号(当然发送的报文刚开始必须要有序号),如果发现没有收到改ack,则发送端超时了再发送上次的报文。

那么问题来了,超时的时间如何确定?发送方多久没有收到期望的ack表示即超时了?

这里至少需要等待一个rtt时间,当然更精确的时间tcp在实践中后面会讲述到。

2 考虑效率

这种停等协议的效率其实是很低的,网络带宽很大,你停停等等的发送数据,会让带宽大部分时间都处于闲置状态,这里就引入了流水线,即不等上一个报文的ack收到,发送方继续发送报文,比如继续发送3个报文

如果采用了流水线机制,会引入问题,如果真的有丢包产生,即期望ack迟迟未到而超时,此时发送端应该如何?这里有两种办法:回退N和选择重传。

这里引入一个值N:允许发送方发送多个分组而不需要等待确认。这个N也叫做滑动窗口大小

其中从32到51即为滑动窗口,其中32-45是已经发送出去的但还没被ack的,46-51是发送端可以继续发送的。

如果收到的ack还是对32的ack

如果选择回退N,那么就要把从32到45的数据再发送一次。反之如果收到了ack 33,则滑动窗口可以向右移动一个。

当然这种回退N的做法比较粗糙,可能32没到,但33-40这些都能够收到了,所以就有了选择重传,不过这需要接收端的配合:是否采用累计ack机制,如果采用累计ack[即每次ack已经收到的最小连续有序的报文的末尾的那个ack,而不ack无序的报文]

这里涉及到的几个技术,包括定时器、序号、确认号、ack等技术都会在tcp中用来实现可靠传输。

三 tcp

上面讲了tcp主要有三个方面,首先来看可靠传输是如何运用上面讲述的原理实践的。

在之前线介绍下tcp连接与报文结构

1 tcp是端到端的连接,是一条逻辑连接,一条连接的状态仅保留在【两个通信端】的tcp程序中,而中间的设施(包括路由器交换机等)都没有。

2 tcp是全双工

3 关于mss与mtu:tcp在组装tcp报文时,他从应用层收到数据后会按照一定大小进行切割,这个大小就是mss,而mss取决于mtu,mtu表示最大链路层帧的长度,一般以太网和ppp链路为1500字节,所以典型的mss一般为1500-20-20=1460,其中20+20为tcp的头部与ip头部长度。

所以一个文件通过tcp传输时会被切割为一个个mss长度的数据然后被组装起来。

4 tcp报文结构:源端口号/目的端口号,序号/确认号,首部长度/标记字段,接受窗口,校验和/紧急数据指针。一般情况为20字节。

5 最重要的两个字段时序号/确认号:这里tcp是流式的协议,这里序号/确认号也都是字节的编号,序号标记了本报文在整个报文段(文件被划分为多个报文段)中的首字节的编号。确认号是期望对方下次发送报文的序号。

可靠传输

6 重传时间的管理:timeoutinternla=estimaterRTT + 4 * DevRTT,这里estimateRTT表示评估下来的rtt时间,他时刻处于动态变化中,estimateRTT=EstmateRTT * a + (1-a) * samepleRTT,其中simpleRTT是上次实际的RTT,在实际中a一般取值1/8,可见把实际RTT的赋值权重更高,而DevRTT则表示RTT的方差,因为要考虑RTT的起伏变化。总的来说时间就是对RTT的一个预估值。

7关于快重传与delay ack: 如果服务端收到了三次冗余的ack,则服务端会立即重传该报文而不必等待超时。delay ack:如果一切都正常,那么客户端不会立即发送ack,而会等待一段时间后看是否还有连续正常的数据到来,这时候发送对后面数据的ack,这样效率更高(因为是累积ack),具体时间约为(500ms)

8 tcp到底是一个回退N还是选择重传的实现:其实是两者的一个折衷结合。

流量控制

第二个点是tcp的流量控制,这里注意不是拥塞控制,

1 流量控制是指发送方要考虑到接收方的接受能力,不能发的太快导致接收方应用程序接受不及时而溢满了对方的接受缓冲区。

2 本质上流量控制和拥塞控制都是通过对发送方发送速率的限制来达到目的。

3 流量控制的核心是:每个tcp连接让发送方维护一个接受窗口,接受窗口表示对方还有多少空间可以被接受,通rwnd表示。发送方需要注意的是发送到连接中但未被确认的数据量 不能超过rwnd,这样可以保证不会使接收房接受缓存益处。

考虑到一个极端情况,如果发送方发现接受方的rwnd为0了,此时发送方不在发送数据,但接收方会慢慢消化自己的缓存,但接收方并不会主动通知发送方【只有接受方在有数据or有确认时才会给发送方发报文),这样就陷入了僵局,为了解决这个问题,tcp规定当rwnd为0后,发送方继续发送只有一个字节数据的报文段,这样将会打破僵局:接受方如果收到该报文并进行ack回报时将会告知发送方的rwnd已经不为0,一切就恢复过来了。

4 udp没有流量控制,所以接受方如果不能及时从接受缓冲中读取到数据(or读取不够快),会有缓存益处并丢失报文的问题。

拥塞控制

最后一个特征是拥塞控制,他的核心目标是为了高效地使用带宽但同时又不至于将网络阻塞到淹没。

1 拥塞窗口 cwnd:对一个tcp发送方向网络中能够发送的速率进行限制。结合前面说到的接受窗口,真实场景下tcp能够发送未确认的数据量不能超过 rwnd与cwnd的最小值。

这里有三个问题

tcp如何限制往一条连接上的发送速率?

tcp如何感知到拥塞了?

tcp采用何种算法进行限制速率f发送?

第一个问题 即调整cwnd的大小即可限制,第二个问题,tcp目前是通过超时以及收到三个冗余ack来进行主观判断。第三个问题是拥塞控制算法

目前tcp常见的拥塞控制算法是:慢启动+拥塞避免+快速恢复

慢启动:按照指数方式扩大cwnd的值,没收到一个ack就扩大一个wcnd,直到发送丢包or收到三个冗余ack,

接下来进入拥塞避免,将wcnd的值调整为当前值的一半,然后每次增加一个cwnd,直到拥塞。以此循环。

目前有一些改良优化的拥塞算法,如bbr等。

4最后谈下拥塞与公平

1tcp为了让道路更通畅,自觉地启用了拥塞控制,而udp没有,所以他是一种不合作的协议。

几个有趣的问题

1 syn flood以及如何避免?

在tcp三次握手时,client首先发送syn包保文,且附带自己的client_isn(序列号)[一般为了安全改isn为随机生成], server收到改syn后,一般来说会开始分配资源,包括缓存、socket、链接状态维护等资源,但如果client是恶意的发送大量的syn并不是想真实建立连接此时服务器将被大量的分配无效资源导致资源枯竭进而导致正常的连接服务不了。

解决办法:如果收到client的syn后,此时服务端并不确认该syn是否为真实有效的syn还是恶意的flood,为了区分,此时server并不急于为此分配资源,而是将生成一个序列号,此序列号为源ip/目的ip/源端口以及只有server内置知道的一个密钥而组成的散列后的值,然后给client回送过去syn+ack的包,注意这里服务端并没有记录任何关于连接的信息,只是回送了一个包【该包的序号为上面的散列值】,也就是并没有任何资源开销。接着,如果客户端会回送一个ack【如果不回送那么server也不损失任何】,服务端需要校验下,他从ack包的ack字段中提取之前的值,如果该值等于 源ip/源端口/目的ip+自己知道的蜜钥组成的散列值-1,则能够确认该ack是合法client回送过来的,此时server将开始为期分配资源。

这个解决办法的核心在于,服务端并不维持任何相关信息【没有资源开销也就没构成攻击】,这个信息是让client带过来的,所以有点类似cookied的使用,故而将这种解决办法称之为syn cookie。

2 mmap

mmap用来扫描端口是否开启,mmap工作原理是发送一个syn包,如果收到了syn+ack说明该端口开了,如果收到一个rst,说明端口没开,而且还有进一步信息:说明mmap与被探测服务间 没有防火墙把这个syn丢掉。如果没有收到任何包,说明这之间有防火墙将syn丢了。

3 client在关闭连接时,time_wait状态为啥最后需要等待2个rtt后才能最终断掉

一是,client最后给server发送了ack(答复server发过来的fin),如果该ack丢了server会继续发fin,此时如果client提早退出则server收不到ack会处于非期望状态,所以要等一等。

二是,这个等待时间也是为了让该条连接上所有的“脏数据包”都消失掉,防止重新建立的连接使用了同样的端口而导致数据污染。

这也是为啥client端立即关闭的端口不能被使用的原因,当然这个time_wait一半都是主动断开的一方留住,在现实场景中也一般都留给了client。

一般来说close_wait留在被动关闭的一方【通常是服务端】,而且时间会很短【服务端不会等待太久再发fin】,如果你看到有过多的close_wait说明没有及时发出fin,一般来说的原因:1 程序不健壮走入了没close fd的分支,2 服务端太忙。

4 在关闭连接时,如果client发送了fin也收到了ack,但服务端一直不发送fin,此时client会怎么样?

这样场景通常是服务端恰好挂了 or 服务端太忙处理不过来来不及发fin,此时client应该要设定一个超时事件(主动关闭掉该连接),否则一直等下去会浪费资源

四 ip层

应用层和运输层是处于网络边缘端上的行为,接下来ip层是网络核心的行为,包括交换机/路由器等。

==============

1 为何需要三次握手,两次握手可以吗

有下面的情况:

1 如果是两次握手的场景,client第一次发送的syn由于网络链路原因被阻塞了,因此经过一段时间后client没有收到回复认为这个syn丢失了,此次再次发起第二个syn,这个syn由于走了不同的路 此时很快到了server,server也回复了,然后两个开始传输数据 然后结束回话。但开始的那个syn经过一段时间后被传送到了server,此时server不知道这个是个无效的syn,并再次回复了,如果只有两次握手,那么在服务端就建立了一个无效的连接(client端并不知道)并等待client发送数据,这样会对server造成攻击。

如果有三次握手就能避免这种情况, client收到server的回复后知道这个链接不是他想要的,这样就会发出rst让服务端知道并关闭连接了。

2 tcp发送窗口是什么意思

是指在不需要对方确认情况下,发送端可以一次性发送多少的字节数。

发送窗口受到两个因素制约(对方通告的接受窗口和网络探测到的拥塞窗口)的较小值。

所以从包中不一定能显示看出发送窗口实际大小(包只能看到发出方自己宣告自己的接受窗口是多少),需要结合上下文。其中接受窗口由自己(也可以说是对方)的协议栈设计就可以确认,包括对目前自己该sockfd上还有多少数据未处理等。

另外发送窗口是随着时间变化的(从上面含义也可以确认),tcp两端都有各自计算出的发送窗口(根据对端和对网络拥塞窗口的计算判断)。

这里就宣告172.17.0.17的接受窗口是64240.

如果某个包宣告自己的接受窗口是0,则告知对方没有发送窗口空间了,不能再继续朝自己发送

(窗口大小在tcp包中占16bit,如果超过2^16-1的窗口,可以用tcp options中的window scal 系数扩大倍数。 

另外mss与发送窗口大小的关系:发送窗口大小说明的是一次性可以发送多少字节,而mss表示的是一个包中可以存放多少数据。比如一次性的发送窗口可以发送16000字节,此时发送方的mss设定为1000,则可以一次性发送16个包。

而如何确认拥塞窗口则是需要手段的,由于网络链路上存在各种网络设备,每个网络设备的处理能力都不太一样,发送方要尽量避免发送太多使得丢包了(这是发送方最忌惮的),发送方当然希望把发送窗口控制在拥塞点以下。问题是连网络设备都不知道自己的拥塞点,即使知道了也无法通知发送方,如何让发送方避免触碰拥塞点

没有一个完美的方案,只能逐步试探,拥塞点是随着时间变化的。

1 连接刚建立时,发送方对网络一无所知,如果一口气发送太多就可能遭到拥塞,

所以在开始时一般认为拥塞窗口初始化为1mss,rfc建议是2个mss。

2 接着就是慢启动,1-2-4-8-16-。。。这个过程的窗口增速很快 但由于基数低,所以传输速度还是比较慢 叫做慢启动。

3 达到一个较大窗口值(这个值通常是之前发生拥塞时的窗口值),此时逐步增加 16-17-18,成为拥塞避免

这样在拥塞避免阶段一定会触发到拥塞点(即发生丢包情况)

但为何在日常中感觉不到拥塞:

* 1是很多客户端的操作系统的接受窗口值设定的比较小,这种情况下发送窗口的上限在于接受窗口,用于触碰不到拥塞点

* 2是很多场景是交互式小数据比如聊天,在慢启动阶段就已经完成了数据传输

* 3 即使偶发拥塞,时间太短感知不明显。

发送方如何判断发生了拥塞:就是发送出去的包不像之前一样及时得到ack了,不过收不到ack不一定是拥塞丢包 也可能是网络延迟导致,所以发送方决定等一等再做判断。这个等一等的时间叫做RTO,而这个过程叫做超时重传

另外这个RTO的选择也是一番讲究的。太长太短都不好。【具体可以设定】

在超时重传后,就有必要调整此时的拥塞窗口了,此时就会再次进入慢启动,将拥塞窗口降低为1-2 mss,重复之前的过程。

不难想象,超时重传会有严重的性能影响,一是RTO阶段时间内只能等待不能穿数据,二是拥塞穿够急剧减小。有些RTO可能达到树秒之久(所以一个优化手段是调小rto时间试试)

另外不一定每次丢包都需要进入超时重传过程,比如拥塞很轻微只有少量丢包,此时可以通过快重传。快重传即收到3个同样的ack后,就知道这个包需要重传了「这里为何是凑满3个?,因为网络包也会有时序,乱序的情况一样会触发dup ack,但乱序并不是丢失,所以需要再等等看是否真的是乱序还是丢失了/】

如果发送了快重传,其实没有必要降低拥塞窗口的【说明目前网络状态还可以】。

对于快重传这个问题,其实还有另外一个场景需要考虑:如果丢的包有几个而不是一个,此时dup ack可能只是序号前的一个,而序号后的一个没有dup ack,此时即使快重传了也还是缺失,此时有几个选择:

1 将dup ack的后面的包都重传一次,这是早期的tcp实现,效率较低

2 比如dup ack 2之后重传2后,如果继续此时还会收到dup ack 3,再重传3即可,一直到dup ack 9 这样就补齐了。这是NewReno方案

3 方案3是 将每次ack时顺便告知对方自己已经收到的序号,因此发送方对丢包细节就更清楚了解了,这就是SACK

几个小结:

1 没有拥塞时 发送窗口越大越好,如果经常发送拥塞,此时限制发送窗口反而更好,因为拥塞对性能影响会很大。

2 超时重传对影响最大(RTO时间 + 锐减拥塞窗口

3 快重传影响很小,没有RTO时间也不减小拥塞窗口

4 丢包对于小文件的影响比大文件要严重许多:大文件由于可以利用dup ack来启动快重传(后续的包多,启动dup ack几率更大),但小文件几乎没有太多后续包,只能启用超时重传

DNS

1 A记录 :直接用于转换domian/ip的记录,比如:

canme: 其实是domain的别名,为何要有别名,比如:www.example.com   mail.example.com map.example.com 都指向的是同一样ip,但如果为每个这样的域名都记录一下在dns系统中,有一些浪费资源,如果能够将mail.example.com / map.example.com 映射到某个cname,这个canme再通过A记录指向ip,这样就后面如果更换ip就只需要更换这个cname即可,做到统一了。

比如这里:

www.baidu.com映射到了www.a.shifen.com这个cname上,这个cname对应的A记录为真实的ip。

再比如www.taobao.com也是通过cname来做映射:

映射到的是www.taobao.com.danuoyi.tbcache.com 

另外cname也可以层层叠套:

cname是一个为了管理方便引入的手段。

dig使用

可以指定去哪个服务器上去查:

dig @8.8.8.8 www.baidu.com

如果没有 指定则会默认使用/etc/resolv.conf作为默认dns地址

可以看到是dig是是查的默认这个地址的情况

srv记录
srv与A/cname不同,他能表现的信息更丰富,包括端口,包括优先级权重等,可以用来做负载均衡

# _服务._协议.名称.       TTL   类别  SRV 优先级   权重    端口 主机.
_sip._tcp.example.com.   86400 IN    SRV 10       60     5060 bigbox.example.com.
_sip._tcp.example.com.   86400 IN    SRV 10       20     5060 smallbox1.example.com.
_sip._tcp.example.com.   86400 IN    SRV 10       20     5060 smallbox2.example.com.
_sip._tcp.example.com.   86400 IN    SRV 20       0      5060 backupbox.example.com.

_Service._Proto.Name TTL Class SRV Priority Weight Port Target

比如类似

_http._tcp.example.com.    SRV 10 50   443   www.test1.com

_http._tcp.example.com.    SRV 10 50   443   www.test2.com

_http._tcp.example.com.    SRV 10 50   443   www.test3.com

Dns的缺点:

1 安全性,很容易被伪造为不同域名看上去一样的钓鱼网站。【这里就需要ssl来通过证书等pki基础设施解决了

2 dns服务器污染

2 dns放大攻击

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值