本文对工程网络中的知识点做下总结,基本都是用到的。真实的网络搭建:https://segmentfault.com/a/11...,二层主要有个VLAN,公司部署网络基本都是这个。三层主要是路由协议。还介绍了些常见的应用协议。最后介绍了些网络调式工具。
二层
交换机:硬件,快,端口多。二层/三层(多用于LAN)
数据链路地址的目的是在同一网络中将数据链路帧从一个网络接口发送至另一个网络接口,MAC地址是物理植入网卡的48比特地址(路由器也有mac地址)
ARP(根据IP地址获取mac地址,将ARP请求帧广播到本地网络上的所有主机),LAN交换机MAC地址表的动态更新:交换机学习“源地址”(记录来源端口和mac地址),基于“目的地址”转发,没有在表中找到目的MAC地址,交换机会转发到除了进入端口以外的所有端口泛洪(flooding)
VLAN
为何要划分VLAN?防止广播flooding扩散,广播只在VLAN上
交换机端口类型:
1.正常只有内部可通信,accesslink 可以根据端口固定划分VLAN,可以根据mac,ip动态划分
2.同一VLAN夸交换机:汇聚link。(只对连接同一VLAN转发,同一交换机找不到才到另一个)
跨VLAN:三层交换机/路由
对个应公司网络架构:核心交换机是三层,接入层是二层,中间其实还有个汇聚层可以做防火墙等
三层
- 路由:软件实现,功能更多,安全认证等,端口少。三层高
协议:mac+ip
转发过程:PC1通过将自己的IPv4地址与子网掩码做与操作,来判断PC 1所属的网段。接下来,PC 1对目的IPv4地址与PC 1的子网掩码做同样的与操作。如果目的网络地址与PC 1网络相同,则PC 1不使用默认网关,而是在ARP缓存中查找目的IPv4地址的设备MAC地址。如果MAC地址不在缓存中,则PC 1产生一个ARP请求来获取地址并将报文发给目的地址。如果目的网络地址位于另一网络,则PC1将报文转发至默认网关,默认网关的MAC地址同上。
根据获得路由的方式可以将其分为静态路由和动态路由,静态路由就是管理员静态配置的路由,动态路由则是路由器通过算法动态地学习和调整而得到的路由。而常说的路由协议就是指这些动态路由的学习算法,根据其作用域的不同,又可分为内部网管协议(IGP)和边界网络协议(BGP);内部网络协议包括RIP,OSPF等。这几类路由协议,小规模私有网络IGP(OSPF),大规模私有网络IBGP,互联网EBGP - IP地址:
在不考虑子网的情况下,ip地址分类:
A,最高位必须是0,由1字节的网络地址和3字节主机地址组成(数字0和 127不作为A类地址,数字127保留给内部回送函数,而数字0则表示该地址是本地宿主机,不能传送,0.0.0.0~126.255.255.255),
B:最高位10,由2个字节的网络地址和2个字节的主机(128.0.0.0~191.255.255.255),
C:110,3字节的网络地址和1字节的主机地址(192.0.0.0~223.255.255.255),
D:1110用于广播,
E:11110保留
在IP地址3种主要类型里,各保留了3个区域作为私有地址(内网),其地址范围如下:
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地址由此被分为三个部分:网络ID,子网ID与主机ID(这两部分共同为原来的主机地址),根据子网掩码来判断子网ID与主机ID,
假设将B类网络154.71.0.0划分5位为子网ID,11位为主机ID。因此,子网掩码有16个1代表网络部分(B类网络),接下来5个1作为子网部分,11个0用作主机ID。二进制数表示为11111111 11111111 11111000 00000000,十进制数表示为255.255.248.0,新的表达法为154.71.150.42/21。IP地址和子网掩码做与操作获取子网地址,以便路由器找到网络。21意思是子网掩码为21个1后面0,即255.255.248.0
协议
路由相关
- RIP
典型DV(Distance Vector,距离矢量,基于跳数,UDP之上)协议,其工作原理如下:
如果更新的某路由表项在路由表中没有,则直接在路由表中添加该路由表项
如果路由表中已有相同目的网络的路由表项,且来源端口相同,那么无条件根据最新的路由信息更新其路由表(不收敛问题,限制最大跳数16超过删除链路或水平分割更新)
如果路由表中已有相同目的网络的路由表项,但来源端口不同,则要比较它们的度量值,将度量值较小的一个作为自己的路由表项
如果路由表中已有相同目的网络的路由表项,且度量值相等,保留原来的路由表项 - 等价路由协议ecmp
如果使用传统的路由技术,发往该目的地址的数据包只能利用其中的一条链路,其它链路处于备份状态或无效状态,并且在动态路由环境下相互的切换需要一定的时间,而等价多路径路由协议可以在该网络环境下同时使用多条链路,不仅增加了传输带宽,并且可以无时延无丢包地备份失效链路的数据传输。对等价的评估很重要,路由器两个出口,两路径,一个带宽是100M,一个是2M,如果部署是ECMP,则网络总带宽只能达到4M的利用率。 - BGP
网络过大的时候,也会导致路由表过大而难以维护,这时候采用分治的方法,将一个大网络划分为若干个小网络,这些小网络称为自治系统(AS),BGP的诞生就是用于自治系统间的通信。每个记录所有路径。可以通过下发BGP配置实现夸运营商路由,http://wulc.me/2016/12/25/计... - EBGP
- OSPF
典型的LS(Link State,链路状态)协议,其思想是通过邻居的LSA(Link-state advertisement, 链路转态通告)构建整个网络的拓扑(DR负责建立拓扑,与所有节点建立关系[并不一定直连],BDR为其备份,变化时通知DR,DR广播),所有路由复制拓扑,并构建以自己为根节点的最小生成树,然后通过dijkstra 计算最短路径,并根据最短路径修改路由表,基于带宽等综合比较,相同权值负载平衡分配。
1.建立路由器毗邻关系
2.选举DR和BDR
3.发现路由
4.选择最佳路由(最小生成树)
5.维护路由信息
- anycast
访问该地址的报文可以被IP网络路由到这一组目标中的任何一台主机上,它提供的是一种无状态的、尽力而为的服务。使用Anycast中的共享单播地址不能作为客户端发起请求,因为请求的响应不一定能返回到发起的Anycast单播地址。因此,目前Anycast仅适合一些特定的上层协议,从目前的实际应用来看, Anycast最广泛的应用是DNS的部署。通常使用Anycast的共享单播地址拥有独立的自治域号,并通过BGP协议与不同自治域网络交换路由,即IP Anycast+BGP。 - DHCP
动态主机设置协议, 给内部网络或网络服务供应商自动分配IP地址。DHCP从一个IP地址池中提供IP地址,基于UDP协议。配置使用DHCP的客户端第一次初始化TCP/IP,会广播一条IP Request,
- NAT
静态NAT:此类NAT在本地和全局地址之间做一到一的永久映射。须注意静态NAT要求用户对每一台主机都有一个真实的Internet IP地址。 ip nat inside source static 10.1.1.1 170.46.2.2
动态NAT:允许用户将一个未登记的IP地址映射到一个登记的IP地址池中的一个。采用动态分配的方法将外部合法地址映射到内部网络,无需像静态NAT那样,通过对路由器进行静态配置来将内部地址映射到外部地址,但是必须有足够的真正的IP地址来进行收发包。一定要检查池中确保有足够地址提供转换给内部主机
ip nat pool todd 170.168.2.3 192.168.2.254 netmask 255.255.255.0
ip nat inside source list 1 pool todd - 端口NAT(PAT)
最为流行的NAT配置类型。通过多个源端口,将多个未登记的IP地址映射到一个合法IP地址(多到一)。使用PAT能够使上千个用户仅使用一个全局IP地址连接到Internet。
ip nat pool globalnet 170.168.2.1 170.168.2.1 netmask 255.255.255.0
ip nat inside source list 1 pool globalnet overload
UDP
- 特点:
1.无连接
2.不可靠
3.面向报文,无边界的,添加首部后直接交付给IP层,不合并也不拆分。所以报文太长后,IP层在传输时会分片,降低效率,太短,IP数据报的首部相对长度太大,也降低IP层效率
4.没有拥塞控制
5.支持一对一,一对多,多对一,多对多的交互通信
6.首部开销小,只有8字节 - UDP首部:源端口号,目的端口号,长度,校验和,各2字节
计算校验和方法:在首部前临时增加一个伪首部:源IP地址(4)目的IP地址(4)0(1)17(1)UDP长度(2),将伪首部,首部,数据(非偶数字节则补0)按二进制运算求和,反码作为校验和
TCP
- 特点
1.面向连接
2.可靠
3.只能一对一连接
4.全双工通信,通信双方在任何时候都可以发送数据,设有发送缓存和接受缓存
5.面向字节流,先把字节写入缓存,一次发送一个数据块(加TCP首部),一块包含多少字节受窗口值和网络拥塞程度决定 -
TCP首部:20B~60B,固定部分:
源端口号(2),目的端口号(2); 序号(4)每个字节都按顺序编号,首部中的序号字段值指的是本报文段所发送的数据的第一个字节的序号; 确认号(4)希望收到对方下一个报文段的第一个数据字节的序号,若确认号\=N,表示N-1为止的所有数据都已正确收到 数据偏移(4bit)首部长度,以4字节长度为计算单位,最多可表示15*4\=60B 保留(6) 紧急URG(1bit)高优先级数据,不安排队顺序传送 确认ACK PUSH,发送端 : TCP将数据包置上PUSH标志时,表示这个数据应该被立即发送,而不要等待额外的数据。 接收端 : 接收端接受到带有PUSH标志的数据时,应该接接受缓存中收到的所有数据(包含当前带PUSH标示的数据包)应该立即提交到应用层。当前没有API通知TCP哪些数据需要被设置PUSH标示,完全由TCP自行判断决定。 复位RST,必须释放连接 同步SYN 终止FIN 窗口(2)指该方接收窗口的窗口值,允许对方发送的数据量 校验和(2)计算方法和UDP一样,伪首部中17改成6即可 紧急指针(2)当URG=1时,指出紧急数据的字节数
- 可靠传输实现
滑动窗口,发送方:经过确认的就往前移动窗口,超时重传,接收方:非按序到达的暂存,确认的都达到后发送确认信息(积累确认),窗口前移。
TCP流量控制:利用滑动窗口实现,接收方给发送方规定窗口大小。
TCP拥塞控制:发送方维持一个拥塞窗口,只要网络没出现拥塞,拥塞窗口就再增大一些,出现拥塞,就减小一些
慢开始(由小到大逐渐增大发送窗口,指的是开始很小,增长速率不慢),拥塞避免(线性增长),快重传,快恢复(当连续收到三个重复确认,将慢开始门限执行乘法减小,然后开始执行拥塞避免)
发送方的窗口大小=min(拥塞窗口大小,接收方窗口)
- TCP连接管理
1.三次握手建立连接:
这里为什么要再发一次ACK=1的确认呢?如果B应答就建立连接,可能出现这种情况:A发送一次请求后延迟,重新发送一次,B接受一个后建立了连接,传完之后,B又收到了之前延迟的请求,又建立了连接,但是A并没有数据要传,浪费了B的资源。发送SYN不能携带数据,但是会消耗一个序号,ACK如果不携带数据就不会消耗序号,所以下一个报文段seq=x+1。
2.四次挥手释放连接:
A收到第一次B的确认后就不能传数据了,A要等待2MSL的原因:一为了保证最后一条确认可以到达B,因为若A发完就关闭了,若此确认丢失,A也收不到B的丢失确认也无法重新发送。二是为了再此时间段内让之前丢失重发的报文都从网络中消失,再开始下一次连接。
在没有数据发送的情况下。直接发送FIN/ACK四次变三次。
TIME_WAIT是肯定必不可少的
3.socket状态 - TCP窗口与重传机制
发送方窗口快照:C3可能为0
假设已发送未确认字节(32至45)分为4段传输:32-34,35-36,37-41,42-45。第1,2,4已经到达,而3段没有收到。接收方只会发回32-36的确认信息。接收方会保留42-45但不会确认
发送设备之后会停止发送,窗口停留在37-41。TCP包括一个传输及重传的计时机制。TCP会重传丢失的片段。对于42-45的处理看SCAK。
1.基于定时器的重传(timeout or timer-based retransmission),这种重传方式是发出去的数据在RTO超时后还没有收到对应的ACK就会进行超时重传。
2.另外TCP还有一种基于ACK报文结构顺序的重传,这种重传叫做快速重传(fast retransmission或者fast retransmit),当TCP注意到累计ack(即TCP头中的ack number)不再推进(当收到p1,p3,p4时都会回p1的ack)或者接收端通过SACK信息指示发送端接收端存在洞(hole)时候就会触发发送端的重传,通常来说快速重传比超时重传更高效
对于1:每个片段在发送是都启动重传计时,当超过这个RTO还没有确认就重传,确认则<=该序号的都移出窗口。
RTO(Retransmission Timeout),RTO应该根据环回时间RTT(round-trip-time)来估计。环回时间应该包括三部分:数据包传送过的时间,接收端处理这个数据包并产生ACK的时间,ACK确认包返回的时间。RTO计算:https://www.cnblogs.com/lshs/...
SACK的选择重传机制:连接的两方设备必须同时支持这一功能,通过连接时使用的SYN片段来协商是否允许SACK
在4个片段的情况下,如果客户端接收到片段4而没有接收到片段3,当它发回确认号为201(片段1和片段2)的确认信息,其中包含一个SACK选项指明:“已接收到字节361至500,但尚未确认”。如果片段4在片段1和2之后到达,上述信息也可以通过第二个确认片段来完成。服务器确认片段4的字节范围,并为片段4打开SACK位。当片段3重传时,服务器看到片段4的SACK位为1,就不会对其重传。
在片段3重传之后,片段4的SACK位被清除。这是为了防止客户端出于某种原因改变片段4已接收的想法。客户端应当发送确认号为501或更高的确认信息,正式确认片段3和4接收到。如果这一情况没有发生,服务器必须接收到片段4的另一条选择确认信息才能将它的SACK位打开,否则,在片段3重传时或计时器超时的情况下会对其自动重传。 -
提升效率
对于ack(1.累计【累计发送连续顺序接收最大的】2.延时【与数据一起发送,最长等待时间一般200ms】)。对于数据1.等大包,2。拥塞控制
Nagle算法,任意时刻,最多只能有一个未被确认的小段(对于发送数据包)。Nagle算法的规则(可参考tcp_output.c文件里tcp_nagle_check函数注释): (1)如果包长度达到MSS,则允许发送; (2)如果该包含有FIN,则允许发送; (3)设置了TCP_NODELAY选项,则允许发送; (4)未设置TCP_CORK选项时,若所有发出去的小数据包(包长度小于MSS)均被确认,则允许发送; (5)上述条件都未满足,但发生了超时(一般为200ms),则立即发送。
delayed ack算法:ACK响应,等待一个超时或者满足特殊条件时再发送。对于Linux实现,这些特殊条件如下:
1)收到的数据已经超过了full frame size 2)或者处于快速回复模式 3)或者出现了乱序的包 4)或者接收窗口的数据足够多
默认情况下,发送数据采用Nagle 算法。这样虽然提高了网络吞吐量,但是实时性却降低了,在一些交互性很强的应用程序来说是不允许的,使用TCP_NODELAY选项可以禁止Nagle 算法。此时,应用程序向内核递交的每个数据包都会立即发送出去。需要注意的是,虽然禁止了Nagle 算法,但网络的传输仍然受到拥塞控制和delay ack的影响。delay ack可以通过TCP_QUICKACK使得机内快速回复模式
Nagle算法完全不受用户socket的控制,你只能简单的设置TCP_NODELAY而禁用它
CORK算法通过设置或者清除TCP_CORK使能或者禁用之,内核会尽力把小数据包拼接成一个大的数据包(一个MTU)再发送出去 - setsockopt选项
TCP_NODELAY禁用nagle,不会有小包等待,提高吞吐量,降低延迟。
TCP_CORK 尽可能多的发送数据,与TCP_NODELAY相反,适用文件服务。
TCP_QUICKACK 快速回复模式,AACK不累计
SO_LINGER作用于TCP close,默认close会立即返回,将丢弃缓存区内的所有数据并且立即终止连接(即发送RST数据包)。设置该选项,只关闭写,不关闭读,保证读Buffer没了,就不会发RST,而是正常的四次挥手。
SO_KEEPALIVE 没有数据时定期发送探测包。
SO_REUSEADDR 重用处于TIME_WAIT状态的socket。
TCP_MAXSEG 设置MSS,即通告对方的窗口大小。
TCP_DEFER_ACCEPT 防止accept之后立刻读数据,而要等client发过来数据再去读
HTTP
内容比较多,参考http权威读书指南。讲一些实际上应用中会用到和注意的
协议格式响应略
- HTTP依赖TCP性能
TCP建立连接建立握手,TCP慢启动拥塞机制,数据聚集的Nagle算法,用于捎带确认的TCP延迟确认算法,TIME_WAIT时延和端口耗尽
延迟确认:由于确认报文很小,TCP允许在输出数据分组捎带确认报文,延时确认算法会在一个特定的窗口时间(通常是100-200毫秒)内将输出确认存放在缓冲区中,以寻找能够捎带他的输出数据分组,如果在该时间段内没有输出数据分组,确认信息再单独发送。但是HTTP具有双峰特性的请求,当希望有反方向回传时,偏偏没有那么多分组
慢启动:新建立连接发送报文数量慢启动过程
Nagle算法:TCP至少40字节头,Nagle算法鼓励发送全尺寸段,只有当所有其他分组都被确认或者缓存中积累了足够发送一个全尺寸分组的数据时,才会将缓存数据发送出去。与延迟确认交互存在问题,确认分组自身会被延迟100-200毫秒,http小报文无法填满一个分组。HTTP尝尝会设置TCP_NODELAY禁用Nagle算法
TIME_WAIT:关闭连接时,会在内存中记录最近关闭连接的IP地址和端口号,通常会维持2MSL,以确保这段时间内部会创建具有相同地址和端口号的新连接。通常不会有什么问题,但是在单台机器上测试时,只有源端口号可变,会出现端口号耗尽情况,测试中需要注意。 - 连接
connection首部的值:只与本连接有关的首部(发往下一跳要删除);任意本连接有关的非标准选项,close(关闭持久连接),在到达一跳时要删除所有的值再自行处理。
持久连接:1.1,默认开启,除非Connection: Close;
管道:在1.1keep-alive基础上,第一个发送之后就可以不等响应发送第二个,要求服务端响应保持按顺序,客户端重传处理。不能用于POST非幂等(一定要等响应才决定是否重发)方法。
关闭连接:当一端关闭输入连接,另一端又发来消息,操作系统会发送一个错误信息,并删除对端还未读取的所有缓存,对于管道,可能会因为一个新连接删除很多缓存未读取的连接数据。应该双方否只关闭输出连接,收到双方关闭信息后再完全关闭。
并行连接:在客户端带宽不足时没有提升;消耗更多内存资源;服务端压力大。一般浏览器会限制最多并发4个,服务端可以随意关闭特定客户端超过连接数的请求。 - web的结构组件:代理(转发所有web流量的可信任中间节点,via),缓存,网关(将HTTP流量转化为其他协议),隧道(在HTTP连接中转发非HTTP数据比如在ssl应用上如下图),agent代理(发起HTTP请求浏览器等),web服务器
- content相关:
分块编码chunked:把报文分割为若干个大小已知的块,块之间是紧挨着发送的,这样就不需要在发送之前知道整个报文的大小了。
范围请求Range,响应Accept-ranges表明接收范围请求,值为单位,若一个请求包含多个范围,响应有Content-Type: multipart/byteranges. - HTTP2.0
在底层传输协议之上分为三层:报文传输,远程操作调用,web应用功能。
报文传输:对报文进行管道话和批量化传输,以降低往返时延;重用连接,以降低时延,提高传输带宽;在同一条连接上并行的复用多个报文流,在防止报文流饿死的同事优化共享连接;对报文进行有效的分段,使报文边界的确定更加容易。
webmux:一个复杂的高性能报文系统,可以在一个复用的TCP连接上并行传输报文,可以对以不同速度产生和消耗独立报文流进行高效的分组,并将其复用到一条或少数几条TCP连接上去。
远程调用:二进制链接协议 -
HTTPS
SSL 基于TCP,SSL不是简单地单个协议,而是两层协议;SSL记录协议(SSL Record Protocol)为多种高层协议(SSL握手协议,SSL修改密码参数协议,SSL报警协议)提供基本的安全服务。
0x01 对对称加密的通俗理解即通信的双方都使用同一个秘钥进行加解密
0x02 对非对称加密算法的通俗理解 [ RSA ]
私钥 + 公钥= 密钥对 即用私钥加密的数据,只有对应的公钥才能解密,用公钥加密的数据,只有对应的私钥才能解密 其实这个很容易理解,因为通信双方的手里都有一套自己的密钥对,通信之前双方会先把自己的公钥都先发给对方 然后对方再拿着这个公钥来加密数据响应给对方,等到到了对方那里,对方再用自己的私钥进行解密,就这么简单
0x03 非对称加密所造成的速度慢的问题解决办法
(1) 先生成一个对称加密算法的密钥,用RSA的方式先安全的发给对方 (2) 随后就不再用RSA了,只用这个对称加密的密钥来互相通信
-> 客户端向服务端发送请求 -> 服务端返回数字证书 -> 客户端用自己的CA[主流的CA机构证书一般都内置在各个主流浏览器中]公钥去解密证书,如果证书有问题会提示风险 -> 如果证书没问题客户端会生成一个对称加密的随机秘钥然后再和刚刚解密的服务器端的公钥对数据进行加密,然后发送给服务器端 -> 服务器端收到以后会用自己的私钥对客户端发来的对称秘钥进行解密
THRIFT
Thrift是一个跨语言的服务部署框架。支持协议:只关心TBinaryProtocol。传输层支持:只关心TFramedTransport,服务模型:用这个TNonblockingServer,TProcessor 服务调用组件,单独将框架时讲解,这里说下协议。
TBinaryProtocol的实现。
writeMessgeBegin方法写了消息头,包括4字节的版本号和类型信息,字符串类型的方法名,4字节的序列号seqId
writeFieldBegin,写了1个字节的字段数据类型,和2个字节字段的顺序号
writeI32,写了4个字节的字节数组
writeString,先写4字节消息头表示字符串长度,再写字符串字节
writeBinary,先写4字节消息头表示字节数组长度,再写字节数组内容
readMessageBegin时,先读4字节版本和类型信息,再读字符串,再读4字节序列号
readFieldBegin,先读1个字节的字段数据类型,再读2个字节的字段顺序号
readString时,先读4字节字符串长度,再读字符串内容。字符串统一采用UTF-8编码
故障排查
tcpdump
wireshark
ping
通过netstat进行流量测量,netstat -i(获取快照),spray -c1000 205.153.63.239(模拟发送数据),netstat -p tcp -s -s(-s输出详细信息)
ttcp
netperf
iperf
treno
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。